summaryrefslogtreecommitdiffstats
path: root/fs/coda
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda')
-rw-r--r--fs/coda/cache.c172
-rw-r--r--fs/coda/cnode.c96
-rw-r--r--fs/coda/coda_linux.c7
-rw-r--r--fs/coda/dir.c43
-rw-r--r--fs/coda/file.c9
-rw-r--r--fs/coda/inode.c130
-rw-r--r--fs/coda/pioctl.c5
-rw-r--r--fs/coda/psdev.c93
-rw-r--r--fs/coda/symlink.c1
-rw-r--r--fs/coda/sysctl.c11
-rw-r--r--fs/coda/upcall.c29
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);
}