diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
commit | 012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch) | |
tree | 87efc733f9b164e8c85c0336f92c8fb7eff6d183 /fs/coda | |
parent | 625a1589d3d6464b5d90b8a0918789e3afffd220 (diff) |
Merge with Linux 2.4.0-test9. Please check DECstation, I had a number
of rejects to fixup while integrating Linus patches. I also found
that this kernel will only boot SMP on Origin; the UP kernel freeze
soon after bootup with SCSI timeout messages. I commit this anyway
since I found that the last CVS versions had the same problem.
Diffstat (limited to 'fs/coda')
-rw-r--r-- | fs/coda/cache.c | 172 | ||||
-rw-r--r-- | fs/coda/cnode.c | 96 | ||||
-rw-r--r-- | fs/coda/coda_linux.c | 7 | ||||
-rw-r--r-- | fs/coda/dir.c | 43 | ||||
-rw-r--r-- | fs/coda/file.c | 9 | ||||
-rw-r--r-- | fs/coda/inode.c | 130 | ||||
-rw-r--r-- | fs/coda/pioctl.c | 5 | ||||
-rw-r--r-- | fs/coda/psdev.c | 93 | ||||
-rw-r--r-- | fs/coda/symlink.c | 1 | ||||
-rw-r--r-- | fs/coda/sysctl.c | 11 | ||||
-rw-r--r-- | fs/coda/upcall.c | 29 |
11 files changed, 245 insertions, 351 deletions
diff --git a/fs/coda/cache.c b/fs/coda/cache.c index e837db96a..db7fbb4ec 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c @@ -24,168 +24,60 @@ #include <linux/coda_fs_i.h> #include <linux/coda_cache.h> -/* create a new acl cache entry and enlist it */ -static struct coda_cache *coda_cache_create(struct inode *inode) -{ - struct coda_inode_info *cii = ITOC(inode); - struct coda_sb_info *sbi = coda_sbp(inode->i_sb); - struct coda_cache *cc = NULL; - ENTRY; - - if ( !sbi || !cii ) { - printk("coda_cache_create: NULL sbi or cii!\n"); - return NULL; - } - - CODA_ALLOC(cc, struct coda_cache *, sizeof(*cc)); - - if ( !cc ) { - printk("Out of memory in coda_cache_create!\n"); - return NULL; - } - - coda_load_creds(&cc->cc_cred); - cc->cc_mask = 0; - - INIT_LIST_HEAD(&cc->cc_cclist); - INIT_LIST_HEAD(&cc->cc_cnlist); - list_add(&cc->cc_cclist, &sbi->sbi_cchead); - list_add(&cc->cc_cnlist, &cii->c_cnhead); - - return cc; -} - -/* destroy an acl cache entry */ -static void coda_cache_destroy(struct coda_cache *el) -{ - ENTRY; - if (list_empty(&el->cc_cclist) || list_empty(&el->cc_cnlist)) { - printk("coda_cache_destroy: loose entry!"); - return; - } - list_del(&el->cc_cclist); - list_del(&el->cc_cnlist); - CODA_FREE(el, sizeof(struct coda_cache)); -} - -/* 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 *cii = ITOC(inode); - struct list_head *le; - struct coda_cache *cc = NULL; - - list_for_each(le, &cii->c_cnhead) - { - /* compare name and creds */ - cc = list_entry(le, struct coda_cache, cc_cnlist); - if ( !coda_cred_ok(&cc->cc_cred) ) - continue; - CDEBUG(D_CACHE, "HIT for ino %ld\n", inode->i_ino ); - return cc; /* cache hit */ - } - return NULL; -} - -/* create or extend an acl cache hit */ +/* replace or extend an acl cache hit */ void coda_cache_enter(struct inode *inode, int mask) { - struct coda_cache *cc; - - cc = coda_cache_find(inode); + struct coda_inode_info *cii = ITOC(inode); + ENTRY; - if (!cc) - cc = coda_cache_create(inode); - if (cc) - cc->cc_mask |= mask; + if ( !coda_cred_ok(&cii->c_cached_cred) ) { + coda_load_creds(&cii->c_cached_cred); + cii->c_cached_perm = mask; + } else + cii->c_cached_perm |= mask; } -/* remove all cached acl matches from an inode */ +/* remove cached acl from an inode */ void coda_cache_clear_inode(struct inode *inode) { - struct list_head *le; - struct coda_inode_info *cii; - struct coda_cache *cc; + struct coda_inode_info *cii = ITOC(inode); ENTRY; - - if ( !inode ) { - CDEBUG(D_CACHE, "coda_cache_clear_inode: NULL inode\n"); - return; - } - cii = ITOC(inode); - - le = cii->c_cnhead.next; - while ( le != &cii->c_cnhead ) { - cc = list_entry(le, struct coda_cache, cc_cnlist); - le = le->next; - coda_cache_destroy(cc); - } + cii->c_cached_perm = 0; } -/* remove all acl caches */ -void coda_cache_clear_all(struct super_block *sb) +/* remove all acl caches for a principal (or all principals when cred == NULL)*/ +void coda_cache_clear_all(struct super_block *sb, struct coda_cred *cred) { - struct list_head *le; - struct coda_cache *cc; - struct coda_sb_info *sbi = coda_sbp(sb); + struct coda_sb_info *sbi; + struct coda_inode_info *cii; + struct list_head *tmp; - if ( !sbi ) { - printk("coda_cache_clear_all: NULL sbi\n"); - return; - } - - le = sbi->sbi_cchead.next; - while ( le != &sbi->sbi_cchead ) { - cc = list_entry(le, struct coda_cache, cc_cclist); - le = le->next; - coda_cache_destroy(cc); - } -} + ENTRY; + sbi = coda_sbp(sb); + if (!sbi) BUG(); -/* remove all acl caches for a principal */ -void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred) -{ - struct list_head *le; - struct coda_cache *cc; - struct coda_sb_info *sbi = coda_sbp(sb); + list_for_each(tmp, &sbi->sbi_cihead) + { + cii = list_entry(tmp, struct coda_inode_info, c_cilist); + if ( cii->c_magic != CODA_CNODE_MAGIC ) BUG(); - if ( !sbi ) { - printk("coda_cache_clear_all: NULL sbi\n"); - return; - } - - le = sbi->sbi_cchead.next; - while ( le != &sbi->sbi_cchead ) { - cc = list_entry(le, struct coda_cache, cc_cclist); - le = le->next; - if ( coda_cred_eq(&cc->cc_cred, cred)) - coda_cache_destroy(cc); + if (!cred || coda_cred_eq(cred, &cii->c_cached_cred)) + cii->c_cached_perm = 0; } } -/* check if the mask has been matched against the acl - already */ +/* check if the mask has been matched against the acl already */ int coda_cache_check(struct inode *inode, int mask) { struct coda_inode_info *cii = ITOC(inode); - struct list_head *le; - struct coda_cache *cc = NULL; + int hit; - list_for_each(le, &cii->c_cnhead) - { - /* compare name and creds */ - cc = list_entry(le, struct coda_cache, cc_cnlist); - if ( (cc->cc_mask & mask) != mask ) - continue; - if ( !coda_cred_ok(&cc->cc_cred) ) - continue; - CDEBUG(D_CACHE, "HIT for ino %ld\n", inode->i_ino ); - return 1; /* cache hit */ - } - CDEBUG(D_CACHE, "MISS for ino %ld\n", inode->i_ino ); - return 0; + hit = ((mask & cii->c_cached_perm) == mask) && + coda_cred_ok(&cii->c_cached_cred); + + CDEBUG(D_CACHE, "%s for ino %ld\n", hit ? "HIT" : "MISS", inode->i_ino); + return hit; } diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 7c5544612..c8dc3dd8f 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -59,7 +59,6 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, struct coda_vattr * attr) { struct inode *inode; - struct coda_sb_info *sbi= coda_sbp(sb); struct coda_inode_info *cii; ino_t ino = attr->va_fileid; @@ -71,50 +70,26 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, /* check if the inode is already initialized */ cii = ITOC(inode); - if (cii->c_magic == CODA_CNODE_MAGIC) { + if (cii->c_fid.Volume != 0 || cii->c_fid.Vnode != 0 || cii->c_fid.Unique != 0) { /* see if it is the right one (might have an inode collision) */ - if ( !coda_fideq(fid, &cii->c_fid) ) { + if ( !coda_fideq(fid, &cii->c_fid) ) { printk("coda_iget: initialized inode old %s new %s!\n", coda_f2s(&cii->c_fid), coda_f2s2(fid)); iput(inode); return ERR_PTR(-ENOENT); } - /* replace the attributes, type might have changed */ - coda_fill_inode(inode, attr); + /* we will still replace the attributes, type might have changed */ goto out; } /* new, empty inode found... initializing */ /* Initialize the Coda inode info structure */ - memset(cii, 0, (int) sizeof(struct coda_inode_info)); - cii->c_magic = CODA_CNODE_MAGIC; cii->c_fid = *fid; - cii->c_flags = 0; cii->c_vnode = inode; - INIT_LIST_HEAD(&(cii->c_cnhead)); - INIT_LIST_HEAD(&(cii->c_volrootlist)); - coda_fill_inode(inode, attr); - - /* check if it is a weird fid (hashed fid != ino), f.i mountpoints - repair object, expanded local-global conflict trees, etc. - */ - if ( coda_f2i(fid) == ino ) - goto out; - - /* check if we expected this weird fid */ - if ( !coda_fid_is_weird(fid) ) { - printk("Coda: unknown weird fid: ino %ld, fid %s." - "Tell Peter.\n", (long)ino, coda_f2s(&cii->c_fid)); - goto out; - } - - /* add the inode to a global list so we can find it back later */ - list_add(&cii->c_volrootlist, &sbi->sbi_volroothead); - CDEBUG(D_CNODE, "Added %ld, %s to volroothead\n", - (long)ino, coda_f2s(&cii->c_fid)); out: + coda_fill_inode(inode, attr); return inode; } @@ -161,22 +136,14 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, struct ViceFid *newfid) { - struct coda_inode_info *cnp; - struct coda_sb_info *sbi= coda_sbp(inode->i_sb); + struct coda_inode_info *cii; - cnp = ITOC(inode); - - if ( ! coda_fideq(&cnp->c_fid, oldfid) ) - printk("What? oldfid != cnp->c_fid. Call 911.\n"); - - cnp->c_fid = *newfid; + cii = ITOC(inode); - list_del(&cnp->c_volrootlist); - INIT_LIST_HEAD(&cnp->c_volrootlist); - if ( coda_fid_is_weird(newfid) ) - list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead); + if ( ! coda_fideq(&cii->c_fid, oldfid) ) + printk("What? oldfid != cii->c_fid. Call 911.\n"); - return; + cii->c_fid = *newfid; } @@ -197,24 +164,18 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) return NULL; } - if ( !fid ) { - printk("coda_fid_to_inode: no fid!\n"); - return NULL; - } CDEBUG(D_INODE, "%s\n", coda_f2s(fid)); + /* weird fids cannot be hashed, have to look for them the hard way */ if ( coda_fid_is_weird(fid) ) { - struct list_head *lh, *le; struct coda_sb_info *sbi = coda_sbp(sb); - le = lh = &sbi->sbi_volroothead; + struct list_head *le; - while ( (le = le->next) != lh ) { - cii = list_entry(le, struct coda_inode_info, - c_volrootlist); - /* paranoia check, should never trigger */ - if ( cii->c_magic != CODA_CNODE_MAGIC ) - printk("coda_fid_to_inode: Bad magic in inode %x.\n", cii->c_magic); + list_for_each(le, &sbi->sbi_cihead) + { + cii = list_entry(le, struct coda_inode_info, c_cilist); + if ( cii->c_magic != CODA_CNODE_MAGIC ) BUG(); CDEBUG(D_DOWNCALL, "iterating, now doing %s, ino %ld\n", coda_f2s(&cii->c_fid), cii->c_vnode->i_ino); @@ -240,26 +201,19 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) /* check if this inode is linked to a cnode */ cii = ITOC(inode); - if ( cii->c_magic != CODA_CNODE_MAGIC ) { - CDEBUG(D_INODE, "uninitialized inode. Return.\n"); - goto bad_inode; - } - /* make sure fid is the one we want */ - if ( !coda_fideq(fid, &(cii->c_fid)) ) { + /* make sure this is the one we want */ + if ( coda_fideq(fid, &cii->c_fid) ) { + CDEBUG(D_INODE, "found %ld\n", inode->i_ino); + return inode; + } + #if 0 - printk("coda_fid2inode: bad cnode (ino %ld, fid %s)", nr, - coda_f2s(fid)); + printk("coda_fid2inode: bad cnode (ino %ld, fid %s)", nr, coda_f2s(fid)); #endif - goto bad_inode; - } - - CDEBUG(D_INODE, "found %ld\n", inode->i_ino); - return inode; + iput(inode); + return NULL; -bad_inode: - iput(inode); - return NULL; } /* the CONTROL inode is made without asking attributes from Venus */ @@ -271,7 +225,7 @@ int coda_cnode_makectl(struct inode **inode, struct super_block *sb) if ( *inode ) { (*inode)->i_op = &coda_ioctl_inode_operations; (*inode)->i_fop = &coda_ioctl_operations; - (*inode)->i_mode = 00444; + (*inode)->i_mode = 0444; error = 0; } else { error = -ENOMEM; diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c index 4a7bebb62..2a3f544f3 100644 --- a/fs/coda/coda_linux.c +++ b/fs/coda/coda_linux.c @@ -23,7 +23,6 @@ #include <linux/coda_linux.h> #include <linux/coda_psdev.h> #include <linux/coda_fs_i.h> -#include <linux/coda_cache.h> /* initialize the debugging variables */ int coda_debug = 0; @@ -71,12 +70,6 @@ int coda_isroot(struct inode *i) } } -/* is this a volume root FID */ -int coda_fid_is_volroot(struct ViceFid *fid) -{ - return ( (fid->Vnode == 1) && (fid->Unique == 1 ) ); -} - int coda_fid_is_weird(struct ViceFid *fid) { /* volume roots */ diff --git a/fs/coda/dir.c b/fs/coda/dir.c index a51bfc647..1629be782 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -170,12 +170,13 @@ int coda_permission(struct inode *inode, int mask) ENTRY; coda_vfs_stat.permission++; - coda_permission_stat.count++; if ( mask == 0 ) return 0; - if ( coda_access_cache == 1 ) { + if ( coda_access_cache ) { + coda_permission_stat.count++; + if ( coda_cache_check(inode, mask) ) { coda_permission_stat.hit_count++; return 0; @@ -472,6 +473,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, const char *new_name = new_dentry->d_name.name; int old_length = old_dentry->d_name.len; int new_length = new_dentry->d_name.len; + int link_adjust = 0; int error; ENTRY; @@ -488,16 +490,16 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, if ( !error ) { if ( new_dentry->d_inode ) { - if ( S_ISDIR(new_dentry->d_inode->i_mode) ) { - old_dir->i_nlink--; - new_dir->i_nlink++; - } - coda_flag_inode(new_dentry->d_inode, C_VATTR); - } + if ( S_ISDIR(new_dentry->d_inode->i_mode) ) + link_adjust = 1; - /* coda_flag_inode(old_dir, C_VATTR); */ - /* coda_flag_inode(new_dir, C_VATTR); */ - old_dir->i_mtime = new_dir->i_mtime = CURRENT_TIME; + coda_dir_changed(old_dir, -link_adjust); + coda_dir_changed(new_dir, link_adjust); + coda_flag_inode(new_dentry->d_inode, C_VATTR); + } else { + coda_flag_inode(old_dir, C_VATTR); + coda_flag_inode(new_dir, C_VATTR); + } } CDEBUG(D_INODE, "result %d\n", error); @@ -578,6 +580,7 @@ int coda_open(struct inode *i, struct file *f) unsigned short flags = f->f_flags & (~O_EXCL); unsigned short coda_flags = coda_flags_to_cflags(flags); struct coda_cred *cred; + struct coda_inode_info *cii; lock_kernel(); ENTRY; @@ -617,8 +620,11 @@ int coda_open(struct inode *i, struct file *f) } i->i_mapping = cont_inode->i_mapping; - CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", - error, atomic_read(&i->i_count), i->i_ino); + cii = ITOC(i); + cii->c_contcount++; + + CDEBUG(D_FILE, "result %d, coda i->i_count is %d, cii->contcount is %d for ino %ld\n", + error, atomic_read(&i->i_count), cii->c_contcount, i->i_ino); CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", cont_inode->i_ino, atomic_read(&cont_inode->i_count), cont_inode->i_op); @@ -634,6 +640,7 @@ int coda_release(struct inode *i, struct file *f) unsigned short flags = (f->f_flags) & (~O_EXCL); unsigned short cflags = coda_flags_to_cflags(flags); struct coda_cred *cred; + struct coda_inode_info *cii; lock_kernel(); ENTRY; @@ -644,11 +651,17 @@ int coda_release(struct inode *i, struct file *f) if (i->i_mapping != &i->i_data) container = (struct inode *)i->i_mapping->host; - CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d) cache (ino %ld, ct %d)\n", - i->i_ino, atomic_read(&i->i_count), + cii = ITOC(i); + CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d, cc %d) cache (ino %ld, ct %d)\n", + i->i_ino, atomic_read(&i->i_count), cii->c_contcount, (container ? container->i_ino : 0), (container ? atomic_read(&container->i_count) : -99)); + if (--cii->c_contcount == 0 && container) { + i->i_mapping = &i->i_data; + iput(container); + } + error = venus_release(i->i_sb, coda_i2f(i), cflags, cred); f->private_data = NULL; diff --git a/fs/coda/file.c b/fs/coda/file.c index 128b07d44..0344c2072 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -23,18 +23,21 @@ #include <linux/coda_linux.h> #include <linux/coda_fs_i.h> #include <linux/coda_psdev.h> -#include <linux/coda_cache.h> #include <linux/coda_proc.h> static ssize_t coda_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; + struct inode *container = (struct inode*)inode->i_mapping->host; ssize_t n; + down(&container->i_sem); + n = generic_file_write(file, buf, count, ppos); + inode->i_size = container->i_size; - inode->i_size = ((struct inode*)inode->i_mapping->host)->i_size; + up(&container->i_sem); return n; } @@ -63,7 +66,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) result = file_fsync(NULL, &cont_dentry, datasync); up(&cont_dentry.d_inode->i_sem); - if ( result == 0 ) { + if ( result == 0 && datasync == 0 ) { lock_kernel(); result = venus_fsync(inode->i_sb, coda_i2f(inode)); unlock_kernel(); diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 84191c494..94a3be389 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -18,6 +18,7 @@ #include <linux/locks.h> #include <linux/unistd.h> #include <linux/smp_lock.h> +#include <linux/file.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -48,6 +49,47 @@ struct super_operations coda_super_operations = statfs: coda_statfs, }; +static int get_device_index(struct coda_mount_data *data) +{ + struct file *file; + struct inode *inode; + int idx; + + if(data == NULL) { + printk("coda_read_super: Bad mount data\n"); + return -1; + } + + if(data->version != CODA_MOUNT_VERSION) { + printk("coda_read_super: Bad mount version\n"); + return -1; + } + + file = fget(data->fd); + inode = NULL; + if(file) + inode = file->f_dentry->d_inode; + + if(!inode || !S_ISCHR(inode->i_mode) || + MAJOR(inode->i_rdev) != CODA_PSDEV_MAJOR) { + if(file) + fput(file); + + printk("coda_read_super: Bad file\n"); + return -1; + } + + idx = MINOR(inode->i_rdev); + fput(file); + + if(idx < 0 || idx >= MAX_CODADEVS) { + printk("coda_read_super: Bad minor number\n"); + return -1; + } + + return idx; +} + static struct super_block * coda_read_super(struct super_block *sb, void *data, int silent) { @@ -57,23 +99,41 @@ static struct super_block * coda_read_super(struct super_block *sb, ViceFid fid; kdev_t dev = sb->s_dev; int error; - + int idx; ENTRY; - vc = &coda_upc_comm; - sbi = &coda_super_info; + idx = get_device_index((struct coda_mount_data *) data); - if ( sbi->sbi_sb ) { - printk("Already mounted\n"); + /* Ignore errors in data, for backward compatibility */ + if(idx == -1) + idx = 0; + + printk(KERN_INFO "coda_read_super: device index: %i\n", idx); + + vc = &coda_comms[idx]; + if (!vc->vc_inuse) { + printk("coda_read_super: No pseudo device\n"); EXIT; return NULL; } + if ( vc->vc_sb ) { + printk("coda_read_super: Device already mounted\n"); + EXIT; + return NULL; + } + + sbi = kmalloc(sizeof(struct coda_sb_info), GFP_KERNEL); + if(!sbi) { + EXIT; + return NULL; + } + + vc->vc_sb = sb; + sbi->sbi_sb = sb; - sbi->sbi_psdev = psdev; sbi->sbi_vcomm = vc; - INIT_LIST_HEAD(&(sbi->sbi_cchead)); - INIT_LIST_HEAD(&(sbi->sbi_volroothead)); + INIT_LIST_HEAD(&sbi->sbi_cihead); sb->u.generic_sbp = sbi; sb->s_blocksize = 1024; /* XXXXX what do we put here?? */ @@ -100,7 +160,6 @@ static struct super_block * coda_read_super(struct super_block *sb, printk("coda_read_super: rootinode is %ld dev %d\n", root->i_ino, root->i_dev); - sbi->sbi_root = root; sb->s_root = d_alloc_root(root); EXIT; return sb; @@ -108,9 +167,9 @@ static struct super_block * coda_read_super(struct super_block *sb, error: EXIT; if (sbi) { - sbi->sbi_vcomm = NULL; - sbi->sbi_root = NULL; - sbi->sbi_sb = NULL; + kfree(sbi); + if(vc) + vc->vc_sb = NULL; } if (root) { iput(root); @@ -120,15 +179,16 @@ static struct super_block * coda_read_super(struct super_block *sb, static void coda_put_super(struct super_block *sb) { - struct coda_sb_info *sb_info; + struct coda_sb_info *sbi; ENTRY; - coda_cache_clear_all(sb); - sb_info = coda_sbp(sb); - coda_super_info.sbi_sb = NULL; + sbi = coda_sbp(sb); + sbi->sbi_vcomm->vc_sb = NULL; + list_del_init(&sbi->sbi_cihead); + printk("Coda: Bye bye.\n"); - memset(sb_info, 0, sizeof(* sb_info)); + kfree(sbi); EXIT; } @@ -136,11 +196,21 @@ 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_sb_info *sbi = coda_sbp(inode->i_sb); struct coda_inode_info *cii; ENTRY; + + if (!sbi) BUG(); + cii = ITOC(inode); - cii->c_magic = 0; - return; + if (cii->c_magic == CODA_CNODE_MAGIC) { + printk("coda_read_inode: initialized inode"); + return; + } + + memset(cii, 0, sizeof(struct coda_inode_info)); + list_add(&cii->c_cilist, &sbi->sbi_cihead); + cii->c_magic = CODA_CNODE_MAGIC; } static void coda_clear_inode(struct inode *inode) @@ -152,15 +222,13 @@ static void coda_clear_inode(struct inode *inode) CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n", inode->i_ino, atomic_read(&inode->i_count)); - if ( inode->i_ino == CTL_INO || cii->c_magic != CODA_CNODE_MAGIC ) - goto out; + if ( cii->c_magic != CODA_CNODE_MAGIC ) + return; - lock_kernel(); + list_del_init(&cii->c_cilist); - if ( !list_empty(&cii->c_volrootlist) ) { - list_del(&cii->c_volrootlist); - INIT_LIST_HEAD(&cii->c_volrootlist); - } + if ( inode->i_ino == CTL_INO ) + goto out; if ( inode->i_mapping != &inode->i_data ) { open_inode = (struct inode *)inode->i_mapping->host; @@ -170,12 +238,11 @@ static void coda_clear_inode(struct inode *inode) iput(open_inode); } - coda_cache_clear_inode(inode); - unlock_kernel(); - CDEBUG(D_DOWNCALL, "clearing inode: %ld, %x\n", inode->i_ino, cii->c_flags); + coda_cache_clear_inode(inode); out: inode->u.coda_i.c_magic = 0; + memset(&inode->u.coda_i.c_fid, 0, sizeof(struct ViceFid)); EXIT; } @@ -238,8 +305,3 @@ static int coda_statfs(struct super_block *sb, struct statfs *buf) DECLARE_FSTYPE( coda_fs_type, "coda", coda_read_super, 0); -int init_coda_fs(void) -{ - return register_filesystem(&coda_fs_type); -} - diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 99ead4e51..6deeb927c 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -23,13 +23,12 @@ #include <linux/coda.h> #include <linux/coda_linux.h> #include <linux/coda_fs_i.h> -#include <linux/coda_cache.h> #include <linux/coda_psdev.h> /* pioctl ops */ static int coda_ioctl_permission(struct inode *inode, int mask); static int coda_pioctl(struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long arg); + unsigned int cmd, unsigned long user_data); /* exported from this file */ struct inode_operations coda_ioctl_inode_operations = @@ -52,7 +51,7 @@ static int coda_ioctl_permission(struct inode *inode, int mask) } static int coda_pioctl(struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long user_data) + unsigned int cmd, unsigned long user_data) { struct nameidata nd; int error; diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index c475b73ac..486e42185 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -46,21 +46,19 @@ #include <linux/coda_linux.h> #include <linux/coda_fs_i.h> #include <linux/coda_psdev.h> -#include <linux/coda_cache.h> #include <linux/coda_proc.h> /* * Coda stuff */ extern struct file_system_type coda_fs_type; -extern int init_coda_fs(void); /* statistics */ int coda_hard = 0; /* allows signals during upcalls */ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */ -struct coda_sb_info coda_super_info; -struct venus_comm coda_upc_comm; + +struct venus_comm coda_comms[MAX_CODADEVS]; /* * Device operations @@ -68,7 +66,7 @@ struct venus_comm coda_upc_comm; static unsigned int coda_psdev_poll(struct file *file, poll_table * wait) { - struct venus_comm *vcp = &coda_upc_comm; + struct venus_comm *vcp = (struct venus_comm *) file->private_data; unsigned int mask = POLLOUT | POLLWRNORM; poll_wait(file, &vcp->vc_waitq, wait); @@ -101,7 +99,7 @@ static int coda_psdev_ioctl(struct inode * inode, struct file * filp, static ssize_t coda_psdev_write(struct file *file, const char *buf, size_t nbytes, loff_t *off) { - struct venus_comm *vcp = &coda_upc_comm; + struct venus_comm *vcp = (struct venus_comm *) file->private_data; struct upc_req *req = NULL; struct upc_req *tmp; struct list_head *lh; @@ -109,8 +107,6 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf, ssize_t retval = 0, count = 0; int error; - if ( !coda_upc_comm.vc_inuse ) - return -EIO; /* Peek at the opcode, uniquefier */ if (copy_from_user(&hdr, buf, 2 * sizeof(u_long))) return -EFAULT; @@ -123,7 +119,7 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf, union outputArgs *dcbuf; int size = sizeof(*dcbuf); - sb = coda_super_info.sbi_sb; + sb = vcp->vc_sb; if ( !sb ) { CDEBUG(D_PSDEV, "coda_psdev_write: downcall, no SB!\n"); count = nbytes; @@ -221,7 +217,7 @@ static ssize_t coda_psdev_read(struct file * file, char * buf, size_t nbytes, loff_t *off) { DECLARE_WAITQUEUE(wait, current); - struct venus_comm *vcp = &coda_upc_comm; + struct venus_comm *vcp = (struct venus_comm *) file->private_data; struct upc_req *req; ssize_t retval = 0, count = 0; @@ -245,7 +241,7 @@ static ssize_t coda_psdev_read(struct file * file, char * buf, schedule(); } - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&vcp->vc_waitq, &wait); if (retval) @@ -285,21 +281,32 @@ out: return (count ? count : retval); } - static int coda_psdev_open(struct inode * inode, struct file * file) { - struct venus_comm *vcp = &coda_upc_comm; + struct venus_comm *vcp; + int idx; ENTRY; - - /* first opener, initialize */ + lock_kernel(); + idx = MINOR(inode->i_rdev); + if(idx >= MAX_CODADEVS) + return -ENODEV; + + vcp = &coda_comms[idx]; + if(vcp->vc_inuse) + return -EBUSY; + if (!vcp->vc_inuse++) { - INIT_LIST_HEAD(&vcp->vc_pending); - INIT_LIST_HEAD(&vcp->vc_processing); - vcp->vc_seq = 0; + INIT_LIST_HEAD(&vcp->vc_pending); + INIT_LIST_HEAD(&vcp->vc_processing); + init_waitqueue_head(&vcp->vc_waitq); + vcp->vc_sb = 0; + vcp->vc_seq = 0; } + + file->private_data = vcp; - CDEBUG(D_PSDEV, "inuse: %d\n", vcp->vc_inuse); + CDEBUG(D_PSDEV, "device %i - inuse: %d\n", idx, vcp->vc_inuse); EXIT; unlock_kernel(); @@ -309,7 +316,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file) static int coda_psdev_release(struct inode * inode, struct file * file) { - struct venus_comm *vcp = &coda_upc_comm; + struct venus_comm *vcp = (struct venus_comm *) file->private_data; struct upc_req *req; struct list_head *lh, *next; ENTRY; @@ -369,29 +376,9 @@ static struct file_operations coda_psdev_fops = { release: coda_psdev_release, }; - - -int __init init_coda(void) -{ - int status; - printk(KERN_INFO "Coda Kernel/Venus communications, v4.6.0, braam@cs.cmu.edu\n"); - - status = init_coda_psdev(); - if ( status ) { - printk("Problem (%d) in init_coda_psdev\n", status); - return status; - } - - status = init_coda_fs(); - if (status) { - printk("coda: failed in init_coda_fs!\n"); - } - return status; -} - static devfs_handle_t devfs_handle = NULL; -int init_coda_psdev(void) +static int init_coda_psdev(void) { if(devfs_register_chrdev(CODA_PSDEV_MAJOR,"coda_psdev", &coda_psdev_fops)) { @@ -404,9 +391,6 @@ int init_coda_psdev(void) CODA_PSDEV_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &coda_psdev_fops, NULL); - memset(&coda_upc_comm, 0, sizeof(coda_upc_comm)); - memset(&coda_super_info, 0, sizeof(coda_super_info)); - init_waitqueue_head(&coda_upc_comm.vc_waitq); coda_sysctl_init(); @@ -414,36 +398,35 @@ int init_coda_psdev(void) } -#ifdef MODULE - MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>"); -int init_module(void) +static int __init init_coda(void) { int status; - printk(KERN_INFO "Coda Kernel/Venus communications (module), v5.0-pre1, braam@cs.cmu.edu.\n"); + printk(KERN_INFO "Coda Kernel/Venus communications, v5.3.9, coda@cs.cmu.edu\n"); + status = init_coda_psdev(); if ( status ) { printk("Problem (%d) in init_coda_psdev\n", status); return status; } - - status = init_coda_fs(); + + status = register_filesystem(&coda_fs_type); if (status) { printk("coda: failed in init_coda_fs!\n"); } return status; } - -void cleanup_module(void) +static void __exit exit_coda(void) { int err; ENTRY; - if ( (err = unregister_filesystem(&coda_fs_type)) != 0 ) { + err = unregister_filesystem(&coda_fs_type); + if ( err != 0 ) { printk("coda: failed to unregister filesystem\n"); } devfs_unregister (devfs_handle); @@ -451,5 +434,5 @@ void cleanup_module(void) coda_sysctl_clean(); } -#endif - +module_init(init_coda); +module_exit(exit_coda); diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c index 252f11664..dbdc946f4 100644 --- a/fs/coda/symlink.c +++ b/fs/coda/symlink.c @@ -20,7 +20,6 @@ #include <linux/coda_linux.h> #include <linux/coda_psdev.h> #include <linux/coda_fs_i.h> -#include <linux/coda_cache.h> #include <linux/coda_proc.h> static int coda_symlink_filler(struct file *file, struct page *page) diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index cbfff3e5b..4215c3b41 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -76,9 +76,9 @@ int coda_upcall_timestamping = 0; /* keep this in sync with coda.h! */ char *coda_upcall_names[] = { "totals ", /* 0 */ - "noop ", /* 1 */ + "- ", /* 1 */ "root ", /* 2 */ - "sync ", /* 3 */ + "open_by_fd ", /* 3 */ "open ", /* 4 */ "close ", /* 5 */ "ioctl ", /* 6 */ @@ -96,7 +96,7 @@ char *coda_upcall_names[] = { "symlink ", /* 18 */ "readlink ", /* 19 */ "fsync ", /* 20 */ - "inactive ", /* 21 */ + "- ", /* 21 */ "vget ", /* 22 */ "signal ", /* 23 */ "replace ", /* 24 */ @@ -104,13 +104,12 @@ char *coda_upcall_names[] = { "purgeuser ", /* 26 */ "zapfile ", /* 27 */ "zapdir ", /* 28 */ - "noop2 ", /* 29 */ + "- ", /* 29 */ "purgefid ", /* 30 */ "open_by_path", /* 31 */ "resolve ", /* 32 */ "reintegrate ", /* 33 */ - "statfs ", /* 34 */ - "make_cinode " /* 35 */ + "statfs " /* 34 */ }; diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 206c9d8b0..6eb6f2e71 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -543,7 +543,8 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid, goto exit; } - error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); + error = coda_upcall(coda_sbp(sb), SIZE(ioctl) + data->vi.in_size, + &outsize, inp); if (error) { printk("coda_pioctl: Venus returns: %d for %s\n", @@ -607,7 +608,8 @@ int venus_statfs(struct super_block *sb, struct statfs *sfs) * */ -static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp) +static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp, + struct venus_comm *vcommp) { DECLARE_WAITQUEUE(wait, current); struct timeval begin = { 0, 0 }, end = { 0, 0 }; @@ -625,7 +627,7 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp) set_current_state(TASK_UNINTERRUPTIBLE); /* venus died */ - if ( !coda_upc_comm.vc_inuse ) + if ( !vcommp->vc_inuse ) break; /* got a reply */ @@ -634,8 +636,8 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp) if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE && signal_pending(current) ) { /* if this process really wants to die, let it go */ - if ( sigismember(&(current->signal), SIGKILL) || - sigismember(&(current->signal), SIGINT) ) + if ( sigismember(&(current->pending.signal), SIGKILL) || + sigismember(&(current->pending.signal), SIGINT) ) break; /* signal is present: after timeout always return really smart idea, probably useless ... */ @@ -645,7 +647,7 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp) schedule(); } remove_wait_queue(&vmp->uc_sleep, &wait); - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); if (coda_upcall_timestamping && begin.tv_sec != 0) { do_gettimeofday(&end); @@ -685,9 +687,9 @@ static int coda_upcall(struct coda_sb_info *sbi, struct upc_req *req; int error = 0; -ENTRY; + ENTRY; - vcommp = &coda_upc_comm; + vcommp = sbi->sbi_vcomm; if ( !vcommp->vc_inuse ) { printk("No pseudo device in upcall comms at %p\n", vcommp); return -ENXIO; @@ -724,7 +726,7 @@ ENTRY; * ENODEV. */ /* Go to sleep. Wake up on signals only after the timeout. */ - runtime = coda_waitfor_upcall(req); + runtime = coda_waitfor_upcall(req, vcommp); coda_upcall_stats(((union inputArgs *)buffer)->ih.opcode, runtime); CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n", @@ -738,11 +740,6 @@ ENTRY; if (req->uc_flags & REQ_WRITE) { out = (union outputArgs *)req->uc_data; /* here we map positive Venus errors to kernel errors */ - if ( out->oh.result < 0 ) { - printk("Tell Peter: Venus returns negative error %ld, for oc %ld!\n", - out->oh.result, out->oh.opcode); - out->oh.result = EINTR; - } error = -out->oh.result; CDEBUG(D_UPCALL, "upcall: (u,o,r) (%ld, %ld, %ld) out at %p\n", @@ -855,7 +852,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) case CODA_FLUSH : { clstats(CODA_FLUSH); CDEBUG(D_DOWNCALL, "CODA_FLUSH\n"); - coda_cache_clear_all(sb); + coda_cache_clear_all(sb, NULL); shrink_dcache_sb(sb); coda_flag_inode(sb->s_root->d_inode, C_FLUSH); return(0); @@ -869,7 +866,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) return 0; } clstats(CODA_PURGEUSER); - coda_cache_clear_cred(sb, cred); + coda_cache_clear_all(sb, cred); return(0); } |