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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  *
  4.  *  Copyright (C) 2000 Stelias Computing, Inc.
  5.  *  Copyright (C) 2000 Red Hat, Inc.
  6.  *  Copyright (C) 2000 Mountain View Data, Inc.
  7.  *
  8.  *  Extended Attribute Support
  9.  *  Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
  10.  */
  11. #include <stdarg.h>
  12. #include <asm/bitops.h>
  13. #include <asm/uaccess.h>
  14. #include <asm/system.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/fsfilter.h>
  29. #include <linux/intermezzo_fs.h>
  30. int filter_print_entry = 0;
  31. int filter_debug = 0xfffffff;
  32. /*
  33.  * The function in this file are responsible for setting up the 
  34.  * correct methods layered file systems like InterMezzo and snapfs
  35.  */
  36. static struct filter_fs filter_oppar[FILTER_FS_TYPES];
  37. /* get to the upper methods (intermezzo, snapfs) */
  38. inline struct super_operations *filter_c2usops(struct filter_fs *cache)
  39. {
  40.         return &cache->o_fops.filter_sops;
  41. }
  42. inline struct inode_operations *filter_c2udiops(struct filter_fs *cache)
  43. {
  44.         return &cache->o_fops.filter_dir_iops;
  45. }
  46. inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache)
  47. {
  48.         return &cache->o_fops.filter_file_iops;
  49. }
  50. inline struct inode_operations *filter_c2usiops(struct filter_fs *cache)
  51. {
  52.         return &cache->o_fops.filter_sym_iops;
  53. }
  54. inline struct file_operations *filter_c2udfops(struct filter_fs *cache)
  55. {
  56.         return &cache->o_fops.filter_dir_fops;
  57. }
  58. inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
  59. {
  60.         return &cache->o_fops.filter_file_fops;
  61. }
  62. inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
  63. {
  64.         return &cache->o_fops.filter_sym_fops;
  65. }
  66. inline struct dentry_operations *filter_c2udops(struct filter_fs *cache)
  67. {
  68.         return &cache->o_fops.filter_dentry_ops;
  69. }
  70. /* get to the cache (lower) methods */
  71. inline struct super_operations *filter_c2csops(struct filter_fs *cache)
  72. {
  73.         return cache->o_caops.cache_sops;
  74. }
  75. inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache)
  76. {
  77.         return cache->o_caops.cache_dir_iops;
  78. }
  79. inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
  80. {
  81.         return cache->o_caops.cache_file_iops;
  82. }
  83. inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
  84. {
  85.         return cache->o_caops.cache_sym_iops;
  86. }
  87. inline struct file_operations *filter_c2cdfops(struct filter_fs *cache)
  88. {
  89.         return cache->o_caops.cache_dir_fops;
  90. }
  91. inline struct file_operations *filter_c2cffops(struct filter_fs *cache)
  92. {
  93.         return cache->o_caops.cache_file_fops;
  94. }
  95. inline struct file_operations *filter_c2csfops(struct filter_fs *cache)
  96. {
  97.         return cache->o_caops.cache_sym_fops;
  98. }
  99. inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache)
  100. {
  101.         return cache->o_caops.cache_dentry_ops;
  102. }
  103. void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type)
  104. {
  105.         if ( strlen(cache_type) == strlen("ext2") &&
  106.              memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
  107. #if CONFIG_EXT2_FS
  108.                 ops->o_trops = &presto_ext2_journal_ops;
  109. #else
  110.                 ops->o_trops = NULL;
  111. #endif
  112.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  113.         }
  114.         if ( strlen(cache_type) == strlen("ext3") &&
  115.              memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
  116. #if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
  117.                 ops->o_trops = &presto_ext3_journal_ops;
  118. #else
  119.                 ops->o_trops = NULL;
  120. #endif
  121.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  122.         }
  123.         if ( strlen(cache_type) == strlen("reiserfs") &&
  124.              memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
  125. #if 0
  126. /* #if defined(CONFIG_REISERFS_FS) || defined(CONFIG_REISERFS_FS_MODULE) */
  127.                 ops->o_trops = &presto_reiserfs_journal_ops;
  128. #else
  129.                 ops->o_trops = NULL;
  130. #endif
  131.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  132.         }
  133.         if ( strlen(cache_type) == strlen("xfs") &&
  134.              memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) {
  135. #if 0
  136.                 //#if defined(CONFIG_XFS_FS) || defined (CONFIG_XFS_FS_MODULE)
  137.                 ops->o_trops = &presto_xfs_journal_ops;
  138. #else
  139.                 ops->o_trops = NULL;
  140. #endif
  141.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  142.         }
  143.         if ( strlen(cache_type) == strlen("obdfs") &&
  144.              memcmp(cache_type, "obdfs", strlen("obdfs")) == 0 ) {
  145. #if defined(CONFIG_OBDFS_FS) || defined (CONFIG_OBDFS_FS_MODULE)
  146.                 ops->o_trops = presto_obdfs_journal_ops;
  147. #else
  148.                 ops->o_trops = NULL;
  149. #endif
  150.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  151.         }
  152. }
  153. /* find the cache for this FS */
  154. struct filter_fs *filter_get_filter_fs(const char *cache_type)
  155. {
  156.         struct filter_fs *ops = NULL;
  157.         FENTRY;
  158.         if ( strlen(cache_type) == strlen("ext2") &&
  159.              memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
  160.                 ops = &filter_oppar[FILTER_FS_EXT2];
  161.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  162.         }
  163.         if ( strlen(cache_type) == strlen("xfs") &&
  164.              memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) {
  165.                 ops = &filter_oppar[FILTER_FS_XFS];
  166.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  167.         }
  168.         if ( strlen(cache_type) == strlen("ext3") &&
  169.              memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
  170.                 ops = &filter_oppar[FILTER_FS_EXT3];
  171.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  172.         }
  173.         if ( strlen(cache_type) == strlen("reiserfs") &&
  174.              memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
  175.                 ops = &filter_oppar[FILTER_FS_REISERFS];
  176.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  177.         }
  178.         if ( strlen(cache_type) == strlen("obdfs") &&
  179.              memcmp(cache_type, "obdfs", strlen("obdfs")) == 0 ) {
  180.                 ops = &filter_oppar[FILTER_FS_OBDFS];
  181.                 FDEBUG(D_SUPER, "ops at %pn", ops);
  182.         }
  183.         if (ops == NULL) {
  184.                 printk("prepare to die: unrecognized cache type for Filtern");
  185.         }
  186.         return ops;
  187.         FEXIT;
  188. }
  189. /*
  190.  *  Frobnicate the InterMezzo operations
  191.  *    this establishes the link between the InterMezzo file system
  192.  *    and the underlying file system used for the cache.
  193.  */
  194. void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_sops, struct super_operations *filter_sops)
  195. {
  196.         /* Get ptr to the shared struct snapfs_ops structure. */
  197.         struct filter_ops *props = &cache->o_fops;
  198.         /* Get ptr to the shared struct cache_ops structure. */
  199.         struct cache_ops *caops = &cache->o_caops;
  200.         FENTRY;
  201.         if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
  202.                 FEXIT;
  203.                 return;
  204.         }
  205.         cache->o_flags |= FILTER_DID_SUPER_OPS;
  206.         /* Set the cache superblock operations to point to the
  207.            superblock operations of the underlying file system.  */
  208.         caops->cache_sops = cache_sops;
  209.         /*
  210.          * Copy the cache (real fs) superblock ops to the "filter"
  211.          * superblock ops as defaults. Some will be changed below
  212.          */
  213.         memcpy(&props->filter_sops, cache_sops, sizeof(*cache_sops));
  214.         /* 'put_super' unconditionally is that of filter */
  215.         if (filter_sops->put_super) { 
  216.                 props->filter_sops.put_super = filter_sops->put_super;
  217.         }
  218.         if (cache_sops->read_inode) {
  219.                 props->filter_sops.read_inode = filter_sops->read_inode;
  220.                 FDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %pn",
  221.                       cache, cache, props->filter_sops.read_inode);
  222.         }
  223.         if (cache_sops->remount_fs)
  224.                 props->filter_sops.remount_fs = filter_sops->remount_fs;
  225.         FEXIT;
  226. }
  227. void filter_setup_dir_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
  228. {
  229.         struct inode_operations *cache_filter_iops;
  230.         struct inode_operations *cache_iops = inode->i_op;
  231.         struct file_operations *cache_fops = inode->i_fop;
  232.         FENTRY;
  233.         if ( cache->o_flags & FILTER_DID_DIR_OPS ) {
  234.                 FEXIT;
  235.                 return;
  236.         }
  237.         cache->o_flags |= FILTER_DID_DIR_OPS;
  238.         /* former ops become cache_ops */
  239.         cache->o_caops.cache_dir_iops = cache_iops;
  240.         cache->o_caops.cache_dir_fops = cache_fops;
  241.         FDEBUG(D_SUPER, "filter at %p, cache iops %p, iops %pn",
  242.                cache, cache_iops, filter_c2udiops(cache));
  243.         /* setup our dir iops: copy and modify */
  244.         memcpy(filter_c2udiops(cache), cache_iops, sizeof(*cache_iops));
  245.         /* abbreviate */
  246.         cache_filter_iops = filter_c2udiops(cache);
  247.         /* methods that filter if cache filesystem has these ops */
  248.         if (cache_iops->lookup && filter_iops->lookup)
  249.                 cache_filter_iops->lookup = filter_iops->lookup;
  250.         if (cache_iops->create && filter_iops->create)
  251.                 cache_filter_iops->create = filter_iops->create;
  252.         if (cache_iops->link && filter_iops->link)
  253.                 cache_filter_iops->link = filter_iops->link;
  254.         if (cache_iops->unlink && filter_iops->unlink)
  255.                 cache_filter_iops->unlink = filter_iops->unlink;
  256.         if (cache_iops->mkdir && filter_iops->mkdir)
  257.                 cache_filter_iops->mkdir = filter_iops->mkdir;
  258.         if (cache_iops->rmdir && filter_iops->rmdir)
  259.                 cache_filter_iops->rmdir = filter_iops->rmdir;
  260.         if (cache_iops->symlink && filter_iops->symlink)
  261.                 cache_filter_iops->symlink = filter_iops->symlink;
  262.         if (cache_iops->rename && filter_iops->rename)
  263.                 cache_filter_iops->rename = filter_iops->rename;
  264.         if (cache_iops->mknod && filter_iops->mknod)
  265.                 cache_filter_iops->mknod = filter_iops->mknod;
  266.         if (cache_iops->permission && filter_iops->permission)
  267.                 cache_filter_iops->permission = filter_iops->permission;
  268.         if (cache_iops->getattr)
  269.                 cache_filter_iops->getattr = filter_iops->getattr;
  270.         /* Some filesystems do not use a setattr method of their own
  271.            instead relying on inode_setattr/write_inode. We still need to
  272.            journal these so we make setattr an unconditional operation. 
  273.            XXX: we should probably check for write_inode. SHP
  274.         */
  275.         /*if (cache_iops->setattr)*/
  276.                 cache_filter_iops->setattr = filter_iops->setattr;
  277. #ifdef CONFIG_FS_EXT_ATTR
  278. /* For now we assume that posix acls are handled through extended
  279. * attributes. If this is not the case, we must explicitly trap 
  280. * posix_set_acl. SHP
  281. */
  282. if (cache_iops->set_ext_attr && filter_iops->set_ext_attr)
  283. cache_filter_iops->set_ext_attr = filter_iops->set_ext_attr;
  284. #endif
  285.         /* copy dir fops */
  286.         memcpy(filter_c2udfops(cache), cache_fops, sizeof(*cache_fops));
  287.         /* unconditional filtering operations */
  288.         filter_c2udfops(cache)->open = filter_fops->open;
  289.         FEXIT;
  290. }
  291. void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
  292. {
  293.         struct inode_operations *pr_iops;
  294.         struct inode_operations *cache_iops = inode->i_op;
  295.         struct file_operations *cache_fops = inode->i_fop;
  296.         FENTRY;
  297.         if ( cache->o_flags & FILTER_DID_FILE_OPS ) {
  298.                 FEXIT;
  299.                 return;
  300.         }
  301.         cache->o_flags |= FILTER_DID_FILE_OPS;
  302.         /* steal the old ops */
  303.         /* former ops become cache_ops */
  304.         cache->o_caops.cache_file_iops = cache_iops;
  305.         cache->o_caops.cache_file_fops = cache_fops;
  306.         
  307.         /* abbreviate */
  308.         pr_iops = filter_c2ufiops(cache); 
  309.         /* setup our dir iops: copy and modify */
  310.         memcpy(pr_iops, cache_iops, sizeof(*cache_iops));
  311.         /* copy dir fops */
  312.         printk("*** cache file ops at %pn", cache_fops);
  313.         memcpy(filter_c2uffops(cache), cache_fops, sizeof(*cache_fops));
  314.         /* assign */
  315.         /* See comments above in filter_setup_dir_ops. SHP */
  316.         /*if (cache_iops->setattr)*/
  317.                 pr_iops->setattr = filter_iops->setattr;
  318.         if (cache_iops->getattr)
  319.                 pr_iops->getattr = filter_iops->getattr;
  320. #ifdef CONFIG_FS_EXT_ATTR
  321.      /* For now we assume that posix acls are handled through extended
  322. * attributes. If this is not the case, we must explicitly trap and 
  323. * posix_set_acl
  324. */
  325. if (cache_iops->set_ext_attr && filter_iops->set_ext_attr)
  326. pr_iops->set_ext_attr = filter_iops->set_ext_attr;
  327. #endif
  328.         /* unconditional filtering operations */
  329.         filter_c2uffops(cache)->open = filter_fops->open;
  330.         filter_c2uffops(cache)->release = filter_fops->release;
  331.         filter_c2uffops(cache)->write = filter_fops->write;
  332.         FEXIT;
  333. }
  334. /* XXX in 2.3 there are "fast" and "slow" symlink ops for ext2 XXX */
  335. void filter_setup_symlink_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
  336. {
  337.         struct inode_operations *pr_iops;
  338.         struct inode_operations *cache_iops = inode->i_op;
  339.         struct file_operations *cache_fops = inode->i_fop;
  340.         FENTRY;
  341.         if ( cache->o_flags & FILTER_DID_SYMLINK_OPS ) {
  342.                 FEXIT;
  343.                 return;
  344.         }
  345.         cache->o_flags |= FILTER_DID_SYMLINK_OPS;
  346.         /* steal the old ops */
  347.         cache->o_caops.cache_sym_iops = cache_iops;
  348.         cache->o_caops.cache_sym_fops = cache_fops;
  349.         /* abbreviate */
  350.         pr_iops = filter_c2usiops(cache); 
  351.         /* setup our dir iops: copy and modify */
  352.         memcpy(pr_iops, cache_iops, sizeof(*cache_iops));
  353.         /* See comments above in filter_setup_dir_ops. SHP */
  354.         /* if (cache_iops->setattr) */
  355.                 pr_iops->setattr = filter_iops->setattr;
  356.         if (cache_iops->getattr)
  357.                 pr_iops->getattr = filter_iops->getattr;
  358.         /* assign */
  359.         /* copy fops - careful for symlinks they might be NULL */
  360.         if ( cache_fops ) { 
  361.                 memcpy(filter_c2usfops(cache), cache_fops, sizeof(*cache_fops));
  362.         }
  363.         FEXIT;
  364. }
  365. void filter_setup_dentry_ops(struct filter_fs *cache,
  366.                              struct dentry_operations *cache_dop,
  367.                              struct dentry_operations *filter_dop)
  368. {
  369.         if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
  370.                 FEXIT;
  371.                 return;
  372.         }
  373.         cache->o_flags |= FILTER_DID_DENTRY_OPS;
  374.         cache->o_caops.cache_dentry_ops = cache_dop;
  375.         memcpy(&cache->o_fops.filter_dentry_ops,
  376.                filter_dop, sizeof(*filter_dop));
  377.         
  378.         if (cache_dop &&  cache_dop != filter_dop && cache_dop->d_revalidate){
  379.                 printk("WARNING: filter overriding revalidation!n");
  380.         }
  381.         return;
  382. }