2 * Mostly platform independent upcall operations to Venus:
10 * Redone for Linux 2.1
11 * Copyright (C) 1997 Carnegie Mellon University
13 * Carnegie Mellon University encourages users of this code to contribute
17 #include <asm/system.h>
18 #include <linux/signal.h>
19 #include <linux/sched.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
23 #include <linux/time.h>
25 #include <linux/file.h>
26 #include <linux/stat.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
29 #include <asm/uaccess.h>
30 #include <linux/vmalloc.h>
31 #include <linux/vfs.h>
33 #include <linux/coda.h>
34 #include <linux/coda_linux.h>
35 #include <linux/coda_psdev.h>
36 #include <linux/coda_fs_i.h>
37 #include <linux/coda_cache.h>
41 static int coda_upcall(struct venus_comm *vc, int inSize, int *outSize,
42 union inputArgs *buffer);
44 static void *alloc_upcall(int opcode, int size)
48 CODA_ALLOC(inp, union inputArgs *, size);
50 return ERR_PTR(-ENOMEM);
52 inp->ih.opcode = opcode;
53 inp->ih.pid = current->pid;
54 inp->ih.pgid = process_group(current);
55 #ifdef CONFIG_CODA_FS_OLD_API
56 memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
57 inp->ih.cred.cr_fsuid = current->fsuid;
59 inp->ih.uid = current->fsuid;
66 inp = (union inputArgs *)alloc_upcall(op, insize); \
67 if (IS_ERR(inp)) { return PTR_ERR(inp); }\
68 outp = (union outputArgs *)(inp); \
72 #define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)
73 #define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)
74 #define SIZE(tag) max_t(unsigned int, INSIZE(tag), OUTSIZE(tag))
78 int venus_rootfid(struct super_block *sb, struct CodaFid *fidp)
81 union outputArgs *outp;
82 int insize, outsize, error;
87 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
89 *fidp = outp->coda_root.VFid;
91 CODA_FREE(inp, insize);
95 int venus_getattr(struct super_block *sb, struct CodaFid *fid,
96 struct coda_vattr *attr)
99 union outputArgs *outp;
100 int insize, outsize, error;
102 insize = SIZE(getattr);
104 inp->coda_getattr.VFid = *fid;
106 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
108 *attr = outp->coda_getattr.attr;
110 CODA_FREE(inp, insize);
114 int venus_setattr(struct super_block *sb, struct CodaFid *fid,
115 struct coda_vattr *vattr)
117 union inputArgs *inp;
118 union outputArgs *outp;
119 int insize, outsize, error;
121 insize = SIZE(setattr);
124 inp->coda_setattr.VFid = *fid;
125 inp->coda_setattr.attr = *vattr;
127 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
129 CODA_FREE(inp, insize);
133 int venus_lookup(struct super_block *sb, struct CodaFid *fid,
134 const char *name, int length, int * type,
135 struct CodaFid *resfid)
137 union inputArgs *inp;
138 union outputArgs *outp;
139 int insize, outsize, error;
142 offset = INSIZE(lookup);
143 insize = max_t(unsigned int, offset + length +1, OUTSIZE(lookup));
146 inp->coda_lookup.VFid = *fid;
147 inp->coda_lookup.name = offset;
148 inp->coda_lookup.flags = CLU_CASE_SENSITIVE;
149 /* send Venus a null terminated string */
150 memcpy((char *)(inp) + offset, name, length);
151 *((char *)inp + offset + length) = '\0';
153 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
155 *resfid = outp->coda_lookup.VFid;
156 *type = outp->coda_lookup.vtype;
159 CODA_FREE(inp, insize);
163 int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
166 union inputArgs *inp;
167 union outputArgs *outp;
168 int insize, outsize, error;
169 #ifdef CONFIG_CODA_FS_OLD_API
170 struct coda_cred cred = { 0, };
174 insize = SIZE(store);
177 #ifdef CONFIG_CODA_FS_OLD_API
178 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
183 inp->coda_store.VFid = *fid;
184 inp->coda_store.flags = flags;
186 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
188 CODA_FREE(inp, insize);
192 int venus_release(struct super_block *sb, struct CodaFid *fid, int flags)
194 union inputArgs *inp;
195 union outputArgs *outp;
196 int insize, outsize, error;
198 insize = SIZE(release);
201 inp->coda_release.VFid = *fid;
202 inp->coda_release.flags = flags;
204 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
206 CODA_FREE(inp, insize);
210 int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
213 union inputArgs *inp;
214 union outputArgs *outp;
215 int insize, outsize, error;
216 #ifdef CONFIG_CODA_FS_OLD_API
217 struct coda_cred cred = { 0, };
221 insize = SIZE(release);
224 #ifdef CONFIG_CODA_FS_OLD_API
225 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
230 inp->coda_close.VFid = *fid;
231 inp->coda_close.flags = flags;
233 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
235 CODA_FREE(inp, insize);
239 int venus_open(struct super_block *sb, struct CodaFid *fid,
240 int flags, struct file **fh)
242 union inputArgs *inp;
243 union outputArgs *outp;
244 int insize, outsize, error;
246 insize = SIZE(open_by_fd);
247 UPARG(CODA_OPEN_BY_FD);
249 inp->coda_open_by_fd.VFid = *fid;
250 inp->coda_open_by_fd.flags = flags;
252 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
254 *fh = outp->coda_open_by_fd.fh;
256 CODA_FREE(inp, insize);
260 int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
261 const char *name, int length,
262 struct CodaFid *newfid, struct coda_vattr *attrs)
264 union inputArgs *inp;
265 union outputArgs *outp;
266 int insize, outsize, error;
269 offset = INSIZE(mkdir);
270 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(mkdir));
273 inp->coda_mkdir.VFid = *dirfid;
274 inp->coda_mkdir.attr = *attrs;
275 inp->coda_mkdir.name = offset;
276 /* Venus must get null terminated string */
277 memcpy((char *)(inp) + offset, name, length);
278 *((char *)inp + offset + length) = '\0';
280 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
282 *attrs = outp->coda_mkdir.attr;
283 *newfid = outp->coda_mkdir.VFid;
286 CODA_FREE(inp, insize);
291 int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
292 struct CodaFid *new_fid, size_t old_length,
293 size_t new_length, const char *old_name,
294 const char *new_name)
296 union inputArgs *inp;
297 union outputArgs *outp;
298 int insize, outsize, error;
301 offset = INSIZE(rename);
302 insize = max_t(unsigned int, offset + new_length + old_length + 8,
306 inp->coda_rename.sourceFid = *old_fid;
307 inp->coda_rename.destFid = *new_fid;
308 inp->coda_rename.srcname = offset;
310 /* Venus must receive an null terminated string */
311 s = ( old_length & ~0x3) +4; /* round up to word boundary */
312 memcpy((char *)(inp) + offset, old_name, old_length);
313 *((char *)inp + offset + old_length) = '\0';
315 /* another null terminated string for Venus */
317 inp->coda_rename.destname = offset;
318 s = ( new_length & ~0x3) +4; /* round up to word boundary */
319 memcpy((char *)(inp) + offset, new_name, new_length);
320 *((char *)inp + offset + new_length) = '\0';
322 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
324 CODA_FREE(inp, insize);
328 int venus_create(struct super_block *sb, struct CodaFid *dirfid,
329 const char *name, int length, int excl, int mode,
330 struct CodaFid *newfid, struct coda_vattr *attrs)
332 union inputArgs *inp;
333 union outputArgs *outp;
334 int insize, outsize, error;
337 offset = INSIZE(create);
338 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(create));
341 inp->coda_create.VFid = *dirfid;
342 inp->coda_create.attr.va_mode = mode;
343 inp->coda_create.excl = excl;
344 inp->coda_create.mode = mode;
345 inp->coda_create.name = offset;
347 /* Venus must get null terminated string */
348 memcpy((char *)(inp) + offset, name, length);
349 *((char *)inp + offset + length) = '\0';
351 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
353 *attrs = outp->coda_create.attr;
354 *newfid = outp->coda_create.VFid;
357 CODA_FREE(inp, insize);
361 int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
362 const char *name, int length)
364 union inputArgs *inp;
365 union outputArgs *outp;
366 int insize, outsize, error;
369 offset = INSIZE(rmdir);
370 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(rmdir));
373 inp->coda_rmdir.VFid = *dirfid;
374 inp->coda_rmdir.name = offset;
375 memcpy((char *)(inp) + offset, name, length);
376 *((char *)inp + offset + length) = '\0';
378 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
380 CODA_FREE(inp, insize);
384 int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
385 const char *name, int length)
387 union inputArgs *inp;
388 union outputArgs *outp;
389 int error=0, insize, outsize, offset;
391 offset = INSIZE(remove);
392 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(remove));
395 inp->coda_remove.VFid = *dirfid;
396 inp->coda_remove.name = offset;
397 memcpy((char *)(inp) + offset, name, length);
398 *((char *)inp + offset + length) = '\0';
400 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
402 CODA_FREE(inp, insize);
406 int venus_readlink(struct super_block *sb, struct CodaFid *fid,
407 char *buffer, int *length)
409 union inputArgs *inp;
410 union outputArgs *outp;
411 int insize, outsize, error;
415 insize = max_t(unsigned int,
416 INSIZE(readlink), OUTSIZE(readlink)+ *length + 1);
417 UPARG(CODA_READLINK);
419 inp->coda_readlink.VFid = *fid;
421 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
423 retlen = outp->coda_readlink.count;
424 if ( retlen > *length )
427 result = (char *)outp + (long)outp->coda_readlink.data;
428 memcpy(buffer, result, retlen);
429 *(buffer + retlen) = '\0';
432 CODA_FREE(inp, insize);
438 int venus_link(struct super_block *sb, struct CodaFid *fid,
439 struct CodaFid *dirfid, const char *name, int len )
441 union inputArgs *inp;
442 union outputArgs *outp;
443 int insize, outsize, error;
446 offset = INSIZE(link);
447 insize = max_t(unsigned int, offset + len + 1, OUTSIZE(link));
450 inp->coda_link.sourceFid = *fid;
451 inp->coda_link.destFid = *dirfid;
452 inp->coda_link.tname = offset;
454 /* make sure strings are null terminated */
455 memcpy((char *)(inp) + offset, name, len);
456 *((char *)inp + offset + len) = '\0';
458 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
460 CODA_FREE(inp, insize);
464 int venus_symlink(struct super_block *sb, struct CodaFid *fid,
465 const char *name, int len,
466 const char *symname, int symlen)
468 union inputArgs *inp;
469 union outputArgs *outp;
470 int insize, outsize, error;
473 offset = INSIZE(symlink);
474 insize = max_t(unsigned int, offset + len + symlen + 8, OUTSIZE(symlink));
477 /* inp->coda_symlink.attr = *tva; XXXXXX */
478 inp->coda_symlink.VFid = *fid;
480 /* Round up to word boundary and null terminate */
481 inp->coda_symlink.srcname = offset;
482 s = ( symlen & ~0x3 ) + 4;
483 memcpy((char *)(inp) + offset, symname, symlen);
484 *((char *)inp + offset + symlen) = '\0';
486 /* Round up to word boundary and null terminate */
488 inp->coda_symlink.tname = offset;
489 s = (len & ~0x3) + 4;
490 memcpy((char *)(inp) + offset, name, len);
491 *((char *)inp + offset + len) = '\0';
493 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
495 CODA_FREE(inp, insize);
499 int venus_fsync(struct super_block *sb, struct CodaFid *fid)
501 union inputArgs *inp;
502 union outputArgs *outp;
503 int insize, outsize, error;
508 inp->coda_fsync.VFid = *fid;
509 error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs),
512 CODA_FREE(inp, insize);
516 int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
518 union inputArgs *inp;
519 union outputArgs *outp;
520 int insize, outsize, error;
522 insize = SIZE(access);
525 inp->coda_access.VFid = *fid;
526 inp->coda_access.flags = mask;
528 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
530 CODA_FREE(inp, insize);
535 int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
536 unsigned int cmd, struct PioctlData *data)
538 union inputArgs *inp;
539 union outputArgs *outp;
540 int insize, outsize, error;
543 insize = VC_MAXMSGSIZE;
546 /* build packet for Venus */
547 if (data->vi.in_size > VC_MAXDATASIZE) {
552 if (data->vi.out_size > VC_MAXDATASIZE) {
557 inp->coda_ioctl.VFid = *fid;
559 /* the cmd field was mutated by increasing its size field to
560 * reflect the path and follow args. We need to subtract that
561 * out before sending the command to Venus. */
562 inp->coda_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));
563 iocsize = ((cmd >> 16) & PIOCPARM_MASK) - sizeof(char *) - sizeof(int);
564 inp->coda_ioctl.cmd |= (iocsize & PIOCPARM_MASK) << 16;
566 /* in->coda_ioctl.rwflag = flag; */
567 inp->coda_ioctl.len = data->vi.in_size;
568 inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
570 /* get the data out of user space */
571 if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
572 data->vi.in, data->vi.in_size) ) {
577 error = coda_upcall(coda_vcp(sb), SIZE(ioctl) + data->vi.in_size,
581 printk("coda_pioctl: Venus returns: %d for %s\n",
582 error, coda_f2s(fid));
586 if (outsize < (long)outp->coda_ioctl.data + outp->coda_ioctl.len) {
591 /* Copy out the OUT buffer. */
592 if (outp->coda_ioctl.len > data->vi.out_size) {
597 /* Copy out the OUT buffer. */
598 if (copy_to_user(data->vi.out,
599 (char *)outp + (long)outp->coda_ioctl.data,
600 outp->coda_ioctl.len)) {
606 CODA_FREE(inp, insize);
610 int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
612 union inputArgs *inp;
613 union outputArgs *outp;
614 int insize, outsize, error;
616 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
619 error = coda_upcall(coda_vcp(dentry->d_sb), insize, &outsize, inp);
621 sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
622 sfs->f_bfree = outp->coda_statfs.stat.f_bfree;
623 sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
624 sfs->f_files = outp->coda_statfs.stat.f_files;
625 sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
628 CODA_FREE(inp, insize);
633 * coda_upcall and coda_downcall routines.
635 static void block_signals(sigset_t *old)
637 spin_lock_irq(¤t->sighand->siglock);
638 *old = current->blocked;
640 sigfillset(¤t->blocked);
641 sigdelset(¤t->blocked, SIGKILL);
642 sigdelset(¤t->blocked, SIGSTOP);
643 sigdelset(¤t->blocked, SIGINT);
646 spin_unlock_irq(¤t->sighand->siglock);
649 static void unblock_signals(sigset_t *old)
651 spin_lock_irq(¤t->sighand->siglock);
652 current->blocked = *old;
654 spin_unlock_irq(¤t->sighand->siglock);
657 /* Don't allow signals to interrupt the following upcalls before venus
659 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
660 * - CODA_STORE (to avoid data loss)
662 #define CODA_INTERRUPTIBLE(r) (!coda_hard && \
663 (((r)->uc_opcode != CODA_CLOSE && \
664 (r)->uc_opcode != CODA_STORE && \
665 (r)->uc_opcode != CODA_RELEASE) || \
666 (r)->uc_flags & REQ_READ))
668 static inline void coda_waitfor_upcall(struct upc_req *req)
670 DECLARE_WAITQUEUE(wait, current);
671 unsigned long timeout = jiffies + coda_timeout * HZ;
678 add_wait_queue(&req->uc_sleep, &wait);
680 if (CODA_INTERRUPTIBLE(req))
681 set_current_state(TASK_INTERRUPTIBLE);
683 set_current_state(TASK_UNINTERRUPTIBLE);
686 if (req->uc_flags & (REQ_WRITE | REQ_ABORT))
689 if (blocked && time_after(jiffies, timeout) &&
690 CODA_INTERRUPTIBLE(req))
692 unblock_signals(&old);
696 if (signal_pending(current)) {
697 list_del(&req->uc_chain);
702 schedule_timeout(HZ);
707 unblock_signals(&old);
709 remove_wait_queue(&req->uc_sleep, &wait);
710 set_current_state(TASK_RUNNING);
715 * coda_upcall will return an error in the case of
716 * failed communication with Venus _or_ will peek at Venus
717 * reply and return Venus' error.
719 * As venus has 2 types of errors, normal errors (positive) and internal
720 * errors (negative), normal errors are negated, while internal errors
721 * are all mapped to -EINTR, while showing a nice warning message. (jh)
723 static int coda_upcall(struct venus_comm *vcp,
724 int inSize, int *outSize,
725 union inputArgs *buffer)
727 union outputArgs *out;
728 union inputArgs *sig_inputArgs;
729 struct upc_req *req, *sig_req;
732 if (!vcp->vc_inuse) {
733 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
737 /* Format the request message. */
738 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
742 req->uc_data = (void *)buffer;
744 req->uc_inSize = inSize;
745 req->uc_outSize = *outSize ? *outSize : inSize;
746 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
747 req->uc_unique = ++vcp->vc_seq;
748 init_waitqueue_head(&req->uc_sleep);
750 /* Fill in the common input args. */
751 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
753 /* Append msg to pending queue and poke Venus. */
754 list_add_tail(&req->uc_chain, &vcp->vc_pending);
756 wake_up_interruptible(&vcp->vc_waitq);
757 /* We can be interrupted while we wait for Venus to process
758 * our request. If the interrupt occurs before Venus has read
759 * the request, we dequeue and return. If it occurs after the
760 * read but before the reply, we dequeue, send a signal
761 * message, and return. If it occurs after the reply we ignore
762 * it. In no case do we want to restart the syscall. If it
763 * was interrupted by a venus shutdown (psdev_close), return
766 /* Go to sleep. Wake up on signals only after the timeout. */
767 coda_waitfor_upcall(req);
769 /* Op went through, interrupt or not... */
770 if (req->uc_flags & REQ_WRITE) {
771 out = (union outputArgs *)req->uc_data;
772 /* here we map positive Venus errors to kernel errors */
773 error = -out->oh.result;
774 *outSize = req->uc_outSize;
779 if ((req->uc_flags & REQ_ABORT) || !signal_pending(current)) {
780 printk(KERN_WARNING "coda: Unexpected interruption.\n");
784 /* Interrupted before venus read it. */
785 if (!(req->uc_flags & REQ_READ))
788 /* Venus saw the upcall, make sure we can send interrupt signal */
789 if (!vcp->vc_inuse) {
790 printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
795 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
796 if (!sig_req) goto exit;
798 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
799 if (!sig_req->uc_data) {
805 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
806 sig_inputArgs->ih.opcode = CODA_SIGNAL;
807 sig_inputArgs->ih.unique = req->uc_unique;
809 sig_req->uc_flags = REQ_ASYNC;
810 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
811 sig_req->uc_unique = sig_inputArgs->ih.unique;
812 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
813 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
815 /* insert at head of queue! */
816 list_add(&(sig_req->uc_chain), &vcp->vc_pending);
817 wake_up_interruptible(&vcp->vc_waitq);
825 The statements below are part of the Coda opportunistic
826 programming -- taken from the Mach/BSD kernel code for Coda.
827 You don't get correct semantics by stating what needs to be
828 done without guaranteeing the invariants needed for it to happen.
829 When will be have time to find out what exactly is going on? (pjb)
834 * There are 7 cases where cache invalidations occur. The semantics
835 * of each is listed here:
837 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
838 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
839 * This call is a result of token expiration.
841 * The next arise as the result of callbacks on a file or directory.
842 * CODA_ZAPFILE -- flush the cached attributes for a file.
844 * CODA_ZAPDIR -- flush the attributes for the dir and
845 * force a new lookup for all the children
849 * The next is a result of Venus detecting an inconsistent file.
850 * CODA_PURGEFID -- flush the attribute for the file
851 * purge it and its children from the dcache
853 * The last allows Venus to replace local fids with global ones
854 * during reintegration.
856 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
858 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
860 struct inode *inode = NULL;
861 struct CodaFid *fid, *newfid;
863 /* Handle invalidation requests. */
864 if ( !sb || !sb->s_root)
869 coda_cache_clear_all(sb);
870 shrink_dcache_sb(sb);
871 if (sb->s_root->d_inode)
872 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
876 coda_cache_clear_all(sb);
880 fid = &out->coda_zapdir.CodaFid;
881 inode = coda_fid_to_inode(fid, sb);
883 coda_flag_inode_children(inode, C_PURGE);
884 coda_flag_inode(inode, C_VATTR);
889 fid = &out->coda_zapfile.CodaFid;
890 inode = coda_fid_to_inode(fid, sb);
892 coda_flag_inode(inode, C_VATTR);
896 fid = &out->coda_purgefid.CodaFid;
897 inode = coda_fid_to_inode(fid, sb);
899 coda_flag_inode_children(inode, C_PURGE);
901 /* catch the dentries later if some are still busy */
902 coda_flag_inode(inode, C_PURGE);
903 d_prune_aliases(inode);
909 fid = &out->coda_replace.OldFid;
910 newfid = &out->coda_replace.NewFid;
911 inode = coda_fid_to_inode(fid, sb);
913 coda_replace_fid(inode, fid, newfid);