dir.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:45k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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