"Fossies" - the Fresh Open Source Software Archive

Member "linux-coda-6.9/linux2.6/inode.c" (1 Dec 2009, 7940 Bytes) of package /linux/misc/old/linux-coda-6.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Super block/filesystem wide operations
    3  *
    4  * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and 
    5  * Michael Callahan <callahan@maths.ox.ac.uk> 
    6  * 
    7  * Rewritten for Linux 2.1.  Peter Braam <braam@cs.cmu.edu>
    8  * Copyright (C) Carnegie Mellon University
    9  */
   10 
   11 #include <linux/module.h>
   12 #include <linux/smp_lock.h>
   13 #include <linux/file.h>
   14 #include <linux/vfs.h>
   15 #include <linux/fs.h>
   16 #include <linux/namei.h>
   17 
   18 #include <linux/coda.h>
   19 #include <linux/coda_linux.h>
   20 #include <linux/coda_psdev.h>
   21 #include <linux/coda_cache.h>
   22 
   23 #include "compat.h"
   24 
   25 /* VFS super_block ops */
   26 static void coda_clear_inode(struct inode *);
   27 static void coda_put_super(struct super_block *);
   28 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) /* 2.6.18-rc1 */
   29 static int coda_statfs(struct super_block *sb, struct kstatfs *buf);
   30 #else
   31 /* git commit 726c334223180e3c0197cc980a432681370d4baf */
   32 static int coda_statfs(struct dentry *dentry, struct kstatfs *buf);
   33 #endif
   34 
   35 static struct kmem_cache * coda_inode_cachep;
   36 
   37 static struct inode *coda_alloc_inode(struct super_block *sb)
   38 {
   39     struct coda_inode_info *ei;
   40     ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, SLAB_KERNEL);
   41     if (!ei)
   42         return NULL;
   43     memset(&ei->c_fid, 0, sizeof(struct CodaFid));
   44     ei->c_flags = 0;
   45     ei->c_uid = 0;
   46     ei->c_cached_perm = 0;
   47     return &ei->vfs_inode;
   48 }
   49 
   50 static void coda_destroy_inode(struct inode *inode)
   51 {
   52     kmem_cache_free(coda_inode_cachep, ITOC(inode));
   53 }
   54 
   55 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) /* 2.6.24-rc1 */
   56 static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
   57 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) /* 2.6.27-rc1 */
   58 /* git commit 4ba9b9d0ba0a49d91fa6417c7510ee36f48cf957 remove useless ctor */
   59 static void init_once(struct kmem_cache * cachep, void * foo)
   60 #else
   61 /* git commit 51cc50685a4275c6a02653670af9f108a64e01cf drop kmem cache argument from constructor */
   62 static void init_once(void * foo)
   63 #endif
   64 {
   65     struct coda_inode_info *ei = (struct coda_inode_info *) foo;
   66 
   67 #ifdef SLAB_CTOR_VERIFY
   68 /* 50953fe9e00ebbeffa032a565ab2f08312d51a87  slab allocators: Remove SLAB_DEBUG_INITIAL flag */
   69 /* a35afb830f8d71ec211531aeb9a621b09a2efb39  Remove SLAB_CTOR_CONSTRUCTOR */
   70     if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
   71         SLAB_CTOR_CONSTRUCTOR)
   72 #endif
   73         inode_init_once(&ei->vfs_inode);
   74 }
   75 
   76 int coda_init_inodecache(void)
   77 {
   78     coda_inode_cachep = kmem_cache_create("coda_inode_cache",
   79                 sizeof(struct coda_inode_info),
   80                 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
   81                 init_once);
   82     if (coda_inode_cachep == NULL)
   83         return -ENOMEM;
   84     return 0;
   85 }
   86 
   87 void coda_destroy_inodecache(void)
   88 {
   89     kmem_cache_destroy(coda_inode_cachep);
   90 }
   91 
   92 static int coda_remount(struct super_block *sb, int *flags, char *data)
   93 {
   94     *flags |= MS_NOATIME;
   95     return 0;
   96 }
   97 
   98 /* exported operations */
   99 static struct super_operations coda_super_operations =
  100 {
  101     .alloc_inode    = coda_alloc_inode,
  102     .destroy_inode  = coda_destroy_inode,
  103     .clear_inode    = coda_clear_inode,
  104     .put_super  = coda_put_super,
  105     .statfs     = coda_statfs,
  106     .remount_fs = coda_remount,
  107 };
  108 
  109 static int coda_fill_super(struct super_block *sb, void *data, int silent)
  110 {
  111         struct inode *root = NULL; 
  112     struct venus_comm *vc = (struct venus_comm *)data;
  113     struct CodaFid fid;
  114         int error;
  115 
  116     if (!vc->vc_inuse) {
  117         printk("coda: CFS device not open, venus dead?\n");
  118         return -EINVAL;
  119     }
  120 
  121     if ( vc->vc_sb ) {
  122         printk("coda: device already in use\n");
  123         return -EBUSY;
  124     }
  125 
  126     vc->vc_sb = sb;
  127 
  128     sb->s_fs_info = vc;
  129     sb->s_flags |= MS_NOATIME;
  130     sb->s_blocksize = 1024; /* XXXXX  what do we put here?? */
  131     sb->s_blocksize_bits = 10;
  132     sb->s_magic = CODA_SUPER_MAGIC;
  133     sb->s_op = &coda_super_operations;
  134 
  135     /* get root fid from Venus: this needs the root inode */
  136     error = venus_rootfid(sb, &fid);
  137     if ( error ) {
  138             printk("coda_read_super: coda_get_rootfid failed with %d\n",
  139                error);
  140         goto error;
  141     }
  142     printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
  143     
  144     /* make root inode */
  145         error = coda_cnode_make(&root, &fid, sb);
  146         if ( error || !root ) {
  147         printk("Failure of coda_cnode_make for root: error %d\n", error);
  148         goto error;
  149     } 
  150 
  151     printk("coda_read_super: rootinode is %ld dev %s\n", 
  152            root->i_ino, root->i_sb->s_id);
  153     sb->s_root = d_alloc_root(root);
  154     if (!sb->s_root)
  155         goto error;
  156         return 0;
  157 
  158  error:
  159     if (root)
  160                 iput(root);
  161     if(vc)
  162         vc->vc_sb = NULL;       
  163 
  164         return -EINVAL;
  165 }
  166 
  167 static void coda_put_super(struct super_block *sb)
  168 {
  169     coda_sbp(sb)->vc_sb = NULL;
  170     sb->s_fs_info = NULL;
  171     printk("Coda: Bye bye.\n");
  172 }
  173 
  174 static void coda_clear_inode(struct inode *inode)
  175 {
  176     coda_cache_clear_inode(inode);
  177 }
  178 
  179 int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  180 {
  181     int err = coda_revalidate_inode(dentry);
  182     if (!err)
  183         generic_fillattr(dentry->d_inode, stat);
  184     return err;
  185 }
  186 
  187 int coda_setattr(struct dentry *de, struct iattr *iattr)
  188 {
  189     struct inode *inode = de->d_inode;
  190     struct coda_vattr vattr;
  191     int error;
  192 
  193     lock_kernel();
  194     
  195     memset(&vattr, 0, sizeof(vattr)); 
  196 
  197     inode->i_ctime = CURRENT_TIME_SEC;
  198     coda_iattr_to_vattr(iattr, &vattr);
  199     vattr.va_type = C_VNON; /* cannot set type */
  200 
  201     /* Venus is responsible for truncating the container-file!!! */
  202     error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
  203 
  204     if ( !error ) {
  205             coda_vattr_to_iattr(inode, &vattr); 
  206         coda_cache_clear_inode(inode);
  207     }
  208 
  209     unlock_kernel();
  210 
  211     return error;
  212 }
  213 
  214 struct inode_operations coda_file_inode_operations = {
  215     .permission = coda_permission,
  216     .getattr    = coda_getattr,
  217     .setattr    = coda_setattr,
  218 };
  219 
  220 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) /* 2.6.18-rc1 */
  221 static int coda_statfs(struct super_block *sb, struct kstatfs *buf)
  222 {
  223 #else
  224 /* git commit 726c334223180e3c0197cc980a432681370d4baf */
  225 static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
  226 {
  227     struct super_block *sb = dentry->d_sb;
  228 #endif
  229     int error;
  230 
  231     lock_kernel();
  232 
  233     error = venus_statfs(sb, buf);
  234 
  235     unlock_kernel();
  236 
  237     if (error) {
  238         /* fake something like AFS does */
  239         buf->f_blocks = 9000000;
  240         buf->f_bfree  = 9000000;
  241         buf->f_bavail = 9000000;
  242         buf->f_files  = 9000000;
  243         buf->f_ffree  = 9000000;
  244     }
  245 
  246     /* and fill in the rest */
  247     buf->f_type = CODA_SUPER_MAGIC;
  248     buf->f_bsize = 1024;
  249     buf->f_namelen = CODA_MAXNAMLEN;
  250 
  251     return 0;
  252 }
  253 
  254 static struct venus_comm *get_device(struct inode *inode)
  255 {
  256     int idx;
  257 
  258     if (!inode)
  259         return NULL;
  260 
  261     if (!S_ISCHR(inode->i_mode) || imajor(inode) != CODA_PSDEV_MAJOR) {
  262         printk("coda_get_sb: Bad file\n");
  263         return NULL;
  264     }
  265 
  266     idx = iminor(inode);
  267     if (idx < 0 || idx >= MAX_CODADEVS) {
  268         printk("coda_get_sb: Bad minor number\n");
  269         return NULL;
  270     }
  271 
  272     return &coda_comms[idx];
  273 }
  274 
  275 /* init_coda: used by filesystems.c to register coda */
  276 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) /* 2.6.18-rc1 */
  277 static struct super_block *coda_get_sb(struct file_system_type *fs_type,
  278     int flags, const char *dev_name, void *data)
  279 #else
  280 /* git commit 454e2398be9b9fa30433fccc548db34d19aa9958 add vfsmount to get_sb */
  281 static int coda_get_sb(struct file_system_type *fs_type, int flags,
  282                const char *dev_name, void *data, struct vfsmount *mnt)
  283 #endif
  284 {
  285     struct coda_mount_data *md;
  286     struct nameidata nd;
  287     struct file *file;
  288     struct venus_comm *vc = NULL;
  289     int err;
  290 
  291     err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
  292     if (!err) {
  293         vc = get_device(nd_path_dentry(nd)->d_inode);
  294         nd_path_release(&nd);
  295     }
  296     if (vc)
  297         goto mount;
  298 
  299     md = (struct coda_mount_data *)data;
  300     if (!md || md->version != CODA_MOUNT_VERSION) {
  301         printk("coda: Bad mount data\n");
  302         goto mount;
  303     }
  304 
  305     file = fget(md->fd);
  306     if (file) {
  307         vc = get_device(file->f_dentry->d_inode);
  308         fput(file);
  309     }
  310 
  311 mount:
  312     if (!vc)
  313         vc = &coda_comms[0];
  314 
  315     return get_sb_nodev(fs_type, flags, vc, coda_fill_super, mnt);
  316 }
  317 
  318 struct file_system_type coda_fs_type = {
  319     .owner      = THIS_MODULE,
  320     .name       = "coda",
  321     .get_sb     = coda_get_sb,
  322     .kill_sb    = kill_anon_super,
  323     .fs_flags   = FS_BINARY_MOUNTDATA,
  324 };
  325