summaryrefslogtreecommitdiffstats
path: root/fs/coda/upcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/upcall.c')
-rw-r--r--fs/coda/upcall.c188
1 files changed, 72 insertions, 116 deletions
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 63586d05c..674c8cb3b 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -40,19 +40,31 @@
#include <linux/coda_proc.h>
-static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize,
+static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize,
union inputArgs *buffer);
+static void *alloc_upcall(int opcode, int size)
+{
+ union inputArgs *inp;
+
+ CODA_ALLOC(inp, union inputArgs *, size);
+ if (!inp)
+ return ERR_PTR(-ENOMEM);
+
+ inp->ih.opcode = opcode;
+ inp->ih.pid = current->pid;
+ inp->ih.pgid = current->pgrp;
+ coda_load_creds(&(inp->ih.cred));
+
+ return (void*)inp;
+}
+
#define UPARG(op)\
do {\
- CODA_ALLOC(inp, union inputArgs *, insize);\
- if ( !inp ) { return -ENOMEM; }\
- outp = (union outputArgs *) (inp);\
- inp->ih.opcode = (op);\
- inp->ih.pid = current->pid;\
- inp->ih.pgid = current->pgrp;\
- coda_load_creds(&(inp->ih.cred));\
- outsize = insize;\
+ inp = (union inputArgs *)alloc_upcall(op, insize); \
+ if (IS_ERR(inp)) { return PTR_ERR(inp); }\
+ outp = (union outputArgs *)(inp); \
+ outsize = insize; \
} while (0)
static inline int max(int a, int b)
@@ -84,12 +96,12 @@ int venus_rootfid(struct super_block *sb, ViceFid *fidp)
if (error) {
printk("coda_get_rootfid: error %d\n", error);
} else {
- *fidp = (ViceFid) outp->coda_root.VFid;
+ *fidp = (ViceFid) outp->coda_root.VFid;
CDEBUG(D_SUPER, "VolumeId: %lx, VnodeId: %lx.\n",
fidp->Volume, fidp->Vnode);
}
- if (inp) CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
EXIT;
return error;
}
@@ -108,11 +120,9 @@ int venus_getattr(struct super_block *sb, struct ViceFid *fid,
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if ( !error )
- *attr = outp->coda_getattr.attr;
+ *attr = outp->coda_getattr.attr;
- if (inp)
- CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
EXIT;
return error;
}
@@ -124,7 +134,7 @@ int venus_setattr(struct super_block *sb, struct ViceFid *fid,
union outputArgs *outp;
int insize, outsize, error;
- insize= SIZE(setattr);
+ insize = SIZE(setattr);
UPARG(CODA_SETATTR);
inp->coda_setattr.VFid = *fid;
@@ -133,7 +143,7 @@ int venus_setattr(struct super_block *sb, struct ViceFid *fid,
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
CDEBUG(D_SUPER, " result %d\n", error);
- if ( inp ) CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
return error;
}
@@ -147,7 +157,7 @@ int venus_lookup(struct super_block *sb, struct ViceFid *fid,
int offset;
offset = INSIZE(lookup);
- insize = max(offset + length +1, OUTSIZE(lookup));
+ insize = max(offset + length +1, OUTSIZE(lookup));
UPARG(CODA_LOOKUP);
inp->coda_lookup.VFid = *fid;
@@ -159,12 +169,10 @@ int venus_lookup(struct super_block *sb, struct ViceFid *fid,
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if ( !error ) {
- *resfid = outp->coda_lookup.VFid;
- *type = outp->coda_lookup.vtype;
- }
- if (inp) CODA_FREE(inp, insize);
-
+ *resfid = outp->coda_lookup.VFid;
+ *type = outp->coda_lookup.vtype;
+
+ CODA_FREE(inp, insize);
return error;
}
@@ -189,8 +197,7 @@ int venus_release(struct super_block *sb, struct ViceFid *fid, int flags,
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if (inp)
- CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
return error;
}
@@ -209,17 +216,10 @@ int venus_open(struct super_block *sb, struct ViceFid *fid,
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if ( !error ) {
- *ino = outp->coda_open.inode;
- *dev = outp->coda_open.dev;
- } else {
- *ino = 0;
- *dev = 0;
- }
-
- if (inp)
- CODA_FREE(inp, insize);
+ *ino = outp->coda_open.inode;
+ *dev = outp->coda_open.dev;
+ CODA_FREE(inp, insize);
return error;
}
@@ -248,8 +248,7 @@ int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid,
*attrs = outp->coda_mkdir.attr;
*newfid = outp->coda_mkdir.VFid;
- if (inp)
- CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
return error;
}
@@ -289,7 +288,7 @@ int venus_rename(struct super_block *sb, struct ViceFid *old_fid,
(char *)inp + (int) inp->coda_rename.destname);
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if (inp) CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
return error;
}
@@ -322,8 +321,7 @@ int venus_create(struct super_block *sb, struct ViceFid *dirfid,
*attrs = outp->coda_create.attr;
*newfid = outp->coda_create.VFid;
- if (inp)
- CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
return error;
}
@@ -345,8 +343,8 @@ int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid,
*((char *)inp + offset + length) = '\0';
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if ( inp )
- CODA_FREE(inp, insize);
+
+ CODA_FREE(inp, insize);
return error;
}
@@ -367,8 +365,8 @@ int venus_remove(struct super_block *sb, struct ViceFid *dirfid,
*((char *)inp + offset + length) = '\0';
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if ( inp )
- CODA_FREE(inp, insize);
+
+ CODA_FREE(inp, insize);
return error;
}
@@ -398,9 +396,9 @@ int venus_readlink(struct super_block *sb, struct ViceFid *fid,
*(buffer + retlen) = '\0';
}
- if (inp) CODA_FREE(inp, insize);
CDEBUG(D_INODE, " result %d\n",error);
EXIT;
+ CODA_FREE(inp, insize);
return error;
}
@@ -428,10 +426,9 @@ int venus_link(struct super_block *sb, struct ViceFid *fid,
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if (inp)
- CODA_FREE(inp, insize);
CDEBUG(D_INODE, " result %d\n",error);
EXIT;
+ CODA_FREE(inp, insize);
return error;
}
@@ -466,10 +463,9 @@ int venus_symlink(struct super_block *sb, struct ViceFid *fid,
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if (inp)
- CODA_FREE(inp, insize);
CDEBUG(D_INODE, " result %d\n",error);
EXIT;
+ CODA_FREE(inp, insize);
return error;
}
@@ -486,8 +482,7 @@ int venus_fsync(struct super_block *sb, struct ViceFid *fid)
error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs),
&outsize, inp);
- if ( inp )
- CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
return error;
}
@@ -505,7 +500,7 @@ int venus_access(struct super_block *sb, struct ViceFid *fid, int mask)
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
- if (inp) CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
EXIT;
return error;
}
@@ -576,8 +571,7 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
}
exit:
- if (inp)
- CODA_FREE(inp, insize);
+ CODA_FREE(inp, insize);
return error;
}
@@ -602,9 +596,9 @@ int venus_statfs(struct super_block *sb, struct statfs *sfs)
printk("coda_statfs: Venus returns: %d\n", error);
}
- if (inp) CODA_FREE(inp, insize);
CDEBUG(D_INODE, " result %d\n",error);
EXIT;
+ CODA_FREE(inp, insize);
return error;
}
@@ -625,16 +619,20 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
add_wait_queue(&vmp->uc_sleep, &wait);
for (;;) {
- if ( coda_hard == 0 )
+ if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE )
set_current_state(TASK_INTERRUPTIBLE);
else
set_current_state(TASK_UNINTERRUPTIBLE);
+ /* venus died */
+ if ( !coda_upc_comm.vc_pid )
+ break;
+
/* got a reply */
if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
break;
- if ( !coda_hard && signal_pending(current) ) {
+ 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) )
@@ -645,7 +643,6 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
break;
}
schedule();
-
}
remove_wait_queue(&vmp->uc_sleep, &wait);
current->state = TASK_RUNNING;
@@ -711,6 +708,7 @@ ENTRY;
/* Append msg to pending queue and poke Venus. */
list_add(&(req->uc_chain), vcommp->vc_pending.prev);
+
CDEBUG(D_UPCALL,
"Proc %d wake Venus for(opc,uniq) =(%d,%d) msg at %p.zzz.\n",
current->pid, req->uc_opcode, req->uc_unique, req);
@@ -848,7 +846,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
{
/* Handle invalidation requests. */
if ( !sb || !sb->s_root || !sb->s_root->d_inode) {
- printk("coda_downcall: opcode %d, no sb!\n", opcode);
+ CDEBUG(D_DOWNCALL, "coda_downcall: opcode %d, no sb!\n", opcode);
return 0;
}
@@ -878,8 +876,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
case CODA_ZAPDIR : {
struct inode *inode;
ViceFid *fid = &out->coda_zapdir.CodaFid;
- CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n",
- coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid));
clstats(CODA_ZAPDIR);
inode = coda_fid_to_inode(fid, sb);
@@ -889,7 +886,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
coda_flag_inode_children(inode, C_PURGE);
CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino);
coda_flag_inode(inode, C_VATTR);
- iput(inode);
+ iput(inode);
} else
CDEBUG(D_DOWNCALL, "zapdir: no inode\n");
@@ -900,14 +897,13 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
struct inode *inode;
struct ViceFid *fid = &out->coda_zapfile.CodaFid;
clstats(CODA_ZAPFILE);
- CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n",
- coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
inode = coda_fid_to_inode(fid, sb);
if ( inode ) {
- CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n",
- inode->i_ino);
+ CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n",
+ inode->i_ino);
coda_flag_inode(inode, C_VATTR);
- iput(inode);
+ iput(inode);
} else
CDEBUG(D_DOWNCALL, "zapfile: no inode\n");
return 0;
@@ -916,61 +912,20 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
case CODA_PURGEFID : {
struct inode *inode;
ViceFid *fid = &out->coda_purgefid.CodaFid;
- CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n",
- coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid));
clstats(CODA_PURGEFID);
inode = coda_fid_to_inode(fid, sb);
if ( inode ) {
- CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n",
- inode->i_ino);
+ CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n",
+ inode->i_ino);
coda_flag_inode_children(inode, C_PURGE);
coda_purge_dentries(inode);
- iput(inode);
- }else
+ iput(inode);
+ } else
CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
return 0;
}
- case CODA_MAKE_CINODE : {
- struct inode *inode;
- ViceFid *fid = &out->coda_make_cinode.CodaFid;
- struct coda_vattr *attr = &out->coda_make_cinode.attr;
- int fd = out->coda_make_cinode.fd;
- struct file *file;
- CDEBUG(D_DOWNCALL, "make_cinode: fid = %s, ino = %ld\n",
- coda_f2s(fid), attr->va_fileid);
-
- inode = coda_iget(sb, fid, attr);
- if ( !inode ) {
- CDEBUG(D_DOWNCALL, "make_cinode: no inode\n");
- return -EINVAL;
- }
-
- file = fget(fd);
- if ( !file ) {
- CDEBUG(D_DOWNCALL, "make_cinode: no file\n");
- iput(inode);
- return -EINVAL;
- }
-
- inode->u.coda_i.c_ovp = file->f_dentry->d_inode;
- inode->i_mapping = file->f_dentry->d_inode->i_mapping;
- file->f_dentry->d_inode = inode;
- file->f_op = &coda_file_operations;
-
- /*
- Unhash the dentry of the container file, as it is
- still owned by the fs that stores the container
- file. A more reliable solution would be to create
- an new dentry owned by Coda, but that would require
- knowledge of the internals of the dcache.
- */
- d_drop(file->f_dentry);
-
- fput(file);
- return 0;
- }
-
case CODA_REPLACE : {
struct inode *inode;
ViceFid *oldfid = &out->coda_replace.OldFid;
@@ -979,9 +934,10 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
CDEBUG(D_DOWNCALL, "CODA_REPLACE\n");
inode = coda_fid_to_inode(oldfid, sb);
if ( inode ) {
- CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino);
+ CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n",
+ inode->i_ino);
coda_replace_fid(inode, oldfid, newfid);
- iput(inode);
+ iput(inode);
}else
CDEBUG(D_DOWNCALL, "purgefid: no inode\n");