diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 06:06:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 06:06:25 +0000 |
commit | aa944aa3453e47706685bc562711a9e87375941e (patch) | |
tree | 8fb37a65f205a90412917ca2b91c429263ef1790 /fs/coda/upcall.c | |
parent | 967c65a99059fd459b956c1588ce0ba227912c4e (diff) |
Merge with Linux 2.1.72, part 2.
The new signal code with exception of the code for the rt signals.
The definitions in <asm/siginfo.h> and <asm/ucontext.h> are currently
just stolen from the Alpha and will need to be overhauled.
Diffstat (limited to 'fs/coda/upcall.c')
-rw-r--r-- | fs/coda/upcall.c | 747 |
1 files changed, 747 insertions, 0 deletions
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c new file mode 100644 index 000000000..43536f622 --- /dev/null +++ b/fs/coda/upcall.c @@ -0,0 +1,747 @@ +/* + * Mostly platform independent upcall operations to Venus: + * -- upcalls + * -- upcall routines + * + * Linux 2.0 version + * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk>, + * Michael Callahan <callahan@maths.ox.ac.uk> + * + * Redone for Linux 2.1 + * Copyright (C) 1997 Carnegie Mellon University + * + * Carnegie Mellon University encourages users of this code to contribute + * improvements to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>. + */ + +#include <asm/system.h> +#include <asm/segment.h> + + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/stat.h> +#include <linux/errno.h> +#include <linux/locks.h> +#include <linux/string.h> +#include <asm/uaccess.h> +#include <linux/vmalloc.h> +#include <asm/segment.h> + +#include <linux/coda.h> +#include <linux/coda_linux.h> +#include <linux/coda_psdev.h> +#include <linux/coda_cnode.h> +#include <linux/coda_namecache.h> + + +static vcsize = (sizeof(struct inputArgs) > sizeof(struct outputArgs)) ? + sizeof(struct inputArgs): sizeof(struct outputArgs); + +/* the upcalls */ +int venus_rootfid(struct super_block *sb, ViceFid *fidp) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int error=0; + int size; +ENTRY; + + UPARG(vcsize, CFS_ROOT); + error = coda_upcall(coda_sbp(sb), VC_IN_NO_DATA, &size, inp); + + if (error) { + printk("coda_get_rootfid: error %d\n", error); + } else { + *fidp = (ViceFid) outp->d.cfs_root.VFid; + CDEBUG(D_SUPER, "VolumeId: %lx, VnodeId: %lx.\n", + fidp->Volume, fidp->Vnode); + } + + if (inp) CODA_FREE(inp, VC_IN_NO_DATA); + EXIT; + return -error; +} + +int venus_getattr(struct super_block *sb, struct ViceFid *fid, + struct coda_vattr *attr) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int size, error; +ENTRY; + + UPARG(vcsize, CFS_GETATTR); + inp->d.cfs_getattr.VFid = *fid; + error = coda_upcall(coda_sbp(sb), vcsize, &size, inp); + + if ( !error ) + *attr = (struct coda_vattr) outp->d.cfs_getattr.attr; + + if (inp) CODA_FREE(inp, sizeof(struct inputArgs)); + EXIT; + return -error; +} + +int venus_setattr(struct super_block *sb, struct ViceFid *fid, + struct coda_vattr *vattr) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int error, size; + + UPARG(vcsize, CFS_SETATTR); + + inp->d.cfs_setattr.VFid = *fid; + inp->d.cfs_setattr.attr = *vattr; + + error = coda_upcall(coda_sbp(sb), vcsize, &size, inp); + + CDEBUG(D_SUPER, " result %ld\n", outp->result); + if ( inp ) CODA_FREE(inp, vcsize); + return -error; +} + +int venus_lookup(struct super_block *sb, struct ViceFid *fid, + const char *name, int length, int * type, + struct ViceFid *resfid) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int insize, size, error=0, payload_offset; + + insize = VC_INSIZE(cfs_lookup_in) + CFS_MAXNAMLEN +1; + UPARG(insize, CFS_LOOKUP); + + inp->d.cfs_lookup.VFid = *fid; + /* send Venus a null terminated string */ + payload_offset = VC_INSIZE(cfs_lookup_in); + inp->d.cfs_lookup.name = (char *) payload_offset; + memcpy((char *)inp + payload_offset, name, length); + *((char *)inp + payload_offset + length) = '\0'; + + size = payload_offset + length + 1; + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if ( !error ) { + *resfid = outp->d.cfs_lookup.VFid; + *type = outp->d.cfs_lookup.vtype; + } + if (inp) CODA_FREE(inp, insize); + + return -error; +} + + +int venus_release(struct super_block *sb, struct ViceFid *fid, int flags) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int size = sizeof(struct outputArgs); + int error = 0; + + CODA_ALLOC(inp, struct inputArgs *, sizeof(struct inputArgs)); + outp = (struct outputArgs *)inp; + INIT_IN(inp, CFS_CLOSE); + coda_load_creds(&(inp->cred)); + + inp->d.cfs_close.VFid = *fid; + inp->d.cfs_close.flags = flags; + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if (inp) CODA_FREE(inp, sizeof(struct inputArgs)); + return -error; +} + +int venus_open(struct super_block *sb, struct ViceFid *fid, + int flags, ino_t *ino, dev_t *dev) +{ + struct inputArgs *inp = NULL; + struct outputArgs *outp = NULL; + int size = sizeof(struct inputArgs); + int error = 0; + + CODA_ALLOC(inp, struct inputArgs *, sizeof(struct inputArgs)); + outp = (struct outputArgs *)inp; + INIT_IN(inp, CFS_OPEN); + coda_load_creds(&(inp->cred)); + + inp->d.cfs_open.VFid = *fid; + inp->d.cfs_open.flags = flags; + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if ( !error ) { + *ino = outp->d.cfs_open.inode; + *dev = outp->d.cfs_open.dev; + } else { + *ino = 0; + *dev = 0; + } + + if (inp) + CODA_FREE(inp, sizeof(struct inputArgs)); + + return -error; +} + +int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid, + const char *name, int length, + struct ViceFid *newfid, struct coda_vattr *attrs) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int error=0, size, payload_offset; + + payload_offset = VC_INSIZE(cfs_mkdir_in); + size = CFS_MAXNAMLEN + payload_offset; + UPARG(size, CFS_MKDIR); + + inp->d.cfs_mkdir.VFid = *dirfid; + inp->d.cfs_mkdir.attr = *attrs; + inp->d.cfs_mkdir.name = (char *) payload_offset; + + /* Venus must get null terminated string */ + memcpy((char *)inp + payload_offset, name, length); + *((char *)inp + payload_offset + length) = '\0'; + size = payload_offset + length + 1; + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + *attrs = outp->d.cfs_mkdir.attr; + *newfid = outp->d.cfs_mkdir.VFid; + + if (inp) + CODA_FREE(inp, size); + return -error; +} + + +int venus_rename(struct super_block *sb, struct ViceFid *old_fid, + struct ViceFid *new_fid, size_t old_length, + size_t new_length, const char *old_name, const char *new_name) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int error, offset, size, s; + + size = 2*CFS_MAXNAMLEN + VC_INSIZE(cfs_rename_in) +8; + UPARG(size, CFS_RENAME); + + inp->d.cfs_rename.sourceFid = *old_fid; + inp->d.cfs_rename.destFid = *new_fid; + + offset = VC_INSIZE(cfs_rename_in); + + /* Venus must receive an null terminated string */ + inp->d.cfs_rename.srcname = (char *)offset; + s = ( old_length & ~0x3) +4; /* round up to word boundary */ + memcpy((char *)inp + offset, old_name, old_length); + *((char *)inp + offset + old_length) = '\0'; + + /* another null terminated string for Venus */ + offset += s; + inp->d.cfs_rename.destname = (char *)offset; + s = ( new_length & ~0x3) +4; /* round up to word boundary */ + memcpy((char *)inp + offset, new_name, new_length); + *((char *)inp + offset + new_length) = '\0'; + + size += s; + CDEBUG(D_INODE, "destname in packet: %s\n", + (char *)inp + (int) inp->d.cfs_rename.destname); + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if (inp) CODA_FREE(inp, size); + return -error; +} + +int venus_create(struct super_block *sb, struct ViceFid *dirfid, + const char *name, int length, int excl, int mode, + struct ViceFid *newfid, struct coda_vattr *attrs) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int error=0, size, payload_offset; + + payload_offset = VC_INSIZE(cfs_create_in); + size = CFS_MAXNAMLEN + payload_offset; + UPARG(size, CFS_CREATE); + + inp->d.cfs_create.VFid = *dirfid; + inp->d.cfs_create.attr.va_mode = mode; + inp->d.cfs_create.excl = excl; + inp->d.cfs_create.mode = mode; + inp->d.cfs_create.name = (char *) payload_offset; + + /* Venus must get null terminated string */ + memcpy((char *)inp + payload_offset, name, length); + *((char *)inp + payload_offset + length) = '\0'; + size = payload_offset + length + 1; + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + *attrs = outp->d.cfs_create.attr; + *newfid = outp->d.cfs_create.VFid; + + if (inp) + CODA_FREE(inp, size); + return -error; +} + +int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid, + const char *name, int length) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int error=0, size, payload_offset; + + payload_offset = VC_INSIZE(cfs_rmdir_in); + size = CFS_MAXNAMLEN + payload_offset; + UPARG(size, CFS_RMDIR); + + inp->d.cfs_rmdir.VFid = *dirfid; + inp->d.cfs_rmdir.name = (char *) payload_offset; + memcpy((char *)inp + payload_offset, name, size); + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + if ( inp ) + CODA_FREE(inp, size); + return -error; +} + +int venus_remove(struct super_block *sb, struct ViceFid *dirfid, + const char *name, int length) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int error=0, size, payload_offset; + + payload_offset = VC_INSIZE(cfs_remove_in); + size = CFS_MAXNAMLEN + payload_offset; + UPARG(size, CFS_REMOVE); + + inp->d.cfs_remove.VFid = *dirfid; + inp->d.cfs_remove.name = (char *)payload_offset; + memcpy((char *)inp + payload_offset, name, size); + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + if ( inp ) + CODA_FREE(inp, size); + return -error; +} + +int venus_readlink(struct super_block *sb, struct ViceFid *fid, + char *buffer, int *length) +{ + int error, size, retlen; + char *result; + struct inputArgs *inp; + struct outputArgs *outp; + char *buf=NULL; /*[CFS_MAXNAMLEN + VC_INSIZE(cfs_readlink_in)];*/ + + size = CFS_MAXPATHLEN + VC_INSIZE(cfs_readlink_in); + UPARG(size, CFS_READLINK); + inp->d.cfs_readlink.VFid = *fid; + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if (! error) { + retlen = outp->d.cfs_readlink.count; + if ( retlen > *length ) + retlen = *length; + *length = retlen; + result = (char *)outp + (int)outp->d.cfs_readlink.data; + memcpy(buffer, result, retlen); + } + + if (inp) CODA_FREE(buf, size); + CDEBUG(D_INODE, " result %d\n",error); + EXIT; + return -error; +} + +int venus_link(struct super_block *sb, struct ViceFid *fid, + struct ViceFid *dirfid, const char *name, int len ) +{ + int error, payload_offset, size; + struct inputArgs *inp; + struct outputArgs *outp; + + size = CFS_MAXNAMLEN + sizeof(struct inputArgs); + UPARG(size, CFS_LINK); + + payload_offset = (VC_INSIZE(cfs_link_in)); + inp->d.cfs_link.sourceFid = *fid; + inp->d.cfs_link.destFid = *dirfid; + inp->d.cfs_link.tname = (char *)payload_offset; + + /* make sure strings are null terminated */ + memcpy((char *)inp + payload_offset, name, len); + *((char *)inp + payload_offset + len) = '\0'; + size = payload_offset + len + 1; + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if (inp) + CODA_FREE(inp, size); + CDEBUG(D_INODE, " result %d\n",error); + EXIT; + return -error; +} + +int venus_symlink(struct super_block *sb, struct ViceFid *fid, + const char *name, int len, + const char *symname, int symlen) +{ + int error, payload_offset, size, s; + struct inputArgs *inp; + struct outputArgs *outp; + + + /* + * allocate space for regular input, + * plus 1 path and 1 name, plus padding + */ + size = sizeof(struct inputArgs) + CFS_MAXNAMLEN + CFS_MAXNAMLEN + 8; + UPARG(size, CFS_SYMLINK); + + /* inp->d.cfs_symlink.attr = *tva; XXXXXX */ + inp->d.cfs_symlink.VFid = *fid; + + payload_offset = VC_INSIZE(cfs_symlink_in); + inp->d.cfs_symlink.srcname =(char*) payload_offset; + + s = ( symlen & ~0x3 ) + 4; /* Round up to word boundary. */ + + /* don't forget to copy out the null termination */ + memcpy((char *)inp + payload_offset, symname, symlen); + *((char *)inp + payload_offset + symlen) = '\0'; + + payload_offset += s; + inp->d.cfs_symlink.tname = (char *) payload_offset; + s = (len & ~0x3) + 4; /* Round up to word boundary. */ + memcpy((char *)inp + payload_offset, name, len); + *((char *)inp + payload_offset + len) = '\0'; + + size = payload_offset + s; + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if (inp) + CODA_FREE(inp, size); + CDEBUG(D_INODE, " result %d\n",error); + EXIT; + return -error; +} + +int venus_access(struct super_block *sb, struct ViceFid *fid, int mask) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int size; + int error; + + size = sizeof(struct inputArgs); + UPARG(size, CFS_ACCESS); + + inp->d.cfs_access.VFid = *fid; + inp->d.cfs_access.flags = mask << 6; + + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if (inp) CODA_FREE(inp, sizeof(struct inputArgs)); + EXIT; + return -error; +} + + +int venus_pioctl(struct super_block *sb, struct ViceFid *fid, + unsigned int cmd, struct PioctlData *data) +{ + struct inputArgs *inp; + struct outputArgs *outp; + int size, error = 0; + int iocsize; + char str[50]; + + size = VC_MAXMSGSIZE; + UPARG(size, CFS_IOCTL); + + /* build packet for Venus */ + if (data->vi.in_size > VC_DATASIZE) { + error = EINVAL; + goto exit; + } + + inp->d.cfs_ioctl.VFid = *fid; + + /* the cmd field was mutated by increasing its size field to + * reflect the path and follow args. We need to subtract that + * out before sending the command to Venus. */ + inp->d.cfs_ioctl.cmd = (cmd & ~(IOCPARM_MASK << 16)); + iocsize = ((cmd >> 16) & IOCPARM_MASK) - sizeof(char *) - sizeof(int); + inp->d.cfs_ioctl.cmd |= (iocsize & IOCPARM_MASK) << 16; + + /* in->d.cfs_ioctl.rwflag = flag; */ + inp->d.cfs_ioctl.len = data->vi.in_size; + inp->d.cfs_ioctl.data = (char *)(VC_INSIZE(cfs_ioctl_in)); + + /* get the data out of user space */ + if ( copy_from_user((char*)inp + (int)inp->d.cfs_ioctl.data, + data->vi.in, data->vi.in_size) ) { + error = EINVAL; + goto exit; + } + error = coda_upcall(coda_sbp(sb), size, &size, inp); + + if (error) { + printk("coda_pioctl: Venus returns: %d for %s\n", + error, coda_f2s(fid, str)); + goto exit; + } + + /* Copy out the OUT buffer. */ + if (outp->d.cfs_ioctl.len > data->vi.out_size) { + CDEBUG(D_FILE, "return len %d <= request len %d\n", + outp->d.cfs_ioctl.len, + data->vi.out_size); + error = EINVAL; + } else { + if (copy_to_user(data->vi.out, + (char *)outp + (int)outp->d.cfs_ioctl.data, + data->vi.out_size)) { + error = EINVAL; + goto exit; + } + } + + exit: + if (inp) + CODA_FREE(inp, VC_MAXMSGSIZE); + return -error; +} + +/* + * coda_upcall and coda_downcall routines. + * + */ + +/* + * 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. + * + */ +int coda_upcall(struct coda_sb_info *sbi, int inSize, int *outSize, + struct inputArgs *buffer) +{ + struct vcomm *vcommp; + struct outputArgs *out; + struct vmsg *vmp; + int error = 0; + +ENTRY; + + if (sbi->sbi_vcomm == NULL) { + return ENODEV; + } + vcommp = sbi->sbi_vcomm; + + clstats(((struct inputArgs *)buffer)->opcode); + + if (!vcomm_open(vcommp)) + return(ENODEV); + + /* Format the request message. */ + CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg)); + vmp->vm_data = (void *)buffer; + vmp->vm_flags = 0; + vmp->vm_inSize = inSize; + vmp->vm_outSize = *outSize ? *outSize : inSize; + vmp->vm_opcode = ((struct inputArgs *)buffer)->opcode; + vmp->vm_unique = ++vcommp->vc_seq; + vmp->vm_sleep = NULL; + + /* Fill in the common input args. */ + ((struct inputArgs *)buffer)->unique = vmp->vm_unique; + + /* Append msg to pending queue and poke Venus. */ + + INSQUE(vmp->vm_chain, vcommp->vc_pending); + CDEBUG(D_UPCALL, + "Proc %d wake Venus for(opc,uniq) =(%d,%d) msg at %x.zzz.\n", + current->pid, vmp->vm_opcode, vmp->vm_unique, (int)vmp); + + wake_up_interruptible(&vcommp->vc_waitq); + /* We can be interrupted while we wait for Venus to process + * our request. If the interrupt occurs before Venus has read + * the request, we dequeue and return. If it occurs after the + * read but before the reply, we dequeue, send a signal + * message, and return. If it occurs after the reply we ignore + * it. In no case do we want to restart the syscall. If it + * was interrupted by a venus shutdown (vcclose), return + * ENODEV. */ + + /* Ignore return, We have to check anyway */ + + + interruptible_sleep_on(&vmp->vm_sleep); + CDEBUG(D_UPCALL, + "..process %d woken up by Venus for vmp at 0x%x, data at %x\n", + current->pid, (int)vmp, (int)vmp->vm_data); + 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 = (struct outputArgs *)vmp->vm_data; + error = out->result; + CDEBUG(D_UPCALL, + "upcall: (u,o,r) (%ld, %ld, %ld) out at %x\n", + out->unique, out->opcode, out->result, (int)out); + *outSize = vmp->vm_outSize; + goto exit; + } + if (!(vmp->vm_flags & VM_READ)) { + /* Interrupted before venus read it. */ + CDEBUG(D_UPCALL, + "Interrupted before read:(op,un) (%d.%d), flags = %x\n", + vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags); + REMQUE(vmp->vm_chain); + error = ERESTARTSYS; + goto exit; + } + if ( vmp->vm_flags & VM_READ) { + /* interrupted after Venus did its read, send signal */ + struct 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); + + REMQUE(vmp->vm_chain); + error = ERESTARTSYS; + + CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg)); + CODA_ALLOC((svmp->vm_data), char *, VC_IN_NO_DATA); + + CDEBUG(D_UPCALL, + "coda_upcall: enqueing signal msg (%d, %d)\n", + svmp->vm_opcode, svmp->vm_unique); + dog = (struct inputArgs *)svmp->vm_data; + dog->opcode = CFS_SIGNAL; + dog->unique = vmp->vm_unique; + + svmp->vm_flags = 0; + svmp->vm_opcode = dog->opcode; + svmp->vm_unique = dog->unique; + svmp->vm_inSize = VC_IN_NO_DATA; + svmp->vm_outSize = VC_IN_NO_DATA; + + /* insert at head of queue! */ + INSQUE(svmp->vm_chain, vcommp->vc_pending); + wake_up_interruptible(&vcommp->vc_waitq); + } + } else { /* If venus died i.e. !VC_OPEN(vcommp) */ + printk("coda_upcall: Venus dead upon (op,un) (%d.%d) flags %d\n", + vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags); + + /* if (! (vmp->vm_flags & VM_WRITE) ) */ + error = ENODEV; + } + + exit: + CODA_FREE(vmp, sizeof(struct vmsg)); + if (error) + badclstats(); + return error; +} + + + + +/* + * There are 7 cases where cache invalidations occur. The semantics + * of each is listed here: + * + * CFS_FLUSH -- flush all entries from the name cache and the cnode cache. + * CFS_PURGEUSER -- flush all entries from the name cache for a specific user + * This call is a result of token expiration. + * Linux does a cfsnc_flush since cred's are not maintained. + * + * 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 -- in linux the same as zap file (no creds). + * + * The next is a result of Venus detecting an inconsistent file. + * CFS_PURGEFID -- flush the attribute for the file + * If it is a dir (odd vnode), purge its + * children from the namecache + * remove the file from the namecache. + * + * The last allows Venus to replace local fids with global ones + * during reintegration. + * + * CFS_REPLACE -- replace one ViceFid with another throughout the name cache */ + +int coda_downcall(int opcode, struct outputArgs * out) +{ + + /* Handle invalidate requests. */ + switch (opcode) { + case CFS_FLUSH : { + clstats(CFS_FLUSH); + cfsnc_flush(); + return(0); + } + case CFS_PURGEUSER : { + clstats(CFS_PURGEUSER); + cfsnc_flush(); + return(0); + } + case CFS_ZAPDIR : { + ViceFid *fid = &out->d.cfs_zapdir.CodaFid; + clstats(CFS_ZAPDIR); + cfsnc_zapfid(fid); + cfsnc_zapParentfid(fid); + CDEBUG(D_UPCALL, "zapdir: fid = (%lx.%lx.%lx), \n",fid->Volume, + fid->Vnode, + fid->Unique); + return(0); + } + case CFS_ZAPVNODE : { + clstats(CFS_ZAPVNODE); + cfsnc_zapfid(&out->d.cfs_zapvnode.VFid); + return(0); + } + case CFS_ZAPFILE : { + clstats(CFS_ZAPFILE); + cfsnc_zapfid(&out->d.cfs_zapfile.CodaFid); + return 0; + } + case CFS_PURGEFID : { + ViceFid *fid = &out->d.cfs_purgefid.CodaFid; + clstats(CFS_PURGEFID); + cfsnc_zapfid(fid); + cfsnc_zapParentfid(fid); + CDEBUG(D_UPCALL, "purgefid: fid = (%lx.%lx.%lx)\n", + fid->Volume, fid->Vnode, + fid->Unique); + return 0; + } + case CFS_REPLACE : { + clstats(CFS_REPLACE); + cfsnc_replace(&out->d.cfs_replace.OldFid, + &out->d.cfs_replace.NewFid); + return (0); + } + } + return 0; +} + + |