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,
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.excl = excl;
349 inp->coda_create.mode = mode;
350 inp->coda_create.name = offset;
352 /* Venus must get null terminated string */
353 memcpy((char *)(inp) + offset, name, length);
354 *((char *)inp + offset + length) = '\0';
356 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
358 *attrs = outp->coda_create.attr;
359 *newfid = outp->coda_create.VFid;
361 CODA_FREE(inp, insize);
365 int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
366 const char *name, int length)
368 union inputArgs *inp;
369 union outputArgs *outp;
370 int insize, outsize, error;
373 offset = INSIZE(rmdir);
374 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(rmdir));
377 inp->coda_rmdir.VFid = *dirfid;
378 inp->coda_rmdir.name = offset;
379 memcpy((char *)(inp) + offset, name, length);
380 *((char *)inp + offset + length) = '\0';
382 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
384 CODA_FREE(inp, insize);
388 int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
389 const char *name, int length)
391 union inputArgs *inp;
392 union outputArgs *outp;
393 int error=0, insize, outsize, offset;
395 offset = INSIZE(remove);
396 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(remove));
399 inp->coda_remove.VFid = *dirfid;
400 inp->coda_remove.name = offset;
401 memcpy((char *)(inp) + offset, name, length);
402 *((char *)inp + offset + length) = '\0';
404 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
406 CODA_FREE(inp, insize);
410 int venus_readlink(struct super_block *sb, struct CodaFid *fid,
411 char *buffer, int *length)
413 union inputArgs *inp;
414 union outputArgs *outp;
415 int insize, outsize, error;
419 insize = max_t(unsigned int,
420 INSIZE(readlink), OUTSIZE(readlink)+ *length + 1);
421 UPARG(CODA_READLINK);
423 inp->coda_readlink.VFid = *fid;
425 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
428 retlen = outp->coda_readlink.count;
429 if ( retlen > *length )
432 result = (char *)outp + (long)outp->coda_readlink.data;
433 memcpy(buffer, result, retlen);
434 *(buffer + retlen) = '\0';
437 CODA_FREE(inp, insize);
443 int venus_link(struct super_block *sb, struct CodaFid *fid,
444 struct CodaFid *dirfid, const char *name, int len )
446 union inputArgs *inp;
447 union outputArgs *outp;
448 int insize, outsize, error;
451 offset = INSIZE(link);
452 insize = max_t(unsigned int, offset + len + 1, OUTSIZE(link));
455 inp->coda_link.sourceFid = *fid;
456 inp->coda_link.destFid = *dirfid;
457 inp->coda_link.tname = offset;
459 /* make sure strings are null terminated */
460 memcpy((char *)(inp) + offset, name, len);
461 *((char *)inp + offset + len) = '\0';
463 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
465 CODA_FREE(inp, insize);
469 int venus_symlink(struct super_block *sb, struct CodaFid *fid,
470 const char *name, int len,
471 const char *symname, int symlen)
473 union inputArgs *inp;
474 union outputArgs *outp;
475 int insize, outsize, error;
478 offset = INSIZE(symlink);
479 insize = max_t(unsigned int, offset + len + symlen + 8, OUTSIZE(symlink));
482 /* inp->coda_symlink.attr = *tva; XXXXXX */
483 inp->coda_symlink.VFid = *fid;
485 /* Round up to word boundary and null terminate */
486 inp->coda_symlink.srcname = offset;
487 s = ( symlen & ~0x3 ) + 4;
488 memcpy((char *)(inp) + offset, symname, symlen);
489 *((char *)inp + offset + symlen) = '\0';
491 /* Round up to word boundary and null terminate */
493 inp->coda_symlink.tname = offset;
494 s = (len & ~0x3) + 4;
495 memcpy((char *)(inp) + offset, name, len);
496 *((char *)inp + offset + len) = '\0';
498 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
500 CODA_FREE(inp, insize);
504 int venus_fsync(struct super_block *sb, struct CodaFid *fid)
506 union inputArgs *inp;
507 union outputArgs *outp;
508 int insize, outsize, error;
513 inp->coda_fsync.VFid = *fid;
514 error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs),
517 CODA_FREE(inp, insize);
521 int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
523 union inputArgs *inp;
524 union outputArgs *outp;
525 int insize, outsize, error;
527 insize = SIZE(access);
530 inp->coda_access.VFid = *fid;
531 inp->coda_access.flags = mask;
533 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
535 CODA_FREE(inp, insize);
540 int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
541 unsigned int cmd, struct PioctlData *data)
543 union inputArgs *inp;
544 union outputArgs *outp;
545 int insize, outsize, error;
548 insize = VC_MAXMSGSIZE;
551 /* build packet for Venus */
552 if (data->vi.in_size > VC_MAXDATASIZE) {
557 if (data->vi.out_size > VC_MAXDATASIZE) {
562 inp->coda_ioctl.VFid = *fid;
564 /* the cmd field was mutated by increasing its size field to
565 * reflect the path and follow args. We need to subtract that
566 * out before sending the command to Venus. */
567 inp->coda_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));
568 iocsize = ((cmd >> 16) & PIOCPARM_MASK) - sizeof(char *) - sizeof(int);
569 inp->coda_ioctl.cmd |= (iocsize & PIOCPARM_MASK) << 16;
571 /* in->coda_ioctl.rwflag = flag; */
572 inp->coda_ioctl.len = data->vi.in_size;
573 inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
575 /* get the data out of user space */
576 if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
577 data->vi.in, data->vi.in_size) ) {
582 error = coda_upcall(coda_sbp(sb), SIZE(ioctl) + data->vi.in_size,
586 printk("coda_pioctl: Venus returns: %d for %s\n",
587 error, coda_f2s(fid));
591 if (outsize < (long)outp->coda_ioctl.data + outp->coda_ioctl.len) {
596 /* Copy out the OUT buffer. */
597 if (outp->coda_ioctl.len > data->vi.out_size) {
602 /* Copy out the OUT buffer. */
603 if (copy_to_user(data->vi.out,
604 (char *)outp + (long)outp->coda_ioctl.data,
605 outp->coda_ioctl.len)) {
611 CODA_FREE(inp, insize);
615 int venus_statfs(struct super_block *sb, struct kstatfs *sfs)
617 union inputArgs *inp;
618 union outputArgs *outp;
619 int insize, outsize, error;
621 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
624 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
627 sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
628 sfs->f_bfree = outp->coda_statfs.stat.f_bfree;
629 sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
630 sfs->f_files = outp->coda_statfs.stat.f_files;
631 sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
633 printk("coda_statfs: Venus returns: %d\n", error);
636 CODA_FREE(inp, insize);
641 * coda_upcall and coda_downcall routines.
645 static inline void coda_waitfor_upcall(struct upc_req *vmp,
646 struct venus_comm *vcommp)
648 DECLARE_WAITQUEUE(wait, current);
650 vmp->uc_posttime = jiffies;
652 add_wait_queue(&vmp->uc_sleep, &wait);
654 if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE )
655 set_current_state(TASK_INTERRUPTIBLE);
657 set_current_state(TASK_UNINTERRUPTIBLE);
660 if ( !vcommp->vc_inuse )
664 if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
667 if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE && signal_pending(current) ) {
668 /* if this process really wants to die, let it go */
669 if ( sigismember(&(current->pending.signal), SIGKILL) ||
670 sigismember(&(current->pending.signal), SIGINT) )
672 /* signal is present: after timeout always return
673 really smart idea, probably useless ... */
674 if ( jiffies - vmp->uc_posttime > coda_timeout * HZ )
679 remove_wait_queue(&vmp->uc_sleep, &wait);
680 set_current_state(TASK_RUNNING);
687 * coda_upcall will return an error in the case of
688 * failed communication with Venus _or_ will peek at Venus
689 * reply and return Venus' error.
691 * As venus has 2 types of errors, normal errors (positive) and internal
692 * errors (negative), normal errors are negated, while internal errors
693 * are all mapped to -EINTR, while showing a nice warning message. (jh)
696 static int coda_upcall(struct coda_sb_info *sbi,
697 int inSize, int *outSize,
698 union inputArgs *buffer)
700 struct venus_comm *vcommp;
701 union outputArgs *out;
705 vcommp = sbi->sbi_vcomm;
706 if ( !vcommp->vc_inuse ) {
707 printk("No pseudo device in upcall comms at %p\n", vcommp);
711 /* Format the request message. */
714 printk("Failed to allocate upc_req structure\n");
717 req->uc_data = (void *)buffer;
719 req->uc_inSize = inSize;
720 req->uc_outSize = *outSize ? *outSize : inSize;
721 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
722 req->uc_unique = ++vcommp->vc_seq;
723 init_waitqueue_head(&req->uc_sleep);
725 /* Fill in the common input args. */
726 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
728 /* Append msg to pending queue and poke Venus. */
729 list_add(&(req->uc_chain), vcommp->vc_pending.prev);
731 wake_up_interruptible(&vcommp->vc_waitq);
732 /* We can be interrupted while we wait for Venus to process
733 * our request. If the interrupt occurs before Venus has read
734 * the request, we dequeue and return. If it occurs after the
735 * read but before the reply, we dequeue, send a signal
736 * message, and return. If it occurs after the reply we ignore
737 * it. In no case do we want to restart the syscall. If it
738 * was interrupted by a venus shutdown (psdev_close), return
741 /* Go to sleep. Wake up on signals only after the timeout. */
742 coda_waitfor_upcall(req, vcommp);
744 if (vcommp->vc_inuse) { /* i.e. Venus is still alive */
745 /* Op went through, interrupt or not... */
746 if (req->uc_flags & REQ_WRITE) {
747 out = (union outputArgs *)req->uc_data;
748 /* here we map positive Venus errors to kernel errors */
749 error = -out->oh.result;
750 *outSize = req->uc_outSize;
753 if ( !(req->uc_flags & REQ_READ) && signal_pending(current)) {
754 /* Interrupted before venus read it. */
755 list_del(&(req->uc_chain));
756 /* perhaps the best way to convince the app to
761 if ( (req->uc_flags & REQ_READ) && signal_pending(current) ) {
762 /* interrupted after Venus did its read, send signal */
763 union inputArgs *sig_inputArgs;
764 struct upc_req *sig_req;
766 list_del(&(req->uc_chain));
768 sig_req = upc_alloc();
769 if (!sig_req) goto exit;
771 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
772 if (!sig_req->uc_data) {
778 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
779 sig_inputArgs->ih.opcode = CODA_SIGNAL;
780 sig_inputArgs->ih.unique = req->uc_unique;
782 sig_req->uc_flags = REQ_ASYNC;
783 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
784 sig_req->uc_unique = sig_inputArgs->ih.unique;
785 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
786 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
788 /* insert at head of queue! */
789 list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
790 wake_up_interruptible(&vcommp->vc_waitq);
792 printk("Coda: Strange interruption..\n");
795 } else { /* If venus died i.e. !VC_OPEN(vcommp) */
796 printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
797 req->uc_opcode, req->uc_unique, req->uc_flags);
807 The statements below are part of the Coda opportunistic
808 programming -- taken from the Mach/BSD kernel code for Coda.
809 You don't get correct semantics by stating what needs to be
810 done without guaranteeing the invariants needed for it to happen.
811 When will be have time to find out what exactly is going on? (pjb)
816 * There are 7 cases where cache invalidations occur. The semantics
817 * of each is listed here:
819 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
820 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
821 * This call is a result of token expiration.
823 * The next arise as the result of callbacks on a file or directory.
824 * CODA_ZAPFILE -- flush the cached attributes for a file.
826 * CODA_ZAPDIR -- flush the attributes for the dir and
827 * force a new lookup for all the children
831 * The next is a result of Venus detecting an inconsistent file.
832 * CODA_PURGEFID -- flush the attribute for the file
833 * purge it and its children from the dcache
835 * The last allows Venus to replace local fids with global ones
836 * during reintegration.
838 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
840 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
842 /* Handle invalidation requests. */
843 if ( !sb || !sb->s_root || !sb->s_root->d_inode)
849 coda_cache_clear_all(sb);
850 shrink_dcache_sb(sb);
851 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
855 case CODA_PURGEUSER : {
856 coda_cache_clear_all(sb);
862 struct CodaFid *fid = &out->coda_zapdir.CodaFid;
864 inode = coda_fid_to_inode(fid, sb);
866 coda_flag_inode_children(inode, C_PURGE);
867 coda_flag_inode(inode, C_VATTR);
874 case CODA_ZAPFILE : {
876 struct CodaFid *fid = &out->coda_zapfile.CodaFid;
877 inode = coda_fid_to_inode(fid, sb);
879 coda_flag_inode(inode, C_VATTR);
885 case CODA_PURGEFID : {
887 struct CodaFid *fid = &out->coda_purgefid.CodaFid;
888 inode = coda_fid_to_inode(fid, sb);
890 coda_flag_inode_children(inode, C_PURGE);
892 /* catch the dentries later if some are still busy */
893 coda_flag_inode(inode, C_PURGE);
894 d_prune_aliases(inode);
901 case CODA_REPLACE : {
903 struct CodaFid *oldfid = &out->coda_replace.OldFid;
904 struct CodaFid *newfid = &out->coda_replace.NewFid;
905 inode = coda_fid_to_inode(oldfid, sb);
907 coda_replace_fid(inode, oldfid, newfid);