diff options
Diffstat (limited to 'fs/coda')
-rw-r--r-- | fs/coda/Makefile | 2 | ||||
-rw-r--r-- | fs/coda/cache.c | 196 | ||||
-rw-r--r-- | fs/coda/cnode.c | 59 | ||||
-rw-r--r-- | fs/coda/coda_linux.c | 23 | ||||
-rw-r--r-- | fs/coda/dir.c | 104 | ||||
-rw-r--r-- | fs/coda/file.c | 49 | ||||
-rw-r--r-- | fs/coda/inode.c (renamed from fs/coda/super.c) | 35 | ||||
-rw-r--r-- | fs/coda/psdev.c | 4 | ||||
-rw-r--r-- | fs/coda/upcall.c | 55 |
9 files changed, 315 insertions, 212 deletions
diff --git a/fs/coda/Makefile b/fs/coda/Makefile index 0a4140745..1f2d0a94c 100644 --- a/fs/coda/Makefile +++ b/fs/coda/Makefile @@ -3,7 +3,7 @@ # O_TARGET := coda.o -O_OBJS := psdev.o cache.o cnode.o super.o dir.o file.o upcall.o coda_linux.o\ +O_OBJS := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o coda_linux.o\ symlink.o pioctl.o sysctl.o M_OBJS := $(O_TARGET) diff --git a/fs/coda/cache.c b/fs/coda/cache.c index 7673bfbdd..cdf586507 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c @@ -24,16 +24,22 @@ #include <linux/coda_fs_i.h> #include <linux/coda_cache.h> -/* Keep various stats */ -struct cfsnc_statistics cfsnc_stat; +static void coda_ccinsert(struct coda_cache *el, struct super_block *sb); +static void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cii); +static void coda_ccremove(struct coda_cache *el); +static void coda_cnremove(struct coda_cache *el); +static void coda_cache_create(struct inode *inode, int mask); +static struct coda_cache * coda_cache_find(struct inode *inode); -/* we need to call INIT_LIST_HEAD on cnp->c_cnhead and sbi->sbi_cchead */ +/* Keep various stats */ +struct cfsnc_statistics cfsnc_stat; -void coda_ccinsert(struct coda_cache *el, struct super_block *sb) +/* insert a acl-cache entry in sb list */ +static void coda_ccinsert(struct coda_cache *el, struct super_block *sb) { struct coda_sb_info *sbi = coda_sbp(sb); -ENTRY; + ENTRY; if ( !sbi || !el) { printk("coda_ccinsert: NULL sbi or el!\n"); return ; @@ -42,17 +48,19 @@ ENTRY; list_add(&el->cc_cclist, &sbi->sbi_cchead); } -void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cnp) +/* insert a acl-cache entry in the inode list */ +static void coda_cninsert(struct coda_cache *el, struct coda_inode_info *cii) { -ENTRY; - if ( !cnp || !el) { - printk("coda_cninsert: NULL cnp or el!\n"); + ENTRY; + if ( !cii || !el) { + printk("coda_cninsert: NULL cii or el!\n"); return ; } - list_add(&el->cc_cnlist, &cnp->c_cnhead); + list_add(&el->cc_cnlist, &cii->c_cnhead); } -void coda_ccremove(struct coda_cache *el) +/* remove a cache entry from the superblock list */ +static void coda_ccremove(struct coda_cache *el) { ENTRY; if (el->cc_cclist.next && el->cc_cclist.prev) @@ -61,7 +69,8 @@ void coda_ccremove(struct coda_cache *el) printk("coda_cnremove: trying to remove 0 entry!"); } -void coda_cnremove(struct coda_cache *el) +/* remove a cache entry from the inode's list */ +static void coda_cnremove(struct coda_cache *el) { ENTRY; if (el->cc_cnlist.next && el->cc_cnlist.prev) @@ -70,10 +79,10 @@ void coda_cnremove(struct coda_cache *el) printk("coda_cnremove: trying to remove 0 entry!"); } - -void coda_cache_create(struct inode *inode, int mask) +/* create a new cache entry and enlist it */ +static void coda_cache_create(struct inode *inode, int mask) { - struct coda_inode_info *cnp = ITOC(inode); + struct coda_inode_info *cii = ITOC(inode); struct super_block *sb = inode->i_sb; struct coda_cache *cc = NULL; ENTRY; @@ -85,17 +94,19 @@ void coda_cache_create(struct inode *inode, int mask) } coda_load_creds(&cc->cc_cred); cc->cc_mask = mask; - coda_cninsert(cc, cnp); + coda_cninsert(cc, cii); coda_ccinsert(cc, sb); } -struct coda_cache * coda_cache_find(struct inode *inode) +/* see if there is a match for the current + credentials already */ +static struct coda_cache * coda_cache_find(struct inode *inode) { - struct coda_inode_info *cnp = ITOC(inode); + struct coda_inode_info *cii = ITOC(inode); struct list_head *lh, *le; struct coda_cache *cc = NULL; - le = lh = &cnp->c_cnhead; + le = lh = &cii->c_cnhead; while( (le = le->next ) != lh ) { /* compare name and creds */ cc = list_entry(le, struct coda_cache, cc_cnlist); @@ -107,6 +118,7 @@ struct coda_cache * coda_cache_find(struct inode *inode) return NULL; } +/* create or extend an acl cache hit */ void coda_cache_enter(struct inode *inode, int mask) { struct coda_cache *cc; @@ -120,17 +132,21 @@ void coda_cache_enter(struct inode *inode, int mask) } } -void coda_cache_clear_cnp(struct coda_inode_info *cnp) +/* remove all cached acl matches from an inode */ +void coda_cache_clear_inode(struct inode *inode) { struct list_head *lh, *le; + struct coda_inode_info *cii; struct coda_cache *cc; + ENTRY; - if ( !cnp ) { - printk("coda_cache_cnp_clear: NULL cnode\n"); + if ( !inode ) { + CDEBUG(D_CACHE, "coda_cache_clear_inode: NULL inode\n"); return; } + cii = ITOC(inode); - lh = le = &cnp->c_cnhead; + lh = le = &cii->c_cnhead; while ( (le = le->next ) != lh ) { cc = list_entry(le, struct coda_cache, cc_cnlist); coda_cnremove(cc); @@ -139,6 +155,7 @@ void coda_cache_clear_cnp(struct coda_inode_info *cnp) } } +/* remove all acl caches */ void coda_cache_clear_all(struct super_block *sb) { struct list_head *lh, *le; @@ -150,6 +167,9 @@ void coda_cache_clear_all(struct super_block *sb) return; } + if ( list_empty(&sbi->sbi_cchead) ) + return; + lh = le = &sbi->sbi_cchead; while ( (le = le->next ) != lh ) { cc = list_entry(le, struct coda_cache, cc_cclist); @@ -159,6 +179,7 @@ void coda_cache_clear_all(struct super_block *sb) } } +/* remove all acl caches for a principal */ void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred) { struct list_head *lh, *le; @@ -170,6 +191,9 @@ void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred) return; } + if (list_empty(&sbi->sbi_cchead)) + return; + lh = le = &sbi->sbi_cchead; while ( (le = le->next ) != lh ) { cc = list_entry(le, struct coda_cache, cc_cclist); @@ -180,15 +204,17 @@ void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred) } } } - + +/* check if the mask has been matched against the acl + already */ int coda_cache_check(struct inode *inode, int mask) { - struct coda_inode_info *cnp = ITOC(inode); + struct coda_inode_info *cii = ITOC(inode); struct list_head *lh, *le; struct coda_cache *cc = NULL; - le = lh = &cnp->c_cnhead; + le = lh = &cii->c_cnhead; while( (le = le->next ) != lh ) { /* compare name and creds */ cc = list_entry(le, struct coda_cache, cc_cnlist); @@ -204,110 +230,70 @@ int coda_cache_check(struct inode *inode, int mask) } -/* DENTRY related stuff */ +/* DCACHE & ZAPPING related stuff */ -/* when the dentry count falls to 0 this is called. If Venus has - asked for it to be flushed, we take it out of the dentry hash - table with d_drop */ - -static void coda_flag_children(struct dentry *parent) +/* the following routines set flags in the inodes. They are + detected by: + - a dentry method: coda_dentry_revalidate (for lookups) + if the flag is C_PURGE + - an inode method coda_revalidate (for attributes) if the + flag is C_ATTR +*/ +static void coda_flag_children(struct dentry *parent, int flag) { struct list_head *child; - struct coda_inode_info *cnp; struct dentry *de; child = parent->d_subdirs.next; while ( child != &parent->d_subdirs ) { de = list_entry(child, struct dentry, d_child); - cnp = ITOC(de->d_inode); - if (cnp) - cnp->c_flags |= C_ZAPFID; - CDEBUG(D_CACHE, "ZAPFID for %s\n", coda_f2s(&cnp->c_fid)); - + coda_flag_inode(de->d_inode, flag); + CDEBUG(D_CACHE, "%d for %*s/%*s\n", flag, + de->d_name.len, de->d_name.name, + de->d_parent->d_name.len, de->d_parent->d_name.name); child = child->next; + if ( !de->d_inode ) + d_drop(de); } return; } -/* flag dentry and possibly children of a dentry with C_ZAPFID */ -void coda_dentry_delete(struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - struct coda_inode_info *cnp = NULL; - ENTRY; - if (inode) { - cnp = ITOC(inode); - if ( cnp ) - CHECK_CNODE(cnp); - } else { - CDEBUG(D_CACHE, "No inode for dentry_delete!\n"); - return; - } - - - if ( !cnp ) { - printk("No cnode for dentry_delete!\n"); - return; - } - - if ( cnp->c_flags & (C_ZAPFID | C_ZAPDIR) ) - d_drop(dentry); - if ( (cnp->c_flags & C_ZAPDIR) && S_ISDIR(inode->i_mode) ) { - coda_flag_children(dentry); - } - return; -} - -static void coda_zap_cnode(struct coda_inode_info *cnp, int flags) +void coda_flag_alias_children(struct inode *inode, int flag) { - cnp->c_flags |= flags; - coda_cache_clear_cnp(cnp); + struct list_head *alias; + struct dentry *alias_de; + + if ( !inode ) + return; + alias = inode->i_dentry.next; + while ( alias != &inode->i_dentry ) { + alias_de = list_entry(alias, struct dentry, d_alias); + if ( !alias_de ) { + printk("Corrupt alias list for %*s\n", + alias_de->d_name.len, alias_de->d_name.name); + return; + } + coda_flag_children(alias_de, flag); + alias= alias->next; + } } - - -/* the dache will notice the flags and drop entries (possibly with - children) the moment they are no longer in use */ -void coda_zapfid(struct ViceFid *fid, struct super_block *sb, int flag) +void coda_flag_inode(struct inode *inode, int flag) { - struct inode *inode = NULL; - struct coda_inode_info *cnp; + struct coda_inode_info *cii; - ENTRY; - - if ( !sb ) { - printk("coda_zapfid: no sb!\n"); + if ( !inode ) { + CDEBUG(D_CACHE, " no inode!\n"); return; } + cii = ITOC(inode); + cii->c_flags |= flag; +} - if ( !fid ) { - printk("coda_zapfid: no fid!\n"); - return; - } - if ( coda_fid_is_volroot(fid) ) { - struct list_head *lh, *le; - struct coda_sb_info *sbi = coda_sbp(sb); - le = lh = &sbi->sbi_volroothead; - while ( (le = le->next) != lh ) { - cnp = list_entry(le, struct coda_inode_info, c_volrootlist); - if ( cnp->c_fid.Volume == fid->Volume) - coda_zap_cnode(cnp, flag); - } - return; - } - inode = coda_fid_to_inode(fid, sb); - if ( !inode ) { - CDEBUG(D_CACHE, "coda_zapfid: no inode!\n"); - return; - } - cnp = ITOC(inode); - coda_zap_cnode(cnp, flag); -} - int cfsnc_nc_info(char *buffer, char **start, off_t offset, int length, int dummy) diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 67133f275..aa67a22e4 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -15,8 +15,6 @@ extern int coda_print_entry; /* cnode.c */ - - static void coda_fill_inode (struct inode *inode, struct coda_vattr *attr) { CDEBUG(D_SUPER, "ino: %ld\n", inode->i_ino); @@ -56,8 +54,8 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) ENTRY; /* - * We get inode numbers from Venus -- see venus source - */ + * We get inode numbers from Venus -- see venus source + */ error = venus_getattr(sb, fid, &attr); if ( error ) { @@ -79,7 +77,7 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) memset(cnp, 0, (int) sizeof(struct coda_inode_info)); cnp->c_fid = *fid; cnp->c_magic = CODA_CNODE_MAGIC; - cnp->c_flags = C_VATTR; + cnp->c_flags = 0; cnp->c_vnode = *inode; INIT_LIST_HEAD(&(cnp->c_cnhead)); INIT_LIST_HEAD(&(cnp->c_volrootlist)); @@ -111,20 +109,51 @@ inline int coda_fideq(ViceFid *fid1, ViceFid *fid2) -/* convert a fid to an inode. Avoids having a hash table - such as present in the Mach minicache */ +/* convert a fid to an inode. Mostly we can compute + the inode number from the FID, but not for volume + mount points: those are in a list */ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) { ino_t nr; struct inode *inode; struct coda_inode_info *cnp; -ENTRY; + ENTRY; CDEBUG(D_INODE, "%s\n", coda_f2s(fid)); + if ( !sb ) { + printk("coda_fid_to_inode: no sb!\n"); + return NULL; + } + + if ( !fid ) { + printk("coda_fid_to_inode: no fid!\n"); + return NULL; + } + + + if ( coda_fid_is_volroot(fid) ) { + struct coda_inode_info *cii; + struct list_head *lh, *le; + struct coda_sb_info *sbi = coda_sbp(sb); + le = lh = &sbi->sbi_volroothead; + + while ( (le = le->next) != lh ) { + cii = list_entry(le, struct coda_inode_info, + c_volrootlist); + if ( cii->c_fid.Volume == fid->Volume) { + inode = cii->c_vnode; + CDEBUG(D_INODE, "volume root, found %ld\n", cii->c_vnode->i_ino); + return cii->c_vnode; + } + + } + return NULL; + } + + /* fid is not volume root, hence ino is computable */ nr = coda_f2i(fid); inode = iget(sb, nr); - if ( !inode ) { printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n", sb, nr); @@ -133,19 +162,25 @@ ENTRY; /* check if this inode is linked to a cnode */ cnp = ITOC(inode); - if ( cnp->c_magic != CODA_CNODE_MAGIC ) { + CDEBUG(D_INODE, "uninitialized inode. Return.\n"); iput(inode); return NULL; } - /* make sure fid is the one we want */ - if ( !coda_fideq(fid, &(cnp->c_fid)) ) { + /* make sure fid is the one we want; + unfortunately Venus will shamelessly send us mount-symlinks. + These have the same inode as the root of the volume they + mount, but the fid will be wrong. + */ + if ( !coda_fideq(fid, &(cnp->c_fid)) && + !coda_fid_is_volroot(&(cnp->c_fid))) { printk("coda_fid2inode: bad cnode! Tell Peter.\n"); iput(inode); return NULL; } + CDEBUG(D_INODE, "found %ld\n", inode->i_ino); iput(inode); return inode; } diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c index e968f3add..4fe096df9 100644 --- a/fs/coda/coda_linux.c +++ b/fs/coda/coda_linux.c @@ -32,14 +32,15 @@ int coda_access_cache = 1; /* caller must allocate 36 byte string ! */ char * coda_f2s(ViceFid *f) { - static char s[50]; + static char s[60]; if ( f ) { - sprintf(s, "(%10lx,%10lx,%10lx)", + sprintf(s, "(%-#lx,%-#lx,%-#lx)", f->Volume, f->Vnode, f->Unique); } return s; } +/* recognize special .CONTROL name */ int coda_iscontrol(const char *name, size_t length) { if ((CFS_CONTROLLEN == length) && @@ -48,16 +49,23 @@ int coda_iscontrol(const char *name, size_t length) return 0; } +/* recognize /coda inode */ int coda_isroot(struct inode *i) { if ( i->i_sb->s_root->d_inode == i ) { - return 1; + return 1; } else { - return 0; + return 0; } } - +/* is this a volume root FID */ +int coda_fid_is_volroot(struct ViceFid *fid) +{ + return ( (fid->Vnode == 1) && (fid->Unique == 1 ) ); +} + +/* put the current process credentials in the cred */ void coda_load_creds(struct coda_cred *cred) { cred->cr_uid = (vuid_t) current->uid; @@ -98,11 +106,6 @@ unsigned short coda_flags_to_cflags(unsigned short flags) } -int coda_fid_is_volroot(struct ViceFid *fid) -{ - return ( (fid->Vnode == 1) && (fid->Unique == 1 ) ); -} - /* utility functions below */ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr) { diff --git a/fs/coda/dir.c b/fs/coda/dir.c index dd20499dc..8fed69242 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -40,17 +40,21 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, /* dir file-ops */ static int coda_readdir(struct file *file, void *dirent, filldir_t filldir); +/* dentry ops */ +int coda_dentry_revalidate(struct dentry *de); + /* support routines */ static int coda_venus_readdir(struct file *filp, void *dirent, filldir_t filldir); int coda_fsync(struct file *, struct dentry *dentry); +static int coda_refresh_inode(struct dentry *dentry); struct dentry_operations coda_dentry_operations = { - NULL, /* revalidate */ + coda_dentry_revalidate, /* revalidate */ NULL, /* hash */ NULL, - coda_dentry_delete + NULL, }; struct inode_operations coda_dir_inode_operations = @@ -74,7 +78,7 @@ struct inode_operations coda_dir_inode_operations = coda_permission, /* permission */ NULL, /* smap */ NULL, /* update page */ - NULL /* revalidate */ + coda_revalidate_inode /* revalidate */ }; struct file_operations coda_dir_operations = { @@ -117,7 +121,6 @@ static int coda_lookup(struct inode *dir, struct dentry *entry) } dircnp = ITOC(dir); - CHECK_CNODE(dircnp); if ( length > CFS_MAXNAMLEN ) { printk("name too long: lookup, %s (%*s)\n", @@ -141,9 +144,13 @@ static int coda_lookup(struct inode *dir, struct dentry *entry) (const char *)name, length, &type, &resfid); res_inode = NULL; - if (!error || (error == -CFS_NOCACHE) ) { - if (error == -CFS_NOCACHE) + if (!error) { + if (type & CFS_NOCACHE) { + type &= (~CFS_NOCACHE); + CDEBUG(D_INODE, "dropme set for %s\n", + coda_f2s(&resfid)); dropme = 1; + } error = coda_cnode_make(&res_inode, &resfid, dir->i_sb); if (error) return -error; @@ -152,7 +159,7 @@ static int coda_lookup(struct inode *dir, struct dentry *entry) coda_f2s(&dircnp->c_fid), length, name, error); return error; } - CDEBUG(D_INODE, "lookup: %s is (%s) type %d result %d, dropme %d\n", + CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n", name, coda_f2s(&resfid), type, error, dropme); exit: @@ -228,7 +235,6 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode) CHECK_CNODE(dircnp); if ( length > CFS_MAXNAMLEN ) { - char str[50]; printk("name too long: create, %s(%s)\n", coda_f2s(&dircnp->c_fid), name); return -ENAMETOOLONG; @@ -238,7 +244,6 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode) 0, mode, &newfid, &attrs); if ( error ) { - char str[50]; CDEBUG(D_INODE, "create: %s, result %d\n", coda_f2s(&newfid), error); d_drop(de); @@ -321,7 +326,6 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, const char * name = de->d_name.name; int len = de->d_name.len; struct coda_inode_info *dir_cnp, *cnp; - char str[50]; int error; ENTRY; @@ -408,7 +412,6 @@ int coda_unlink(struct inode *dir, struct dentry *de) int error; const char *name = de->d_name.name; int len = de->d_name.len; - char fidstr[50]; ENTRY; @@ -781,3 +784,82 @@ exit: CODA_FREE(buff, size); return error; } + +int coda_dentry_revalidate(struct dentry *de) +{ + int valid = 1; + struct inode *inode = de->d_inode; + struct coda_inode_info *cii; + ENTRY; + + if (inode) { + if (is_bad_inode(inode)) + return 0; + cii = ITOC(de->d_inode); + if (cii->c_flags & C_PURGE) + valid = 0; + } + return valid || coda_isroot(de->d_inode); +} + + +static int coda_refresh_inode(struct dentry *dentry) +{ + struct coda_vattr attr; + int error; + int old_mode; + ino_t old_ino; + struct inode *inode = dentry->d_inode; + struct coda_inode_info *cii = ITOC(inode); + + ENTRY; + error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); + if ( error ) { + make_bad_inode(inode); + return -EIO; + } + + /* this baby may be lost if: + - it's type changed + - it's ino changed + */ + old_mode = inode->i_mode; + old_ino = inode->i_ino; + coda_vattr_to_iattr(inode, &attr); + + if ((inode->i_ino != old_ino) || + ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT))) { + make_bad_inode(inode); + inode->i_mode = old_mode; + return -EIO; + } + + cii->c_flags &= ~C_VATTR; + return 0; +} + + +/* + * This is called when we want to check if the inode has + * changed on the server. Coda makes this easy since the + * cache manager Venus issues a downcall to the kernel when this + * happens + */ + +int coda_revalidate_inode(struct dentry *dentry) +{ + int error = 0; + struct coda_inode_info *cii = ITOC(dentry->d_inode); + + ENTRY; + CDEBUG(D_INODE, "revalidating: %*s/%*s\n", + dentry->d_name.len, dentry->d_name.name, + dentry->d_parent->d_name.len, dentry->d_parent->d_name.name); + + if ( cii->c_flags & (C_VATTR | C_PURGE )) { + error = coda_refresh_inode(dentry); + } + + return error; +} + diff --git a/fs/coda/file.c b/fs/coda/file.c index b33680cc3..ae1dd9776 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -30,7 +30,7 @@ static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *o static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off); static int coda_file_mmap(struct file * file, struct vm_area_struct * vma); -/* exported from this file */ +/* also exported from this file (used for dirs) */ int coda_fsync(struct file *, struct dentry *dentry); struct inode_operations coda_file_inode_operations = { @@ -43,7 +43,7 @@ struct inode_operations coda_file_inode_operations = { NULL, /* mkdir */ NULL, /* rmdir */ NULL, /* mknod */ - NULL, /* rename */ + NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ coda_readpage, /* readpage */ @@ -53,7 +53,7 @@ struct inode_operations coda_file_inode_operations = { coda_permission, /* permission */ NULL, /* smap */ NULL, /* update page */ - NULL /* revalidate */ + coda_revalidate_inode /* revalidate */ }; struct file_operations coda_file_operations = { @@ -74,41 +74,47 @@ struct file_operations coda_file_operations = { }; /* File file operations */ -static int coda_readpage(struct file * file, struct page * page) +static int coda_readpage(struct file * coda_file, struct page * page) { - struct dentry *de = file->f_dentry; - struct inode *inode = de->d_inode; + struct dentry *de = coda_file->f_dentry; + struct inode *coda_inode = de->d_inode; struct dentry cont_dentry; - struct inode *cont_inode; - struct coda_inode_info *cnp; + struct file cont_file; + struct coda_inode_info *cii; ENTRY; - cnp = ITOC(inode); - CHECK_CNODE(cnp); + cii = ITOC(coda_inode); - if ( ! cnp->c_ovp ) { - printk("coda_readpage: no open inode for ino %ld\n", inode->i_ino); + if ( ! cii->c_ovp ) { + printk("coda_readpage: no open inode for ino %ld, %s\n", + coda_inode->i_ino, de->d_name.name); return -ENXIO; } + + coda_prepare_openfile(coda_inode, coda_file, cii->c_ovp, + &cont_file, &cont_dentry); - cont_inode = cnp->c_ovp; - cont_dentry.d_inode = cont_inode; - - CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", inode->i_ino, cont_inode->i_ino, page->offset); + CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", + coda_inode->i_ino, cii->c_ovp->i_ino, page->offset); - generic_readpage(&cont_dentry, page); + generic_readpage(&cont_file, page); EXIT; return 0; } static int coda_file_mmap(struct file * file, struct vm_area_struct * vma) { - struct coda_inode_info *cnp; - cnp = ITOC(file->f_dentry->d_inode); - cnp->c_mmcount++; + struct coda_inode_info *cii; + int res; + + ENTRY; + cii = ITOC(file->f_dentry->d_inode); + cii->c_mmcount++; - return generic_file_mmap(file, vma); + res =generic_file_mmap(file, vma); + EXIT; + return res; } static ssize_t coda_file_read(struct file *coda_file, char *buff, @@ -120,7 +126,6 @@ static ssize_t coda_file_read(struct file *coda_file, char *buff, struct file cont_file; struct dentry cont_dentry; int result = 0; - ENTRY; cnp = ITOC(coda_inode); diff --git a/fs/coda/super.c b/fs/coda/inode.c index 5410fb50d..96d07e265 100644 --- a/fs/coda/super.c +++ b/fs/coda/inode.c @@ -4,7 +4,7 @@ * 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> + * Rewritten for Linux 2.1. Peter Braam <braam@cs.cmu.edu> * Copyright (C) Carnegie Mellon University */ @@ -81,7 +81,6 @@ static struct super_block * coda_read_super(struct super_block *sb, ViceFid fid; kdev_t dev = sb->s_dev; int error; - char str[50]; ENTRY; MOD_INC_USE_COUNT; @@ -180,10 +179,10 @@ static void coda_put_super(struct super_block *sb) /* all filling in of inodes postponed until lookup */ static void coda_read_inode(struct inode *inode) { - struct coda_inode_info *cnp; + struct coda_inode_info *cii; ENTRY; - cnp = ITOC(inode); - cnp->c_magic = 0; + cii = ITOC(inode); + cii->c_magic = 0; return; } @@ -200,32 +199,32 @@ static void coda_put_inode(struct inode *in) static void coda_delete_inode(struct inode *inode) { - struct coda_inode_info *cnp; + struct coda_inode_info *cii; struct inode *open_inode; ENTRY; CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n", inode->i_ino, inode->i_count); - cnp = ITOC(inode); - if ( inode->i_ino == CTL_INO || cnp->c_magic != CODA_CNODE_MAGIC ) { + cii = ITOC(inode); + if ( inode->i_ino == CTL_INO || cii->c_magic != CODA_CNODE_MAGIC ) { clear_inode(inode); return; } - if ( coda_fid_is_volroot(&cnp->c_fid) ) - list_del(&cnp->c_volrootlist); + if ( coda_fid_is_volroot(&cii->c_fid) ) + list_del(&cii->c_volrootlist); - open_inode = cnp->c_ovp; + open_inode = cii->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; + cii->c_ovp = NULL; iput(open_inode); } - coda_cache_clear_cnp(cnp); + coda_cache_clear_inode(inode); inode->u.generic_ip = NULL; clear_inode(inode); @@ -235,24 +234,24 @@ static void coda_delete_inode(struct inode *inode) static int coda_notify_change(struct dentry *de, struct iattr *iattr) { struct inode *inode = de->d_inode; - struct coda_inode_info *cnp; + struct coda_inode_info *cii; struct coda_vattr vattr; int error; ENTRY; memset(&vattr, 0, sizeof(vattr)); - cnp = ITOC(inode); - CHECK_CNODE(cnp); + cii = ITOC(inode); + CHECK_CNODE(cii); coda_iattr_to_vattr(iattr, &vattr); 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); + error = venus_setattr(inode->i_sb, &cii->c_fid, &vattr); if ( !error ) { coda_vattr_to_iattr(inode, &vattr); - coda_cache_clear_cnp(cnp); + coda_cache_clear_inode(inode); } CDEBUG(D_SUPER, "inode.i_mode %o, error %d\n", inode->i_mode, error); diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 04333e046..119d14f51 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -65,7 +65,7 @@ extern int cfsnc_nc_info(char *buffer, char **start, off_t offset, int length, i /* statistics */ struct coda_upcallstats coda_callstats; int coda_hard = 0; /* introduces a timeout on upcalls */ -unsigned long coda_timeout = 10; /* .. secs, then signals will dequeue */ +unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */ extern struct coda_sb_info coda_super_info[MAX_CODADEVS]; struct vcomm psdev_vcomm[MAX_CODADEVS]; @@ -447,7 +447,7 @@ MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>"); int init_module(void) { int status; - printk(KERN_INFO "Coda Kernel/User communications module 1.0\n"); + printk(KERN_INFO "Coda Kernel/User communications module 2.0\n"); status = init_coda_psdev(); if ( status ) { diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index ac625ad17..13d3127c6 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -500,7 +500,6 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid, union outputArgs *outp; int insize, outsize, error; int iocsize; - char str[50]; insize = VC_MAXMSGSIZE; UPARG(CFS_IOCTL); @@ -587,7 +586,6 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid, static inline void coda_waitfor_upcall(struct vmsg *vmp) { struct wait_queue wait = { current, NULL }; - old_sigset_t pending; vmp->vm_posttime = jiffies; @@ -608,13 +606,9 @@ static inline void coda_waitfor_upcall(struct vmsg *vmp) if ( jiffies > vmp->vm_posttime + coda_timeout * HZ ) break; - spin_lock_irq(¤t->sigmask_lock); - pending = current->blocked.sig[0] & current->signal.sig[0]; - spin_unlock_irq(¤t->sigmask_lock); - /* if this process really wants to die, let it go */ - if ( sigismember(&pending, SIGKILL) || - sigismember(&pending, SIGINT) ) + if ( sigismember(¤t->signal, SIGKILL) || + sigismember(¤t->signal, SIGINT) ) break; else schedule(); @@ -765,10 +759,14 @@ ENTRY; * This call is a result of token expiration. * * The next arise as the result of callbacks on a file or directory. - * CFS_ZAPDIR -- flush the attributes for the dir from its cnode. - * Zap all children of this directory from the namecache. * CFS_ZAPFILE -- flush the cached attributes for a file. - * CFS_ZAPVNODE -- intended to be a zapfile for just one cred. Not used? + + * CFS_ZAPDIR -- flush the attributes for the dir and + * force a new lookup for all the children + of this dir. + + * CFS_ZAPVNODE -- intended to be a zapfile for just one cred. + Not used? * * The next is a result of Venus detecting an inconsistent file. * CFS_PURGEFID -- flush the attribute for the file @@ -803,53 +801,48 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) return(0); } case CFS_ZAPDIR : { + struct inode *inode; ViceFid *fid = &out->cfs_zapdir.CodaFid; - char str[50]; if ( !fid ) { printk("ZAPDIR: Null fid\n"); return 0; } CDEBUG(D_DOWNCALL, "zapdir: fid = %s\n", coda_f2s(fid)); clstats(CFS_ZAPDIR); - coda_zapfid(fid, sb, C_ZAPDIR); - return(0); - } - case CFS_ZAPVNODE : { - ViceFid *fid = &out->cfs_zapvnode.VFid; - char str[50]; - struct coda_cred *cred = &out->cfs_zapvnode.cred; - if ( !fid || !cred ) { - printk("ZAPVNODE: Null fid or cred\n"); - return 0; - } - CDEBUG(D_DOWNCALL, "zapvnode: fid = %s\n", coda_f2s(fid)); - coda_zapfid(fid, sb, C_ZAPFID); - coda_cache_clear_cred(sb, cred); - clstats(CFS_ZAPVNODE); + inode = coda_fid_to_inode(fid, sb); + coda_flag_inode(inode, C_VATTR); + coda_cache_clear_inode(inode); + coda_flag_alias_children(inode, C_PURGE); return(0); } + + case CFS_ZAPVNODE : case CFS_ZAPFILE : { + struct inode *inode; struct ViceFid *fid = &out->cfs_zapfile.CodaFid; - char str[50]; clstats(CFS_ZAPFILE); if ( !fid ) { printk("ZAPFILE: Null fid\n"); return 0; } CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid)); - coda_zapfid(fid, sb, C_ZAPFID); + inode = coda_fid_to_inode(fid, sb); + coda_flag_inode(inode, C_VATTR); + coda_cache_clear_inode(inode); return 0; } case CFS_PURGEFID : { + struct inode *inode; ViceFid *fid = &out->cfs_purgefid.CodaFid; - char str[50]; if ( !fid ) { printk("PURGEFID: Null fid\n"); return 0; } CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid)); clstats(CFS_PURGEFID); - coda_zapfid(fid, sb, C_ZAPDIR); + inode = coda_fid_to_inode(fid, sb); + coda_flag_inode(inode, C_PURGE); + coda_cache_clear_inode(inode); return 0; } case CFS_REPLACE : { |