The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/intermezzo/dir.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
    2  * vim:expandtab:shiftwidth=8:tabstop=8:
    3  *
    4  *  Copyright (C) 2000 Stelias Computing, Inc.
    5  *  Copyright (C) 2000 Red Hat, Inc.
    6  *  Copyright (C) 2000 Tacitus Systems
    7  *  Copyright (C) 2000 Peter J. Braam
    8  *
    9  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
   10  *
   11  *   InterMezzo is free software; you can redistribute it and/or
   12  *   modify it under the terms of version 2 of the GNU General Public
   13  *   License as published by the Free Software Foundation.
   14  *
   15  *   InterMezzo is distributed in the hope that it will be useful,
   16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18  *   GNU General Public License for more details.
   19  *
   20  *   You should have received a copy of the GNU General Public License
   21  *   along with InterMezzo; if not, write to the Free Software
   22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   23  */
   24 
   25 #include <stdarg.h>
   26 
   27 #include <asm/bitops.h>
   28 #include <asm/uaccess.h>
   29 #include <asm/system.h>
   30 #include <linux/smp_lock.h>
   31 
   32 #include <linux/errno.h>
   33 #include <linux/fs.h>
   34 #include <linux/ext2_fs.h>
   35 #include <linux/slab.h>
   36 #include <linux/vmalloc.h>
   37 #include <linux/sched.h>
   38 #include <linux/stat.h>
   39 #include <linux/string.h>
   40 #include <linux/locks.h>
   41 #include <linux/blkdev.h>
   42 #include <linux/init.h>
   43 #define __NO_VERSION__
   44 #include <linux/module.h>
   45 
   46 #include <linux/intermezzo_fs.h>
   47 #include <linux/intermezzo_psdev.h>
   48 
   49 static inline void presto_relock_sem(struct inode *dir) 
   50 {
   51         /* the lock from sys_mkdir / lookup_create */
   52         down(&dir->i_sem);
   53         /* the rest is done by the do_{create,mkdir, ...} */
   54 }
   55 
   56 static inline void presto_relock_other(struct inode *dir) 
   57 {
   58         /* vfs_mkdir locks */
   59         down(&dir->i_zombie);
   60         lock_kernel(); 
   61 }
   62 
   63 static inline void presto_fulllock(struct inode *dir) 
   64 {
   65         /* the lock from sys_mkdir / lookup_create */
   66         down(&dir->i_sem);
   67         /* vfs_mkdir locks */
   68         down(&dir->i_zombie);
   69         lock_kernel(); 
   70 }
   71 
   72 static inline void presto_unlock(struct inode *dir) 
   73 {
   74         /* vfs_mkdir locks */
   75         unlock_kernel(); 
   76         up(&dir->i_zombie);
   77         /* the lock from sys_mkdir / lookup_create */
   78         up(&dir->i_sem);
   79 }
   80 
   81 
   82 /*
   83  * these are initialized in super.c
   84  */
   85 extern int presto_permission(struct inode *inode, int mask);
   86 static int izo_authorized_uid = 0;
   87 
   88 int izo_dentry_is_ilookup(struct dentry *dentry, ino_t *id,
   89                           unsigned int *generation)
   90 {
   91         char tmpname[64];
   92         char *next;
   93 
   94         ENTRY;
   95         /* prefix is 7 characters: '...ino:' */
   96         if ( dentry->d_name.len < 7 || dentry->d_name.len > 64 ||
   97              memcmp(dentry->d_name.name, PRESTO_ILOOKUP_MAGIC, 7) != 0 ) {
   98                 EXIT;
   99                 return 0;
  100         }
  101 
  102         memcpy(tmpname, dentry->d_name.name + 7, dentry->d_name.len - 7);
  103         *(tmpname + dentry->d_name.len - 7) = '\0';
  104 
  105         /* name is of the form ...ino:<inode number>:<generation> */
  106         *id = simple_strtoul(tmpname, &next, 16);
  107         if ( *next == PRESTO_ILOOKUP_SEP ) {
  108                 *generation = simple_strtoul(next + 1, 0, 16);
  109                 CDEBUG(D_INODE, "ino string: %s, Id = %lx (%lu), "
  110                        "generation %x (%d)\n",
  111                        tmpname, *id, *id, *generation, *generation);
  112                 EXIT;
  113                 return 1;
  114         } else {
  115                 EXIT;
  116                 return 0;
  117         }
  118 }
  119 
  120 struct dentry *presto_tmpfs_ilookup(struct inode *dir, 
  121                                     struct dentry *dentry,
  122                                     ino_t ino, 
  123                                     unsigned int generation)
  124 {
  125         return dentry; 
  126 }
  127 
  128 
  129 inline int presto_can_ilookup(void)
  130 {
  131         return (current->euid == izo_authorized_uid ||
  132                 capable(CAP_DAC_READ_SEARCH));
  133 }
  134 
  135 struct dentry *presto_iget_ilookup(struct inode *dir, 
  136                                           struct dentry *dentry,
  137                                           ino_t ino, 
  138                                           unsigned int generation)
  139 {
  140         struct inode *inode;
  141         int error;
  142 
  143         ENTRY;
  144 
  145         if ( !presto_can_ilookup() ) {
  146                 CERROR("ilookup denied: euid %u, authorized_uid %u\n",
  147                        current->euid, izo_authorized_uid);
  148                 return ERR_PTR(-EPERM);
  149         }
  150         error = -ENOENT;
  151         inode = iget(dir->i_sb, ino);
  152         if (!inode) { 
  153                 CERROR("fatal: NULL inode ino %lu\n", ino); 
  154                 goto cleanup_iput;
  155         }
  156         if (is_bad_inode(inode) || inode->i_nlink == 0) {
  157                 CERROR("fatal: bad inode ino %lu, links %d\n", ino, inode->i_nlink); 
  158                 goto cleanup_iput;
  159         }
  160         if (inode->i_generation != generation) {
  161                 CERROR("fatal: bad generation %u (want %u)\n",
  162                        inode->i_generation, generation);
  163                 goto cleanup_iput;
  164         }
  165 
  166         d_instantiate(dentry, inode);
  167         dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; /* NFS hack */
  168 
  169         EXIT;
  170         return NULL;
  171 
  172 cleanup_iput:
  173         if (inode)
  174                 iput(inode);
  175         return ERR_PTR(error);
  176 }
  177 
  178 struct dentry *presto_add_ilookup_dentry(struct dentry *parent,
  179                                          struct dentry *real)
  180 {
  181         struct inode *inode = real->d_inode;
  182         struct dentry *de;
  183         char buf[32];
  184         char *ptr = buf;
  185         struct dentry *inodir;
  186         struct presto_dentry_data *dd;
  187 
  188         inodir = lookup_one_len("..iopen..", parent,  strlen("..iopen..")); 
  189         if (!inodir || IS_ERR(inodir) || !inodir->d_inode ) { 
  190                 CERROR("%s: bad ..iopen.. lookup\n", __FUNCTION__); 
  191                 return NULL; 
  192         }
  193         inodir->d_inode->i_op = &presto_dir_iops;
  194 
  195         snprintf(ptr, 32, "...ino:%lx:%x", inode->i_ino, inode->i_generation);
  196 
  197         de = lookup_one_len(ptr, inodir,  strlen(ptr)); 
  198         if (!de || IS_ERR(de)) {
  199                 CERROR("%s: bad ...ino lookup %ld\n", 
  200                        __FUNCTION__, PTR_ERR(de)); 
  201                 dput(inodir);
  202                 return NULL; 
  203         }
  204 
  205         dd = presto_d2d(real);
  206         if (!dd) 
  207                 BUG();
  208 
  209         /* already exists */
  210         if (de->d_inode)
  211                 BUG();
  212 #if 0 
  213                 if (de->d_inode != inode ) { 
  214                         CERROR("XX de->d_inode %ld, inode %ld\n", 
  215                                de->d_inode->i_ino, inode->i_ino); 
  216                         BUG();
  217                 }
  218                 if (dd->dd_inodentry) { 
  219                         CERROR("inodentry exists %ld \n", inode->i_ino);
  220                         BUG();
  221                 }
  222                 dput(inodir);
  223                 return de;
  224         }
  225 #endif 
  226 
  227         if (presto_d2d(de)) 
  228                 BUG();
  229 
  230         atomic_inc(&inode->i_count);
  231         de->d_op = &presto_dentry_ops;
  232         d_add(de, inode);
  233         if (!de->d_op)
  234                 CERROR("DD: no ops dentry %p, dd %p\n", de, dd);
  235         dd->dd_inodentry = de;
  236         dd->dd_count++;
  237         de->d_fsdata = dd;
  238 
  239         dput(inodir);
  240         return de;
  241 }
  242 
  243 struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry)
  244 {
  245         int rc = 0;
  246         struct dentry *de;
  247         struct presto_cache *cache;
  248         int minor;
  249         ino_t ino;
  250         unsigned int generation;
  251         struct inode_operations *iops;
  252         int is_ilookup = 0;
  253 
  254         ENTRY;
  255         cache = presto_get_cache(dir);
  256         if (cache == NULL) {
  257                 CERROR("InterMezzo BUG: no cache in presto_lookup "
  258                        "(dir ino: %ld)!\n", dir->i_ino);
  259                 EXIT;
  260                 return NULL;
  261         }
  262         minor = presto_c2m(cache);
  263 
  264         iops = filter_c2cdiops(cache->cache_filter);
  265         if (!iops || !iops->lookup) {
  266                 CERROR("InterMezzo BUG: filesystem has no lookup\n");
  267                 EXIT;
  268                 return NULL;
  269         }
  270 
  271 
  272         CDEBUG(D_CACHE, "dentry %p, dir ino: %ld, name: %*s, islento: %d\n",
  273                dentry, dir->i_ino, dentry->d_name.len, dentry->d_name.name,
  274                ISLENTO(minor));
  275 
  276         if (dentry->d_fsdata)
  277                 CERROR("DD -- BAD dentry %p has data\n", dentry);
  278                        
  279         dentry->d_fsdata = NULL;
  280 #if 0
  281         if (ext2_check_for_iopen(dir, dentry))
  282                 de = NULL;
  283         else {
  284 #endif
  285                 if ( izo_dentry_is_ilookup(dentry, &ino, &generation) ) { 
  286                         de = cache->cache_filter->o_trops->tr_ilookup
  287                                 (dir, dentry, ino, generation);
  288                         is_ilookup = 1;
  289                 } else
  290                         de = iops->lookup(dir, dentry);
  291 #if 0
  292         }
  293 #endif
  294 
  295         if ( IS_ERR(de) ) {
  296                 CERROR("dentry lookup error %ld\n", PTR_ERR(de));
  297                 return de;
  298         }
  299 
  300         /* some file systems have no read_inode: set methods here */
  301         if (dentry->d_inode)
  302                 presto_set_ops(dentry->d_inode, cache->cache_filter);
  303 
  304         filter_setup_dentry_ops(cache->cache_filter,
  305                                 dentry->d_op, &presto_dentry_ops);
  306         dentry->d_op = filter_c2udops(cache->cache_filter);
  307 
  308         /* In lookup we will tolerate EROFS return codes from presto_set_dd
  309          * to placate NFS. EROFS indicates that a fileset was not found but
  310          * we should still be able to continue through a lookup.
  311          * Anything else is a hard error and must be returned to VFS. */
  312         if (!is_ilookup)
  313                 rc = presto_set_dd(dentry);
  314         if (rc && rc != -EROFS) {
  315                 CERROR("presto_set_dd failed (dir %ld, name %*s): %d\n",
  316                        dir->i_ino, dentry->d_name.len, dentry->d_name.name, rc);
  317                 return ERR_PTR(rc);
  318         }
  319 
  320         EXIT;
  321         return NULL;
  322 }
  323 
  324 static inline int presto_check_set_fsdata (struct dentry *de)
  325 {
  326         if (presto_d2d(de) == NULL) {
  327 #ifdef PRESTO_NO_NFS
  328                 CERROR("dentry without fsdata: %p: %*s\n", de, 
  329                                 de->d_name.len, de->d_name.name);
  330                 BUG();
  331 #endif
  332                 return presto_set_dd (de);
  333         }
  334 
  335         return 0;
  336 }
  337 
  338 int presto_setattr(struct dentry *de, struct iattr *iattr)
  339 {
  340         int error;
  341         struct presto_cache *cache;
  342         struct presto_file_set *fset;
  343         struct lento_vfs_context info = { 0, 0, 0 };
  344 
  345         ENTRY;
  346 
  347         error = presto_prep(de, &cache, &fset);
  348         if ( error ) {
  349                 EXIT;
  350                 return error;
  351         }
  352 
  353         if (!iattr->ia_valid)
  354                 CDEBUG(D_INODE, "presto_setattr: iattr is not valid\n");
  355 
  356         CDEBUG(D_INODE, "valid %#x, mode %#o, uid %u, gid %u, size %Lu, "
  357                "atime %lu mtime %lu ctime %lu flags %d\n",
  358                iattr->ia_valid, iattr->ia_mode, iattr->ia_uid, iattr->ia_gid,
  359                iattr->ia_size, iattr->ia_atime, iattr->ia_mtime,
  360                iattr->ia_ctime, iattr->ia_attr_flags);
  361         
  362         if ( presto_get_permit(de->d_inode) < 0 ) {
  363                 EXIT;
  364                 return -EROFS;
  365         }
  366 
  367         if (!ISLENTO(presto_c2m(cache)))
  368                 info.flags = LENTO_FL_KML;
  369         info.flags |= LENTO_FL_IGNORE_TIME;
  370         error = presto_do_setattr(fset, de, iattr, &info);
  371         presto_put_permit(de->d_inode);
  372         return error;
  373 }
  374 
  375 /*
  376  *  Now the meat: the fs operations that require journaling
  377  *
  378  *
  379  *  XXX: some of these need modifications for hierarchical filesets
  380  */
  381 
  382 int presto_prep(struct dentry *dentry, struct presto_cache **cache,
  383                 struct presto_file_set **fset)
  384 {       
  385         int rc;
  386 
  387         /* NFS might pass us dentries which have not gone through lookup.
  388          * Test and set d_fsdata for such dentries
  389          */
  390         rc = presto_check_set_fsdata (dentry);
  391         if (rc) return rc;
  392 
  393         *fset = presto_fset(dentry);
  394         if ( *fset == NULL ) {
  395                 CERROR("No file set for dentry at %p: %*s\n", dentry,
  396                                 dentry->d_name.len, dentry->d_name.name);
  397                 return -EROFS;
  398         }
  399 
  400         *cache = (*fset)->fset_cache;
  401         if ( *cache == NULL ) {
  402                 CERROR("PRESTO: BAD, BAD: cannot find cache\n");
  403                 return -EBADF;
  404         }
  405 
  406         CDEBUG(D_PIOCTL, "---> cache flags %x, fset flags %x\n",
  407               (*cache)->cache_flags, (*fset)->fset_flags);
  408         if( presto_is_read_only(*fset) ) {
  409                 CERROR("PRESTO: cannot modify read-only fileset, minor %d.\n",
  410                        presto_c2m(*cache));
  411                 return -EROFS;
  412         }
  413         return 0;
  414 }
  415 
  416 static int presto_create(struct inode * dir, struct dentry * dentry, int mode)
  417 {
  418         int error;
  419         struct presto_cache *cache;
  420         struct dentry *parent = dentry->d_parent;
  421         struct lento_vfs_context info;
  422         struct presto_file_set *fset;
  423 
  424         ENTRY;
  425         error = presto_check_set_fsdata(dentry);
  426         if ( error ) {
  427                 EXIT;
  428                 return error;
  429         }
  430 
  431         error = presto_prep(dentry->d_parent, &cache, &fset);
  432         if ( error ) {
  433                 EXIT;
  434                 return error;
  435         }
  436         presto_unlock(dir);
  437 
  438         /* Does blocking and non-blocking behavious need to be 
  439            checked for.  Without blocking (return 1), the permit
  440            was acquired without reintegration
  441         */
  442         if ( presto_get_permit(dir) < 0 ) {
  443                 EXIT;
  444                 presto_fulllock(dir);
  445                 return -EROFS;
  446         }
  447 
  448         presto_relock_sem(dir);
  449         parent = dentry->d_parent; 
  450         memset(&info, 0, sizeof(info));
  451         if (!ISLENTO(presto_c2m(cache)))
  452                 info.flags = LENTO_FL_KML;
  453         info.flags |= LENTO_FL_IGNORE_TIME;
  454         error = presto_do_create(fset, parent, dentry, mode, &info);
  455 
  456         presto_relock_other(dir);
  457         presto_put_permit(dir);
  458         EXIT;
  459         return error;
  460 }
  461 
  462 static int presto_link(struct dentry *old_dentry, struct inode *dir,
  463                 struct dentry *new_dentry)
  464 {
  465         int error;
  466         struct presto_cache *cache, *new_cache;
  467         struct presto_file_set *fset, *new_fset;
  468         struct dentry *parent = new_dentry->d_parent;
  469         struct lento_vfs_context info;
  470 
  471         ENTRY;
  472         error = presto_prep(old_dentry, &cache, &fset);
  473         if ( error ) {
  474                 EXIT;
  475                 return error;
  476         }
  477 
  478         error = presto_check_set_fsdata(new_dentry);
  479         if ( error ) {
  480                 EXIT;
  481                 return error;
  482         }
  483 
  484         error = presto_prep(new_dentry->d_parent, &new_cache, &new_fset);
  485         if ( error ) {
  486                 EXIT;
  487                 return error;
  488         }
  489 
  490         if (fset != new_fset) { 
  491                 EXIT;
  492                 return -EXDEV;
  493         }
  494 
  495         presto_unlock(dir);
  496         if ( presto_get_permit(old_dentry->d_inode) < 0 ) {
  497                 EXIT;
  498                 presto_fulllock(dir);
  499                 return -EROFS;
  500         }
  501 
  502         if ( presto_get_permit(dir) < 0 ) {
  503                 EXIT;
  504                 presto_fulllock(dir);
  505                 return -EROFS;
  506         }
  507 
  508         presto_relock_sem(dir);
  509         parent = new_dentry->d_parent;
  510 
  511         memset(&info, 0, sizeof(info));
  512         if (!ISLENTO(presto_c2m(cache)))
  513                 info.flags = LENTO_FL_KML;
  514         info.flags |= LENTO_FL_IGNORE_TIME;
  515         error = presto_do_link(fset, old_dentry, parent,
  516                                new_dentry, &info);
  517 
  518 #if 0
  519         /* XXX for links this is not right */
  520         if (cache->cache_filter->o_trops->tr_add_ilookup ) { 
  521                 struct dentry *d;
  522                 d = cache->cache_filter->o_trops->tr_add_ilookup
  523                         (dir->i_sb->s_root, new_dentry, 1); 
  524         }
  525 #endif 
  526 
  527         presto_relock_other(dir);
  528         presto_put_permit(dir);
  529         presto_put_permit(old_dentry->d_inode);
  530         return error;
  531 }
  532 
  533 static int presto_mkdir(struct inode * dir, struct dentry * dentry, int mode)
  534 {
  535         int error;
  536         struct presto_file_set *fset;
  537         struct presto_cache *cache;
  538         struct dentry *parent = dentry->d_parent;
  539         struct lento_vfs_context info;
  540 
  541         ENTRY;
  542 
  543         error = presto_check_set_fsdata(dentry);
  544         if ( error  ) {
  545                 EXIT;
  546                 return error;
  547         }
  548 
  549         error = presto_prep(dentry->d_parent, &cache, &fset);
  550         if ( error  ) {
  551                 EXIT;
  552                 return error;
  553         }
  554 
  555         presto_unlock(dir); 
  556 
  557         if ( presto_get_permit(dir) < 0 ) {
  558                 EXIT;
  559                 presto_fulllock(dir);
  560                 return -EROFS;
  561         }
  562 
  563         memset(&info, 0, sizeof(info));
  564         if (!ISLENTO(presto_c2m(cache)))
  565                 info.flags = LENTO_FL_KML;
  566         info.flags |= LENTO_FL_IGNORE_TIME;
  567 
  568         presto_relock_sem(dir); 
  569         parent = dentry->d_parent;
  570         error = presto_do_mkdir(fset, parent, dentry, mode, &info);
  571         presto_relock_other(dir); 
  572         presto_put_permit(dir);
  573         return error;
  574 }
  575 
  576 
  577 
  578 static int presto_symlink(struct inode *dir, struct dentry *dentry,
  579                    const char *name)
  580 {
  581         int error;
  582         struct presto_cache *cache;
  583         struct presto_file_set *fset;
  584         struct dentry *parent = dentry->d_parent;
  585         struct lento_vfs_context info;
  586 
  587         ENTRY;
  588         error = presto_check_set_fsdata(dentry);
  589         if ( error ) {
  590                 EXIT;
  591                 return error;
  592         }
  593 
  594         error = presto_prep(dentry->d_parent, &cache, &fset);
  595         if ( error ) {
  596                 EXIT;
  597                 return error;
  598         }
  599 
  600         presto_unlock(dir);
  601         if ( presto_get_permit(dir) < 0 ) {
  602                 EXIT;
  603                 presto_fulllock(dir);
  604                 return -EROFS;
  605         }
  606 
  607         presto_relock_sem(dir);
  608         parent = dentry->d_parent;
  609         memset(&info, 0, sizeof(info));
  610         if (!ISLENTO(presto_c2m(cache)))
  611                 info.flags = LENTO_FL_KML;
  612         info.flags |= LENTO_FL_IGNORE_TIME;
  613         error = presto_do_symlink(fset, parent, dentry, name, &info);
  614         presto_relock_other(dir);
  615         presto_put_permit(dir);
  616         return error;
  617 }
  618 
  619 int presto_unlink(struct inode *dir, struct dentry *dentry)
  620 {
  621         int error;
  622         struct presto_cache *cache;
  623         struct presto_file_set *fset;
  624         struct dentry *parent = dentry->d_parent;
  625         struct lento_vfs_context info;
  626 
  627         ENTRY;
  628         error = presto_check_set_fsdata(dentry);
  629         if ( error ) {
  630                 EXIT;
  631                 return error;
  632         }
  633 
  634         error = presto_prep(dentry->d_parent, &cache, &fset);
  635         if ( error  ) {
  636                 EXIT;
  637                 return error;
  638         }
  639 
  640         presto_unlock(dir);
  641         if ( presto_get_permit(dir) < 0 ) {
  642                 EXIT;
  643                 presto_fulllock(dir);
  644                 return -EROFS;
  645         }
  646 
  647         presto_relock_sem(dir);
  648         parent = dentry->d_parent;
  649         memset(&info, 0, sizeof(info));
  650         if (!ISLENTO(presto_c2m(cache)))
  651                 info.flags = LENTO_FL_KML;
  652         info.flags |= LENTO_FL_IGNORE_TIME;
  653 
  654         error = presto_do_unlink(fset, parent, dentry, &info);
  655 
  656         presto_relock_other(dir);
  657         presto_put_permit(dir);
  658         return error;
  659 }
  660 
  661 static int presto_rmdir(struct inode *dir, struct dentry *dentry)
  662 {
  663         int error;
  664         struct presto_cache *cache;
  665         struct presto_file_set *fset;
  666         struct dentry *parent = dentry->d_parent;
  667         struct lento_vfs_context info;
  668 
  669         ENTRY;
  670         CDEBUG(D_FILE, "prepping presto\n");
  671         error = presto_check_set_fsdata(dentry);
  672 
  673         if ( error ) {
  674                 EXIT;
  675                 return error;
  676         }
  677 
  678         error = presto_prep(dentry->d_parent, &cache, &fset);
  679         if ( error ) {
  680                 EXIT;
  681                 return error;
  682         }
  683 
  684         CDEBUG(D_FILE, "unlocking\n");
  685         /* We need to dget() before the dput in double_unlock, to ensure we
  686          * still have dentry references.  double_lock doesn't do dget for us.
  687          */
  688         unlock_kernel();
  689         if (d_unhashed(dentry))
  690                 d_rehash(dentry);
  691         double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
  692         double_up(&dir->i_sem, &dentry->d_inode->i_sem);
  693 
  694         CDEBUG(D_FILE, "getting permit\n");
  695         if ( presto_get_permit(parent->d_inode) < 0 ) {
  696                 EXIT;
  697                 double_down(&dir->i_sem, &dentry->d_inode->i_sem);
  698                 double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
  699                 
  700                 lock_kernel();
  701                 return -EROFS;
  702         }
  703         CDEBUG(D_FILE, "locking\n");
  704 
  705         double_down(&dir->i_sem, &dentry->d_inode->i_sem);
  706         parent = dentry->d_parent;
  707         memset(&info, 0, sizeof(info));
  708         if (!ISLENTO(presto_c2m(cache)))
  709                 info.flags = LENTO_FL_KML;
  710         info.flags |= LENTO_FL_IGNORE_TIME;
  711         error = presto_do_rmdir(fset, parent, dentry, &info);
  712         presto_put_permit(parent->d_inode);
  713         lock_kernel();
  714         EXIT;
  715         return error;
  716 }
  717 
  718 static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
  719 {
  720         int error;
  721         struct presto_cache *cache;
  722         struct presto_file_set *fset;
  723         struct dentry *parent = dentry->d_parent;
  724         struct lento_vfs_context info;
  725 
  726         ENTRY;
  727         error = presto_check_set_fsdata(dentry);
  728         if ( error ) {
  729                 EXIT;
  730                 return error;
  731         }
  732 
  733         error = presto_prep(dentry->d_parent, &cache, &fset);
  734         if ( error  ) {
  735                 EXIT;
  736                 return error;
  737         }
  738 
  739         presto_unlock(dir);
  740         if ( presto_get_permit(dir) < 0 ) {
  741                 EXIT;
  742                 presto_fulllock(dir);
  743                 return -EROFS;
  744         }
  745         
  746         presto_relock_sem(dir);
  747         parent = dentry->d_parent;
  748         memset(&info, 0, sizeof(info));
  749         if (!ISLENTO(presto_c2m(cache)))
  750                 info.flags = LENTO_FL_KML;
  751         info.flags |= LENTO_FL_IGNORE_TIME;
  752         error = presto_do_mknod(fset, parent, dentry, mode, rdev, &info);
  753         presto_relock_other(dir);
  754         presto_put_permit(dir);
  755         EXIT;
  756         return error;
  757 }
  758 
  759 inline void presto_triple_unlock(struct inode *old_dir, struct inode *new_dir, 
  760                                  struct dentry *old_dentry, 
  761                                  struct dentry *new_dentry, int triple)
  762 {
  763         /* rename_dir case */ 
  764         if (S_ISDIR(old_dentry->d_inode->i_mode)) { 
  765                 if (triple) {                   
  766                         triple_up(&old_dir->i_zombie,
  767                                   &new_dir->i_zombie,
  768                                   &new_dentry->d_inode->i_zombie);
  769                 } else { 
  770                         double_up(&old_dir->i_zombie,
  771                                   &new_dir->i_zombie);
  772                 }
  773                 up(&old_dir->i_sb->s_vfs_rename_sem);
  774         } else /* this case is rename_other */
  775                 double_up(&old_dir->i_zombie, &new_dir->i_zombie);
  776         /* done by do_rename */
  777         unlock_kernel();
  778         double_up(&old_dir->i_sem, &new_dir->i_sem);
  779 }
  780 
  781 inline void presto_triple_fulllock(struct inode *old_dir, 
  782                                    struct inode *new_dir, 
  783                                    struct dentry *old_dentry, 
  784                                    struct dentry *new_dentry, int triple)
  785 {
  786         /* done by do_rename */
  787         double_down(&old_dir->i_sem, &new_dir->i_sem);
  788         lock_kernel();
  789         /* rename_dir case */ 
  790         if (S_ISDIR(old_dentry->d_inode->i_mode)) { 
  791                 down(&old_dir->i_sb->s_vfs_rename_sem);
  792                 if (triple) {                   
  793                         triple_down(&old_dir->i_zombie,
  794                                   &new_dir->i_zombie,
  795                                   &new_dentry->d_inode->i_zombie);
  796                 } else { 
  797                         double_down(&old_dir->i_zombie,
  798                                   &new_dir->i_zombie);
  799                 }
  800         } else /* this case is rename_other */
  801                 double_down(&old_dir->i_zombie, &new_dir->i_zombie);
  802 }
  803 
  804 inline void presto_triple_relock_sem(struct inode *old_dir, 
  805                                    struct inode *new_dir, 
  806                                    struct dentry *old_dentry, 
  807                                    struct dentry *new_dentry, int triple)
  808 {
  809         /* done by do_rename */
  810         double_down(&old_dir->i_sem, &new_dir->i_sem);
  811         lock_kernel();
  812 }
  813 
  814 inline void presto_triple_relock_other(struct inode *old_dir, 
  815                                    struct inode *new_dir, 
  816                                    struct dentry *old_dentry, 
  817                                    struct dentry *new_dentry, int triple)
  818 {
  819         /* rename_dir case */ 
  820         if (S_ISDIR(old_dentry->d_inode->i_mode)) { 
  821                 down(&old_dir->i_sb->s_vfs_rename_sem);
  822                 if (triple) {                   
  823                         triple_down(&old_dir->i_zombie,
  824                                   &new_dir->i_zombie,
  825                                   &new_dentry->d_inode->i_zombie);
  826                 } else { 
  827                         double_down(&old_dir->i_zombie,
  828                                   &new_dir->i_zombie);
  829                 }
  830         } else /* this case is rename_other */
  831                 double_down(&old_dir->i_zombie, &new_dir->i_zombie);
  832 }
  833 
  834 
  835 // XXX this can be optimized: renamtes across filesets only require 
  836 //     multiple KML records, but can locally be executed normally. 
  837 int presto_rename(struct inode *old_dir, struct dentry *old_dentry,
  838                   struct inode *new_dir, struct dentry *new_dentry)
  839 {
  840         int error;
  841         struct presto_cache *cache, *new_cache;
  842         struct presto_file_set *fset, *new_fset;
  843         struct lento_vfs_context info;
  844         struct dentry *old_parent = old_dentry->d_parent;
  845         struct dentry *new_parent = new_dentry->d_parent;
  846         int triple;
  847 
  848         ENTRY;
  849         error = presto_prep(old_dentry, &cache, &fset);
  850         if ( error ) {
  851                 EXIT;
  852                 return error;
  853         }
  854         error = presto_prep(new_parent, &new_cache, &new_fset);
  855         if ( error ) {
  856                 EXIT;
  857                 return error;
  858         }
  859 
  860         if ( fset != new_fset ) {
  861                 EXIT;
  862                 return -EXDEV;
  863         }
  864 
  865         /* We need to do dget before the dput in double_unlock, to ensure we
  866          * still have dentry references.  double_lock doesn't do dget for us.
  867          */
  868 
  869         triple = (S_ISDIR(old_dentry->d_inode->i_mode) && new_dentry->d_inode)?
  870                 1:0;
  871 
  872         presto_triple_unlock(old_dir, new_dir, old_dentry, new_dentry, triple); 
  873 
  874         if ( presto_get_permit(old_dir) < 0 ) {
  875                 EXIT;
  876                 presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple); 
  877                 return -EROFS;
  878         }
  879         if ( presto_get_permit(new_dir) < 0 ) {
  880                 EXIT;
  881                 presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple); 
  882                 return -EROFS;
  883         }
  884 
  885         presto_triple_relock_sem(old_dir, new_dir, old_dentry, new_dentry, triple); 
  886         memset(&info, 0, sizeof(info));
  887         if (!ISLENTO(presto_c2m(cache)))
  888                 info.flags = LENTO_FL_KML;
  889         info.flags |= LENTO_FL_IGNORE_TIME;
  890         error = do_rename(fset, old_parent, old_dentry, new_parent,
  891                           new_dentry, &info);
  892         presto_triple_relock_other(old_dir, new_dir, old_dentry, new_dentry, triple); 
  893 
  894         presto_put_permit(new_dir);
  895         presto_put_permit(old_dir);
  896         return error;
  897 }
  898 
  899 /* basically this allows the ilookup processes access to all files for
  900  * reading, while not making ilookup totally insecure.  This could all
  901  * go away if we could set the CAP_DAC_READ_SEARCH capability for the client.
  902  */
  903 /* If posix acls are available, the underlying cache fs will export the
  904  * appropriate permission function. Thus we do not worry here about ACLs
  905  * or EAs. -SHP
  906  */
  907 int presto_permission(struct inode *inode, int mask)
  908 {
  909         unsigned short mode = inode->i_mode;
  910         struct presto_cache *cache;
  911         int rc;
  912 
  913         ENTRY;
  914         if ( presto_can_ilookup() && !(mask & S_IWOTH)) {
  915                 CDEBUG(D_CACHE, "ilookup on %ld OK\n", inode->i_ino);
  916                 EXIT;
  917                 return 0;
  918         }
  919 
  920         cache = presto_get_cache(inode);
  921 
  922         if ( cache ) {
  923                 /* we only override the file/dir permission operations */
  924                 struct inode_operations *fiops = filter_c2cfiops(cache->cache_filter);
  925                 struct inode_operations *diops = filter_c2cdiops(cache->cache_filter);
  926 
  927                 if ( S_ISREG(mode) && fiops && fiops->permission ) {
  928                         EXIT;
  929                         return fiops->permission(inode, mask);
  930                 }
  931                 if ( S_ISDIR(mode) && diops && diops->permission ) {
  932                         EXIT;
  933                         return diops->permission(inode, mask);
  934                 }
  935         }
  936 
  937         /* The cache filesystem doesn't have its own permission function,
  938          * but we don't want to duplicate the VFS code here.  In order
  939          * to avoid looping from permission calling this function again,
  940          * we temporarily override the permission operation while we call
  941          * the VFS permission function.
  942          */
  943         inode->i_op->permission = NULL;
  944         rc = permission(inode, mask);
  945         inode->i_op->permission = &presto_permission;
  946 
  947         EXIT;
  948         return rc;
  949 }
  950 
  951 
  952 int presto_ioctl(struct inode *inode, struct file *file,
  953                         unsigned int cmd, unsigned long arg)
  954 {
  955         char buf[1024];
  956         struct izo_ioctl_data *data = NULL;
  957         struct presto_dentry_data *dd;
  958         int rc;
  959 
  960         ENTRY;
  961 
  962         /* Try the filesystem's ioctl first, and return if it succeeded. */
  963         dd = presto_d2d(file->f_dentry); 
  964         if (dd && dd->dd_fset) { 
  965                 int (*cache_ioctl)(struct inode *, struct file *, unsigned int, unsigned long ) = filter_c2cdfops(dd->dd_fset->fset_cache->cache_filter)->ioctl;
  966                 rc = -ENOTTY;
  967                 if (cache_ioctl)
  968                         rc = cache_ioctl(inode, file, cmd, arg);
  969                 if (rc != -ENOTTY) {
  970                         EXIT;
  971                         return rc;
  972                 }
  973         }
  974 
  975         if (current->euid != 0 && current->euid != izo_authorized_uid) {
  976                 EXIT;
  977                 return -EPERM;
  978         }
  979 
  980         memset(buf, 0, sizeof(buf));
  981         
  982         if (izo_ioctl_getdata(buf, buf + 1024, (void *)arg)) { 
  983                 CERROR("intermezzo ioctl: data error\n");
  984                 return -EINVAL;
  985         }
  986         data = (struct izo_ioctl_data *)buf;
  987         
  988         switch(cmd) {
  989         case IZO_IOC_REINTKML: { 
  990                 int rc;
  991                 int cperr;
  992                 rc = kml_reint_rec(file, data);
  993 
  994                 EXIT;
  995                 cperr = copy_to_user((char *)arg, data, sizeof(*data));
  996                 if (cperr) { 
  997                         CERROR("WARNING: cperr %d\n", cperr); 
  998                         rc = -EFAULT;
  999                 }
 1000                 return rc;
 1001         }
 1002 
 1003         case IZO_IOC_GET_RCVD: {
 1004                 struct izo_rcvd_rec rec;
 1005                 struct presto_file_set *fset;
 1006                 int rc;
 1007 
 1008                 fset = presto_fset(file->f_dentry);
 1009                 if (fset == NULL) {
 1010                         EXIT;
 1011                         return -ENODEV;
 1012                 }
 1013                 rc = izo_rcvd_get(&rec, fset, data->ioc_uuid);
 1014                 if (rc < 0) {
 1015                         EXIT;
 1016                         return rc;
 1017                 }
 1018 
 1019                 EXIT;
 1020                 return copy_to_user((char *)arg, &rec, sizeof(rec))? -EFAULT : 0;
 1021         }
 1022 
 1023         case IZO_IOC_REPSTATUS: {
 1024                 __u64 client_kmlsize;
 1025                 struct izo_rcvd_rec *lr_client;
 1026                 struct izo_rcvd_rec rec;
 1027                 struct presto_file_set *fset;
 1028                 int minor;
 1029                 int rc;
 1030 
 1031                 fset = presto_fset(file->f_dentry);
 1032                 if (fset == NULL) {
 1033                         EXIT;
 1034                         return -ENODEV;
 1035                 }
 1036                 minor = presto_f2m(fset);
 1037 
 1038                 client_kmlsize = data->ioc_kmlsize;
 1039                 lr_client =  (struct izo_rcvd_rec *) data->ioc_pbuf1;
 1040 
 1041                 rc = izo_repstatus(fset, client_kmlsize, 
 1042                                        lr_client, &rec);
 1043                 if (rc < 0) {
 1044                         EXIT;
 1045                         return rc;
 1046                 }
 1047 
 1048                 EXIT;
 1049                 return copy_to_user((char *)arg, &rec, sizeof(rec))? -EFAULT : 0;
 1050         }
 1051 
 1052         case IZO_IOC_GET_CHANNEL: {
 1053                 struct presto_file_set *fset;
 1054 
 1055                 fset = presto_fset(file->f_dentry);
 1056                 if (fset == NULL) {
 1057                         EXIT;
 1058                         return -ENODEV;
 1059                 }
 1060                 
 1061                 data->ioc_dev = fset->fset_cache->cache_psdev->uc_minor;
 1062                 CDEBUG(D_PSDEV, "CHANNEL %d\n", data->ioc_dev); 
 1063                 EXIT;
 1064                 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT : 0;
 1065         }
 1066 
 1067         case IZO_IOC_SET_IOCTL_UID:
 1068                 izo_authorized_uid = data->ioc_uid;
 1069                 EXIT;
 1070                 return 0;
 1071 
 1072         case IZO_IOC_SET_PID:
 1073                 rc = izo_psdev_setpid(data->ioc_dev);
 1074                 EXIT;
 1075                 return rc;
 1076 
 1077         case IZO_IOC_SET_CHANNEL:
 1078                 rc = izo_psdev_setchannel(file, data->ioc_dev);
 1079                 EXIT;
 1080                 return rc;
 1081 
 1082         case IZO_IOC_GET_KML_SIZE: {
 1083                 struct presto_file_set *fset;
 1084                 __u64 kmlsize;
 1085 
 1086                 fset = presto_fset(file->f_dentry);
 1087                 if (fset == NULL) {
 1088                         EXIT;
 1089                         return -ENODEV;
 1090                 }
 1091 
 1092                 kmlsize = presto_kml_offset(fset) + fset->fset_kml_logical_off;
 1093 
 1094                 EXIT;
 1095                 return copy_to_user((char *)arg, &kmlsize, sizeof(kmlsize))?-EFAULT : 0;
 1096         }
 1097 
 1098         case IZO_IOC_PURGE_FILE_DATA: {
 1099                 struct presto_file_set *fset;
 1100 
 1101                 fset = presto_fset(file->f_dentry);
 1102                 if (fset == NULL) {
 1103                         EXIT;
 1104                         return -ENODEV;
 1105                 }
 1106 
 1107                 rc = izo_purge_file(fset, data->ioc_inlbuf1);
 1108                 EXIT;
 1109                 return rc;
 1110         }
 1111 
 1112         case IZO_IOC_GET_FILEID: {
 1113                 rc = izo_get_fileid(file, data);
 1114                 EXIT;
 1115                 if (rc)
 1116                         return rc;
 1117                 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT : 0;
 1118         }
 1119 
 1120         case IZO_IOC_SET_FILEID: {
 1121                 rc = izo_set_fileid(file, data);
 1122                 EXIT;
 1123                 if (rc)
 1124                         return rc;
 1125                 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT  : 0;
 1126         }
 1127 
 1128         case IZO_IOC_ADJUST_LML: { 
 1129                 struct lento_vfs_context *info; 
 1130                 info = (struct lento_vfs_context *)data->ioc_inlbuf1;
 1131                 rc = presto_adjust_lml(file, info); 
 1132                 EXIT;
 1133                 return rc;
 1134         }
 1135 
 1136         case IZO_IOC_CONNECT: {
 1137                 struct presto_file_set *fset;
 1138                 int minor;
 1139 
 1140                 fset = presto_fset(file->f_dentry);
 1141                 if (fset == NULL) {
 1142                         EXIT;
 1143                         return -ENODEV;
 1144                 }
 1145                 minor = presto_f2m(fset);
 1146 
 1147                 rc = izo_upc_connect(minor, data->ioc_ino,
 1148                                      data->ioc_generation, data->ioc_uuid,
 1149                                      data->ioc_flags);
 1150                 EXIT;
 1151                 return rc;
 1152         }
 1153 
 1154         case IZO_IOC_GO_FETCH_KML: {
 1155                 struct presto_file_set *fset;
 1156                 int minor;
 1157 
 1158                 fset = presto_fset(file->f_dentry);
 1159                 if (fset == NULL) {
 1160                         EXIT;
 1161                         return -ENODEV;
 1162                 }
 1163                 minor = presto_f2m(fset);
 1164 
 1165                 rc = izo_upc_go_fetch_kml(minor, fset->fset_name,
 1166                                           data->ioc_uuid, data->ioc_kmlsize);
 1167                 EXIT;
 1168                 return rc;
 1169         }
 1170 
 1171         case IZO_IOC_REVOKE_PERMIT:
 1172                 if (data->ioc_flags)
 1173                         rc = izo_revoke_permit(file->f_dentry, data->ioc_uuid);
 1174                 else
 1175                         rc = izo_revoke_permit(file->f_dentry, NULL);
 1176                 EXIT;
 1177                 return rc;
 1178 
 1179         case IZO_IOC_CLEAR_FSET:
 1180                 rc = izo_clear_fsetroot(file->f_dentry);
 1181                 EXIT;
 1182                 return rc;
 1183 
 1184         case IZO_IOC_CLEAR_ALL_FSETS: { 
 1185                 struct presto_file_set *fset;
 1186 
 1187                 fset = presto_fset(file->f_dentry);
 1188                 if (fset == NULL) {
 1189                         EXIT;
 1190                         return -ENODEV;
 1191                 }
 1192 
 1193                 rc = izo_clear_all_fsetroots(fset->fset_cache);
 1194                 EXIT;
 1195                 return rc;
 1196         }
 1197 
 1198         case IZO_IOC_SET_FSET:
 1199                 /*
 1200                  * Mark this dentry as being a fileset root.
 1201                  */
 1202                 rc = presto_set_fsetroot_from_ioc(file->f_dentry, 
 1203                                                   data->ioc_inlbuf1,
 1204                                                   data->ioc_flags);
 1205                 EXIT;
 1206                 return rc;
 1207 
 1208 
 1209         case IZO_IOC_MARK: {
 1210                 int res = 0;  /* resulting flags - returned to user */
 1211                 int error;
 1212 
 1213                 CDEBUG(D_DOWNCALL, "mark inode: %ld, and: %x, or: %x, what %d\n",
 1214                        file->f_dentry->d_inode->i_ino, data->ioc_and_flag,
 1215                        data->ioc_or_flag, data->ioc_mark_what);
 1216 
 1217                 switch (data->ioc_mark_what) {
 1218                 case MARK_DENTRY:               
 1219                         error = izo_mark_dentry(file->f_dentry,
 1220                                                    data->ioc_and_flag,
 1221                                                    data->ioc_or_flag, &res);
 1222                         break;
 1223                 case MARK_FSET:
 1224                         error = izo_mark_fset(file->f_dentry,
 1225                                                  data->ioc_and_flag,
 1226                                                  data->ioc_or_flag, &res);
 1227                         break;
 1228                 case MARK_CACHE:
 1229                         error = izo_mark_cache(file->f_dentry,
 1230                                                   data->ioc_and_flag,
 1231                                                   data->ioc_or_flag, &res);
 1232                         break;
 1233                 case MARK_GETFL: {
 1234                         int fflags, cflags;
 1235                         data->ioc_and_flag = 0xffffffff;
 1236                         data->ioc_or_flag = 0; 
 1237                         error = izo_mark_dentry(file->f_dentry,
 1238                                                    data->ioc_and_flag,
 1239                                                    data->ioc_or_flag, &res);
 1240                         if (error) 
 1241                                 break;
 1242                         error = izo_mark_fset(file->f_dentry,
 1243                                                  data->ioc_and_flag,
 1244                                                  data->ioc_or_flag, &fflags);
 1245                         if (error) 
 1246                                 break;
 1247                         error = izo_mark_cache(file->f_dentry,
 1248                                                   data->ioc_and_flag,
 1249                                                   data->ioc_or_flag,
 1250                                                   &cflags);
 1251 
 1252                         if (error) 
 1253                                 break;
 1254                         data->ioc_and_flag = fflags;
 1255                         data->ioc_or_flag = cflags;
 1256                         break;
 1257                 }
 1258                 default:
 1259                         error = -EINVAL;
 1260                 }
 1261 
 1262                 if (error) { 
 1263                         EXIT;
 1264                         return error;
 1265                 }
 1266                 data->ioc_mark_what = res;
 1267                 CDEBUG(D_DOWNCALL, "mark inode: %ld, and: %x, or: %x, what %x\n",
 1268                        file->f_dentry->d_inode->i_ino, data->ioc_and_flag,
 1269                        data->ioc_or_flag, data->ioc_mark_what);
 1270 
 1271                 EXIT;
 1272                 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT : 0;
 1273         }
 1274 #if 0
 1275         case IZO_IOC_CLIENT_MAKE_BRANCH: {
 1276                 struct presto_file_set *fset;
 1277                 int minor;
 1278 
 1279                 fset = presto_fset(file->f_dentry);
 1280                 if (fset == NULL) {
 1281                         EXIT;
 1282                         return -ENODEV;
 1283                 }
 1284                 minor = presto_f2m(fset);
 1285 
 1286                 rc = izo_upc_client_make_branch(minor, fset->fset_name,
 1287                                                 data->ioc_inlbuf1,
 1288                                                 data->ioc_inlbuf2);
 1289                 EXIT;
 1290                 return rc;
 1291         }
 1292 #endif
 1293         case IZO_IOC_SERVER_MAKE_BRANCH: {
 1294                 struct presto_file_set *fset;
 1295                 int minor;
 1296 
 1297                 fset = presto_fset(file->f_dentry);
 1298                 if (fset == NULL) {
 1299                         EXIT;
 1300                         return -ENODEV;
 1301                 }
 1302                 minor = presto_f2m(fset);
 1303 
 1304                 izo_upc_server_make_branch(minor, data->ioc_inlbuf1);
 1305                 EXIT;
 1306                 return 0;
 1307         }
 1308         case IZO_IOC_SET_KMLSIZE: {
 1309                 struct presto_file_set *fset;
 1310                 int minor;
 1311                 struct izo_rcvd_rec rec;
 1312 
 1313                 fset = presto_fset(file->f_dentry);
 1314                 if (fset == NULL) {
 1315                         EXIT;
 1316                         return -ENODEV;
 1317                 }
 1318                 minor = presto_f2m(fset);
 1319 
 1320                 rc = izo_upc_set_kmlsize(minor, fset->fset_name, data->ioc_uuid,
 1321                                          data->ioc_kmlsize);
 1322 
 1323                 if (rc != 0) {
 1324                         EXIT;
 1325                         return rc;
 1326                 }
 1327 
 1328                 rc = izo_rcvd_get(&rec, fset, data->ioc_uuid);
 1329                 if (rc == -EINVAL) {
 1330                         /* We don't know anything about this uuid yet; no
 1331                          * worries. */
 1332                         memset(&rec, 0, sizeof(rec));
 1333                 } else if (rc <= 0) {
 1334                         CERROR("InterMezzo: error reading last_rcvd: %d\n", rc);
 1335                         EXIT;
 1336                         return rc;
 1337                 }
 1338                 rec.lr_remote_offset = data->ioc_kmlsize;
 1339                 rc = izo_rcvd_write(fset, &rec);
 1340                 if (rc <= 0) {
 1341                         CERROR("InterMezzo: error writing last_rcvd: %d\n", rc);
 1342                         EXIT;
 1343                         return rc;
 1344                 }
 1345                 EXIT;
 1346                 return rc;
 1347         }
 1348         case IZO_IOC_BRANCH_UNDO: {
 1349                 struct presto_file_set *fset;
 1350                 int minor;
 1351 
 1352                 fset = presto_fset(file->f_dentry);
 1353                 if (fset == NULL) {
 1354                         EXIT;
 1355                         return -ENODEV;
 1356                 }
 1357                 minor = presto_f2m(fset);
 1358 
 1359                 rc = izo_upc_branch_undo(minor, fset->fset_name,
 1360                                          data->ioc_inlbuf1);
 1361                 EXIT;
 1362                 return rc;
 1363         }
 1364         case IZO_IOC_BRANCH_REDO: {
 1365                 struct presto_file_set *fset;
 1366                 int minor;
 1367 
 1368                 fset = presto_fset(file->f_dentry);
 1369                 if (fset == NULL) {
 1370                         EXIT;
 1371                         return -ENODEV;
 1372                 }
 1373                 minor = presto_f2m(fset);
 1374 
 1375                 rc = izo_upc_branch_redo(minor, fset->fset_name,
 1376                                          data->ioc_inlbuf1);
 1377                 EXIT;
 1378                 return rc;
 1379         }
 1380 
 1381         case TCGETS:
 1382                 EXIT;
 1383                 return -EINVAL;
 1384 
 1385         default:
 1386                 EXIT;
 1387                 return -EINVAL;
 1388                 
 1389         }
 1390         EXIT;
 1391         return 0;
 1392 }
 1393 
 1394 struct file_operations presto_dir_fops = {
 1395         .ioctl =  presto_ioctl
 1396 };
 1397 
 1398 struct inode_operations presto_dir_iops = {
 1399         .create       = presto_create,
 1400         .lookup       = presto_lookup,
 1401         .link         = presto_link,
 1402         .unlink       = presto_unlink,
 1403         .symlink      = presto_symlink,
 1404         .mkdir        = presto_mkdir,
 1405         .rmdir        = presto_rmdir,
 1406         .mknod        = presto_mknod,
 1407         .rename       = presto_rename,
 1408         .permission   = presto_permission,
 1409         .setattr      = presto_setattr,
 1410 #ifdef CONFIG_FS_EXT_ATTR
 1411         .set_ext_attr = presto_set_ext_attr,
 1412 #endif
 1413 };
 1414 
 1415 

Cache object: ff8f7b6aff6e7a3c3f3bebe6f7ba27d8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.