Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Super block/filesystem wide operations
0004  *
0005  * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and 
0006  * Michael Callahan <callahan@maths.ox.ac.uk> 
0007  * 
0008  * Rewritten for Linux 2.1.  Peter Braam <braam@cs.cmu.edu>
0009  * Copyright (C) Carnegie Mellon University
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mm.h>
0015 #include <linux/string.h>
0016 #include <linux/stat.h>
0017 #include <linux/errno.h>
0018 #include <linux/unistd.h>
0019 #include <linux/mutex.h>
0020 #include <linux/spinlock.h>
0021 #include <linux/file.h>
0022 #include <linux/vfs.h>
0023 #include <linux/slab.h>
0024 #include <linux/pid_namespace.h>
0025 #include <linux/uaccess.h>
0026 #include <linux/fs.h>
0027 #include <linux/vmalloc.h>
0028 
0029 #include <linux/coda.h>
0030 #include "coda_psdev.h"
0031 #include "coda_linux.h"
0032 #include "coda_cache.h"
0033 
0034 #include "coda_int.h"
0035 
0036 /* VFS super_block ops */
0037 static void coda_evict_inode(struct inode *);
0038 static void coda_put_super(struct super_block *);
0039 static int coda_statfs(struct dentry *dentry, struct kstatfs *buf);
0040 
0041 static struct kmem_cache * coda_inode_cachep;
0042 
0043 static struct inode *coda_alloc_inode(struct super_block *sb)
0044 {
0045     struct coda_inode_info *ei;
0046     ei = alloc_inode_sb(sb, coda_inode_cachep, GFP_KERNEL);
0047     if (!ei)
0048         return NULL;
0049     memset(&ei->c_fid, 0, sizeof(struct CodaFid));
0050     ei->c_flags = 0;
0051     ei->c_uid = GLOBAL_ROOT_UID;
0052     ei->c_cached_perm = 0;
0053     spin_lock_init(&ei->c_lock);
0054     return &ei->vfs_inode;
0055 }
0056 
0057 static void coda_free_inode(struct inode *inode)
0058 {
0059     kmem_cache_free(coda_inode_cachep, ITOC(inode));
0060 }
0061 
0062 static void init_once(void *foo)
0063 {
0064     struct coda_inode_info *ei = (struct coda_inode_info *) foo;
0065 
0066     inode_init_once(&ei->vfs_inode);
0067 }
0068 
0069 int __init coda_init_inodecache(void)
0070 {
0071     coda_inode_cachep = kmem_cache_create("coda_inode_cache",
0072                 sizeof(struct coda_inode_info), 0,
0073                 SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|
0074                 SLAB_ACCOUNT, init_once);
0075     if (coda_inode_cachep == NULL)
0076         return -ENOMEM;
0077     return 0;
0078 }
0079 
0080 void coda_destroy_inodecache(void)
0081 {
0082     /*
0083      * Make sure all delayed rcu free inodes are flushed before we
0084      * destroy cache.
0085      */
0086     rcu_barrier();
0087     kmem_cache_destroy(coda_inode_cachep);
0088 }
0089 
0090 static int coda_remount(struct super_block *sb, int *flags, char *data)
0091 {
0092     sync_filesystem(sb);
0093     *flags |= SB_NOATIME;
0094     return 0;
0095 }
0096 
0097 /* exported operations */
0098 static const struct super_operations coda_super_operations =
0099 {
0100     .alloc_inode    = coda_alloc_inode,
0101     .free_inode = coda_free_inode,
0102     .evict_inode    = coda_evict_inode,
0103     .put_super  = coda_put_super,
0104     .statfs     = coda_statfs,
0105     .remount_fs = coda_remount,
0106 };
0107 
0108 static int get_device_index(struct coda_mount_data *data)
0109 {
0110     struct fd f;
0111     struct inode *inode;
0112     int idx;
0113 
0114     if (data == NULL) {
0115         pr_warn("%s: Bad mount data\n", __func__);
0116         return -1;
0117     }
0118 
0119     if (data->version != CODA_MOUNT_VERSION) {
0120         pr_warn("%s: Bad mount version\n", __func__);
0121         return -1;
0122     }
0123 
0124     f = fdget(data->fd);
0125     if (!f.file)
0126         goto Ebadf;
0127     inode = file_inode(f.file);
0128     if (!S_ISCHR(inode->i_mode) || imajor(inode) != CODA_PSDEV_MAJOR) {
0129         fdput(f);
0130         goto Ebadf;
0131     }
0132 
0133     idx = iminor(inode);
0134     fdput(f);
0135 
0136     if (idx < 0 || idx >= MAX_CODADEVS) {
0137         pr_warn("%s: Bad minor number\n", __func__);
0138         return -1;
0139     }
0140 
0141     return idx;
0142 Ebadf:
0143     pr_warn("%s: Bad file\n", __func__);
0144     return -1;
0145 }
0146 
0147 static int coda_fill_super(struct super_block *sb, void *data, int silent)
0148 {
0149     struct inode *root = NULL;
0150     struct venus_comm *vc;
0151     struct CodaFid fid;
0152     int error;
0153     int idx;
0154 
0155     if (task_active_pid_ns(current) != &init_pid_ns)
0156         return -EINVAL;
0157 
0158     idx = get_device_index((struct coda_mount_data *) data);
0159 
0160     /* Ignore errors in data, for backward compatibility */
0161     if(idx == -1)
0162         idx = 0;
0163     
0164     pr_info("%s: device index: %i\n", __func__,  idx);
0165 
0166     vc = &coda_comms[idx];
0167     mutex_lock(&vc->vc_mutex);
0168 
0169     if (!vc->vc_inuse) {
0170         pr_warn("%s: No pseudo device\n", __func__);
0171         error = -EINVAL;
0172         goto unlock_out;
0173     }
0174 
0175     if (vc->vc_sb) {
0176         pr_warn("%s: Device already mounted\n", __func__);
0177         error = -EBUSY;
0178         goto unlock_out;
0179     }
0180 
0181     vc->vc_sb = sb;
0182     mutex_unlock(&vc->vc_mutex);
0183 
0184     sb->s_fs_info = vc;
0185     sb->s_flags |= SB_NOATIME;
0186     sb->s_blocksize = 4096; /* XXXXX  what do we put here?? */
0187     sb->s_blocksize_bits = 12;
0188     sb->s_magic = CODA_SUPER_MAGIC;
0189     sb->s_op = &coda_super_operations;
0190     sb->s_d_op = &coda_dentry_operations;
0191     sb->s_time_gran = 1;
0192     sb->s_time_min = S64_MIN;
0193     sb->s_time_max = S64_MAX;
0194 
0195     error = super_setup_bdi(sb);
0196     if (error)
0197         goto error;
0198 
0199     /* get root fid from Venus: this needs the root inode */
0200     error = venus_rootfid(sb, &fid);
0201     if ( error ) {
0202         pr_warn("%s: coda_get_rootfid failed with %d\n",
0203             __func__, error);
0204         goto error;
0205     }
0206     pr_info("%s: rootfid is %s\n", __func__, coda_f2s(&fid));
0207     
0208     /* make root inode */
0209         root = coda_cnode_make(&fid, sb);
0210         if (IS_ERR(root)) {
0211         error = PTR_ERR(root);
0212         pr_warn("Failure of coda_cnode_make for root: error %d\n",
0213             error);
0214         goto error;
0215     } 
0216 
0217     pr_info("%s: rootinode is %ld dev %s\n",
0218         __func__, root->i_ino, root->i_sb->s_id);
0219     sb->s_root = d_make_root(root);
0220     if (!sb->s_root) {
0221         error = -EINVAL;
0222         goto error;
0223     }
0224     return 0;
0225 
0226 error:
0227     mutex_lock(&vc->vc_mutex);
0228     vc->vc_sb = NULL;
0229     sb->s_fs_info = NULL;
0230 unlock_out:
0231     mutex_unlock(&vc->vc_mutex);
0232     return error;
0233 }
0234 
0235 static void coda_put_super(struct super_block *sb)
0236 {
0237     struct venus_comm *vcp = coda_vcp(sb);
0238     mutex_lock(&vcp->vc_mutex);
0239     vcp->vc_sb = NULL;
0240     sb->s_fs_info = NULL;
0241     mutex_unlock(&vcp->vc_mutex);
0242     mutex_destroy(&vcp->vc_mutex);
0243 
0244     pr_info("Bye bye.\n");
0245 }
0246 
0247 static void coda_evict_inode(struct inode *inode)
0248 {
0249     truncate_inode_pages_final(&inode->i_data);
0250     clear_inode(inode);
0251     coda_cache_clear_inode(inode);
0252 }
0253 
0254 int coda_getattr(struct user_namespace *mnt_userns, const struct path *path,
0255          struct kstat *stat, u32 request_mask, unsigned int flags)
0256 {
0257     int err = coda_revalidate_inode(d_inode(path->dentry));
0258     if (!err)
0259         generic_fillattr(&init_user_ns, d_inode(path->dentry), stat);
0260     return err;
0261 }
0262 
0263 int coda_setattr(struct user_namespace *mnt_userns, struct dentry *de,
0264          struct iattr *iattr)
0265 {
0266     struct inode *inode = d_inode(de);
0267     struct coda_vattr vattr;
0268     int error;
0269 
0270     memset(&vattr, 0, sizeof(vattr)); 
0271 
0272     inode->i_ctime = current_time(inode);
0273     coda_iattr_to_vattr(iattr, &vattr);
0274     vattr.va_type = C_VNON; /* cannot set type */
0275 
0276     /* Venus is responsible for truncating the container-file!!! */
0277     error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
0278 
0279     if (!error) {
0280             coda_vattr_to_iattr(inode, &vattr); 
0281         coda_cache_clear_inode(inode);
0282     }
0283     return error;
0284 }
0285 
0286 const struct inode_operations coda_file_inode_operations = {
0287     .permission = coda_permission,
0288     .getattr    = coda_getattr,
0289     .setattr    = coda_setattr,
0290 };
0291 
0292 static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
0293 {
0294     int error;
0295     
0296     error = venus_statfs(dentry, buf);
0297 
0298     if (error) {
0299         /* fake something like AFS does */
0300         buf->f_blocks = 9000000;
0301         buf->f_bfree  = 9000000;
0302         buf->f_bavail = 9000000;
0303         buf->f_files  = 9000000;
0304         buf->f_ffree  = 9000000;
0305     }
0306 
0307     /* and fill in the rest */
0308     buf->f_type = CODA_SUPER_MAGIC;
0309     buf->f_bsize = 4096;
0310     buf->f_namelen = CODA_MAXNAMLEN;
0311 
0312     return 0; 
0313 }
0314 
0315 /* init_coda: used by filesystems.c to register coda */
0316 
0317 static struct dentry *coda_mount(struct file_system_type *fs_type,
0318     int flags, const char *dev_name, void *data)
0319 {
0320     return mount_nodev(fs_type, flags, data, coda_fill_super);
0321 }
0322 
0323 struct file_system_type coda_fs_type = {
0324     .owner      = THIS_MODULE,
0325     .name       = "coda",
0326     .mount      = coda_mount,
0327     .kill_sb    = kill_anon_super,
0328     .fs_flags   = FS_BINARY_MOUNTDATA,
0329 };
0330 MODULE_ALIAS_FS("coda");
0331