diff options
Diffstat (limited to 'fs/coda/super.c')
-rw-r--r-- | fs/coda/super.c | 444 |
1 files changed, 101 insertions, 343 deletions
diff --git a/fs/coda/super.c b/fs/coda/super.c index 85a5ccbb3..5410fb50d 100644 --- a/fs/coda/super.c +++ b/fs/coda/super.c @@ -1,13 +1,14 @@ /* * Super block/filesystem wide operations * - * Peter J. Braam <braam@maths.ox.ac.uk>, - * Michael Callahan <callahan@maths.ox.ac.uk> Aug 1996 - * Rewritten for Linux 2.1.57 Peter Braam <braam@cs.cmu.edu> + * Copryright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and + * Michael Callahan <callahan@maths.ox.ac.uk> + * + * Rewritten for Linux 2.1.?? Peter Braam <braam@cs.cmu.edu> + * Copyright (C) Carnegie Mellon University */ #define __NO_VERSION__ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> @@ -32,45 +33,25 @@ #include <linux/coda.h> #include <linux/coda_linux.h> #include <linux/coda_psdev.h> -#include <linux/coda_cnode.h> -#include <linux/coda_namecache.h> +#include <linux/coda_fs_i.h> +#include <linux/coda_cache.h> /* VFS super_block ops */ static struct super_block *coda_read_super(struct super_block *, void *, int); static void coda_read_inode(struct inode *); -static int coda_notify_change(struct inode *inode, struct iattr *attr); +static int coda_notify_change(struct dentry *dentry, struct iattr *attr); static void coda_put_inode(struct inode *); static void coda_delete_inode(struct inode *); static void coda_put_super(struct super_block *); static int coda_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); - /* helper functions */ -void print_vattr( struct coda_vattr *attr ); -static inline struct coda_sb_info *coda_psinode2sb(struct inode *inode); static inline struct vcomm *coda_psinode2vcomm(struct inode *inode); static int coda_get_psdev(void *, struct inode **); -static void coda_vattr_to_iattr(struct inode *, struct coda_vattr *); -static void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *); -int coda_fetch_inode(struct inode *, struct coda_vattr *); - -extern inline struct vcomm *coda_psdev_vcomm(struct inode *inode); -extern int coda_cnode_make(struct inode **inode, ViceFid *fid, - struct super_block *sb); -extern struct cnode *coda_cnode_alloc(void); -extern void coda_cnode_free(struct cnode *); -char *coda_f2s(struct ViceFid *, char *); - -extern int cfsnc_initialized; -extern int coda_debug; -extern int coda_print_entry; - -extern struct inode_operations coda_file_inode_operations; -extern struct inode_operations coda_dir_inode_operations; -extern struct inode_operations coda_ioctl_inode_operations; -extern struct inode_operations coda_symlink_inode_operations; +static struct coda_sb_info *coda_psinode2sbi(struct inode *inode); + /* exported operations */ struct super_operations coda_super_operations = { @@ -91,37 +72,39 @@ struct super_operations coda_super_operations = struct coda_sb_info coda_super_info[MAX_CODADEVS]; - static struct super_block * coda_read_super(struct super_block *sb, void *data, int silent) { struct inode *psdev = 0, *root = 0; struct coda_sb_info *sbi = NULL; - struct vcomm *vc; + struct vcomm *vc = NULL; ViceFid fid; kdev_t dev = sb->s_dev; int error; char str[50]; -ENTRY; + ENTRY; MOD_INC_USE_COUNT; if (coda_get_psdev(data, &psdev)) - goto exit; + goto error; vc = coda_psinode2vcomm(psdev); if ( !vc ) - goto exit; + goto error; + vc->vc_sb = sb; + vc->vc_inuse = 1; - sbi = coda_psinode2sb(psdev); + sbi = coda_psinode2sbi(psdev); if ( !sbi ) - goto exit; - + goto error; sbi->sbi_psdev = psdev; sbi->sbi_vcomm = vc; + INIT_LIST_HEAD(&(sbi->sbi_cchead)); + INIT_LIST_HEAD(&(sbi->sbi_volroothead)); lock_super(sb); sb->u.generic_sbp = sbi; - sb->s_blocksize = 1024; /* XXXXX */ + sb->s_blocksize = 1024; /* XXXXX what do we put here?? */ sb->s_blocksize_bits = 10; sb->s_magic = CODA_SUPER_MAGIC; sb->s_dev = dev; @@ -129,22 +112,22 @@ ENTRY; /* get root fid from Venus: this needs the root inode */ error = venus_rootfid(sb, &fid); - if ( error ) { - unlock_super(sb); printk("coda_read_super: coda_get_rootfid failed with %d\n", - error); - goto exit; + error); + sb->s_dev = 0; + unlock_super(sb); + goto error; } - printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid, str)); + printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid)); + /* make root inode */ error = coda_cnode_make(&root, &fid, sb); if ( error || !root ) { printk("Failure of coda_cnode_make for root: error %d\n", error); - unlock_super(sb); sb->s_dev = 0; - root = NULL; - goto exit; + unlock_super(sb); + goto error; } printk("coda_read_super: rootinode is %ld dev %d\n", @@ -152,22 +135,27 @@ ENTRY; sbi->sbi_root = root; sb->s_root = d_alloc_root(root, NULL); unlock_super(sb); + EXIT; return sb; -EXIT; -exit: +error: +EXIT; MOD_DEC_USE_COUNT; - sbi->sbi_vcomm = NULL; - sbi->sbi_root = NULL; + if (sbi) { + sbi->sbi_vcomm = NULL; + sbi->sbi_root = NULL; + } + if ( vc ) { + vc->vc_sb = NULL; + vc->vc_inuse = 0; + } if (root) { iput(root); - coda_cnode_free(ITOC(root)); } sb->s_dev = 0; return NULL; } - static void coda_put_super(struct super_block *sb) { struct coda_sb_info *sb_info; @@ -177,78 +165,94 @@ static void coda_put_super(struct super_block *sb) lock_super(sb); sb->s_dev = 0; + coda_cache_clear_all(sb); sb_info = coda_sbp(sb); + sb_info->sbi_vcomm->vc_inuse = 0; + sb_info->sbi_vcomm->vc_sb = NULL; + printk("Coda: Bye bye.\n"); memset(sb_info, 0, sizeof(* sb_info)); unlock_super(sb); MOD_DEC_USE_COUNT; -EXIT; + EXIT; } + /* all filling in of inodes postponed until lookup */ static void coda_read_inode(struct inode *inode) { - inode->u.generic_ip = NULL; - /* inode->i_blksize = inode->i_sb->s_blocksize; - inode->i_mode = 0; - inode->i_op = NULL; - NFS_CACHEINV(inode); */ + struct coda_inode_info *cnp; + ENTRY; + cnp = ITOC(inode); + cnp->c_magic = 0; + return; } -static void coda_put_inode(struct inode *inode) +static void coda_put_inode(struct inode *in) { - CDEBUG(D_INODE,"ino: %ld, cnp: %x\n", inode->i_ino, - (int) inode->u.generic_ip); + ENTRY; + + CDEBUG(D_INODE,"ino: %ld, count %d\n", in->i_ino, in->i_count); + + if ( in->i_count == 1 ) + in->i_nlink = 0; + } static void coda_delete_inode(struct inode *inode) { - struct cnode *cnp; + struct coda_inode_info *cnp; struct inode *open_inode; ENTRY; CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n", inode->i_ino, inode->i_count); - if ( inode->i_ino == CTL_INO ) { + cnp = ITOC(inode); + if ( inode->i_ino == CTL_INO || cnp->c_magic != CODA_CNODE_MAGIC ) { clear_inode(inode); return; } - cnp = ITOC(inode); + + if ( coda_fid_is_volroot(&cnp->c_fid) ) + list_del(&cnp->c_volrootlist); open_inode = cnp->c_ovp; if ( open_inode ) { CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n", open_inode->i_ino, open_inode->i_count); cnp->c_ovp = NULL; - cnp->c_odentry.d_inode = NULL; - iput( open_inode ); + iput(open_inode); } + + coda_cache_clear_cnp(cnp); + inode->u.generic_ip = NULL; - coda_cnode_free(cnp); clear_inode(inode); -EXIT; + EXIT; } -static int coda_notify_change(struct inode *inode, struct iattr *iattr) +static int coda_notify_change(struct dentry *de, struct iattr *iattr) { - struct cnode *cnp; + struct inode *inode = de->d_inode; + struct coda_inode_info *cnp; struct coda_vattr vattr; int error; -ENTRY; + + ENTRY; memset(&vattr, 0, sizeof(vattr)); cnp = ITOC(inode); CHECK_CNODE(cnp); coda_iattr_to_vattr(iattr, &vattr); - vattr.va_type = VNON; /* cannot set type */ + vattr.va_type = C_VNON; /* cannot set type */ CDEBUG(D_SUPER, "vattr.va_mode %o\n", vattr.va_mode); error = venus_setattr(inode->i_sb, &cnp->c_fid, &vattr); if ( !error ) { coda_vattr_to_iattr(inode, &vattr); - cfsnc_zapfid(&(cnp->c_fid)); + coda_cache_clear_cnp(cnp); } CDEBUG(D_SUPER, "inode.i_mode %o, error %d\n", inode->i_mode, error); @@ -257,14 +261,12 @@ ENTRY; return error; } -/* we need _something_ */ +/* we need _something_ for this routine. Let's mimic AFS */ static int coda_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { struct statfs tmp; -#define NB_SFS_SIZ 0x895440 - tmp.f_type = CODA_SUPER_MAGIC; tmp.f_bsize = 1024; tmp.f_blocks = 9000000; @@ -284,278 +286,38 @@ struct file_system_type coda_fs_type = { "coda", 0, coda_read_super, NULL }; - - - int init_coda_fs(void) { return register_filesystem(&coda_fs_type); } +/* MODULE stuff is in psdev.c */ -/* utility functions below */ -static void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr) -{ - int inode_type; - /* inode's i_dev, i_flags, i_ino are set by iget - XXX: is this all we need ?? - */ - switch (attr->va_type) { - case VNON: - inode_type = 0; - break; - case VREG: - inode_type = S_IFREG; - break; - case VDIR: - inode_type = S_IFDIR; - break; - case VLNK: - inode_type = S_IFLNK; - break; - default: - inode_type = 0; - } - inode->i_mode |= inode_type; - - if (attr->va_mode != (u_short) -1) - inode->i_mode = attr->va_mode | inode_type; - if (attr->va_uid != -1) - inode->i_uid = (uid_t) attr->va_uid; - if (attr->va_gid != -1) - inode->i_gid = (gid_t) attr->va_gid; - if (attr->va_nlink != -1) - inode->i_nlink = attr->va_nlink; - if (attr->va_size != -1) - inode->i_size = attr->va_size; - /* XXX This needs further study */ - /* - inode->i_blksize = attr->va_blocksize; - inode->i_blocks = attr->va_size/attr->va_blocksize - + (attr->va_size % attr->va_blocksize ? 1 : 0); - */ - if (attr->va_atime.tv_sec != -1) - inode->i_atime = attr->va_atime.tv_sec; - if (attr->va_mtime.tv_sec != -1) - inode->i_mtime = attr->va_mtime.tv_sec; - if (attr->va_ctime.tv_sec != -1) - inode->i_ctime = attr->va_ctime.tv_sec; -} -/* - * BSD sets attributes that need not be modified to -1. - * Linux uses the valid field to indicate what should be - * looked at. The BSD type field needs to be deduced from linux - * mode. - * So we have to do some translations here. - */ - -void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr) -{ - umode_t mode; - unsigned int valid; - - /* clean out */ - vattr->va_mode = (umode_t) -1; - vattr->va_uid = (vuid_t) -1; - vattr->va_gid = (vgid_t) -1; - vattr->va_size = (off_t) -1; - vattr->va_atime.tv_sec = (time_t) -1; - vattr->va_mtime.tv_sec = (time_t) -1; - vattr->va_ctime.tv_sec = (time_t) -1; - vattr->va_atime.tv_nsec = (time_t) -1; - vattr->va_mtime.tv_nsec = (time_t) -1; - vattr->va_ctime.tv_nsec = (time_t) -1; - vattr->va_type = VNON; - vattr->va_fileid = (long)-1; - vattr->va_gen = (long)-1; - vattr->va_bytes = (long)-1; - vattr->va_fsid = (long)-1; - vattr->va_nlink = (short)-1; - vattr->va_blocksize = (long)-1; - vattr->va_rdev = (dev_t)-1; - vattr->va_flags = 0; - - /* determine the type */ - mode = iattr->ia_mode; - if ( S_ISDIR(mode) ) { - vattr->va_type = VDIR; - } else if ( S_ISREG(mode) ) { - vattr->va_type = VREG; - } else if ( S_ISLNK(mode) ) { - vattr->va_type = VLNK; - } else { - /* don't do others */ - vattr->va_type = VNON; - } - - /* set those vattrs that need change */ - valid = iattr->ia_valid; - if ( valid & ATTR_MODE ) { - vattr->va_mode = iattr->ia_mode; - } - if ( valid & ATTR_UID ) { - vattr->va_uid = (vuid_t) iattr->ia_uid; - } - if ( valid & ATTR_GID ) { - vattr->va_gid = (vgid_t) iattr->ia_gid; - } - if ( valid & ATTR_SIZE ) { - vattr->va_size = iattr->ia_size; - } - if ( valid & ATTR_ATIME ) { - vattr->va_atime.tv_sec = iattr->ia_atime; - vattr->va_atime.tv_nsec = 0; - } - if ( valid & ATTR_MTIME ) { - vattr->va_mtime.tv_sec = iattr->ia_mtime; - vattr->va_mtime.tv_nsec = 0; - } - if ( valid & ATTR_CTIME ) { - vattr->va_ctime.tv_sec = iattr->ia_ctime; - vattr->va_ctime.tv_nsec = 0; - } - -} - - -void print_vattr(struct coda_vattr *attr) -{ - char *typestr; - - switch (attr->va_type) { - case VNON: - typestr = "VNON"; - break; - case VREG: - typestr = "VREG"; - break; - case VDIR: - typestr = "VDIR"; - break; - case VBLK: - typestr = "VBLK"; - break; - case VCHR: - typestr = "VCHR"; - break; - case VLNK: - typestr = "VLNK"; - break; - case VSOCK: - typestr = "VSCK"; - break; - case VFIFO: - typestr = "VFFO"; - break; - case VBAD: - typestr = "VBAD"; - break; - default: - typestr = "????"; - break; - } - - - printk("attr: type %s (%o) mode %o uid %d gid %d fsid %d rdev %d\n", - typestr, (int)attr->va_type, (int)attr->va_mode, (int)attr->va_uid, - (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev); - - printk(" fileid %d nlink %d size %d blocksize %d bytes %d\n", - (int)attr->va_fileid, (int)attr->va_nlink, - (int)attr->va_size, - (int)attr->va_blocksize,(int)attr->va_bytes); - printk(" gen %ld flags %ld vaflags %d\n", - attr->va_gen, attr->va_flags, attr->va_vaflags); - printk(" atime sec %d nsec %d\n", - (int)attr->va_atime.tv_sec, (int)attr->va_atime.tv_nsec); - printk(" mtime sec %d nsec %d\n", - (int)attr->va_mtime.tv_sec, (int)attr->va_mtime.tv_nsec); - printk(" ctime sec %d nsec %d\n", - (int)attr->va_ctime.tv_sec, (int)attr->va_ctime.tv_nsec); -} - -/* */ -int coda_fetch_inode (struct inode *inode, struct coda_vattr *attr) -{ - struct cnode *cp; - int ino, error=0; - CDEBUG(D_SUPER, "fetch for ino: %ld\n", inode->i_ino); - - ino = inode->i_ino; - if (!ino) - printk("coda_fetch_inode: inode called with i_ino = 0 (don't worry)\n"); - - inode->i_op = NULL; - inode->i_mode = 0; - - cp = ITOC(inode); - CHECK_CNODE(cp); - - /* root inode */ - if (cp->c_fid.Volume == 0 && - cp->c_fid.Vnode == 0 && - cp->c_fid.Unique == 0) { - inode->i_ino = 1; - inode->i_op = NULL; - return 0; - } - - if (IS_CTL_FID( &(cp->c_fid) )) { - /* This is the special magic control file. - Venus doesn't want - to hear a GETATTR about this! */ - inode->i_op = &coda_ioctl_inode_operations; - return 0; - } - - if ( ! attr ) { - printk("coda_fetch_inode: called with NULL vattr, ino %ld\n", - inode->i_ino); - return -1; /* XXX */ - } - - if (coda_debug & D_SUPER ) print_vattr(attr); - coda_vattr_to_iattr(inode, attr); - - if (S_ISREG(inode->i_mode)) - inode->i_op = &coda_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &coda_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &coda_symlink_inode_operations; - else { - printk ("coda_read_inode: what kind of inode is this? i_mode = %o\n", inode->i_mode); - inode->i_op = NULL; - } - return error; -} - -static inline struct vcomm * -coda_psinode2vcomm(struct inode *inode) +/* helpers */ +static inline struct vcomm *coda_psinode2vcomm(struct inode *inode) { unsigned int minor = MINOR(inode->i_rdev); -CDEBUG(D_PSDEV,"minor %d\n", minor); + CDEBUG(D_PSDEV,"minor %d\n", minor); if ( minor < MAX_CODADEVS ) return &(psdev_vcomm[minor]); else return NULL; } -static inline struct coda_sb_info * -coda_psinode2sb(struct inode *inode) +static struct coda_sb_info *coda_psinode2sbi(struct inode *inode) { unsigned int minor = MINOR(inode->i_rdev); -CDEBUG(D_PSDEV,"minor %d\n", minor); - if ( minor < MAX_CODADEVS ) + CDEBUG(D_PSDEV,"minor %d\n", minor); + if ( (minor >= 0) && (minor < MAX_CODADEVS)) return &(coda_super_info[minor]); else return NULL; } -static int -coda_get_psdev(void *data, struct inode **res_dev) +/* name lookup for psdev passed in by mount */ +static int coda_get_psdev(void *data, struct inode **res_dev) { char **psdev_path; struct inode *psdev = 0; @@ -563,50 +325,46 @@ coda_get_psdev(void *data, struct inode **res_dev) if ( ! data ) { - printk("coda_read_super: no data!\n"); - goto error; - } else { - psdev_path = data; - } + printk("coda_get_psdev: no data!\n"); + return 1; + } + + psdev_path = data; ent = namei((char *) *psdev_path); if (IS_ERR(ent)) { printk("namei error %ld for %d\n", PTR_ERR(ent), (int) psdev_path); - goto error; + return 1; } psdev = ent->d_inode; - if (!S_ISCHR(psdev->i_mode)) { printk("not a character device\n"); - goto error; + return 1; } -CDEBUG(D_PSDEV,"major %d, minor %d, count %d\n", MAJOR(psdev->i_rdev), - MINOR(psdev->i_rdev), psdev->i_count); + CDEBUG(D_PSDEV,"major %d, minor %d, count %d\n", + MAJOR(psdev->i_rdev), + MINOR(psdev->i_rdev), psdev->i_count); if (MAJOR(psdev->i_rdev) != CODA_PSDEV_MAJOR) { printk("device %d not a Coda PSDEV device\n", MAJOR(psdev->i_rdev)); - goto error; + return 1; } if (MINOR(psdev->i_rdev) >= MAX_CODADEVS) { printk("minor %d not an allocated Coda PSDEV\n", psdev->i_rdev); - goto error; + return 1; } if (psdev->i_count < 1) { printk("coda device minor %d not open (i_count = %d)\n", MINOR(psdev->i_rdev), psdev->i_count); - goto error; + return 1; } *res_dev = psdev; - + EXIT; return 0; - -EXIT; -error: - return 1; } |