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 <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>
38 #include <linux/coda_proc.h>
40 static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize,
41 union inputArgs *buffer);
43 static void *alloc_upcall(int opcode, int size)
47 CODA_ALLOC(inp, union inputArgs *, size);
49 return ERR_PTR(-ENOMEM);
51 inp->ih.opcode = opcode;
52 inp->ih.pid = current->pid;
53 inp->ih.pgid = process_group(current);
54 #ifdef CONFIG_CODA_FS_OLD_API
55 memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
56 inp->ih.cred.cr_fsuid = current->fsuid;
58 inp->ih.uid = current->fsuid;
65 inp = (union inputArgs *)alloc_upcall(op, insize); \
66 if (IS_ERR(inp)) { return PTR_ERR(inp); }\
67 outp = (union outputArgs *)(inp); \
71 #define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)
72 #define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)
73 #define SIZE(tag) max_t(unsigned int, INSIZE(tag), OUTSIZE(tag))
77 int venus_rootfid(struct super_block *sb, struct CodaFid *fidp)
80 union outputArgs *outp;
81 int insize, outsize, error;
86 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
89 printk("coda_get_rootfid: error %d\n", error);
91 *fidp = outp->coda_root.VFid;
94 CODA_FREE(inp, insize);
98 int venus_getattr(struct super_block *sb, struct CodaFid *fid,
99 struct coda_vattr *attr)
101 union inputArgs *inp;
102 union outputArgs *outp;
103 int insize, outsize, error;
105 insize = SIZE(getattr);
107 inp->coda_getattr.VFid = *fid;
109 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
111 *attr = outp->coda_getattr.attr;
113 CODA_FREE(inp, insize);
117 int venus_setattr(struct super_block *sb, struct CodaFid *fid,
118 struct coda_vattr *vattr)
120 union inputArgs *inp;
121 union outputArgs *outp;
122 int insize, outsize, error;
124 insize = SIZE(setattr);
127 inp->coda_setattr.VFid = *fid;
128 inp->coda_setattr.attr = *vattr;
130 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
132 CODA_FREE(inp, insize);
136 int venus_lookup(struct super_block *sb, struct CodaFid *fid,
137 const char *name, int length, int * type,
138 struct CodaFid *resfid)
140 union inputArgs *inp;
141 union outputArgs *outp;
142 int insize, outsize, error;
145 offset = INSIZE(lookup);
146 insize = max_t(unsigned int, offset + length +1, OUTSIZE(lookup));
149 inp->coda_lookup.VFid = *fid;
150 inp->coda_lookup.name = offset;
151 inp->coda_lookup.flags = CLU_CASE_SENSITIVE;
152 /* send Venus a null terminated string */
153 memcpy((char *)(inp) + offset, name, length);
154 *((char *)inp + offset + length) = '\0';
156 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
158 *resfid = outp->coda_lookup.VFid;
159 *type = outp->coda_lookup.vtype;
161 CODA_FREE(inp, insize);
165 int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
168 union inputArgs *inp;
169 union outputArgs *outp;
170 int insize, outsize, error;
171 #ifdef CONFIG_CODA_FS_OLD_API
172 struct coda_cred cred = { 0, };
176 insize = SIZE(store);
179 #ifdef CONFIG_CODA_FS_OLD_API
180 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
185 inp->coda_store.VFid = *fid;
186 inp->coda_store.flags = flags;
188 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
190 CODA_FREE(inp, insize);
194 int venus_release(struct super_block *sb, struct CodaFid *fid, int flags)
196 union inputArgs *inp;
197 union outputArgs *outp;
198 int insize, outsize, error;
200 insize = SIZE(release);
203 inp->coda_release.VFid = *fid;
204 inp->coda_release.flags = flags;
206 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
208 CODA_FREE(inp, insize);
212 int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
215 union inputArgs *inp;
216 union outputArgs *outp;
217 int insize, outsize, error;
218 #ifdef CONFIG_CODA_FS_OLD_API
219 struct coda_cred cred = { 0, };
223 insize = SIZE(release);
226 #ifdef CONFIG_CODA_FS_OLD_API
227 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
232 inp->coda_close.VFid = *fid;
233 inp->coda_close.flags = flags;
235 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
237 CODA_FREE(inp, insize);
241 int venus_open(struct super_block *sb, struct CodaFid *fid,
242 int flags, struct file **fh)
244 union inputArgs *inp;
245 union outputArgs *outp;
246 int insize, outsize, error;
248 insize = SIZE(open_by_fd);
249 UPARG(CODA_OPEN_BY_FD);
251 inp->coda_open_by_fd.VFid = *fid;
252 inp->coda_open_by_fd.flags = flags;
254 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
256 *fh = outp->coda_open_by_fd.fh;
258 CODA_FREE(inp, insize);
262 int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
263 const char *name, int length,
264 struct CodaFid *newfid, struct coda_vattr *attrs)
266 union inputArgs *inp;
267 union outputArgs *outp;
268 int insize, outsize, error;
271 offset = INSIZE(mkdir);
272 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(mkdir));
275 inp->coda_mkdir.VFid = *dirfid;
276 inp->coda_mkdir.attr = *attrs;
277 inp->coda_mkdir.name = offset;
278 /* Venus must get null terminated string */
279 memcpy((char *)(inp) + offset, name, length);
280 *((char *)inp + offset + length) = '\0';
282 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
284 *attrs = outp->coda_mkdir.attr;
285 *newfid = outp->coda_mkdir.VFid;
287 CODA_FREE(inp, insize);
292 int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
293 struct CodaFid *new_fid, size_t old_length,
294 size_t new_length, const char *old_name,
295 const char *new_name)
297 union inputArgs *inp;
298 union outputArgs *outp;
299 int insize, outsize, error;
302 offset = INSIZE(rename);
303 insize = max_t(unsigned int, offset + new_length + old_length + 8,
307 inp->coda_rename.sourceFid = *old_fid;
308 inp->coda_rename.destFid = *new_fid;
309 inp->coda_rename.srcname = offset;
311 /* Venus must receive an null terminated string */
312 s = ( old_length & ~0x3) +4; /* round up to word boundary */
313 memcpy((char *)(inp) + offset, old_name, old_length);
314 *((char *)inp + offset + old_length) = '\0';
316 /* another null terminated string for Venus */
318 inp->coda_rename.destname = offset;
319 s = ( new_length & ~0x3) +4; /* round up to word boundary */
320 memcpy((char *)(inp) + offset, new_name, new_length);
321 *((char *)inp + offset + new_length) = '\0';
323 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
325 CODA_FREE(inp, insize);
329 int venus_create(struct super_block *sb, struct CodaFid *dirfid,
330 const char *name, int length, int excl, int mode,
331 struct CodaFid *newfid, struct coda_vattr *attrs)
333 union inputArgs *inp;
334 union outputArgs *outp;
335 int insize, outsize, error;
338 offset = INSIZE(create);
339 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(create));
342 inp->coda_create.VFid = *dirfid;
343 inp->coda_create.attr.va_mode = mode;
344 inp->coda_create.excl = excl;
345 inp->coda_create.mode = mode;
346 inp->coda_create.name = offset;
348 /* Venus must get null terminated string */
349 memcpy((char *)(inp) + offset, name, length);
350 *((char *)inp + offset + length) = '\0';
352 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
354 *attrs = outp->coda_create.attr;
355 *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_sbp(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_sbp(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_sbp(sb), insize, &outsize, inp);
424 retlen = outp->coda_readlink.count;
425 if ( retlen > *length )
428 result = (char *)outp + (long)outp->coda_readlink.data;
429 memcpy(buffer, result, retlen);
430 *(buffer + retlen) = '\0';
433 CODA_FREE(inp, insize);
439 int venus_link(struct super_block *sb, struct CodaFid *fid,
440 struct CodaFid *dirfid, const char *name, int len )
442 union inputArgs *inp;
443 union outputArgs *outp;
444 int insize, outsize, error;
447 offset = INSIZE(link);
448 insize = max_t(unsigned int, offset + len + 1, OUTSIZE(link));
451 inp->coda_link.sourceFid = *fid;
452 inp->coda_link.destFid = *dirfid;
453 inp->coda_link.tname = offset;
455 /* make sure strings are null terminated */
456 memcpy((char *)(inp) + offset, name, len);
457 *((char *)inp + offset + len) = '\0';
459 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
461 CODA_FREE(inp, insize);
465 int venus_symlink(struct super_block *sb, struct CodaFid *fid,
466 const char *name, int len,
467 const char *symname, int symlen)
469 union inputArgs *inp;
470 union outputArgs *outp;
471 int insize, outsize, error;
474 offset = INSIZE(symlink);
475 insize = max_t(unsigned int, offset + len + symlen + 8, OUTSIZE(symlink));
478 /* inp->coda_symlink.attr = *tva; XXXXXX */
479 inp->coda_symlink.VFid = *fid;
481 /* Round up to word boundary and null terminate */
482 inp->coda_symlink.srcname = offset;
483 s = ( symlen & ~0x3 ) + 4;
484 memcpy((char *)(inp) + offset, symname, symlen);
485 *((char *)inp + offset + symlen) = '\0';
487 /* Round up to word boundary and null terminate */
489 inp->coda_symlink.tname = offset;
490 s = (len & ~0x3) + 4;
491 memcpy((char *)(inp) + offset, name, len);
492 *((char *)inp + offset + len) = '\0';
494 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
496 CODA_FREE(inp, insize);
500 int venus_fsync(struct super_block *sb, struct CodaFid *fid)
502 union inputArgs *inp;
503 union outputArgs *outp;
504 int insize, outsize, error;
509 inp->coda_fsync.VFid = *fid;
510 error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs),
513 CODA_FREE(inp, insize);
517 int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
519 union inputArgs *inp;
520 union outputArgs *outp;
521 int insize, outsize, error;
523 insize = SIZE(access);
526 inp->coda_access.VFid = *fid;
527 inp->coda_access.flags = mask;
529 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
531 CODA_FREE(inp, insize);
536 int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
537 unsigned int cmd, struct PioctlData *data)
539 union inputArgs *inp;
540 union outputArgs *outp;
541 int insize, outsize, error;
544 insize = VC_MAXMSGSIZE;
547 /* build packet for Venus */
548 if (data->vi.in_size > VC_MAXDATASIZE) {
553 if (data->vi.out_size > VC_MAXDATASIZE) {
558 inp->coda_ioctl.VFid = *fid;
560 /* the cmd field was mutated by increasing its size field to
561 * reflect the path and follow args. We need to subtract that
562 * out before sending the command to Venus. */
563 inp->coda_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));
564 iocsize = ((cmd >> 16) & PIOCPARM_MASK) - sizeof(char *) - sizeof(int);
565 inp->coda_ioctl.cmd |= (iocsize & PIOCPARM_MASK) << 16;
567 /* in->coda_ioctl.rwflag = flag; */
568 inp->coda_ioctl.len = data->vi.in_size;
569 inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
571 /* get the data out of user space */
572 if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
573 data->vi.in, data->vi.in_size) ) {
578 error = coda_upcall(coda_sbp(sb), SIZE(ioctl) + data->vi.in_size,
582 printk("coda_pioctl: Venus returns: %d for %s\n",
583 error, coda_f2s(fid));
587 if (outsize < (long)outp->coda_ioctl.data + outp->coda_ioctl.len) {
592 /* Copy out the OUT buffer. */
593 if (outp->coda_ioctl.len > data->vi.out_size) {
598 /* Copy out the OUT buffer. */
599 if (copy_to_user(data->vi.out,
600 (char *)outp + (long)outp->coda_ioctl.data,
601 outp->coda_ioctl.len)) {
607 CODA_FREE(inp, insize);
611 int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
613 union inputArgs *inp;
614 union outputArgs *outp;
615 int insize, outsize, error;
617 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
620 error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp);
623 sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
624 sfs->f_bfree = outp->coda_statfs.stat.f_bfree;
625 sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
626 sfs->f_files = outp->coda_statfs.stat.f_files;
627 sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
629 printk("coda_statfs: Venus returns: %d\n", error);
632 CODA_FREE(inp, insize);
637 * coda_upcall and coda_downcall routines.
639 static void block_signals(sigset_t *old)
641 spin_lock_irq(¤t->sighand->siglock);
642 *old = current->blocked;
644 sigfillset(¤t->blocked);
645 sigdelset(¤t->blocked, SIGKILL);
646 sigdelset(¤t->blocked, SIGSTOP);
647 sigdelset(¤t->blocked, SIGINT);
650 spin_unlock_irq(¤t->sighand->siglock);
653 static void unblock_signals(sigset_t *old)
655 spin_lock_irq(¤t->sighand->siglock);
656 current->blocked = *old;
658 spin_unlock_irq(¤t->sighand->siglock);
661 /* Don't allow signals to interrupt the following upcalls before venus
663 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
664 * - CODA_STORE (to avoid data loss)
666 #define CODA_INTERRUPTIBLE(r) (!coda_hard && \
667 (((r)->uc_opcode != CODA_CLOSE && \
668 (r)->uc_opcode != CODA_STORE && \
669 (r)->uc_opcode != CODA_RELEASE) || \
670 (r)->uc_flags & REQ_READ))
672 static inline void coda_waitfor_upcall(struct upc_req *req)
674 DECLARE_WAITQUEUE(wait, current);
675 unsigned long timeout = jiffies + coda_timeout * HZ;
682 add_wait_queue(&req->uc_sleep, &wait);
684 if (CODA_INTERRUPTIBLE(req))
685 set_current_state(TASK_INTERRUPTIBLE);
687 set_current_state(TASK_UNINTERRUPTIBLE);
690 if (req->uc_flags & (REQ_WRITE | REQ_ABORT))
693 if (blocked && time_after(jiffies, timeout) &&
694 CODA_INTERRUPTIBLE(req))
696 unblock_signals(&old);
700 if (signal_pending(current)) {
701 list_del(&req->uc_chain);
706 schedule_timeout(HZ);
711 unblock_signals(&old);
713 remove_wait_queue(&req->uc_sleep, &wait);
714 set_current_state(TASK_RUNNING);
719 * coda_upcall will return an error in the case of
720 * failed communication with Venus _or_ will peek at Venus
721 * reply and return Venus' error.
723 * As venus has 2 types of errors, normal errors (positive) and internal
724 * errors (negative), normal errors are negated, while internal errors
725 * are all mapped to -EINTR, while showing a nice warning message. (jh)
728 static int coda_upcall(struct coda_sb_info *sbi,
729 int inSize, int *outSize,
730 union inputArgs *buffer)
732 struct venus_comm *vcommp;
733 union outputArgs *out;
734 union inputArgs *sig_inputArgs;
735 struct upc_req *req, *sig_req;
738 vcommp = sbi->sbi_vcomm;
739 if (!vcommp->vc_inuse) {
740 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
744 /* Format the request message. */
745 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
749 req->uc_data = (void *)buffer;
751 req->uc_inSize = inSize;
752 req->uc_outSize = *outSize ? *outSize : inSize;
753 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
754 req->uc_unique = ++vcommp->vc_seq;
755 init_waitqueue_head(&req->uc_sleep);
757 /* Fill in the common input args. */
758 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
760 /* Append msg to pending queue and poke Venus. */
761 list_add_tail(&req->uc_chain, &vcommp->vc_pending);
763 wake_up_interruptible(&vcommp->vc_waitq);
764 /* We can be interrupted while we wait for Venus to process
765 * our request. If the interrupt occurs before Venus has read
766 * the request, we dequeue and return. If it occurs after the
767 * read but before the reply, we dequeue, send a signal
768 * message, and return. If it occurs after the reply we ignore
769 * it. In no case do we want to restart the syscall. If it
770 * was interrupted by a venus shutdown (psdev_close), return
773 /* Go to sleep. Wake up on signals only after the timeout. */
774 coda_waitfor_upcall(req);
776 /* Op went through, interrupt or not... */
777 if (req->uc_flags & REQ_WRITE) {
778 out = (union outputArgs *)req->uc_data;
779 /* here we map positive Venus errors to kernel errors */
780 error = -out->oh.result;
781 *outSize = req->uc_outSize;
786 if ((req->uc_flags & REQ_ABORT) || !signal_pending(current)) {
787 printk(KERN_WARNING "coda: Unexpected interruption.\n");
791 /* Interrupted before venus read it. */
792 if (!(req->uc_flags & REQ_READ))
795 /* Venus saw the upcall, make sure we can send interrupt signal */
796 if (!vcommp->vc_inuse) {
797 printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
802 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
803 if (!sig_req) goto exit;
805 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
806 if (!sig_req->uc_data) {
812 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
813 sig_inputArgs->ih.opcode = CODA_SIGNAL;
814 sig_inputArgs->ih.unique = req->uc_unique;
816 sig_req->uc_flags = REQ_ASYNC;
817 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
818 sig_req->uc_unique = sig_inputArgs->ih.unique;
819 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
820 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
822 /* insert at head of queue! */
823 list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
824 wake_up_interruptible(&vcommp->vc_waitq);
832 The statements below are part of the Coda opportunistic
833 programming -- taken from the Mach/BSD kernel code for Coda.
834 You don't get correct semantics by stating what needs to be
835 done without guaranteeing the invariants needed for it to happen.
836 When will be have time to find out what exactly is going on? (pjb)
841 * There are 7 cases where cache invalidations occur. The semantics
842 * of each is listed here:
844 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
845 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
846 * This call is a result of token expiration.
848 * The next arise as the result of callbacks on a file or directory.
849 * CODA_ZAPFILE -- flush the cached attributes for a file.
851 * CODA_ZAPDIR -- flush the attributes for the dir and
852 * force a new lookup for all the children
856 * The next is a result of Venus detecting an inconsistent file.
857 * CODA_PURGEFID -- flush the attribute for the file
858 * purge it and its children from the dcache
860 * The last allows Venus to replace local fids with global ones
861 * during reintegration.
863 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
865 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
867 /* Handle invalidation requests. */
868 if ( !sb || !sb->s_root || !sb->s_root->d_inode)
874 coda_cache_clear_all(sb);
875 shrink_dcache_sb(sb);
876 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
880 case CODA_PURGEUSER : {
881 coda_cache_clear_all(sb);
887 struct CodaFid *fid = &out->coda_zapdir.CodaFid;
889 inode = coda_fid_to_inode(fid, sb);
891 coda_flag_inode_children(inode, C_PURGE);
892 coda_flag_inode(inode, C_VATTR);
899 case CODA_ZAPFILE : {
901 struct CodaFid *fid = &out->coda_zapfile.CodaFid;
902 inode = coda_fid_to_inode(fid, sb);
904 coda_flag_inode(inode, C_VATTR);
910 case CODA_PURGEFID : {
912 struct CodaFid *fid = &out->coda_purgefid.CodaFid;
913 inode = coda_fid_to_inode(fid, sb);
915 coda_flag_inode_children(inode, C_PURGE);
917 /* catch the dentries later if some are still busy */
918 coda_flag_inode(inode, C_PURGE);
919 d_prune_aliases(inode);
926 case CODA_REPLACE : {
928 struct CodaFid *oldfid = &out->coda_replace.OldFid;
929 struct CodaFid *newfid = &out->coda_replace.NewFid;
930 inode = coda_fid_to_inode(oldfid, sb);
932 coda_replace_fid(inode, oldfid, newfid);