2 * Mostly platform independent upcall operations to Venus:
7 * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk>,
8 * Michael Callahan <callahan@maths.ox.ac.uk>
10 * Redone for Linux 2.1
11 * Copyright (C) 1997 Carnegie Mellon University
13 * Carnegie Mellon University encourages users of this code to contribute
14 * improvements to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
17 #include <asm/system.h>
18 #include <asm/signal.h>
19 #include <linux/signal.h>
21 #include <linux/types.h>
22 #include <linux/kernel.h>
24 #include <linux/time.h>
26 #include <linux/file.h>
27 #include <linux/stat.h>
28 #include <linux/errno.h>
29 #include <linux/string.h>
30 #include <asm/uaccess.h>
31 #include <linux/vmalloc.h>
32 #include <linux/vfs.h>
34 #include <linux/coda.h>
35 #include <linux/coda_linux.h>
36 #include <linux/coda_psdev.h>
37 #include <linux/coda_fs_i.h>
38 #include <linux/coda_cache.h>
39 #include <linux/coda_proc.h>
41 #define upc_alloc() kmalloc(sizeof(struct upc_req), GFP_KERNEL)
42 #define upc_free(r) kfree(r)
44 static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize,
45 union inputArgs *buffer);
47 static void *alloc_upcall(int opcode, int size)
51 CODA_ALLOC(inp, union inputArgs *, size);
53 return ERR_PTR(-ENOMEM);
55 inp->ih.opcode = opcode;
56 inp->ih.pid = current->pid;
57 inp->ih.pgid = process_group(current);
58 #ifdef CONFIG_CODA_FS_OLD_API
59 memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
60 inp->ih.cred.cr_fsuid = current->fsuid;
62 inp->ih.uid = current->fsuid;
69 inp = (union inputArgs *)alloc_upcall(op, insize); \
70 if (IS_ERR(inp)) { return PTR_ERR(inp); }\
71 outp = (union outputArgs *)(inp); \
75 #define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)
76 #define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)
77 #define SIZE(tag) max_t(unsigned int, INSIZE(tag), OUTSIZE(tag))
81 int venus_rootfid(struct super_block *sb, struct CodaFid *fidp)
84 union outputArgs *outp;
85 int insize, outsize, error;
90 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
93 printk("coda_get_rootfid: error %d\n", error);
95 *fidp = outp->coda_root.VFid;
98 CODA_FREE(inp, insize);
102 int venus_getattr(struct super_block *sb, struct CodaFid *fid,
103 struct coda_vattr *attr)
105 union inputArgs *inp;
106 union outputArgs *outp;
107 int insize, outsize, error;
109 insize = SIZE(getattr);
111 inp->coda_getattr.VFid = *fid;
113 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
115 *attr = outp->coda_getattr.attr;
117 CODA_FREE(inp, insize);
121 int venus_setattr(struct super_block *sb, struct CodaFid *fid,
122 struct coda_vattr *vattr)
124 union inputArgs *inp;
125 union outputArgs *outp;
126 int insize, outsize, error;
128 insize = SIZE(setattr);
131 inp->coda_setattr.VFid = *fid;
132 inp->coda_setattr.attr = *vattr;
134 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
136 CODA_FREE(inp, insize);
140 int venus_lookup(struct super_block *sb, struct CodaFid *fid,
141 const char *name, int length, int * type,
142 struct CodaFid *resfid)
144 union inputArgs *inp;
145 union outputArgs *outp;
146 int insize, outsize, error;
149 offset = INSIZE(lookup);
150 insize = max_t(unsigned int, offset + length +1, OUTSIZE(lookup));
153 inp->coda_lookup.VFid = *fid;
154 inp->coda_lookup.name = offset;
155 inp->coda_lookup.flags = CLU_CASE_SENSITIVE;
156 /* send Venus a null terminated string */
157 memcpy((char *)(inp) + offset, name, length);
158 *((char *)inp + offset + length) = '\0';
160 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
162 *resfid = outp->coda_lookup.VFid;
163 *type = outp->coda_lookup.vtype;
165 CODA_FREE(inp, insize);
169 int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
172 union inputArgs *inp;
173 union outputArgs *outp;
174 int insize, outsize, error;
175 #ifdef CONFIG_CODA_FS_OLD_API
176 struct coda_cred cred = { 0, };
180 insize = SIZE(store);
183 #ifdef CONFIG_CODA_FS_OLD_API
184 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
189 inp->coda_store.VFid = *fid;
190 inp->coda_store.flags = flags;
192 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
194 CODA_FREE(inp, insize);
198 int venus_release(struct super_block *sb, struct CodaFid *fid, int flags)
200 union inputArgs *inp;
201 union outputArgs *outp;
202 int insize, outsize, error;
204 insize = SIZE(release);
207 inp->coda_release.VFid = *fid;
208 inp->coda_release.flags = flags;
210 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
212 CODA_FREE(inp, insize);
216 int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
219 union inputArgs *inp;
220 union outputArgs *outp;
221 int insize, outsize, error;
222 #ifdef CONFIG_CODA_FS_OLD_API
223 struct coda_cred cred = { 0, };
227 insize = SIZE(release);
230 #ifdef CONFIG_CODA_FS_OLD_API
231 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
236 inp->coda_close.VFid = *fid;
237 inp->coda_close.flags = flags;
239 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
241 CODA_FREE(inp, insize);
245 int venus_open(struct super_block *sb, struct CodaFid *fid,
246 int flags, struct file **fh)
248 union inputArgs *inp;
249 union outputArgs *outp;
250 int insize, outsize, error;
252 insize = SIZE(open_by_fd);
253 UPARG(CODA_OPEN_BY_FD);
255 inp->coda_open.VFid = *fid;
256 inp->coda_open.flags = flags;
258 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
260 *fh = outp->coda_open_by_fd.fh;
262 CODA_FREE(inp, insize);
266 int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
267 const char *name, int length,
268 struct CodaFid *newfid, struct coda_vattr *attrs)
270 union inputArgs *inp;
271 union outputArgs *outp;
272 int insize, outsize, error;
275 offset = INSIZE(mkdir);
276 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(mkdir));
279 inp->coda_mkdir.VFid = *dirfid;
280 inp->coda_mkdir.attr = *attrs;
281 inp->coda_mkdir.name = offset;
282 /* Venus must get null terminated string */
283 memcpy((char *)(inp) + offset, name, length);
284 *((char *)inp + offset + length) = '\0';
286 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
288 *attrs = outp->coda_mkdir.attr;
289 *newfid = outp->coda_mkdir.VFid;
291 CODA_FREE(inp, insize);
296 int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
297 struct CodaFid *new_fid, size_t old_length,
298 size_t new_length, const char *old_name,
299 const char *new_name)
301 union inputArgs *inp;
302 union outputArgs *outp;
303 int insize, outsize, error;
306 offset = INSIZE(rename);
307 insize = max_t(unsigned int, offset + new_length + old_length + 8,
311 inp->coda_rename.sourceFid = *old_fid;
312 inp->coda_rename.destFid = *new_fid;
313 inp->coda_rename.srcname = offset;
315 /* Venus must receive an null terminated string */
316 s = ( old_length & ~0x3) +4; /* round up to word boundary */
317 memcpy((char *)(inp) + offset, old_name, old_length);
318 *((char *)inp + offset + old_length) = '\0';
320 /* another null terminated string for Venus */
322 inp->coda_rename.destname = offset;
323 s = ( new_length & ~0x3) +4; /* round up to word boundary */
324 memcpy((char *)(inp) + offset, new_name, new_length);
325 *((char *)inp + offset + new_length) = '\0';
327 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
329 CODA_FREE(inp, insize);
333 int venus_create(struct super_block *sb, struct CodaFid *dirfid,
334 const char *name, int length, int excl, int mode, dev_t rdev,
335 struct CodaFid *newfid, struct coda_vattr *attrs)
337 union inputArgs *inp;
338 union outputArgs *outp;
339 int insize, outsize, error;
342 offset = INSIZE(create);
343 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(create));
346 inp->coda_create.VFid = *dirfid;
347 inp->coda_create.attr.va_mode = mode;
348 inp->coda_create.attr.va_rdev = huge_encode_dev(rdev);
349 inp->coda_create.excl = excl;
350 inp->coda_create.mode = mode;
351 inp->coda_create.name = offset;
353 /* Venus must get null terminated string */
354 memcpy((char *)(inp) + offset, name, length);
355 *((char *)inp + offset + length) = '\0';
357 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
359 *attrs = outp->coda_create.attr;
360 *newfid = outp->coda_create.VFid;
362 CODA_FREE(inp, insize);
366 int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
367 const char *name, int length)
369 union inputArgs *inp;
370 union outputArgs *outp;
371 int insize, outsize, error;
374 offset = INSIZE(rmdir);
375 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(rmdir));
378 inp->coda_rmdir.VFid = *dirfid;
379 inp->coda_rmdir.name = offset;
380 memcpy((char *)(inp) + offset, name, length);
381 *((char *)inp + offset + length) = '\0';
383 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
385 CODA_FREE(inp, insize);
389 int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
390 const char *name, int length)
392 union inputArgs *inp;
393 union outputArgs *outp;
394 int error=0, insize, outsize, offset;
396 offset = INSIZE(remove);
397 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(remove));
400 inp->coda_remove.VFid = *dirfid;
401 inp->coda_remove.name = offset;
402 memcpy((char *)(inp) + offset, name, length);
403 *((char *)inp + offset + length) = '\0';
405 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
407 CODA_FREE(inp, insize);
411 int venus_readlink(struct super_block *sb, struct CodaFid *fid,
412 char *buffer, int *length)
414 union inputArgs *inp;
415 union outputArgs *outp;
416 int insize, outsize, error;
420 insize = max_t(unsigned int,
421 INSIZE(readlink), OUTSIZE(readlink)+ *length + 1);
422 UPARG(CODA_READLINK);
424 inp->coda_readlink.VFid = *fid;
426 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
429 retlen = outp->coda_readlink.count;
430 if ( retlen > *length )
433 result = (char *)outp + (long)outp->coda_readlink.data;
434 memcpy(buffer, result, retlen);
435 *(buffer + retlen) = '\0';
438 CODA_FREE(inp, insize);
444 int venus_link(struct super_block *sb, struct CodaFid *fid,
445 struct CodaFid *dirfid, const char *name, int len )
447 union inputArgs *inp;
448 union outputArgs *outp;
449 int insize, outsize, error;
452 offset = INSIZE(link);
453 insize = max_t(unsigned int, offset + len + 1, OUTSIZE(link));
456 inp->coda_link.sourceFid = *fid;
457 inp->coda_link.destFid = *dirfid;
458 inp->coda_link.tname = offset;
460 /* make sure strings are null terminated */
461 memcpy((char *)(inp) + offset, name, len);
462 *((char *)inp + offset + len) = '\0';
464 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
466 CODA_FREE(inp, insize);
470 int venus_symlink(struct super_block *sb, struct CodaFid *fid,
471 const char *name, int len,
472 const char *symname, int symlen)
474 union inputArgs *inp;
475 union outputArgs *outp;
476 int insize, outsize, error;
479 offset = INSIZE(symlink);
480 insize = max_t(unsigned int, offset + len + symlen + 8, OUTSIZE(symlink));
483 /* inp->coda_symlink.attr = *tva; XXXXXX */
484 inp->coda_symlink.VFid = *fid;
486 /* Round up to word boundary and null terminate */
487 inp->coda_symlink.srcname = offset;
488 s = ( symlen & ~0x3 ) + 4;
489 memcpy((char *)(inp) + offset, symname, symlen);
490 *((char *)inp + offset + symlen) = '\0';
492 /* Round up to word boundary and null terminate */
494 inp->coda_symlink.tname = offset;
495 s = (len & ~0x3) + 4;
496 memcpy((char *)(inp) + offset, name, len);
497 *((char *)inp + offset + len) = '\0';
499 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
501 CODA_FREE(inp, insize);
505 int venus_fsync(struct super_block *sb, struct CodaFid *fid)
507 union inputArgs *inp;
508 union outputArgs *outp;
509 int insize, outsize, error;
514 inp->coda_fsync.VFid = *fid;
515 error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs),
518 CODA_FREE(inp, insize);
522 int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
524 union inputArgs *inp;
525 union outputArgs *outp;
526 int insize, outsize, error;
528 insize = SIZE(access);
531 inp->coda_access.VFid = *fid;
532 inp->coda_access.flags = mask;
534 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
536 CODA_FREE(inp, insize);
541 int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
542 unsigned int cmd, struct PioctlData *data)
544 union inputArgs *inp;
545 union outputArgs *outp;
546 int insize, outsize, error;
549 insize = VC_MAXMSGSIZE;
552 /* build packet for Venus */
553 if (data->vi.in_size > VC_MAXDATASIZE) {
558 if (data->vi.out_size > VC_MAXDATASIZE) {
563 inp->coda_ioctl.VFid = *fid;
565 /* the cmd field was mutated by increasing its size field to
566 * reflect the path and follow args. We need to subtract that
567 * out before sending the command to Venus. */
568 inp->coda_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));
569 iocsize = ((cmd >> 16) & PIOCPARM_MASK) - sizeof(char *) - sizeof(int);
570 inp->coda_ioctl.cmd |= (iocsize & PIOCPARM_MASK) << 16;
572 /* in->coda_ioctl.rwflag = flag; */
573 inp->coda_ioctl.len = data->vi.in_size;
574 inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
576 /* get the data out of user space */
577 if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
578 data->vi.in, data->vi.in_size) ) {
583 error = coda_upcall(coda_sbp(sb), SIZE(ioctl) + data->vi.in_size,
587 printk("coda_pioctl: Venus returns: %d for %s\n",
588 error, coda_f2s(fid));
592 if (outsize < (long)outp->coda_ioctl.data + outp->coda_ioctl.len) {
597 /* Copy out the OUT buffer. */
598 if (outp->coda_ioctl.len > data->vi.out_size) {
603 /* Copy out the OUT buffer. */
604 if (copy_to_user(data->vi.out,
605 (char *)outp + (long)outp->coda_ioctl.data,
606 outp->coda_ioctl.len)) {
612 CODA_FREE(inp, insize);
616 int venus_statfs(struct super_block *sb, struct kstatfs *sfs)
618 union inputArgs *inp;
619 union outputArgs *outp;
620 int insize, outsize, error;
622 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
625 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
628 sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
629 sfs->f_bfree = outp->coda_statfs.stat.f_bfree;
630 sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
631 sfs->f_files = outp->coda_statfs.stat.f_files;
632 sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
634 printk("coda_statfs: Venus returns: %d\n", error);
637 CODA_FREE(inp, insize);
642 * coda_upcall and coda_downcall routines.
646 static inline void coda_waitfor_upcall(struct upc_req *vmp,
647 struct venus_comm *vcommp)
649 DECLARE_WAITQUEUE(wait, current);
651 vmp->uc_posttime = jiffies;
653 add_wait_queue(&vmp->uc_sleep, &wait);
655 if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE )
656 set_current_state(TASK_INTERRUPTIBLE);
658 set_current_state(TASK_UNINTERRUPTIBLE);
661 if ( !vcommp->vc_inuse )
665 if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
668 if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE && signal_pending(current) ) {
669 /* if this process really wants to die, let it go */
670 if ( sigismember(&(current->pending.signal), SIGKILL) ||
671 sigismember(&(current->pending.signal), SIGINT) )
673 /* signal is present: after timeout always return
674 really smart idea, probably useless ... */
675 if ( jiffies - vmp->uc_posttime > coda_timeout * HZ )
680 remove_wait_queue(&vmp->uc_sleep, &wait);
681 set_current_state(TASK_RUNNING);
688 * coda_upcall will return an error in the case of
689 * failed communication with Venus _or_ will peek at Venus
690 * reply and return Venus' error.
692 * As venus has 2 types of errors, normal errors (positive) and internal
693 * errors (negative), normal errors are negated, while internal errors
694 * are all mapped to -EINTR, while showing a nice warning message. (jh)
697 static int coda_upcall(struct coda_sb_info *sbi,
698 int inSize, int *outSize,
699 union inputArgs *buffer)
701 struct venus_comm *vcommp;
702 union outputArgs *out;
706 vcommp = sbi->sbi_vcomm;
707 if ( !vcommp->vc_inuse ) {
708 printk("No pseudo device in upcall comms at %p\n", vcommp);
712 /* Format the request message. */
715 printk("Failed to allocate upc_req structure\n");
718 req->uc_data = (void *)buffer;
720 req->uc_inSize = inSize;
721 req->uc_outSize = *outSize ? *outSize : inSize;
722 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
723 req->uc_unique = ++vcommp->vc_seq;
724 init_waitqueue_head(&req->uc_sleep);
726 /* Fill in the common input args. */
727 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
729 /* Append msg to pending queue and poke Venus. */
730 list_add(&(req->uc_chain), vcommp->vc_pending.prev);
732 wake_up_interruptible(&vcommp->vc_waitq);
733 /* We can be interrupted while we wait for Venus to process
734 * our request. If the interrupt occurs before Venus has read
735 * the request, we dequeue and return. If it occurs after the
736 * read but before the reply, we dequeue, send a signal
737 * message, and return. If it occurs after the reply we ignore
738 * it. In no case do we want to restart the syscall. If it
739 * was interrupted by a venus shutdown (psdev_close), return
742 /* Go to sleep. Wake up on signals only after the timeout. */
743 coda_waitfor_upcall(req, vcommp);
745 if (vcommp->vc_inuse) { /* i.e. Venus is still alive */
746 /* Op went through, interrupt or not... */
747 if (req->uc_flags & REQ_WRITE) {
748 out = (union outputArgs *)req->uc_data;
749 /* here we map positive Venus errors to kernel errors */
750 error = -out->oh.result;
751 *outSize = req->uc_outSize;
754 if ( !(req->uc_flags & REQ_READ) && signal_pending(current)) {
755 /* Interrupted before venus read it. */
756 list_del(&(req->uc_chain));
757 /* perhaps the best way to convince the app to
762 if ( (req->uc_flags & REQ_READ) && signal_pending(current) ) {
763 /* interrupted after Venus did its read, send signal */
764 union inputArgs *sig_inputArgs;
765 struct upc_req *sig_req;
767 list_del(&(req->uc_chain));
769 sig_req = upc_alloc();
770 if (!sig_req) goto exit;
772 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
773 if (!sig_req->uc_data) {
779 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
780 sig_inputArgs->ih.opcode = CODA_SIGNAL;
781 sig_inputArgs->ih.unique = req->uc_unique;
783 sig_req->uc_flags = REQ_ASYNC;
784 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
785 sig_req->uc_unique = sig_inputArgs->ih.unique;
786 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
787 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
789 /* insert at head of queue! */
790 list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
791 wake_up_interruptible(&vcommp->vc_waitq);
793 printk("Coda: Strange interruption..\n");
796 } else { /* If venus died i.e. !VC_OPEN(vcommp) */
797 printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
798 req->uc_opcode, req->uc_unique, req->uc_flags);
808 The statements below are part of the Coda opportunistic
809 programming -- taken from the Mach/BSD kernel code for Coda.
810 You don't get correct semantics by stating what needs to be
811 done without guaranteeing the invariants needed for it to happen.
812 When will be have time to find out what exactly is going on? (pjb)
817 * There are 7 cases where cache invalidations occur. The semantics
818 * of each is listed here:
820 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
821 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
822 * This call is a result of token expiration.
824 * The next arise as the result of callbacks on a file or directory.
825 * CODA_ZAPFILE -- flush the cached attributes for a file.
827 * CODA_ZAPDIR -- flush the attributes for the dir and
828 * force a new lookup for all the children
832 * The next is a result of Venus detecting an inconsistent file.
833 * CODA_PURGEFID -- flush the attribute for the file
834 * purge it and its children from the dcache
836 * The last allows Venus to replace local fids with global ones
837 * during reintegration.
839 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
841 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
843 /* Handle invalidation requests. */
844 if ( !sb || !sb->s_root || !sb->s_root->d_inode)
850 coda_cache_clear_all(sb);
851 shrink_dcache_sb(sb);
852 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
856 case CODA_PURGEUSER : {
857 coda_cache_clear_all(sb);
863 struct CodaFid *fid = &out->coda_zapdir.CodaFid;
865 inode = coda_fid_to_inode(fid, sb);
867 coda_flag_inode_children(inode, C_PURGE);
868 coda_flag_inode(inode, C_VATTR);
875 case CODA_ZAPFILE : {
877 struct CodaFid *fid = &out->coda_zapfile.CodaFid;
878 inode = coda_fid_to_inode(fid, sb);
880 coda_flag_inode(inode, C_VATTR);
886 case CODA_PURGEFID : {
888 struct CodaFid *fid = &out->coda_purgefid.CodaFid;
889 inode = coda_fid_to_inode(fid, sb);
891 coda_flag_inode_children(inode, C_PURGE);
893 /* catch the dentries later if some are still busy */
894 coda_flag_inode(inode, C_PURGE);
895 d_prune_aliases(inode);
902 case CODA_REPLACE : {
904 struct CodaFid *oldfid = &out->coda_replace.OldFid;
905 struct CodaFid *newfid = &out->coda_replace.NewFid;
906 inode = coda_fid_to_inode(oldfid, sb);
908 coda_replace_fid(inode, oldfid, newfid);