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


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

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

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

    1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
    2  * vim:expandtab:shiftwidth=8:tabstop=8:
    3  *
    4  *  Copyright (C) 2000 Stelias Computing, Inc.
    5  *  Copyright (C) 2000 Red Hat, Inc.
    6  *  Copyright (C) 2000 Mountain View Data, Inc.
    7  *
    8  *  Extended Attribute Support
    9  *  Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
   10  *
   11  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
   12  *
   13  *   InterMezzo is free software; you can redistribute it and/or
   14  *   modify it under the terms of version 2 of the GNU General Public
   15  *   License as published by the Free Software Foundation.
   16  *
   17  *   InterMezzo is distributed in the hope that it will be useful,
   18  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20  *   GNU General Public License for more details.
   21  *
   22  *   You should have received a copy of the GNU General Public License
   23  *   along with InterMezzo; if not, write to the Free Software
   24  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   25  *
   26  */
   27 
   28 #include <stdarg.h>
   29 
   30 #include <asm/bitops.h>
   31 #include <asm/uaccess.h>
   32 #include <asm/system.h>
   33 
   34 #include <linux/errno.h>
   35 #include <linux/fs.h>
   36 #include <linux/ext2_fs.h>
   37 #include <linux/slab.h>
   38 #include <linux/vmalloc.h>
   39 #include <linux/sched.h>
   40 #include <linux/stat.h>
   41 #include <linux/string.h>
   42 #include <linux/locks.h>
   43 #include <linux/blkdev.h>
   44 #include <linux/init.h>
   45 #define __NO_VERSION__
   46 #include <linux/module.h>
   47 
   48 #include <linux/fsfilter.h>
   49 #include <linux/intermezzo_fs.h>
   50 
   51 
   52 int filter_print_entry = 0;
   53 int filter_debug = 0xfffffff;
   54 /*
   55  * The function in this file are responsible for setting up the 
   56  * correct methods layered file systems like InterMezzo and snapfs
   57  */
   58 
   59 
   60 static struct filter_fs filter_oppar[FILTER_FS_TYPES];
   61 
   62 /* get to the upper methods (intermezzo, snapfs) */
   63 inline struct super_operations *filter_c2usops(struct filter_fs *cache)
   64 {
   65         return &cache->o_fops.filter_sops;
   66 }
   67 
   68 inline struct inode_operations *filter_c2udiops(struct filter_fs *cache)
   69 {
   70         return &cache->o_fops.filter_dir_iops;
   71 }
   72 
   73 
   74 inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache)
   75 {
   76         return &cache->o_fops.filter_file_iops;
   77 }
   78 
   79 inline struct inode_operations *filter_c2usiops(struct filter_fs *cache)
   80 {
   81         return &cache->o_fops.filter_sym_iops;
   82 }
   83 
   84 
   85 inline struct file_operations *filter_c2udfops(struct filter_fs *cache)
   86 {
   87         return &cache->o_fops.filter_dir_fops;
   88 }
   89 
   90 inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
   91 {
   92         return &cache->o_fops.filter_file_fops;
   93 }
   94 
   95 inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
   96 {
   97         return &cache->o_fops.filter_sym_fops;
   98 }
   99 
  100 inline struct dentry_operations *filter_c2udops(struct filter_fs *cache)
  101 {
  102         return &cache->o_fops.filter_dentry_ops;
  103 }
  104 
  105 /* get to the cache (lower) methods */
  106 inline struct super_operations *filter_c2csops(struct filter_fs *cache)
  107 {
  108         return cache->o_caops.cache_sops;
  109 }
  110 
  111 inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache)
  112 {
  113         return cache->o_caops.cache_dir_iops;
  114 }
  115 
  116 inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
  117 {
  118         return cache->o_caops.cache_file_iops;
  119 }
  120 
  121 inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
  122 {
  123         return cache->o_caops.cache_sym_iops;
  124 }
  125 
  126 inline struct file_operations *filter_c2cdfops(struct filter_fs *cache)
  127 {
  128         return cache->o_caops.cache_dir_fops;
  129 }
  130 
  131 inline struct file_operations *filter_c2cffops(struct filter_fs *cache)
  132 {
  133         return cache->o_caops.cache_file_fops;
  134 }
  135 
  136 inline struct file_operations *filter_c2csfops(struct filter_fs *cache)
  137 {
  138         return cache->o_caops.cache_sym_fops;
  139 }
  140 
  141 inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache)
  142 {
  143         return cache->o_caops.cache_dentry_ops;
  144 }
  145 
  146 
  147 void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type)
  148 {
  149         if ( strlen(cache_type) == strlen("ext2") &&
  150              memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
  151 #if CONFIG_EXT2_FS
  152                 ops->o_trops = &presto_ext2_journal_ops;
  153 #else
  154                 ops->o_trops = NULL;
  155 #endif
  156                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  157         }
  158 
  159         if ( strlen(cache_type) == strlen("ext3") &&
  160              memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
  161 #if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
  162                 ops->o_trops = &presto_ext3_journal_ops;
  163 #else
  164                 ops->o_trops = NULL;
  165 #endif
  166                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  167         }
  168 
  169         if ( strlen(cache_type) == strlen("tmpfs") &&
  170              memcmp(cache_type, "tmpfs", strlen("tmpfs")) == 0 ) {
  171 #if defined(CONFIG_TMPFS)
  172                 ops->o_trops = &presto_tmpfs_journal_ops;
  173 #else
  174                 ops->o_trops = NULL;
  175 #endif
  176                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  177         }
  178 
  179         if ( strlen(cache_type) == strlen("reiserfs") &&
  180              memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
  181 #if 0
  182                 /* #if defined(CONFIG_REISERFS_FS) || defined(CONFIG_REISERFS_FS_MODULE) */
  183                 ops->o_trops = &presto_reiserfs_journal_ops;
  184 #else
  185                 ops->o_trops = NULL;
  186 #endif
  187                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  188         }
  189 
  190         if ( strlen(cache_type) == strlen("xfs") &&
  191              memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) {
  192 #if 0
  193 /*#if defined(CONFIG_XFS_FS) || defined (CONFIG_XFS_FS_MODULE) */
  194                 ops->o_trops = &presto_xfs_journal_ops;
  195 #else
  196                 ops->o_trops = NULL;
  197 #endif
  198                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  199         }
  200 
  201         if ( strlen(cache_type) == strlen("obdfs") &&
  202              memcmp(cache_type, "obdfs", strlen("obdfs")) == 0 ) {
  203 #if defined(CONFIG_OBDFS_FS) || defined (CONFIG_OBDFS_FS_MODULE)
  204                 ops->o_trops = presto_obdfs_journal_ops;
  205 #else
  206                 ops->o_trops = NULL;
  207 #endif
  208                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  209         }
  210 }
  211 
  212 
  213 /* find the cache for this FS */
  214 struct filter_fs *filter_get_filter_fs(const char *cache_type)
  215 {
  216         struct filter_fs *ops = NULL;
  217         FENTRY;
  218 
  219         if ( strlen(cache_type) == strlen("ext2") &&
  220              memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
  221                 ops = &filter_oppar[FILTER_FS_EXT2];
  222                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  223         }
  224 
  225         if ( strlen(cache_type) == strlen("xfs") &&
  226              memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) {
  227                 ops = &filter_oppar[FILTER_FS_XFS];
  228                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  229         }
  230 
  231         if ( strlen(cache_type) == strlen("ext3") &&
  232              memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
  233                 ops = &filter_oppar[FILTER_FS_EXT3];
  234                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  235         }
  236 
  237         if ( strlen(cache_type) == strlen("tmpfs") &&
  238              memcmp(cache_type, "tmpfs", strlen("tmpfs")) == 0 ) {
  239                 ops = &filter_oppar[FILTER_FS_TMPFS];
  240                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  241         }
  242 
  243         if ( strlen(cache_type) == strlen("reiserfs") &&
  244              memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
  245                 ops = &filter_oppar[FILTER_FS_REISERFS];
  246                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  247         }
  248         if ( strlen(cache_type) == strlen("obdfs") &&
  249              memcmp(cache_type, "obdfs", strlen("obdfs")) == 0 ) {
  250                 ops = &filter_oppar[FILTER_FS_OBDFS];
  251                 FDEBUG(D_SUPER, "ops at %p\n", ops);
  252         }
  253 
  254         if (ops == NULL) {
  255                 CERROR("prepare to die: unrecognized cache type for Filter\n");
  256         }
  257         return ops;
  258         FEXIT;
  259 }
  260 
  261 
  262 /*
  263  *  Frobnicate the InterMezzo operations
  264  *    this establishes the link between the InterMezzo file system
  265  *    and the underlying file system used for the cache.
  266  */
  267 
  268 void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_sops, struct super_operations *filter_sops)
  269 {
  270         /* Get ptr to the shared struct snapfs_ops structure. */
  271         struct filter_ops *props = &cache->o_fops;
  272         /* Get ptr to the shared struct cache_ops structure. */
  273         struct cache_ops *caops = &cache->o_caops;
  274 
  275         FENTRY;
  276 
  277         if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
  278                 FEXIT;
  279                 return;
  280         }
  281         cache->o_flags |= FILTER_DID_SUPER_OPS;
  282 
  283         /* Set the cache superblock operations to point to the
  284            superblock operations of the underlying file system.  */
  285         caops->cache_sops = cache_sops;
  286 
  287         /*
  288          * Copy the cache (real fs) superblock ops to the "filter"
  289          * superblock ops as defaults. Some will be changed below
  290          */
  291         memcpy(&props->filter_sops, cache_sops, sizeof(*cache_sops));
  292 
  293         /* 'put_super' unconditionally is that of filter */
  294         if (filter_sops->put_super) { 
  295                 props->filter_sops.put_super = filter_sops->put_super;
  296         }
  297 
  298         if (cache_sops->read_inode) {
  299                 props->filter_sops.read_inode = filter_sops->read_inode;
  300                 FDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
  301                       cache, cache, props->filter_sops.read_inode);
  302         }
  303 
  304         if (cache_sops->remount_fs)
  305                 props->filter_sops.remount_fs = filter_sops->remount_fs;
  306         FEXIT;
  307 }
  308 
  309 
  310 void filter_setup_dir_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
  311 {
  312         struct inode_operations *cache_filter_iops;
  313         struct inode_operations *cache_iops = inode->i_op;
  314         struct file_operations *cache_fops = inode->i_fop;
  315         FENTRY;
  316 
  317         if ( cache->o_flags & FILTER_DID_DIR_OPS ) {
  318                 FEXIT;
  319                 return;
  320         }
  321         cache->o_flags |= FILTER_DID_DIR_OPS;
  322 
  323         /* former ops become cache_ops */
  324         cache->o_caops.cache_dir_iops = cache_iops;
  325         cache->o_caops.cache_dir_fops = cache_fops;
  326         FDEBUG(D_SUPER, "filter at %p, cache iops %p, iops %p\n",
  327                cache, cache_iops, filter_c2udiops(cache));
  328 
  329         /* setup our dir iops: copy and modify */
  330         memcpy(filter_c2udiops(cache), cache_iops, sizeof(*cache_iops));
  331 
  332         /* abbreviate */
  333         cache_filter_iops = filter_c2udiops(cache);
  334 
  335         /* methods that filter if cache filesystem has these ops */
  336         if (cache_iops->lookup && filter_iops->lookup)
  337                 cache_filter_iops->lookup = filter_iops->lookup;
  338         if (cache_iops->create && filter_iops->create)
  339                 cache_filter_iops->create = filter_iops->create;
  340         if (cache_iops->link && filter_iops->link)
  341                 cache_filter_iops->link = filter_iops->link;
  342         if (cache_iops->unlink && filter_iops->unlink)
  343                 cache_filter_iops->unlink = filter_iops->unlink;
  344         if (cache_iops->mkdir && filter_iops->mkdir)
  345                 cache_filter_iops->mkdir = filter_iops->mkdir;
  346         if (cache_iops->rmdir && filter_iops->rmdir)
  347                 cache_filter_iops->rmdir = filter_iops->rmdir;
  348         if (cache_iops->symlink && filter_iops->symlink)
  349                 cache_filter_iops->symlink = filter_iops->symlink;
  350         if (cache_iops->rename && filter_iops->rename)
  351                 cache_filter_iops->rename = filter_iops->rename;
  352         if (cache_iops->mknod && filter_iops->mknod)
  353                 cache_filter_iops->mknod = filter_iops->mknod;
  354         if (cache_iops->permission && filter_iops->permission)
  355                 cache_filter_iops->permission = filter_iops->permission;
  356         if (cache_iops->getattr)
  357                 cache_filter_iops->getattr = filter_iops->getattr;
  358         /* Some filesystems do not use a setattr method of their own
  359            instead relying on inode_setattr/write_inode. We still need to
  360            journal these so we make setattr an unconditional operation. 
  361            XXX: we should probably check for write_inode. SHP
  362         */
  363         /*if (cache_iops->setattr)*/
  364                 cache_filter_iops->setattr = filter_iops->setattr;
  365 #ifdef CONFIG_FS_EXT_ATTR
  366         /* For now we assume that posix acls are handled through extended
  367         * attributes. If this is not the case, we must explicitly trap 
  368         * posix_set_acl. SHP
  369         */
  370         if (cache_iops->set_ext_attr && filter_iops->set_ext_attr)
  371                 cache_filter_iops->set_ext_attr = filter_iops->set_ext_attr;
  372 #endif
  373 
  374 
  375         /* copy dir fops */
  376         memcpy(filter_c2udfops(cache), cache_fops, sizeof(*cache_fops));
  377 
  378         /* unconditional filtering operations */
  379         filter_c2udfops(cache)->ioctl = filter_fops->ioctl;
  380 
  381         FEXIT;
  382 }
  383 
  384 
  385 void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
  386 {
  387         struct inode_operations *pr_iops;
  388         struct inode_operations *cache_iops = inode->i_op;
  389         struct file_operations *cache_fops = inode->i_fop;
  390         FENTRY;
  391 
  392         if ( cache->o_flags & FILTER_DID_FILE_OPS ) {
  393                 FEXIT;
  394                 return;
  395         }
  396         cache->o_flags |= FILTER_DID_FILE_OPS;
  397 
  398         /* steal the old ops */
  399         /* former ops become cache_ops */
  400         cache->o_caops.cache_file_iops = cache_iops;
  401         cache->o_caops.cache_file_fops = cache_fops;
  402         
  403         /* abbreviate */
  404         pr_iops = filter_c2ufiops(cache); 
  405 
  406         /* setup our dir iops: copy and modify */
  407         memcpy(pr_iops, cache_iops, sizeof(*cache_iops));
  408 
  409         /* copy dir fops */
  410         CERROR("*** cache file ops at %p\n", cache_fops);
  411         memcpy(filter_c2uffops(cache), cache_fops, sizeof(*cache_fops));
  412 
  413         /* assign */
  414         /* See comments above in filter_setup_dir_ops. SHP */
  415         /*if (cache_iops->setattr)*/
  416                 pr_iops->setattr = filter_iops->setattr;
  417         if (cache_iops->getattr)
  418                 pr_iops->getattr = filter_iops->getattr;
  419         /* XXX Should this be conditional rmr ? */
  420         pr_iops->permission = filter_iops->permission;
  421 #ifdef CONFIG_FS_EXT_ATTR
  422         /* For now we assume that posix acls are handled through extended
  423         * attributes. If this is not the case, we must explicitly trap and 
  424         * posix_set_acl
  425         */
  426         if (cache_iops->set_ext_attr && filter_iops->set_ext_attr)
  427                 pr_iops->set_ext_attr = filter_iops->set_ext_attr;
  428 #endif
  429 
  430 
  431         /* unconditional filtering operations */
  432         filter_c2uffops(cache)->open = filter_fops->open;
  433         filter_c2uffops(cache)->release = filter_fops->release;
  434         filter_c2uffops(cache)->write = filter_fops->write;
  435         filter_c2uffops(cache)->ioctl = filter_fops->ioctl;
  436 
  437         FEXIT;
  438 }
  439 
  440 /* XXX in 2.3 there are "fast" and "slow" symlink ops for ext2 XXX */
  441 void filter_setup_symlink_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
  442 {
  443         struct inode_operations *pr_iops;
  444         struct inode_operations *cache_iops = inode->i_op;
  445         struct file_operations *cache_fops = inode->i_fop;
  446         FENTRY;
  447 
  448         if ( cache->o_flags & FILTER_DID_SYMLINK_OPS ) {
  449                 FEXIT;
  450                 return;
  451         }
  452         cache->o_flags |= FILTER_DID_SYMLINK_OPS;
  453 
  454         /* steal the old ops */
  455         cache->o_caops.cache_sym_iops = cache_iops;
  456         cache->o_caops.cache_sym_fops = cache_fops;
  457 
  458         /* abbreviate */
  459         pr_iops = filter_c2usiops(cache); 
  460 
  461         /* setup our dir iops: copy and modify */
  462         memcpy(pr_iops, cache_iops, sizeof(*cache_iops));
  463 
  464         /* See comments above in filter_setup_dir_ops. SHP */
  465         /* if (cache_iops->setattr) */
  466                 pr_iops->setattr = filter_iops->setattr;
  467         if (cache_iops->getattr)
  468                 pr_iops->getattr = filter_iops->getattr;
  469 
  470         /* assign */
  471         /* copy fops - careful for symlinks they might be NULL */
  472         if ( cache_fops ) { 
  473                 memcpy(filter_c2usfops(cache), cache_fops, sizeof(*cache_fops));
  474         }
  475 
  476         FEXIT;
  477 }
  478 
  479 void filter_setup_dentry_ops(struct filter_fs *cache,
  480                              struct dentry_operations *cache_dop,
  481                              struct dentry_operations *filter_dop)
  482 {
  483         if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
  484                 FEXIT;
  485                 return;
  486         }
  487         cache->o_flags |= FILTER_DID_DENTRY_OPS;
  488 
  489         cache->o_caops.cache_dentry_ops = cache_dop;
  490         memcpy(&cache->o_fops.filter_dentry_ops,
  491                filter_dop, sizeof(*filter_dop));
  492         
  493         if (cache_dop &&  cache_dop != filter_dop && cache_dop->d_revalidate){
  494                 CERROR("WARNING: filter overriding revalidation!\n");
  495         }
  496         return;
  497 }

Cache object: efe2996ebc874e7f189a5d153d784b06


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


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