dir.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:26k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *
  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.  */
  10. #include <stdarg.h>
  11. #include <asm/bitops.h>
  12. #include <asm/uaccess.h>
  13. #include <asm/system.h>
  14. #include <linux/smp_lock.h>
  15. #include <linux/errno.h>
  16. #include <linux/fs.h>
  17. #include <linux/ext2_fs.h>
  18. #include <linux/slab.h>
  19. #include <linux/vmalloc.h>
  20. #include <linux/sched.h>
  21. #include <linux/stat.h>
  22. #include <linux/string.h>
  23. #include <linux/locks.h>
  24. #include <linux/blkdev.h>
  25. #include <linux/init.h>
  26. #define __NO_VERSION__
  27. #include <linux/module.h>
  28. #include <linux/intermezzo_fs.h>
  29. #include <linux/intermezzo_upcall.h>
  30. #include <linux/intermezzo_psdev.h>
  31. static inline void presto_relock_sem(struct inode *dir) 
  32. {
  33. /* the lock from sys_mkdir / lookup_create */
  34. down(&dir->i_sem);
  35. /* the rest is done by the do_{create,mkdir, ...} */
  36. }
  37. static inline void presto_relock_other(struct inode *dir) 
  38. {
  39. /* vfs_mkdir locks */
  40.         down(&dir->i_zombie);
  41. lock_kernel(); 
  42. }
  43. static inline void presto_fulllock(struct inode *dir) 
  44. {
  45. /* the lock from sys_mkdir / lookup_create */
  46. down(&dir->i_sem);
  47. /* vfs_mkdir locks */
  48.         down(&dir->i_zombie);
  49. lock_kernel(); 
  50. }
  51. static inline void presto_unlock(struct inode *dir) 
  52. {
  53. /* vfs_mkdir locks */
  54. unlock_kernel(); 
  55.         up(&dir->i_zombie);
  56. /* the lock from sys_mkdir / lookup_create */
  57. up(&dir->i_sem);
  58. }
  59. /*
  60.  * these are initialized in super.c
  61.  */
  62. extern int presto_permission(struct inode *inode, int mask);
  63. int presto_ilookup_uid = 0;
  64. extern int presto_prep(struct dentry *, struct presto_cache **,
  65.                        struct presto_file_set **);
  66. static int dentry2id(struct dentry *dentry, ino_t *id, unsigned int *generation)
  67. {
  68.         char *tmpname;
  69.         char *next;
  70.         int error = 0;
  71.         ENTRY;
  72.         if (dentry->d_name.len > EXT2_NAME_LEN) {
  73.                 EXIT;
  74.                 return -ENAMETOOLONG;
  75.         }
  76.         /* prefix is 7 characters: '...ino:' */
  77.         if ( dentry->d_name.len < 7 ||
  78.              memcmp(dentry->d_name.name, PRESTO_ILOOKUP_MAGIC, 7) != 0 ) {
  79.                 EXIT;
  80.                 return 1;
  81.         }
  82.         PRESTO_ALLOC(tmpname, char *, dentry->d_name.len - 7 + 1);
  83.         if ( !tmpname ) {
  84.                 EXIT;
  85.                 return -ENOMEM;
  86.         }
  87.         memcpy(tmpname, dentry->d_name.name + 7, dentry->d_name.len - 7);
  88.         *(tmpname + dentry->d_name.len) = '';
  89.         /* name is of the form <inode number>:<generation> */
  90.         *id = simple_strtoul(tmpname, &next, 0);
  91.         if ( *next == PRESTO_ILOOKUP_SEP ) {
  92.                 *generation = simple_strtoul(next + 1, 0, 0);
  93.                 CDEBUG(D_INODE, "INO to find = %sn", tmpname);
  94.                 CDEBUG(D_INODE, "Id = %lx (%lu), generation %x (%d)n",
  95.                        *id, *id, *generation, *generation);
  96.         } else
  97.                 error = 1;
  98.         PRESTO_FREE(tmpname, dentry->d_name.len - 7 + 1);
  99.         EXIT;
  100.         return error;
  101. }
  102. static int presto_opendir_upcall(int minor, struct dentry *de, 
  103.                           struct dentry *root, int async)
  104. {
  105.         int rc;
  106.         char *path, *buffer;
  107.         int pathlen;
  108.         PRESTO_ALLOC(buffer, char *, PAGE_SIZE);
  109.         if ( !buffer ) {
  110.                 printk("PRESTO: out of memory!n");
  111.                 return ENOMEM;
  112.         }
  113.         path = presto_path(de, root, buffer, PAGE_SIZE);
  114.         pathlen = MYPATHLEN(buffer, path);
  115.         CDEBUG(D_INODE, "path: %*s, len %dn", pathlen, path, pathlen);
  116.         rc = lento_opendir(minor, pathlen, path, async);
  117.         PRESTO_FREE(buffer, PAGE_SIZE);
  118.         return rc;
  119. }
  120. inline int presto_can_ilookup(void)
  121. {
  122.         return (current->euid == presto_ilookup_uid ||
  123.                 capable(CAP_DAC_READ_SEARCH));
  124. }
  125. struct dentry *presto_ilookup(struct inode *dir, struct dentry *dentry,
  126.                             ino_t ino, unsigned int generation)
  127. {
  128.         struct inode *inode;
  129.         int error;
  130.         ENTRY;
  131.         /* if we can't ilookup, forbid anything with this name to
  132.          * avoid any security issues/name clashes.
  133.          */
  134.         if ( !presto_can_ilookup() ) {
  135.                 CDEBUG(D_CACHE, "ilookup denied: euid %u, ilookup_uid %un",
  136.                        current->euid, presto_ilookup_uid);
  137.                 EXIT;
  138.                 return ERR_PTR(-EPERM);
  139.         }
  140.         inode = iget(dir->i_sb, ino);
  141.         if (!inode || !inode->i_nlink || is_bad_inode(inode)) {
  142.                 CDEBUG(D_PIOCTL, "fatal: invalid inode %ld (%s).n",
  143.                        ino, inode ? inode->i_nlink ? "bad inode" :
  144.                        "no links" : "NULL");
  145.                 error = -ENOENT;
  146.                 EXIT;
  147.                 goto cleanup_iput;
  148.         }
  149.         /* We need to make sure we have the right inode (by checking the
  150.          * generation) so we don't write into the wrong file (old inode was
  151.          * deleted and then a new one was created with the same number).
  152.          */
  153.         if (inode->i_generation != generation) {
  154.                 CDEBUG(D_PIOCTL, "fatal: bad generation %u (want %u)n",
  155.                        inode->i_generation, generation);
  156.                 error = -ENOENT;
  157.                 EXIT;
  158.                 goto cleanup_iput;
  159.         }
  160.         d_instantiate(dentry, inode);
  161.         dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; /* NFS hack */
  162.         EXIT;
  163.         return NULL;
  164. cleanup_iput:
  165.         if (inode)
  166.                 iput(inode);
  167.         return ERR_PTR(error);
  168. }
  169. struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry)
  170. {
  171.         int rc = 0;
  172.         struct dentry *de;
  173.         struct presto_cache *cache;
  174.         struct presto_file_set *fset;
  175.         int error; 
  176.         int minor;
  177.         ino_t ino;
  178.         unsigned int generation;
  179.         ENTRY;
  180.         error = presto_prep(dentry->d_parent, &cache, &fset);
  181.         if ( error  ) {
  182.                 EXIT;
  183.                 return ERR_PTR(error);
  184.         }
  185.         minor = presto_c2m(cache);
  186.         CDEBUG(D_CACHE, "dir ino: %ld, name: %*sn",
  187.                dir->i_ino, dentry->d_name.len, dentry->d_name.name);
  188.         if ( ISLENTO(minor) )
  189.                 CDEBUG(D_CACHE, "We are lenton");
  190.         rc = dentry2id(dentry, &ino, &generation);
  191.         CDEBUG(D_CACHE, "dentry2id returned %dn", rc);
  192.         if ( rc < 0 ) {
  193.                 EXIT;
  194.                 goto exit;
  195.         }
  196.         if ( rc == 0 ) {
  197.                 de = presto_ilookup(dir, dentry, ino, generation);
  198.         } else {
  199.                 struct inode_operations *iops = filter_c2cdiops(cache->cache_filter);
  200.                 rc = 0;
  201.                 /* recursively do a cache lookup in dir */
  202.                 if (iops && iops->lookup) 
  203.                         de = iops->lookup(dir, dentry);
  204.                 else {
  205.                         printk("filesystem has no lookupn");
  206.                         EXIT;
  207.                         goto exit;
  208.                 }
  209.         }
  210.         /* XXX this needs some work to handle returning de if we get it */
  211.         filter_setup_dentry_ops(cache->cache_filter, 
  212.                                 dentry->d_op, &presto_dentry_ops);
  213.         dentry->d_op = filter_c2udops(cache->cache_filter);
  214.         if ( IS_ERR(de) ) {
  215.                 rc = PTR_ERR(de);
  216.                 CDEBUG(D_CACHE, "dentry lookup error %dn", rc);
  217.                 EXIT;
  218.                 goto exit;
  219.         }
  220.         /* some file systems set the methods in lookup, not in
  221.            read_inode, as a result we should set the methods here 
  222.            as well as in read_inode 
  223.         */
  224. if (dentry->d_inode) {
  225. presto_set_ops(dentry->d_inode, cache->cache_filter); 
  226. }
  227.         EXIT;
  228. exit:
  229.         return ERR_PTR(rc);
  230. }
  231. int presto_setattr(struct dentry *de, struct iattr *iattr)
  232. {
  233.         int error;
  234.         struct presto_cache *cache;
  235.         struct presto_file_set *fset;
  236.         struct lento_vfs_context info = { 0, 0, 0 };
  237.         ENTRY;
  238.         error = presto_prep(de, &cache, &fset);
  239.         if ( error ) {
  240.                 EXIT;
  241.                 return error;
  242.         }
  243.         if (!iattr->ia_valid)
  244.                 CDEBUG(D_INODE, "presto_setattr: iattr is not validn");
  245.         CDEBUG(D_INODE, "valid %#x, mode %#o, uid %u, gid %u, size %Lu, "
  246.                "atime %lu mtime %lu ctime %lu flags %dn",
  247.                iattr->ia_valid, iattr->ia_mode, iattr->ia_uid, iattr->ia_gid,
  248.                iattr->ia_size, iattr->ia_atime, iattr->ia_mtime,
  249.                iattr->ia_ctime, iattr->ia_attr_flags);
  250.         
  251.         if ( presto_get_permit(de->d_inode) < 0 ) {
  252.                 EXIT;
  253.                 return -EROFS;
  254.         }
  255.         if (!ISLENTO(presto_c2m(cache)))
  256.                 info.flags = LENTO_FL_KML;
  257. info.flags |= LENTO_FL_IGNORE_TIME;
  258.         error = presto_do_setattr(fset, de, iattr, &info);
  259.         presto_put_permit(de->d_inode);
  260.         return error;
  261. }
  262. /*
  263.  *  Now the meat: the fs operations that require journaling
  264.  *
  265.  *
  266.  *  XXX: some of these need modifications for hierarchical filesets
  267.  */
  268. int presto_prep(struct dentry *dentry, struct presto_cache **cache,
  269.                 struct presto_file_set **fset)
  270. {
  271.         *fset = presto_fset(dentry);
  272.         if ( !*fset ) {
  273.                 CDEBUG(D_INODE, "No file set for dentry at %pn", dentry);
  274.                 return -EROFS;
  275.         }
  276.         *cache = (*fset)->fset_cache;
  277.         if ( !*cache ) {
  278.                 printk("PRESTO: BAD, BAD: cannot find cachen");
  279.                 return -EBADF;
  280.         }
  281.         CDEBUG(D_PIOCTL, "---> cache flags %x, fset flags %xn",
  282.               (*cache)->cache_flags, (*fset)->fset_flags);
  283.         if( presto_is_read_only(*fset) ) {
  284.                 printk("PRESTO: cannot modify read-only fileset, minor %d.n",
  285.                        presto_c2m(*cache));
  286.                 return -EROFS;
  287.         }
  288.         return 0;
  289. }
  290. static int presto_create(struct inode * dir, struct dentry * dentry, int mode)
  291. {
  292.         int error;
  293.         struct presto_cache *cache;
  294.         struct dentry *parent = dentry->d_parent;
  295.         struct lento_vfs_context info;
  296.         struct presto_file_set *fset;
  297.         ENTRY;
  298.         error = presto_prep(dentry->d_parent, &cache, &fset);
  299.         if ( error ) {
  300.                 EXIT;
  301.                 return error;
  302.         }
  303. presto_unlock(dir);
  304.         /* Does blocking and non-blocking behavious need to be 
  305.            checked for.  Without blocking (return 1), the permit
  306.            was acquired without reintegration
  307.         */
  308.         if ( presto_get_permit(dir) < 0 ) {
  309.                 EXIT;
  310.                 presto_fulllock(dir);
  311.                 return -EROFS;
  312.         }
  313.         presto_relock_sem(dir);
  314. parent = dentry->d_parent; 
  315.         memset(&info, 0, sizeof(info));
  316.         if (!ISLENTO(presto_c2m(cache)))
  317.                 info.flags = LENTO_FL_KML;
  318. info.flags |= LENTO_FL_IGNORE_TIME;
  319.         error = presto_do_create(fset, parent, dentry, mode, &info);
  320.         presto_relock_other(dir);
  321.         presto_put_permit(dir);
  322.         EXIT;
  323.         return error;
  324. }
  325. static int presto_link(struct dentry *old_dentry, struct inode *dir,
  326.                 struct dentry *new_dentry)
  327. {
  328.         int error;
  329.         struct presto_cache *cache, *new_cache;
  330.         struct presto_file_set *fset, *new_fset;
  331.         struct dentry *parent = new_dentry->d_parent;
  332.         struct lento_vfs_context info;
  333.         ENTRY;
  334.         error = presto_prep(old_dentry, &cache, &fset);
  335.         if ( error ) {
  336.                 EXIT;
  337.                 return error;
  338.         }
  339.         error = presto_prep(new_dentry->d_parent, &new_cache, &new_fset);
  340.         if ( error ) {
  341.                 EXIT;
  342.                 return error;
  343.         }
  344.         if (fset != new_fset) { 
  345.                 EXIT;
  346.                 return -EXDEV;
  347.         }
  348.         presto_unlock(dir);
  349.         if ( presto_get_permit(old_dentry->d_inode) < 0 ) {
  350.                 EXIT;
  351.                 presto_fulllock(dir);
  352.                 return -EROFS;
  353.         }
  354.         if ( presto_get_permit(dir) < 0 ) {
  355.                 EXIT;
  356.                 presto_fulllock(dir);
  357.                 return -EROFS;
  358.         }
  359. presto_relock_sem(dir);
  360.         parent = new_dentry->d_parent;
  361.         memset(&info, 0, sizeof(info));
  362.         if (!ISLENTO(presto_c2m(cache)))
  363.                 info.flags = LENTO_FL_KML;
  364. info.flags |= LENTO_FL_IGNORE_TIME;
  365.         error = presto_do_link(fset, old_dentry, parent,
  366.                                new_dentry, &info);
  367.         presto_relock_other(dir);
  368.         presto_put_permit(dir);
  369.         presto_put_permit(old_dentry->d_inode);
  370.         return error;
  371. }
  372. static int presto_mkdir(struct inode * dir, struct dentry * dentry, int mode)
  373. {
  374.         int error;
  375.         struct presto_file_set *fset;
  376.         struct presto_cache *cache;
  377.         struct dentry *parent = dentry->d_parent;
  378.         struct lento_vfs_context info;
  379.         ENTRY;
  380.         error = presto_prep(dentry->d_parent, &cache, &fset);
  381.         if ( error  ) {
  382.                 EXIT;
  383.                 return error;
  384.         }
  385. presto_unlock(dir); 
  386.         if ( presto_get_permit(dir) < 0 ) {
  387.                 EXIT;
  388.                 presto_fulllock(dir);
  389.                 return -EROFS;
  390.         }
  391.         memset(&info, 0, sizeof(info));
  392.         if (!ISLENTO(presto_c2m(cache)))
  393.                 info.flags = LENTO_FL_KML;
  394. info.flags |= LENTO_FL_IGNORE_TIME;
  395. presto_relock_sem(dir); 
  396. parent = dentry->d_parent;
  397.         error = presto_do_mkdir(fset, parent, dentry, mode, &info);
  398. presto_relock_other(dir); 
  399.         presto_put_permit(dir);
  400.         return error;
  401. }
  402. static int presto_symlink(struct inode *dir, struct dentry *dentry,
  403.                    const char *name)
  404. {
  405.         int error;
  406.         struct presto_cache *cache;
  407.         struct presto_file_set *fset;
  408.         struct dentry *parent = dentry->d_parent;
  409.         struct lento_vfs_context info;
  410.         ENTRY;
  411.         error = presto_prep(dentry->d_parent, &cache, &fset);
  412.         if ( error ) {
  413.                 EXIT;
  414.                 return error;
  415.         }
  416.         presto_unlock(dir);
  417.         if ( presto_get_permit(dir) < 0 ) {
  418.                 EXIT;
  419. presto_fulllock(dir);
  420.                 return -EROFS;
  421.         }
  422. presto_relock_sem(dir);
  423.         parent = dentry->d_parent;
  424.         memset(&info, 0, sizeof(info));
  425.         if (!ISLENTO(presto_c2m(cache)))
  426.                 info.flags = LENTO_FL_KML;
  427. info.flags |= LENTO_FL_IGNORE_TIME;
  428.         error = presto_do_symlink(fset, parent, dentry, name, &info);
  429.         presto_relock_other(dir);
  430.         presto_put_permit(dir);
  431.         return error;
  432. }
  433. int presto_unlink(struct inode *dir, struct dentry *dentry)
  434. {
  435.         int error;
  436.         struct presto_cache *cache;
  437.         struct presto_file_set *fset;
  438.         struct dentry *parent = dentry->d_parent;
  439.         struct lento_vfs_context info;
  440.         ENTRY;
  441.         error = presto_prep(dentry->d_parent, &cache, &fset);
  442.         if ( error  ) {
  443.                 EXIT;
  444.                 return error;
  445.         }
  446.         presto_unlock(dir);
  447.         if ( presto_get_permit(dir) < 0 ) {
  448.                 EXIT;
  449. presto_fulllock(dir);
  450.                 return -EROFS;
  451.         }
  452. presto_relock_sem(dir);
  453.         parent = dentry->d_parent;
  454.         memset(&info, 0, sizeof(info));
  455.         if (!ISLENTO(presto_c2m(cache)))
  456.                 info.flags = LENTO_FL_KML;
  457. info.flags |= LENTO_FL_IGNORE_TIME;
  458.         error = presto_do_unlink(fset, parent, dentry, &info);
  459.         presto_relock_other(dir);
  460.         presto_put_permit(dir);
  461.         return error;
  462. }
  463. static int presto_rmdir(struct inode *dir, struct dentry *dentry)
  464. {
  465.         int error;
  466.         struct presto_cache *cache;
  467.         struct presto_file_set *fset;
  468.         struct dentry *parent = dentry->d_parent;
  469.         struct lento_vfs_context info;
  470.         ENTRY;
  471.         CDEBUG(D_FILE, "prepping preston");
  472.         error = presto_prep(dentry->d_parent, &cache, &fset);
  473.         if ( error ) {
  474.                 EXIT;
  475.                 return error;
  476.         }
  477.         CDEBUG(D_FILE, "unlockingn");
  478.         /* We need to dget() before the dput in double_unlock, to ensure we
  479.          * still have dentry references.  double_lock doesn't do dget for us.
  480.          */
  481. unlock_kernel();
  482. if (d_unhashed(dentry))
  483. d_rehash(dentry);
  484.         double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
  485.         double_up(&dir->i_sem, &dentry->d_inode->i_sem);
  486.         CDEBUG(D_FILE, "getting permitn");
  487.         if ( presto_get_permit(parent->d_inode) < 0 ) {
  488.                 EXIT;
  489. double_down(&dir->i_sem, &dentry->d_inode->i_sem);
  490. double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
  491. lock_kernel();
  492.                 return -EROFS;
  493.         }
  494.         CDEBUG(D_FILE, "lockingn");
  495. double_down(&dir->i_sem, &dentry->d_inode->i_sem);
  496. parent = dentry->d_parent;
  497.         memset(&info, 0, sizeof(info));
  498.         if (!ISLENTO(presto_c2m(cache)))
  499.                 info.flags = LENTO_FL_KML;
  500. info.flags |= LENTO_FL_IGNORE_TIME;
  501.         error = presto_do_rmdir(fset, parent, dentry, &info);
  502.         presto_put_permit(parent->d_inode);
  503. lock_kernel();
  504.         EXIT;
  505.         return error;
  506. }
  507. static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
  508. {
  509.         int error;
  510.         struct presto_cache *cache;
  511.         struct presto_file_set *fset;
  512.         struct dentry *parent = dentry->d_parent;
  513.         struct lento_vfs_context info;
  514.         ENTRY;
  515.         error = presto_prep(dentry->d_parent, &cache, &fset);
  516.         if ( error  ) {
  517.                 EXIT;
  518.                 return error;
  519.         }
  520.         presto_unlock(dir);
  521.         if ( presto_get_permit(dir) < 0 ) {
  522.                 EXIT;
  523.                 presto_fulllock(dir);
  524.                 return -EROFS;
  525.         }
  526. presto_relock_sem(dir);
  527.         parent = dentry->d_parent;
  528.         memset(&info, 0, sizeof(info));
  529.         if (!ISLENTO(presto_c2m(cache)))
  530.                 info.flags = LENTO_FL_KML;
  531. info.flags |= LENTO_FL_IGNORE_TIME;
  532.         error = presto_do_mknod(fset, parent, dentry, mode, rdev, &info);
  533.         presto_relock_other(dir);
  534.         presto_put_permit(dir);
  535.         EXIT;
  536.         return error;
  537. }
  538. inline void presto_triple_unlock(struct inode *old_dir, struct inode *new_dir, 
  539.  struct dentry *old_dentry, 
  540.  struct dentry *new_dentry, int triple)
  541. {
  542. /* rename_dir case */ 
  543. if (S_ISDIR(old_dentry->d_inode->i_mode)) { 
  544. if (triple) {
  545. triple_up(&old_dir->i_zombie,
  546.   &new_dir->i_zombie,
  547.   &new_dentry->d_inode->i_zombie);
  548. } else { 
  549. double_up(&old_dir->i_zombie,
  550.   &new_dir->i_zombie);
  551. }
  552. up(&old_dir->i_sb->s_vfs_rename_sem);
  553. } else /* this case is rename_other */
  554. double_up(&old_dir->i_zombie, &new_dir->i_zombie);
  555. /* done by do_rename */
  556. unlock_kernel();
  557. double_up(&old_dir->i_sem, &new_dir->i_sem);
  558. }
  559. inline void presto_triple_fulllock(struct inode *old_dir, 
  560.    struct inode *new_dir, 
  561.    struct dentry *old_dentry, 
  562.    struct dentry *new_dentry, int triple)
  563. {
  564. /* done by do_rename */
  565. double_down(&old_dir->i_sem, &new_dir->i_sem);
  566. lock_kernel();
  567. /* rename_dir case */ 
  568. if (S_ISDIR(old_dentry->d_inode->i_mode)) { 
  569. down(&old_dir->i_sb->s_vfs_rename_sem);
  570. if (triple) {
  571. triple_down(&old_dir->i_zombie,
  572.   &new_dir->i_zombie,
  573.   &new_dentry->d_inode->i_zombie);
  574. } else { 
  575. double_down(&old_dir->i_zombie,
  576.   &new_dir->i_zombie);
  577. }
  578. } else /* this case is rename_other */
  579. double_down(&old_dir->i_zombie, &new_dir->i_zombie);
  580. }
  581. inline void presto_triple_relock_sem(struct inode *old_dir, 
  582.    struct inode *new_dir, 
  583.    struct dentry *old_dentry, 
  584.    struct dentry *new_dentry, int triple)
  585. {
  586. /* done by do_rename */
  587. double_down(&old_dir->i_sem, &new_dir->i_sem);
  588. lock_kernel();
  589. }
  590. inline void presto_triple_relock_other(struct inode *old_dir, 
  591.    struct inode *new_dir, 
  592.    struct dentry *old_dentry, 
  593.    struct dentry *new_dentry, int triple)
  594. {
  595. /* rename_dir case */ 
  596. if (S_ISDIR(old_dentry->d_inode->i_mode)) { 
  597. down(&old_dir->i_sb->s_vfs_rename_sem);
  598. if (triple) {
  599. triple_down(&old_dir->i_zombie,
  600.   &new_dir->i_zombie,
  601.   &new_dentry->d_inode->i_zombie);
  602. } else { 
  603. double_down(&old_dir->i_zombie,
  604.   &new_dir->i_zombie);
  605. }
  606. } else /* this case is rename_other */
  607. double_down(&old_dir->i_zombie, &new_dir->i_zombie);
  608. }
  609. // XXX this can be optimized: renamtes across filesets only require 
  610. //     multiple KML records, but can locally be executed normally. 
  611. int presto_rename(struct inode *old_dir, struct dentry *old_dentry,
  612.                   struct inode *new_dir, struct dentry *new_dentry)
  613. {
  614.         int error;
  615.         struct presto_cache *cache, *new_cache;
  616.         struct presto_file_set *fset, *new_fset;
  617.         struct lento_vfs_context info;
  618.         struct dentry *old_parent = old_dentry->d_parent;
  619.         struct dentry *new_parent = new_dentry->d_parent;
  620.         int triple;
  621.         ENTRY;
  622.         error = presto_prep(old_dentry, &cache, &fset);
  623.         if ( error ) {
  624.                 EXIT;
  625.                 return error;
  626.         }
  627.         error = presto_prep(new_parent, &new_cache, &new_fset);
  628.         if ( error ) {
  629.                 EXIT;
  630.                 return error;
  631.         }
  632.         if ( fset != new_fset ) {
  633.                 EXIT;
  634.                 return -EXDEV;
  635.         }
  636.         /* We need to do dget before the dput in double_unlock, to ensure we
  637.          * still have dentry references.  double_lock doesn't do dget for us.
  638.          */
  639.         triple = (S_ISDIR(old_dentry->d_inode->i_mode) && new_dentry->d_inode)?
  640.                 1:0;
  641. presto_triple_unlock(old_dir, new_dir, old_dentry, new_dentry, triple); 
  642.         if ( presto_get_permit(old_dir) < 0 ) {
  643.                 EXIT;
  644. presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple); 
  645.                 return -EROFS;
  646.         }
  647.         if ( presto_get_permit(new_dir) < 0 ) {
  648.                 EXIT;
  649. presto_triple_fulllock(old_dir, new_dir, old_dentry, new_dentry, triple); 
  650.                 return -EROFS;
  651.         }
  652. presto_triple_relock_sem(old_dir, new_dir, old_dentry, new_dentry, triple); 
  653.         memset(&info, 0, sizeof(info));
  654.         if (!ISLENTO(presto_c2m(cache)))
  655.                 info.flags = LENTO_FL_KML;
  656. info.flags |= LENTO_FL_IGNORE_TIME;
  657.         error = presto_do_rename(fset, old_parent, old_dentry, new_parent,
  658.                                  new_dentry, &info);
  659. presto_triple_relock_other(old_dir, new_dir, old_dentry, new_dentry, triple); 
  660.         presto_put_permit(new_dir);
  661.         presto_put_permit(old_dir);
  662.         return error;
  663. }
  664. /* basically this allows the ilookup processes access to all files for
  665.  * reading, while not making ilookup totally insecure.  This could all
  666.  * go away if we could set the CAP_DAC_READ_SEARCH capability for the client.
  667.  */
  668. /* If posix acls are available, the underlying cache fs will export the
  669.  * appropriate permission function. Thus we do not worry here about ACLs
  670.  * or EAs. -SHP
  671.  */
  672. int presto_permission(struct inode *inode, int mask)
  673. {
  674.         unsigned short mode = inode->i_mode;
  675.         struct presto_cache *cache;
  676.         int rc;
  677.         ENTRY;
  678.         if ( presto_can_ilookup() && !(mask & S_IWOTH)) {
  679.                 CDEBUG(D_CACHE, "ilookup on %ld OKn", inode->i_ino);
  680.                 EXIT;
  681.                 return 0;
  682.         }
  683.         cache = presto_get_cache(inode);
  684.         if ( cache ) {
  685.                 /* we only override the file/dir permission operations */
  686.                 struct inode_operations *fiops = filter_c2cfiops(cache->cache_filter);
  687.                 struct inode_operations *diops = filter_c2cdiops(cache->cache_filter);
  688.                 if ( S_ISREG(mode) && fiops && fiops->permission ) {
  689.                         EXIT;
  690.                         return fiops->permission(inode, mask);
  691.                 }
  692.                 if ( S_ISDIR(mode) && diops && diops->permission ) {
  693.                         EXIT;
  694.                         return diops->permission(inode, mask);
  695.                 }
  696.         }
  697.         /* The cache filesystem doesn't have its own permission function,
  698.          * but we don't want to duplicate the VFS code here.  In order
  699.          * to avoid looping from permission calling this function again,
  700.          * we temporarily override the permission operation while we call
  701.          * the VFS permission function.
  702.          */
  703.         inode->i_op->permission = NULL;
  704.         rc = permission(inode, mask);
  705.         inode->i_op->permission = &presto_permission;
  706.         EXIT;
  707.         return rc;
  708. }
  709. static int presto_dir_open(struct inode *inode, struct file *file)
  710. {
  711.         int rc = 0;
  712.         struct dentry *de = file->f_dentry;
  713.         struct file_operations *fops;
  714.         struct presto_cache *cache;
  715.         struct presto_file_set *fset;
  716.         int minor;
  717.         int error; 
  718.         ENTRY;
  719.         error = presto_prep(file->f_dentry, &cache, &fset);
  720.         if ( error  ) {
  721.                 EXIT;
  722.                 make_bad_inode(inode);
  723.                 return error;
  724.         }
  725.         minor = presto_c2m(cache);
  726.         CDEBUG(D_CACHE, "minor %d, DATA_OK: %d, ino: %ldn",
  727.                minor, presto_chk(de, PRESTO_DATA), inode->i_ino);
  728.         if ( ISLENTO(minor) )
  729.                 goto cache;
  730.         if ( !presto_chk(de, PRESTO_DATA) ) {
  731.                 CDEBUG(D_CACHE, "doing lento_opendirn");
  732.                 rc = presto_opendir_upcall(minor, file->f_dentry, fset->fset_mtpt, SYNCHRONOUS);
  733.         }
  734.         if ( rc ) {
  735.                 printk("presto_dir_open: DATA_OK: %d, ino: %ld, error %dn",
  736.                        presto_chk(de, PRESTO_DATA), inode->i_ino, rc);
  737.                 return rc ;
  738.         }
  739.  cache:
  740.         fops = filter_c2cdfops(cache->cache_filter);
  741.         if ( fops->open ) {
  742.                 rc = fops->open(inode, file);
  743.         }
  744.         presto_set(de, PRESTO_DATA | PRESTO_ATTR);
  745.         CDEBUG(D_CACHE, "returns %d, data %d, attr %dn", rc,
  746.                presto_chk(de, PRESTO_DATA), presto_chk(de, PRESTO_ATTR));
  747.         return 0;
  748. }
  749. struct file_operations presto_dir_fops = {
  750.         open: presto_dir_open
  751. };
  752. struct inode_operations presto_dir_iops = {
  753.         create: presto_create,
  754.         lookup: presto_lookup,
  755.         link:   presto_link,
  756.         unlink: presto_unlink,
  757.         symlink:        presto_symlink,
  758.         mkdir:  presto_mkdir,
  759.         rmdir:  presto_rmdir,
  760.         mknod:  presto_mknod,
  761.         rename: presto_rename,
  762.         permission:     presto_permission,
  763.         setattr:        presto_setattr,
  764. #ifdef CONFIG_FS_EXT_ATTR
  765. set_ext_attr: presto_set_ext_attr,
  766. #endif
  767. };