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 venus_comm *vc, 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_vcp(sb), insize, &outsize, inp);
88 *fidp = outp->coda_root.VFid;
90 CODA_FREE(inp, insize);
94 int venus_getattr(struct super_block *sb, struct CodaFid *fid,
95 struct coda_vattr *attr)
98 union outputArgs *outp;
99 int insize, outsize, error;
101 insize = SIZE(getattr);
103 inp->coda_getattr.VFid = *fid;
105 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
107 *attr = outp->coda_getattr.attr;
109 CODA_FREE(inp, insize);
113 int venus_setattr(struct super_block *sb, struct CodaFid *fid,
114 struct coda_vattr *vattr)
116 union inputArgs *inp;
117 union outputArgs *outp;
118 int insize, outsize, error;
120 insize = SIZE(setattr);
123 inp->coda_setattr.VFid = *fid;
124 inp->coda_setattr.attr = *vattr;
126 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
128 CODA_FREE(inp, insize);
132 int venus_lookup(struct super_block *sb, struct CodaFid *fid,
133 const char *name, int length, int * type,
134 struct CodaFid *resfid)
136 union inputArgs *inp;
137 union outputArgs *outp;
138 int insize, outsize, error;
141 offset = INSIZE(lookup);
142 insize = max_t(unsigned int, offset + length +1, OUTSIZE(lookup));
145 inp->coda_lookup.VFid = *fid;
146 inp->coda_lookup.name = offset;
147 inp->coda_lookup.flags = CLU_CASE_SENSITIVE;
148 /* send Venus a null terminated string */
149 memcpy((char *)(inp) + offset, name, length);
150 *((char *)inp + offset + length) = '\0';
152 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
154 *resfid = outp->coda_lookup.VFid;
155 *type = outp->coda_lookup.vtype;
158 CODA_FREE(inp, insize);
162 int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
165 union inputArgs *inp;
166 union outputArgs *outp;
167 int insize, outsize, error;
168 #ifdef CONFIG_CODA_FS_OLD_API
169 struct coda_cred cred = { 0, };
173 insize = SIZE(store);
176 #ifdef CONFIG_CODA_FS_OLD_API
177 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
182 inp->coda_store.VFid = *fid;
183 inp->coda_store.flags = flags;
185 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
187 CODA_FREE(inp, insize);
191 int venus_release(struct super_block *sb, struct CodaFid *fid, int flags)
193 union inputArgs *inp;
194 union outputArgs *outp;
195 int insize, outsize, error;
197 insize = SIZE(release);
200 inp->coda_release.VFid = *fid;
201 inp->coda_release.flags = flags;
203 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
205 CODA_FREE(inp, insize);
209 int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
212 union inputArgs *inp;
213 union outputArgs *outp;
214 int insize, outsize, error;
215 #ifdef CONFIG_CODA_FS_OLD_API
216 struct coda_cred cred = { 0, };
220 insize = SIZE(release);
223 #ifdef CONFIG_CODA_FS_OLD_API
224 memcpy(&(inp->ih.cred), &cred, sizeof(cred));
229 inp->coda_close.VFid = *fid;
230 inp->coda_close.flags = flags;
232 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
234 CODA_FREE(inp, insize);
238 int venus_open(struct super_block *sb, struct CodaFid *fid,
239 int flags, struct file **fh)
241 union inputArgs *inp;
242 union outputArgs *outp;
243 int insize, outsize, error;
245 insize = SIZE(open_by_fd);
246 UPARG(CODA_OPEN_BY_FD);
248 inp->coda_open_by_fd.VFid = *fid;
249 inp->coda_open_by_fd.flags = flags;
251 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
253 *fh = outp->coda_open_by_fd.fh;
255 CODA_FREE(inp, insize);
259 int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
260 const char *name, int length,
261 struct CodaFid *newfid, struct coda_vattr *attrs)
263 union inputArgs *inp;
264 union outputArgs *outp;
265 int insize, outsize, error;
268 offset = INSIZE(mkdir);
269 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(mkdir));
272 inp->coda_mkdir.VFid = *dirfid;
273 inp->coda_mkdir.attr = *attrs;
274 inp->coda_mkdir.name = offset;
275 /* Venus must get null terminated string */
276 memcpy((char *)(inp) + offset, name, length);
277 *((char *)inp + offset + length) = '\0';
279 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
281 *attrs = outp->coda_mkdir.attr;
282 *newfid = outp->coda_mkdir.VFid;
285 CODA_FREE(inp, insize);
290 int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
291 struct CodaFid *new_fid, size_t old_length,
292 size_t new_length, const char *old_name,
293 const char *new_name)
295 union inputArgs *inp;
296 union outputArgs *outp;
297 int insize, outsize, error;
300 offset = INSIZE(rename);
301 insize = max_t(unsigned int, offset + new_length + old_length + 8,
305 inp->coda_rename.sourceFid = *old_fid;
306 inp->coda_rename.destFid = *new_fid;
307 inp->coda_rename.srcname = offset;
309 /* Venus must receive an null terminated string */
310 s = ( old_length & ~0x3) +4; /* round up to word boundary */
311 memcpy((char *)(inp) + offset, old_name, old_length);
312 *((char *)inp + offset + old_length) = '\0';
314 /* another null terminated string for Venus */
316 inp->coda_rename.destname = offset;
317 s = ( new_length & ~0x3) +4; /* round up to word boundary */
318 memcpy((char *)(inp) + offset, new_name, new_length);
319 *((char *)inp + offset + new_length) = '\0';
321 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
323 CODA_FREE(inp, insize);
327 int venus_create(struct super_block *sb, struct CodaFid *dirfid,
328 const char *name, int length, int excl, int mode,
329 struct CodaFid *newfid, struct coda_vattr *attrs)
331 union inputArgs *inp;
332 union outputArgs *outp;
333 int insize, outsize, error;
336 offset = INSIZE(create);
337 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(create));
340 inp->coda_create.VFid = *dirfid;
341 inp->coda_create.attr.va_mode = mode;
342 inp->coda_create.excl = excl;
343 inp->coda_create.mode = mode;
344 inp->coda_create.name = offset;
346 /* Venus must get null terminated string */
347 memcpy((char *)(inp) + offset, name, length);
348 *((char *)inp + offset + length) = '\0';
350 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
352 *attrs = outp->coda_create.attr;
353 *newfid = outp->coda_create.VFid;
356 CODA_FREE(inp, insize);
360 int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
361 const char *name, int length)
363 union inputArgs *inp;
364 union outputArgs *outp;
365 int insize, outsize, error;
368 offset = INSIZE(rmdir);
369 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(rmdir));
372 inp->coda_rmdir.VFid = *dirfid;
373 inp->coda_rmdir.name = offset;
374 memcpy((char *)(inp) + offset, name, length);
375 *((char *)inp + offset + length) = '\0';
377 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
379 CODA_FREE(inp, insize);
383 int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
384 const char *name, int length)
386 union inputArgs *inp;
387 union outputArgs *outp;
388 int error=0, insize, outsize, offset;
390 offset = INSIZE(remove);
391 insize = max_t(unsigned int, offset + length + 1, OUTSIZE(remove));
394 inp->coda_remove.VFid = *dirfid;
395 inp->coda_remove.name = offset;
396 memcpy((char *)(inp) + offset, name, length);
397 *((char *)inp + offset + length) = '\0';
399 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
401 CODA_FREE(inp, insize);
405 int venus_readlink(struct super_block *sb, struct CodaFid *fid,
406 char *buffer, int *length)
408 union inputArgs *inp;
409 union outputArgs *outp;
410 int insize, outsize, error;
414 insize = max_t(unsigned int,
415 INSIZE(readlink), OUTSIZE(readlink)+ *length + 1);
416 UPARG(CODA_READLINK);
418 inp->coda_readlink.VFid = *fid;
420 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
422 retlen = outp->coda_readlink.count;
423 if ( retlen > *length )
426 result = (char *)outp + (long)outp->coda_readlink.data;
427 memcpy(buffer, result, retlen);
428 *(buffer + retlen) = '\0';
431 CODA_FREE(inp, insize);
437 int venus_link(struct super_block *sb, struct CodaFid *fid,
438 struct CodaFid *dirfid, const char *name, int len )
440 union inputArgs *inp;
441 union outputArgs *outp;
442 int insize, outsize, error;
445 offset = INSIZE(link);
446 insize = max_t(unsigned int, offset + len + 1, OUTSIZE(link));
449 inp->coda_link.sourceFid = *fid;
450 inp->coda_link.destFid = *dirfid;
451 inp->coda_link.tname = offset;
453 /* make sure strings are null terminated */
454 memcpy((char *)(inp) + offset, name, len);
455 *((char *)inp + offset + len) = '\0';
457 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
459 CODA_FREE(inp, insize);
463 int venus_symlink(struct super_block *sb, struct CodaFid *fid,
464 const char *name, int len,
465 const char *symname, int symlen)
467 union inputArgs *inp;
468 union outputArgs *outp;
469 int insize, outsize, error;
472 offset = INSIZE(symlink);
473 insize = max_t(unsigned int, offset + len + symlen + 8, OUTSIZE(symlink));
476 /* inp->coda_symlink.attr = *tva; XXXXXX */
477 inp->coda_symlink.VFid = *fid;
479 /* Round up to word boundary and null terminate */
480 inp->coda_symlink.srcname = offset;
481 s = ( symlen & ~0x3 ) + 4;
482 memcpy((char *)(inp) + offset, symname, symlen);
483 *((char *)inp + offset + symlen) = '\0';
485 /* Round up to word boundary and null terminate */
487 inp->coda_symlink.tname = offset;
488 s = (len & ~0x3) + 4;
489 memcpy((char *)(inp) + offset, name, len);
490 *((char *)inp + offset + len) = '\0';
492 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
494 CODA_FREE(inp, insize);
498 int venus_fsync(struct super_block *sb, struct CodaFid *fid)
500 union inputArgs *inp;
501 union outputArgs *outp;
502 int insize, outsize, error;
507 inp->coda_fsync.VFid = *fid;
508 error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs),
511 CODA_FREE(inp, insize);
515 int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
517 union inputArgs *inp;
518 union outputArgs *outp;
519 int insize, outsize, error;
521 insize = SIZE(access);
524 inp->coda_access.VFid = *fid;
525 inp->coda_access.flags = mask;
527 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
529 CODA_FREE(inp, insize);
534 int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
535 unsigned int cmd, struct PioctlData *data)
537 union inputArgs *inp;
538 union outputArgs *outp;
539 int insize, outsize, error;
542 insize = VC_MAXMSGSIZE;
545 /* build packet for Venus */
546 if (data->vi.in_size > VC_MAXDATASIZE) {
551 if (data->vi.out_size > VC_MAXDATASIZE) {
556 inp->coda_ioctl.VFid = *fid;
558 /* the cmd field was mutated by increasing its size field to
559 * reflect the path and follow args. We need to subtract that
560 * out before sending the command to Venus. */
561 inp->coda_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));
562 iocsize = ((cmd >> 16) & PIOCPARM_MASK) - sizeof(char *) - sizeof(int);
563 inp->coda_ioctl.cmd |= (iocsize & PIOCPARM_MASK) << 16;
565 /* in->coda_ioctl.rwflag = flag; */
566 inp->coda_ioctl.len = data->vi.in_size;
567 inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
569 /* get the data out of user space */
570 if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
571 data->vi.in, data->vi.in_size) ) {
576 error = coda_upcall(coda_vcp(sb), SIZE(ioctl) + data->vi.in_size,
580 printk("coda_pioctl: Venus returns: %d for %s\n",
581 error, coda_f2s(fid));
585 if (outsize < (long)outp->coda_ioctl.data + outp->coda_ioctl.len) {
590 /* Copy out the OUT buffer. */
591 if (outp->coda_ioctl.len > data->vi.out_size) {
596 /* Copy out the OUT buffer. */
597 if (copy_to_user(data->vi.out,
598 (char *)outp + (long)outp->coda_ioctl.data,
599 outp->coda_ioctl.len)) {
605 CODA_FREE(inp, insize);
609 int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
611 union inputArgs *inp;
612 union outputArgs *outp;
613 int insize, outsize, error;
615 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
618 error = coda_upcall(coda_vcp(dentry->d_sb), insize, &outsize, inp);
620 sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
621 sfs->f_bfree = outp->coda_statfs.stat.f_bfree;
622 sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
623 sfs->f_files = outp->coda_statfs.stat.f_files;
624 sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
627 CODA_FREE(inp, insize);
632 * coda_upcall and coda_downcall routines.
634 static void block_signals(sigset_t *old)
636 spin_lock_irq(¤t->sighand->siglock);
637 *old = current->blocked;
639 sigfillset(¤t->blocked);
640 sigdelset(¤t->blocked, SIGKILL);
641 sigdelset(¤t->blocked, SIGSTOP);
642 sigdelset(¤t->blocked, SIGINT);
645 spin_unlock_irq(¤t->sighand->siglock);
648 static void unblock_signals(sigset_t *old)
650 spin_lock_irq(¤t->sighand->siglock);
651 current->blocked = *old;
653 spin_unlock_irq(¤t->sighand->siglock);
656 /* Don't allow signals to interrupt the following upcalls before venus
658 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
659 * - CODA_STORE (to avoid data loss)
661 #define CODA_INTERRUPTIBLE(r) (!coda_hard && \
662 (((r)->uc_opcode != CODA_CLOSE && \
663 (r)->uc_opcode != CODA_STORE && \
664 (r)->uc_opcode != CODA_RELEASE) || \
665 (r)->uc_flags & REQ_READ))
667 static inline void coda_waitfor_upcall(struct upc_req *req)
669 DECLARE_WAITQUEUE(wait, current);
670 unsigned long timeout = jiffies + coda_timeout * HZ;
677 add_wait_queue(&req->uc_sleep, &wait);
679 if (CODA_INTERRUPTIBLE(req))
680 set_current_state(TASK_INTERRUPTIBLE);
682 set_current_state(TASK_UNINTERRUPTIBLE);
685 if (req->uc_flags & (REQ_WRITE | REQ_ABORT))
688 if (blocked && time_after(jiffies, timeout) &&
689 CODA_INTERRUPTIBLE(req))
691 unblock_signals(&old);
695 if (signal_pending(current)) {
696 list_del(&req->uc_chain);
701 schedule_timeout(HZ);
706 unblock_signals(&old);
708 remove_wait_queue(&req->uc_sleep, &wait);
709 set_current_state(TASK_RUNNING);
714 * coda_upcall will return an error in the case of
715 * failed communication with Venus _or_ will peek at Venus
716 * reply and return Venus' error.
718 * As venus has 2 types of errors, normal errors (positive) and internal
719 * errors (negative), normal errors are negated, while internal errors
720 * are all mapped to -EINTR, while showing a nice warning message. (jh)
722 static int coda_upcall(struct venus_comm *vcp,
723 int inSize, int *outSize,
724 union inputArgs *buffer)
726 union outputArgs *out;
727 union inputArgs *sig_inputArgs;
728 struct upc_req *req, *sig_req;
731 if (!vcp->vc_inuse) {
732 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
736 /* Format the request message. */
737 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
741 req->uc_data = (void *)buffer;
743 req->uc_inSize = inSize;
744 req->uc_outSize = *outSize ? *outSize : inSize;
745 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
746 req->uc_unique = ++vcp->vc_seq;
747 init_waitqueue_head(&req->uc_sleep);
749 /* Fill in the common input args. */
750 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
752 /* Append msg to pending queue and poke Venus. */
753 list_add_tail(&req->uc_chain, &vcp->vc_pending);
755 wake_up_interruptible(&vcp->vc_waitq);
756 /* We can be interrupted while we wait for Venus to process
757 * our request. If the interrupt occurs before Venus has read
758 * the request, we dequeue and return. If it occurs after the
759 * read but before the reply, we dequeue, send a signal
760 * message, and return. If it occurs after the reply we ignore
761 * it. In no case do we want to restart the syscall. If it
762 * was interrupted by a venus shutdown (psdev_close), return
765 /* Go to sleep. Wake up on signals only after the timeout. */
766 coda_waitfor_upcall(req);
768 /* Op went through, interrupt or not... */
769 if (req->uc_flags & REQ_WRITE) {
770 out = (union outputArgs *)req->uc_data;
771 /* here we map positive Venus errors to kernel errors */
772 error = -out->oh.result;
773 *outSize = req->uc_outSize;
778 if ((req->uc_flags & REQ_ABORT) || !signal_pending(current)) {
779 printk(KERN_WARNING "coda: Unexpected interruption.\n");
783 /* Interrupted before venus read it. */
784 if (!(req->uc_flags & REQ_READ))
787 /* Venus saw the upcall, make sure we can send interrupt signal */
788 if (!vcp->vc_inuse) {
789 printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
794 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
795 if (!sig_req) goto exit;
797 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
798 if (!sig_req->uc_data) {
804 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
805 sig_inputArgs->ih.opcode = CODA_SIGNAL;
806 sig_inputArgs->ih.unique = req->uc_unique;
808 sig_req->uc_flags = REQ_ASYNC;
809 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
810 sig_req->uc_unique = sig_inputArgs->ih.unique;
811 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
812 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
814 /* insert at head of queue! */
815 list_add(&(sig_req->uc_chain), &vcp->vc_pending);
816 wake_up_interruptible(&vcp->vc_waitq);
824 The statements below are part of the Coda opportunistic
825 programming -- taken from the Mach/BSD kernel code for Coda.
826 You don't get correct semantics by stating what needs to be
827 done without guaranteeing the invariants needed for it to happen.
828 When will be have time to find out what exactly is going on? (pjb)
833 * There are 7 cases where cache invalidations occur. The semantics
834 * of each is listed here:
836 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
837 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
838 * This call is a result of token expiration.
840 * The next arise as the result of callbacks on a file or directory.
841 * CODA_ZAPFILE -- flush the cached attributes for a file.
843 * CODA_ZAPDIR -- flush the attributes for the dir and
844 * force a new lookup for all the children
848 * The next is a result of Venus detecting an inconsistent file.
849 * CODA_PURGEFID -- flush the attribute for the file
850 * purge it and its children from the dcache
852 * The last allows Venus to replace local fids with global ones
853 * during reintegration.
855 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
857 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
859 struct inode *inode = NULL;
860 struct CodaFid *fid, *newfid;
862 /* Handle invalidation requests. */
863 if ( !sb || !sb->s_root)
868 coda_cache_clear_all(sb);
869 shrink_dcache_sb(sb);
870 if (sb->s_root->d_inode)
871 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
875 coda_cache_clear_all(sb);
879 fid = &out->coda_zapdir.CodaFid;
880 inode = coda_fid_to_inode(fid, sb);
882 coda_flag_inode_children(inode, C_PURGE);
883 coda_flag_inode(inode, C_VATTR);
888 fid = &out->coda_zapfile.CodaFid;
889 inode = coda_fid_to_inode(fid, sb);
891 coda_flag_inode(inode, C_VATTR);
895 fid = &out->coda_purgefid.CodaFid;
896 inode = coda_fid_to_inode(fid, sb);
898 coda_flag_inode_children(inode, C_PURGE);
900 /* catch the dentries later if some are still busy */
901 coda_flag_inode(inode, C_PURGE);
902 d_prune_aliases(inode);
908 fid = &out->coda_replace.OldFid;
909 newfid = &out->coda_replace.NewFid;
910 inode = coda_fid_to_inode(fid, sb);
912 coda_replace_fid(inode, fid, newfid);