patch-2.1.109 linux/fs/coda/upcall.c
Next file: linux/fs/namei.c
Previous file: linux/fs/coda/psdev.c
Back to the patch index
Back to the overall index
- Lines: 467
- Date:
Fri Jul 10 15:33:37 1998
- Orig file:
v2.1.108/linux/fs/coda/upcall.c
- Orig date:
Sun Jun 7 11:16:36 1998
diff -u --recursive --new-file v2.1.108/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
@@ -46,7 +46,8 @@
#define UPARG(op)\
do {\
CODA_ALLOC(inp, union inputArgs *, insize);\
- outp = (union outputArgs *) (inp);\
+ if ( !inp ) { return -ENOMEM; }\
+ outp = (union outputArgs *) (inp);\
inp->ih.opcode = (op);\
inp->ih.pid = current->pid;\
inp->ih.pgid = current->pgrp;\
@@ -90,7 +91,7 @@
if (inp) CODA_FREE(inp, insize);
EXIT;
- return -error;
+ return error;
}
int venus_getattr(struct super_block *sb, struct ViceFid *fid,
@@ -98,19 +99,22 @@
{
union inputArgs *inp;
union outputArgs *outp;
- int insize, outsize, error;
-ENTRY;
+ int insize, outsize, error;
+ ENTRY;
+
insize = SIZE(getattr);
UPARG(CFS_GETATTR);
inp->cfs_getattr.VFid = *fid;
+
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
if ( !error )
*attr = outp->cfs_getattr.attr;
- if (inp) CODA_FREE(inp, insize);
+ if (inp)
+ CODA_FREE(inp, insize);
EXIT;
- return -error;
+ return error;
}
int venus_setattr(struct super_block *sb, struct ViceFid *fid,
@@ -130,7 +134,7 @@
CDEBUG(D_SUPER, " result %d\n", error);
if ( inp ) CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_lookup(struct super_block *sb, struct ViceFid *fid,
@@ -160,7 +164,7 @@
}
if (inp) CODA_FREE(inp, insize);
- return -error;
+ return error;
}
@@ -180,7 +184,7 @@
if (inp)
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_open(struct super_block *sb, struct ViceFid *fid,
@@ -209,7 +213,7 @@
if (inp)
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid,
@@ -239,7 +243,7 @@
if (inp)
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
@@ -279,11 +283,11 @@
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
if (inp) CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_create(struct super_block *sb, struct ViceFid *dirfid,
- const char *name, int length, int excl, int mode,
+ const char *name, int length, int excl, int mode, int rdev,
struct ViceFid *newfid, struct coda_vattr *attrs)
{
union inputArgs *inp;
@@ -297,6 +301,7 @@
inp->cfs_create.VFid = *dirfid;
inp->cfs_create.attr.va_mode = mode;
+ inp->cfs_create.attr.va_rdev = rdev;
inp->cfs_create.excl = excl;
inp->cfs_create.mode = mode;
inp->cfs_create.name = offset;
@@ -312,7 +317,7 @@
if (inp)
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid,
@@ -335,7 +340,7 @@
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
if ( inp )
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_remove(struct super_block *sb, struct ViceFid *dirfid,
@@ -357,7 +362,7 @@
error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
if ( inp )
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_readlink(struct super_block *sb, struct ViceFid *fid,
@@ -389,7 +394,7 @@
if (inp) CODA_FREE(inp, insize);
CDEBUG(D_INODE, " result %d\n",error);
EXIT;
- return -error;
+ return error;
}
@@ -420,7 +425,7 @@
CODA_FREE(inp, insize);
CDEBUG(D_INODE, " result %d\n",error);
EXIT;
- return -error;
+ return error;
}
int venus_symlink(struct super_block *sb, struct ViceFid *fid,
@@ -458,7 +463,7 @@
CODA_FREE(inp, insize);
CDEBUG(D_INODE, " result %d\n",error);
EXIT;
- return -error;
+ return error;
}
int venus_fsync(struct super_block *sb, struct ViceFid *fid)
@@ -476,7 +481,7 @@
if ( inp )
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
int venus_access(struct super_block *sb, struct ViceFid *fid, int mask)
@@ -495,7 +500,7 @@
if (inp) CODA_FREE(inp, insize);
EXIT;
- return -error;
+ return error;
}
@@ -575,7 +580,7 @@
exit:
if (inp)
CODA_FREE(inp, insize);
- return -error;
+ return error;
}
/*
@@ -583,12 +588,6 @@
*
*/
-/*
- * coda_upcall will return a POSITIVE error in the case of
- * failed communication with Venus _or_ will peek at Venus
- * reply and return Venus' error, also POSITIVE.
- *
- */
static inline unsigned long coda_waitfor_upcall(struct vmsg *vmp)
{
struct wait_queue wait = { current, NULL };
@@ -608,18 +607,18 @@
if ( vmp->vm_flags & VM_WRITE )
break;
- if ( ! signal_pending(current) )
- schedule();
- /* signal is present: after timeout always return */
- if ( jiffies > vmp->vm_posttime + coda_timeout * HZ )
- break;
-
- /* if this process really wants to die, let it go */
- if ( sigismember(¤t->signal, SIGKILL) ||
- sigismember(¤t->signal, SIGINT) )
- break;
- else
- schedule();
+ if ( !coda_hard && signal_pending(current) ) {
+ /* if this process really wants to die, let it go */
+ if ( sigismember(&(current->signal), SIGKILL) ||
+ sigismember(&(current->signal), SIGINT) )
+ break;
+ /* signal is present: after timeout always return
+ really smart idea, probably useless ... */
+ if ( jiffies > vmp->vm_posttime + coda_timeout * HZ )
+ break;
+ }
+ schedule();
+
}
remove_wait_queue(&vmp->vm_sleep, &wait);
current->state = TASK_RUNNING;
@@ -630,6 +629,16 @@
}
+/*
+ * coda_upcall will return an error in the case of
+ * failed communication with Venus _or_ will peek at Venus
+ * reply and return Venus' error.
+ *
+ * As venus has 2 types of errors, normal errors (positive) and internal
+ * errors (negative), normal errors are negated, while internal errors
+ * are all mapped to -EINTR, while showing a nice warning message. (jh)
+ *
+ */
static int coda_upcall(struct coda_sb_info *sbi,
int inSize, int *outSize,
union inputArgs *buffer)
@@ -643,13 +652,13 @@
ENTRY;
if (sbi->sbi_vcomm == NULL) {
- return ENODEV;
+ return -ENODEV;
}
vcommp = sbi->sbi_vcomm;
if (!vcomm_open(vcommp))
- return(ENODEV);
+ return -ENXIO;
/* Format the request message. */
CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
@@ -693,9 +702,14 @@
if (vcomm_open(vcommp)) { /* i.e. Venus is still alive */
/* Op went through, interrupt or not... */
if (vmp->vm_flags & VM_WRITE) {
- error = 0;
out = (union outputArgs *)vmp->vm_data;
- error = out->oh.result;
+ /* 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",
out->oh.unique, out->oh.opcode, out->oh.result, out);
@@ -708,48 +722,49 @@
"Interrupted before read:(op,un) (%d.%d), flags = %x\n",
vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
coda_q_remove(&(vmp->vm_chain));
- error = ERESTARTNOHAND;
+ /* perhaps the best way to convince the app to
+ give up? */
+ error = -EINTR;
goto exit;
}
if ( (vmp->vm_flags & VM_READ) && signal_pending(current) ) {
- /* interrupted after Venus did its read, send signal */
- union inputArgs *dog;
- struct vmsg *svmp;
-
- CDEBUG(D_UPCALL,
- "Sending Venus a signal: op = %d.%d, flags = %x\n",
- vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
-
- coda_q_remove(&(vmp->vm_chain));
- error = ERESTARTNOHAND;
-
- CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
- CODA_ALLOC((svmp->vm_data), char *, sizeof(struct cfs_in_hdr));
-
- dog = (union inputArgs *)svmp->vm_data;
- dog->ih.opcode = CFS_SIGNAL;
- dog->ih.unique = vmp->vm_unique;
-
- svmp->vm_flags = 0;
- svmp->vm_opcode = dog->ih.opcode;
- svmp->vm_unique = dog->ih.unique;
- svmp->vm_inSize = sizeof(struct cfs_in_hdr);
- svmp->vm_outSize = sizeof(struct cfs_in_hdr);
- CDEBUG(D_UPCALL,
- "coda_upcall: enqueing signal msg (%d, %d)\n",
- svmp->vm_opcode, svmp->vm_unique);
-
- /* insert at head of queue! */
- coda_q_insert(&(svmp->vm_chain), vcommp->vc_pending.forw);
- wake_up_interruptible(&vcommp->vc_waitq);
+ /* interrupted after Venus did its read, send signal */
+ union inputArgs *dog;
+ struct vmsg *svmp;
+
+ CDEBUG(D_UPCALL,
+ "Sending Venus a signal: op = %d.%d, flags = %x\n",
+ vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
+
+ coda_q_remove(&(vmp->vm_chain));
+ error = -EINTR;
+ CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
+ CODA_ALLOC((svmp->vm_data), char *, sizeof(struct cfs_in_hdr));
+
+ dog = (union inputArgs *)svmp->vm_data;
+ dog->ih.opcode = CFS_SIGNAL;
+ dog->ih.unique = vmp->vm_unique;
+
+ svmp->vm_flags = 0;
+ svmp->vm_opcode = dog->ih.opcode;
+ svmp->vm_unique = dog->ih.unique;
+ svmp->vm_inSize = sizeof(struct cfs_in_hdr);
+ svmp->vm_outSize = sizeof(struct cfs_in_hdr);
+ CDEBUG(D_UPCALL,
+ "coda_upcall: enqueing signal msg (%d, %d)\n",
+ svmp->vm_opcode, svmp->vm_unique);
+
+ /* insert at head of queue! */
+ coda_q_insert(&(svmp->vm_chain), vcommp->vc_pending.forw);
+ wake_up_interruptible(&vcommp->vc_waitq);
} else {
printk("Coda: Strange interruption..\n");
- error = EINTR;
+ error = -EINTR;
}
} else { /* If venus died i.e. !VC_OPEN(vcommp) */
printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
- error = ENODEV;
+ error = -ENODEV;
}
exit:
@@ -759,7 +774,13 @@
return error;
}
-
+/*
+ The statements below are part of the Coda opportunistic
+ programming -- taken from the Mach/BSD kernel code for Coda.
+ You don't get correct semantics by stating what needs to be
+ done without guaranteeing the invariants needed for it to happen.
+ When will be have time to find out what exactly is going on? (pjb)
+*/
/*
@@ -790,7 +811,7 @@
int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
{
- /* Handle invalidation requests. */
+ /* Handle invalidation requests. */
if ( !sb ) {
printk("coda_downcall: opcode %d, no sb!\n", opcode);
return 0;
@@ -821,15 +842,19 @@
case CFS_ZAPDIR : {
struct inode *inode;
ViceFid *fid = &out->cfs_zapdir.CodaFid;
- CDEBUG(D_DOWNCALL, "zapdir: fid = %s\n", coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid));
clstats(CFS_ZAPDIR);
inode = coda_fid_to_inode(fid, sb);
- if ( inode ) {
+ if (inode) {
+ CDEBUG(D_DOWNCALL, "zapdir: inode = %ld children flagged\n",
+ inode->i_ino);
+ coda_purge_children(inode);
+ CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino);
coda_flag_inode(inode, C_VATTR);
- coda_cache_clear_inode(inode);
- coda_flag_alias_children(inode, C_PURGE);
- }
+ } else
+ CDEBUG(D_DOWNCALL, "zapdir: no inode\n");
+
return(0);
}
@@ -840,9 +865,10 @@
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);
coda_flag_inode(inode, C_VATTR);
- coda_cache_clear_inode(inode);
- }
+ } else
+ CDEBUG(D_DOWNCALL, "zapfile: no inode\n");
return 0;
}
@@ -853,19 +879,26 @@
clstats(CFS_PURGEFID);
inode = coda_fid_to_inode(fid, sb);
if ( inode ) {
- coda_flag_inode(inode, C_PURGE);
- coda_cache_clear_inode(inode);
- }
+ CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", inode->i_ino);
+ coda_purge_children(inode);
+ coda_purge_dentries(inode);
+ }else
+ CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
return 0;
}
case CFS_REPLACE : {
- printk("CFS_REPLACCE\n");
+ struct inode *inode;
+ ViceFid *fid = &out->cfs_replace.OldFid;
clstats(CFS_REPLACE);
CDEBUG(D_DOWNCALL, "CFS_REPLACE\n");
- coda_cache_clear_all(sb);
- shrink_dcache_sb(sb);
- return (0);
+ inode = coda_fid_to_inode(fid, sb);
+ if ( inode ) {
+ CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino);
+ coda_purge_dentries(inode);
+ }else
+ CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
+ return 0;
}
}
return 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov