Annotation of src/sys/coda/coda_vnops.c, Revision 1.25.2.3
1.1 rvb 1: /*
1.3 rvb 2: coda_create/vn_open
1.2 rvb 3: remove/unlink
4: link
5: mkdir
6: rmdir
7: symlink
1.1 rvb 8: */
1.25.2.3! jdolecek 9: /* $NetBSD: coda_vnops.c,v 1.25.2.2 2002/01/10 19:50:54 thorpej Exp $ */
1.1 rvb 10:
1.2 rvb 11: /*
12: *
13: * Coda: an Experimental Distributed File System
14: * Release 3.1
15: *
16: * Copyright (c) 1987-1998 Carnegie Mellon University
17: * All Rights Reserved
18: *
19: * Permission to use, copy, modify and distribute this software and its
20: * documentation is hereby granted, provided that both the copyright
21: * notice and this permission notice appear in all copies of the
22: * software, derivative works or modified versions, and any portions
23: * thereof, and that both notices appear in supporting documentation, and
24: * that credit is given to Carnegie Mellon University in all documents
25: * and publicity pertaining to direct or indirect use of this code or its
26: * derivatives.
27: *
28: * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
29: * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
30: * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
31: * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
32: * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
33: * ANY DERIVATIVE WORK.
34: *
35: * Carnegie Mellon encourages users of this software to return any
36: * improvements or extensions that they make, and to grant Carnegie
37: * Mellon the rights to redistribute these changes without encumbrance.
38: *
1.4 rvb 39: * @(#) coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:26:46 rvb Exp $
1.2 rvb 40: */
1.1 rvb 41:
42: /*
43: * Mach Operating System
44: * Copyright (c) 1990 Carnegie-Mellon University
45: * Copyright (c) 1989 Carnegie-Mellon University
46: * All rights reserved. The CMU software License Agreement specifies
47: * the terms and conditions for use and redistribution.
48: */
49:
50: /*
51: * This code was written for the Coda file system at Carnegie Mellon
52: * University. Contributers include David Steere, James Kistler, and
53: * M. Satyanarayanan.
54: */
55:
1.25.2.2 thorpej 56: #include <sys/cdefs.h>
1.25.2.3! jdolecek 57: __KERNEL_RCSID(0, "$NetBSD: coda_vnops.c,v 1.25.2.2 2002/01/10 19:50:54 thorpej Exp $");
1.25.2.2 thorpej 58:
1.1 rvb 59: #include <sys/param.h>
60: #include <sys/systm.h>
61: #include <sys/malloc.h>
62: #include <sys/errno.h>
63: #include <sys/acct.h>
64: #include <sys/file.h>
65: #include <sys/uio.h>
66: #include <sys/namei.h>
67: #include <sys/ioctl.h>
68: #include <sys/mount.h>
69: #include <sys/proc.h>
70: #include <sys/select.h>
71: #include <sys/user.h>
72: #include <miscfs/genfs/genfs.h>
73:
1.4 rvb 74: #include <coda/coda.h>
75: #include <coda/cnode.h>
76: #include <coda/coda_vnops.h>
77: #include <coda/coda_venus.h>
78: #include <coda/coda_opstats.h>
79: #include <coda/coda_subr.h>
80: #include <coda/coda_namecache.h>
81: #include <coda/coda_pioctl.h>
1.1 rvb 82:
83: /*
84: * These flags select various performance enhancements.
85: */
1.3 rvb 86: int coda_attr_cache = 1; /* Set to cache attributes in the kernel */
87: int coda_symlink_cache = 1; /* Set to cache symbolic link information */
88: int coda_access_cache = 1; /* Set to handle some access checks directly */
1.1 rvb 89:
90: /* structure to keep track of vfs calls */
91:
1.3 rvb 92: struct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE];
1.1 rvb 93:
1.3 rvb 94: #define MARK_ENTRY(op) (coda_vnodeopstats[op].entries++)
95: #define MARK_INT_SAT(op) (coda_vnodeopstats[op].sat_intrn++)
96: #define MARK_INT_FAIL(op) (coda_vnodeopstats[op].unsat_intrn++)
97: #define MARK_INT_GEN(op) (coda_vnodeopstats[op].gen_intrn++)
1.1 rvb 98:
99: /* What we are delaying for in printf */
1.3 rvb 100: int coda_printf_delay = 0; /* in microseconds */
101: int coda_vnop_print_entry = 0;
102: static int coda_lockdebug = 0;
1.1 rvb 103:
104: /* Definition of the vfs operation vector */
105:
106: /*
107: * Some NetBSD details:
108: *
1.3 rvb 109: * coda_start is called at the end of the mount syscall.
110: * coda_init is called at boot time.
1.1 rvb 111: */
112:
1.25.2.2 thorpej 113: #define ENTRY if(coda_vnop_print_entry) myprintf(("Entered %s\n",__func__))
1.1 rvb 114:
115: /* Definition of the vnode operation vector */
116:
1.23 jdolecek 117: const struct vnodeopv_entry_desc coda_vnodeop_entries[] = {
1.3 rvb 118: { &vop_default_desc, coda_vop_error },
119: { &vop_lookup_desc, coda_lookup }, /* lookup */
120: { &vop_create_desc, coda_create }, /* create */
1.5 rvb 121: { &vop_mknod_desc, coda_vop_error }, /* mknod */
1.3 rvb 122: { &vop_open_desc, coda_open }, /* open */
123: { &vop_close_desc, coda_close }, /* close */
124: { &vop_access_desc, coda_access }, /* access */
1.5 rvb 125: { &vop_getattr_desc, coda_getattr }, /* getattr */
126: { &vop_setattr_desc, coda_setattr }, /* setattr */
1.3 rvb 127: { &vop_read_desc, coda_read }, /* read */
128: { &vop_write_desc, coda_write }, /* write */
1.11 wrstuden 129: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
1.3 rvb 130: { &vop_ioctl_desc, coda_ioctl }, /* ioctl */
131: /* 1.3 { &vop_select_desc, coda_select }, select */
1.24 chs 132: { &vop_mmap_desc, genfs_mmap }, /* mmap */
1.3 rvb 133: { &vop_fsync_desc, coda_fsync }, /* fsync */
134: { &vop_remove_desc, coda_remove }, /* remove */
135: { &vop_link_desc, coda_link }, /* link */
136: { &vop_rename_desc, coda_rename }, /* rename */
137: { &vop_mkdir_desc, coda_mkdir }, /* mkdir */
138: { &vop_rmdir_desc, coda_rmdir }, /* rmdir */
1.5 rvb 139: { &vop_symlink_desc, coda_symlink }, /* symlink */
140: { &vop_readdir_desc, coda_readdir }, /* readdir */
1.3 rvb 141: { &vop_readlink_desc, coda_readlink }, /* readlink */
1.5 rvb 142: { &vop_abortop_desc, coda_abortop }, /* abortop */
1.3 rvb 143: { &vop_inactive_desc, coda_inactive }, /* inactive */
1.5 rvb 144: { &vop_reclaim_desc, coda_reclaim }, /* reclaim */
1.3 rvb 145: { &vop_lock_desc, coda_lock }, /* lock */
146: { &vop_unlock_desc, coda_unlock }, /* unlock */
147: { &vop_bmap_desc, coda_bmap }, /* bmap */
148: { &vop_strategy_desc, coda_strategy }, /* strategy */
1.5 rvb 149: { &vop_print_desc, coda_vop_error }, /* print */
1.3 rvb 150: { &vop_islocked_desc, coda_islocked }, /* islocked */
151: { &vop_pathconf_desc, coda_vop_error }, /* pathconf */
1.5 rvb 152: { &vop_advlock_desc, coda_vop_nop }, /* advlock */
1.3 rvb 153: { &vop_bwrite_desc, coda_vop_error }, /* bwrite */
154: { &vop_lease_desc, coda_vop_nop }, /* lease */
155: { &vop_blkatoff_desc, coda_vop_error }, /* blkatoff */
156: { &vop_valloc_desc, coda_vop_error }, /* valloc */
1.5 rvb 157: { &vop_vfree_desc, coda_vop_error }, /* vfree */
1.3 rvb 158: { &vop_truncate_desc, coda_vop_error }, /* truncate */
159: { &vop_update_desc, coda_vop_error }, /* update */
1.1 rvb 160: { &vop_seek_desc, genfs_seek }, /* seek */
1.5 rvb 161: { &vop_poll_desc, genfs_poll }, /* poll */
1.25 chs 162: { &vop_getpages_desc, coda_getpages }, /* getpages */
163: { &vop_putpages_desc, coda_putpages }, /* putpages */
1.24 chs 164: { NULL, NULL }
1.1 rvb 165: };
166:
1.23 jdolecek 167: const struct vnodeopv_desc coda_vnodeop_opv_desc =
1.3 rvb 168: { &coda_vnodeop_p, coda_vnodeop_entries };
1.1 rvb 169:
170: /* Definitions of NetBSD vnodeop interfaces */
171:
172: /* A generic panic: we were called with something we didn't define yet */
173: int
1.3 rvb 174: coda_vop_error(void *anon) {
1.1 rvb 175: struct vnodeop_desc **desc = (struct vnodeop_desc **)anon;
176:
1.9 rvb 177: myprintf(("coda_vop_error: Vnode operation %s called, but not defined.\n",
1.1 rvb 178: (*desc)->vdesc_name));
1.9 rvb 179: /*
1.3 rvb 180: panic("coda_nbsd_vop_error");
1.1 rvb 181: return 0;
1.9 rvb 182: */
183: return EIO;
1.1 rvb 184: }
185:
186: /* A generic do-nothing. For lease_check, advlock */
187: int
1.3 rvb 188: coda_vop_nop(void *anon) {
1.1 rvb 189: struct vnodeop_desc **desc = (struct vnodeop_desc **)anon;
190:
1.3 rvb 191: if (codadebug) {
1.1 rvb 192: myprintf(("Vnode operation %s called, but unsupported\n",
193: (*desc)->vdesc_name));
194: }
195: return (0);
196: }
197:
198: int
1.3 rvb 199: coda_vnodeopstats_init(void)
1.1 rvb 200: {
1.17 augustss 201: int i;
1.1 rvb 202:
1.3 rvb 203: for(i=0;i<CODA_VNODEOPS_SIZE;i++) {
204: coda_vnodeopstats[i].opcode = i;
205: coda_vnodeopstats[i].entries = 0;
206: coda_vnodeopstats[i].sat_intrn = 0;
207: coda_vnodeopstats[i].unsat_intrn = 0;
208: coda_vnodeopstats[i].gen_intrn = 0;
1.1 rvb 209: }
210:
211: return 0;
212: }
213:
214: /*
1.3 rvb 215: * coda_open calls Venus to return the device, inode pair of the cache
216: * file holding the data. Using iget, coda_open finds the vnode of the
1.1 rvb 217: * cache file, and then opens it.
218: */
219: int
1.3 rvb 220: coda_open(v)
1.1 rvb 221: void *v;
222: {
223: /*
224: * NetBSD can pass the O_EXCL flag in mode, even though the check
225: * has already happened. Venus defensively assumes that if open
226: * is passed the EXCL, it must be a bug. We strip the flag here.
227: */
228: /* true args */
229: struct vop_open_args *ap = v;
1.17 augustss 230: struct vnode **vpp = &(ap->a_vp);
1.1 rvb 231: struct cnode *cp = VTOC(*vpp);
232: int flag = ap->a_mode & (~O_EXCL);
233: struct ucred *cred = ap->a_cred;
234: struct proc *p = ap->a_p;
235: /* locals */
236: int error;
237: struct vnode *vp;
238: dev_t dev;
239: ino_t inode;
240:
1.3 rvb 241: MARK_ENTRY(CODA_OPEN_STATS);
1.1 rvb 242:
243: /* Check for open of control file. */
244: if (IS_CTL_VP(*vpp)) {
245: /* XXX */
246: /* if (WRITEABLE(flag)) */
247: if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) {
1.3 rvb 248: MARK_INT_FAIL(CODA_OPEN_STATS);
1.1 rvb 249: return(EACCES);
250: }
1.3 rvb 251: MARK_INT_SAT(CODA_OPEN_STATS);
1.1 rvb 252: return(0);
253: }
254:
255: error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, p, &dev, &inode);
256: if (error)
257: return (error);
258: if (!error) {
1.3 rvb 259: CODADEBUG( CODA_OPEN,myprintf(("open: dev %d inode %d result %d\n",
1.1 rvb 260: dev, inode, error)); )
261: }
262:
263: /* Translate the <device, inode> pair for the cache file into
264: an inode pointer. */
1.3 rvb 265: error = coda_grab_vnode(dev, inode, &vp);
1.1 rvb 266: if (error)
267: return (error);
268:
269: /* We get the vnode back locked in both Mach and NetBSD. Needs unlocked */
1.2 rvb 270: VOP_UNLOCK(vp, 0);
1.1 rvb 271: /* Keep a reference until the close comes in. */
272: vref(*vpp);
273:
274: /* Save the vnode pointer for the cache file. */
275: if (cp->c_ovp == NULL) {
276: cp->c_ovp = vp;
277: } else {
278: if (cp->c_ovp != vp)
1.3 rvb 279: panic("coda_open: cp->c_ovp != ITOV(ip)");
1.1 rvb 280: }
281: cp->c_ocount++;
282:
283: /* Flush the attribute cached if writing the file. */
284: if (flag & FWRITE) {
285: cp->c_owrite++;
286: cp->c_flags &= ~C_VATTR;
287: }
288:
289: /* Save the <device, inode> pair for the cache file to speed
290: up subsequent page_read's. */
291: cp->c_device = dev;
292: cp->c_inode = inode;
293:
294: /* Open the cache file. */
295: error = VOP_OPEN(vp, flag, cred, p);
296: return(error);
297: }
298:
299: /*
300: * Close the cache file used for I/O and notify Venus.
301: */
302: int
1.3 rvb 303: coda_close(v)
1.1 rvb 304: void *v;
305: {
306: /* true args */
307: struct vop_close_args *ap = v;
308: struct vnode *vp = ap->a_vp;
309: struct cnode *cp = VTOC(vp);
310: int flag = ap->a_fflag;
311: struct ucred *cred = ap->a_cred;
312: struct proc *p = ap->a_p;
313: /* locals */
314: int error;
315:
1.3 rvb 316: MARK_ENTRY(CODA_CLOSE_STATS);
1.1 rvb 317:
318: /* Check for close of control file. */
319: if (IS_CTL_VP(vp)) {
1.3 rvb 320: MARK_INT_SAT(CODA_CLOSE_STATS);
1.1 rvb 321: return(0);
322: }
323:
324: if (IS_UNMOUNTING(cp)) {
325: if (cp->c_ovp) {
1.7 rvb 326: #ifdef CODA_VERBOSE
1.3 rvb 327: printf("coda_close: destroying container ref %d, ufs vp %p of vp %p/cp %p\n",
1.1 rvb 328: vp->v_usecount, cp->c_ovp, vp, cp);
1.5 rvb 329: #endif
1.8 rvb 330: #ifdef hmm
1.1 rvb 331: vgone(cp->c_ovp);
1.8 rvb 332: #else
1.14 wrstuden 333: vn_lock(cp->c_ovp, LK_EXCLUSIVE | LK_RETRY);
1.8 rvb 334: VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */
1.14 wrstuden 335: vput(cp->c_ovp);
1.8 rvb 336: #endif
1.1 rvb 337: } else {
1.7 rvb 338: #ifdef CODA_VERBOSE
1.3 rvb 339: printf("coda_close: NO container vp %p/cp %p\n", vp, cp);
1.5 rvb 340: #endif
1.1 rvb 341: }
342: return ENODEV;
343: } else {
1.14 wrstuden 344: vn_lock(cp->c_ovp, LK_EXCLUSIVE | LK_RETRY);
1.1 rvb 345: VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */
1.14 wrstuden 346: vput(cp->c_ovp);
1.1 rvb 347: }
348:
349: if (--cp->c_ocount == 0)
350: cp->c_ovp = NULL;
351:
352: if (flag & FWRITE) /* file was opened for write */
353: --cp->c_owrite;
354:
355: error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, p);
356: vrele(CTOV(cp));
357:
1.3 rvb 358: CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)); )
1.1 rvb 359: return(error);
360: }
361:
362: int
1.3 rvb 363: coda_read(v)
1.1 rvb 364: void *v;
365: {
366: struct vop_read_args *ap = v;
367:
368: ENTRY;
1.3 rvb 369: return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ,
1.1 rvb 370: ap->a_ioflag, ap->a_cred, ap->a_uio->uio_procp));
371: }
372:
373: int
1.3 rvb 374: coda_write(v)
1.1 rvb 375: void *v;
376: {
377: struct vop_write_args *ap = v;
378:
379: ENTRY;
1.3 rvb 380: return(coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE,
1.1 rvb 381: ap->a_ioflag, ap->a_cred, ap->a_uio->uio_procp));
382: }
383:
384: int
1.3 rvb 385: coda_rdwr(vp, uiop, rw, ioflag, cred, p)
1.1 rvb 386: struct vnode *vp;
387: struct uio *uiop;
388: enum uio_rw rw;
389: int ioflag;
390: struct ucred *cred;
391: struct proc *p;
392: {
393: /* upcall decl */
394: /* NOTE: container file operation!!! */
395: /* locals */
396: struct cnode *cp = VTOC(vp);
397: struct vnode *cfvp = cp->c_ovp;
398: int igot_internally = 0;
399: int opened_internally = 0;
400: int error = 0;
401:
1.3 rvb 402: MARK_ENTRY(CODA_RDWR_STATS);
1.1 rvb 403:
1.12 matt 404: CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %lu, %lld, %d)\n", rw,
405: uiop->uio_iov->iov_base,
406: (unsigned long) uiop->uio_resid,
407: (long long) uiop->uio_offset, uiop->uio_segflg)); )
1.1 rvb 408:
409: /* Check for rdwr of control object. */
410: if (IS_CTL_VP(vp)) {
1.3 rvb 411: MARK_INT_FAIL(CODA_RDWR_STATS);
1.1 rvb 412: return(EINVAL);
413: }
414:
415: /* Redirect the request to UFS. */
416:
417: /*
418: * If file is not already open this must be a page
419: * {read,write} request. Iget the cache file's inode
420: * pointer if we still have its <device, inode> pair.
421: * Otherwise, we must do an internal open to derive the
422: * pair.
423: */
424: if (cfvp == NULL) {
425: /*
426: * If we're dumping core, do the internal open. Otherwise
427: * venus won't have the correct size of the core when
428: * it's completely written.
429: */
430: if (cp->c_inode != 0 && !(p && (p->p_acflag & ACORE))) {
431: igot_internally = 1;
1.3 rvb 432: error = coda_grab_vnode(cp->c_device, cp->c_inode, &cfvp);
1.1 rvb 433: if (error) {
1.3 rvb 434: MARK_INT_FAIL(CODA_RDWR_STATS);
1.1 rvb 435: return(error);
436: }
437: /*
438: * We get the vnode back locked in both Mach and
439: * NetBSD. Needs unlocked
440: */
1.2 rvb 441: VOP_UNLOCK(cfvp, 0);
1.1 rvb 442: }
443: else {
444: opened_internally = 1;
1.3 rvb 445: MARK_INT_GEN(CODA_OPEN_STATS);
1.1 rvb 446: error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE),
447: cred, p);
1.18 phil 448: #ifdef CODA_VERBOSE
1.3 rvb 449: printf("coda_rdwr: Internally Opening %p\n", vp);
1.18 phil 450: #endif
1.1 rvb 451: if (error) {
1.3 rvb 452: MARK_INT_FAIL(CODA_RDWR_STATS);
1.1 rvb 453: return(error);
454: }
455: cfvp = cp->c_ovp;
456: }
457: }
458:
459: /* Have UFS handle the call. */
1.22 chs 460: CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = (%lx.%lx.%lx), refcnt = %d\n",
1.1 rvb 461: cp->c_fid.Volume, cp->c_fid.Vnode,
462: cp->c_fid.Unique, CTOV(cp)->v_usecount)); )
463:
464: if (rw == UIO_READ) {
465: error = VOP_READ(cfvp, uiop, ioflag, cred);
466: } else {
467: error = VOP_WRITE(cfvp, uiop, ioflag, cred);
468: }
469:
470: if (error)
1.3 rvb 471: MARK_INT_FAIL(CODA_RDWR_STATS);
1.1 rvb 472: else
1.3 rvb 473: MARK_INT_SAT(CODA_RDWR_STATS);
1.1 rvb 474:
475: /* Do an internal close if necessary. */
476: if (opened_internally) {
1.3 rvb 477: MARK_INT_GEN(CODA_CLOSE_STATS);
1.1 rvb 478: (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, p);
479: }
480:
481: /* Invalidate cached attributes if writing. */
482: if (rw == UIO_WRITE)
483: cp->c_flags &= ~C_VATTR;
484: return(error);
485: }
486:
487: int
1.3 rvb 488: coda_ioctl(v)
1.1 rvb 489: void *v;
490: {
491: /* true args */
492: struct vop_ioctl_args *ap = v;
493: struct vnode *vp = ap->a_vp;
494: int com = ap->a_command;
495: caddr_t data = ap->a_data;
496: int flag = ap->a_fflag;
497: struct ucred *cred = ap->a_cred;
498: struct proc *p = ap->a_p;
499: /* locals */
500: int error;
501: struct vnode *tvp;
502: struct nameidata ndp;
503: struct PioctlData *iap = (struct PioctlData *)data;
504:
1.3 rvb 505: MARK_ENTRY(CODA_IOCTL_STATS);
1.1 rvb 506:
1.3 rvb 507: CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));)
1.1 rvb 508:
509: /* Don't check for operation on a dying object, for ctlvp it
510: shouldn't matter */
511:
512: /* Must be control object to succeed. */
513: if (!IS_CTL_VP(vp)) {
1.3 rvb 514: MARK_INT_FAIL(CODA_IOCTL_STATS);
515: CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != ctlvp"));)
1.1 rvb 516: return (EOPNOTSUPP);
517: }
518: /* Look up the pathname. */
519:
520: /* Should we use the name cache here? It would get it from
521: lookupname sooner or later anyway, right? */
522:
523: NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), UIO_USERSPACE, ((caddr_t)iap->path), p);
524: error = namei(&ndp);
525: tvp = ndp.ni_vp;
526:
527: if (error) {
1.3 rvb 528: MARK_INT_FAIL(CODA_IOCTL_STATS);
529: CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup returns %d\n",
1.1 rvb 530: error));)
531: return(error);
532: }
533:
534: /*
535: * Make sure this is a coda style cnode, but it may be a
536: * different vfsp
537: */
538: /* XXX: this totally violates the comment about vtagtype in vnode.h */
1.3 rvb 539: if (tvp->v_tag != VT_CODA) {
1.1 rvb 540: vrele(tvp);
1.3 rvb 541: MARK_INT_FAIL(CODA_IOCTL_STATS);
542: CODADEBUG(CODA_IOCTL,
543: myprintf(("coda_ioctl error: %s not a coda object\n",
1.1 rvb 544: iap->path));)
545: return(EINVAL);
546: }
547:
548: if (iap->vi.in_size > VC_MAXDATASIZE) {
549: vrele(tvp);
550: return(EINVAL);
551: }
552: error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, data, cred, p);
553:
554: if (error)
1.3 rvb 555: MARK_INT_FAIL(CODA_IOCTL_STATS);
1.1 rvb 556: else
1.3 rvb 557: CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", error)); )
1.1 rvb 558:
559: vrele(tvp);
560: return(error);
561: }
562:
563: /*
564: * To reduce the cost of a user-level venus;we cache attributes in
565: * the kernel. Each cnode has storage allocated for an attribute. If
566: * c_vattr is valid, return a reference to it. Otherwise, get the
567: * attributes from venus and store them in the cnode. There is some
568: * question if this method is a security leak. But I think that in
569: * order to make this call, the user must have done a lookup and
570: * opened the file, and therefore should already have access.
571: */
572: int
1.3 rvb 573: coda_getattr(v)
1.1 rvb 574: void *v;
575: {
576: /* true args */
577: struct vop_getattr_args *ap = v;
578: struct vnode *vp = ap->a_vp;
579: struct cnode *cp = VTOC(vp);
580: struct vattr *vap = ap->a_vap;
581: struct ucred *cred = ap->a_cred;
582: struct proc *p = ap->a_p;
583: /* locals */
584: int error;
585:
1.3 rvb 586: MARK_ENTRY(CODA_GETATTR_STATS);
1.1 rvb 587:
588: /* Check for getattr of control object. */
589: if (IS_CTL_VP(vp)) {
1.3 rvb 590: MARK_INT_FAIL(CODA_GETATTR_STATS);
1.1 rvb 591: return(ENOENT);
592: }
593:
594: /* Check to see if the attributes have already been cached */
595: if (VALID_VATTR(cp)) {
1.3 rvb 596: CODADEBUG(CODA_GETATTR, { myprintf(("attr cache hit: (%lx.%lx.%lx)\n",
1.1 rvb 597: cp->c_fid.Volume,
598: cp->c_fid.Vnode,
599: cp->c_fid.Unique));});
1.3 rvb 600: CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR))
1.1 rvb 601: print_vattr(&cp->c_vattr); );
602:
603: *vap = cp->c_vattr;
1.3 rvb 604: MARK_INT_SAT(CODA_GETATTR_STATS);
1.1 rvb 605: return(0);
606: }
607:
608: error = venus_getattr(vtomi(vp), &cp->c_fid, cred, p, vap);
609:
610: if (!error) {
1.3 rvb 611: CODADEBUG(CODA_GETATTR, myprintf(("getattr miss (%lx.%lx.%lx): result %d\n",
1.1 rvb 612: cp->c_fid.Volume,
613: cp->c_fid.Vnode,
614: cp->c_fid.Unique,
615: error)); )
616:
1.3 rvb 617: CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR))
1.1 rvb 618: print_vattr(vap); );
619:
620: /* If not open for write, store attributes in cnode */
1.3 rvb 621: if ((cp->c_owrite == 0) && (coda_attr_cache)) {
1.1 rvb 622: cp->c_vattr = *vap;
623: cp->c_flags |= C_VATTR;
624: }
625:
626: }
627: return(error);
628: }
629:
630: int
1.3 rvb 631: coda_setattr(v)
1.1 rvb 632: void *v;
633: {
634: /* true args */
635: struct vop_setattr_args *ap = v;
1.17 augustss 636: struct vnode *vp = ap->a_vp;
1.1 rvb 637: struct cnode *cp = VTOC(vp);
1.17 augustss 638: struct vattr *vap = ap->a_vap;
1.1 rvb 639: struct ucred *cred = ap->a_cred;
640: struct proc *p = ap->a_p;
641: /* locals */
642: int error;
643:
1.3 rvb 644: MARK_ENTRY(CODA_SETATTR_STATS);
1.1 rvb 645:
646: /* Check for setattr of control object. */
647: if (IS_CTL_VP(vp)) {
1.3 rvb 648: MARK_INT_FAIL(CODA_SETATTR_STATS);
1.1 rvb 649: return(ENOENT);
650: }
651:
1.3 rvb 652: if (codadebug & CODADBGMSK(CODA_SETATTR)) {
1.1 rvb 653: print_vattr(vap);
654: }
655: error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred, p);
656:
657: if (!error)
658: cp->c_flags &= ~C_VATTR;
659:
1.3 rvb 660: CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error)); )
1.1 rvb 661: return(error);
662: }
663:
664: int
1.3 rvb 665: coda_access(v)
1.1 rvb 666: void *v;
667: {
668: /* true args */
669: struct vop_access_args *ap = v;
670: struct vnode *vp = ap->a_vp;
671: struct cnode *cp = VTOC(vp);
672: int mode = ap->a_mode;
673: struct ucred *cred = ap->a_cred;
674: struct proc *p = ap->a_p;
675: /* locals */
676: int error;
677:
1.3 rvb 678: MARK_ENTRY(CODA_ACCESS_STATS);
1.1 rvb 679:
680: /* Check for access of control object. Only read access is
681: allowed on it. */
682: if (IS_CTL_VP(vp)) {
683: /* bogus hack - all will be marked as successes */
1.3 rvb 684: MARK_INT_SAT(CODA_ACCESS_STATS);
1.1 rvb 685: return(((mode & VREAD) && !(mode & (VWRITE | VEXEC)))
686: ? 0 : EACCES);
687: }
688:
689: /*
690: * if the file is a directory, and we are checking exec (eg lookup)
691: * access, and the file is in the namecache, then the user must have
692: * lookup access to it.
693: */
1.3 rvb 694: if (coda_access_cache) {
1.1 rvb 695: if ((vp->v_type == VDIR) && (mode & VEXEC)) {
1.3 rvb 696: if (coda_nc_lookup(cp, ".", 1, cred)) {
697: MARK_INT_SAT(CODA_ACCESS_STATS);
1.1 rvb 698: return(0); /* it was in the cache */
699: }
700: }
701: }
702:
703: error = venus_access(vtomi(vp), &cp->c_fid, mode, cred, p);
704:
705: return(error);
706: }
707:
708: /*
1.3 rvb 709: * CODA abort op, called after namei() when a CREATE/DELETE isn't actually
710: * done. If a buffer has been saved in anticipation of a coda_create or
711: * a coda_remove, delete it.
1.1 rvb 712: */
713: /* ARGSUSED */
714: int
1.3 rvb 715: coda_abortop(v)
1.1 rvb 716: void *v;
717: {
718: /* true args */
719: struct vop_abortop_args /* {
720: struct vnode *a_dvp;
721: struct componentname *a_cnp;
722: } */ *ap = v;
723: /* upcall decl */
724: /* locals */
725:
726: if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
1.20 thorpej 727: PNBUF_PUT(ap->a_cnp->cn_pnbuf);
1.1 rvb 728: return (0);
729: }
730:
731: int
1.3 rvb 732: coda_readlink(v)
1.1 rvb 733: void *v;
734: {
735: /* true args */
736: struct vop_readlink_args *ap = v;
737: struct vnode *vp = ap->a_vp;
738: struct cnode *cp = VTOC(vp);
739: struct uio *uiop = ap->a_uio;
740: struct ucred *cred = ap->a_cred;
741: struct proc *p = ap->a_uio->uio_procp;
742: /* locals */
743: int error;
744: char *str;
745: int len;
746:
1.3 rvb 747: MARK_ENTRY(CODA_READLINK_STATS);
1.1 rvb 748:
749: /* Check for readlink of control object. */
750: if (IS_CTL_VP(vp)) {
1.3 rvb 751: MARK_INT_FAIL(CODA_READLINK_STATS);
1.1 rvb 752: return(ENOENT);
753: }
754:
1.3 rvb 755: if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { /* symlink was cached */
1.1 rvb 756: uiop->uio_rw = UIO_READ;
757: error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop);
758: if (error)
1.3 rvb 759: MARK_INT_FAIL(CODA_READLINK_STATS);
1.1 rvb 760: else
1.3 rvb 761: MARK_INT_SAT(CODA_READLINK_STATS);
1.1 rvb 762: return(error);
763: }
764:
765: error = venus_readlink(vtomi(vp), &cp->c_fid, cred, p, &str, &len);
766:
767: if (!error) {
768: uiop->uio_rw = UIO_READ;
769: error = uiomove(str, len, uiop);
770:
1.3 rvb 771: if (coda_symlink_cache) {
1.1 rvb 772: cp->c_symlink = str;
773: cp->c_symlen = len;
774: cp->c_flags |= C_SYMLINK;
775: } else
1.3 rvb 776: CODA_FREE(str, len);
1.1 rvb 777: }
778:
1.3 rvb 779: CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n",error));)
1.1 rvb 780: return(error);
781: }
782:
783: int
1.3 rvb 784: coda_fsync(v)
1.1 rvb 785: void *v;
786: {
787: /* true args */
788: struct vop_fsync_args *ap = v;
789: struct vnode *vp = ap->a_vp;
790: struct cnode *cp = VTOC(vp);
791: struct ucred *cred = ap->a_cred;
792: struct proc *p = ap->a_p;
793: /* locals */
794: struct vnode *convp = cp->c_ovp;
795: int error;
796:
1.3 rvb 797: MARK_ENTRY(CODA_FSYNC_STATS);
1.1 rvb 798:
799: /* Check for fsync on an unmounting object */
800: /* The NetBSD kernel, in it's infinite wisdom, can try to fsync
801: * after an unmount has been initiated. This is a Bad Thing,
802: * which we have to avoid. Not a legitimate failure for stats.
803: */
804: if (IS_UNMOUNTING(cp)) {
805: return(ENODEV);
806: }
807:
808: /* Check for fsync of control object. */
809: if (IS_CTL_VP(vp)) {
1.3 rvb 810: MARK_INT_SAT(CODA_FSYNC_STATS);
1.1 rvb 811: return(0);
812: }
813:
814: if (convp)
1.21 fvdl 815: VOP_FSYNC(convp, cred, MNT_WAIT, 0, 0, p);
1.1 rvb 816:
817: /*
818: * We can expect fsync on any vnode at all if venus is pruging it.
819: * Venus can't very well answer the fsync request, now can it?
820: * Hopefully, it won't have to, because hopefully, venus preserves
821: * the (possibly untrue) invariant that it never purges an open
822: * vnode. Hopefully.
823: */
824: if (cp->c_flags & C_PURGING) {
825: return(0);
826: }
827:
828: error = venus_fsync(vtomi(vp), &cp->c_fid, cred, p);
829:
1.3 rvb 830: CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n",error)); );
1.1 rvb 831: return(error);
832: }
833:
834: int
1.3 rvb 835: coda_inactive(v)
1.1 rvb 836: void *v;
837: {
838: /* XXX - at the moment, inactive doesn't look at cred, and doesn't
839: have a proc pointer. Oops. */
840: /* true args */
841: struct vop_inactive_args *ap = v;
842: struct vnode *vp = ap->a_vp;
843: struct cnode *cp = VTOC(vp);
844: struct ucred *cred __attribute__((unused)) = NULL;
845: struct proc *p __attribute__((unused)) = curproc;
846: /* upcall decl */
847: /* locals */
848:
849: /* We don't need to send inactive to venus - DCS */
1.3 rvb 850: MARK_ENTRY(CODA_INACTIVE_STATS);
1.1 rvb 851:
852: if (IS_CTL_VP(vp)) {
1.3 rvb 853: MARK_INT_SAT(CODA_INACTIVE_STATS);
1.1 rvb 854: return 0;
855: }
856:
1.3 rvb 857: CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %lx.%lx.%lx. vfsp %p\n",
1.1 rvb 858: cp->c_fid.Volume, cp->c_fid.Vnode,
859: cp->c_fid.Unique, vp->v_mount));)
860:
861: /* If an array has been allocated to hold the symlink, deallocate it */
1.3 rvb 862: if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) {
1.1 rvb 863: if (cp->c_symlink == NULL)
1.3 rvb 864: panic("coda_inactive: null symlink pointer in cnode");
1.1 rvb 865:
1.3 rvb 866: CODA_FREE(cp->c_symlink, cp->c_symlen);
1.1 rvb 867: cp->c_flags &= ~C_SYMLINK;
868: cp->c_symlen = 0;
869: }
870:
871: /* Remove it from the table so it can't be found. */
1.3 rvb 872: coda_unsave(cp);
1.25.2.3! jdolecek 873: if (vp->v_mount->mnt_data == NULL) {
1.1 rvb 874: myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p wasn't dying\n", vp));
1.3 rvb 875: panic("badness in coda_inactive\n");
1.1 rvb 876: }
877:
878: if (IS_UNMOUNTING(cp)) {
879: #ifdef DEBUG
1.22 chs 880: printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", vp->v_usecount, vp, cp);
1.1 rvb 881: if (cp->c_ovp != NULL)
1.22 chs 882: printf("coda_inactive: cp->ovp != NULL use %d: vp %p, cp %p\n",
1.1 rvb 883: vp->v_usecount, vp, cp);
884: #endif
1.10 wrstuden 885: lockmgr(&vp->v_lock, LK_RELEASE, &vp->v_interlock);
1.1 rvb 886: } else {
1.5 rvb 887: #ifdef OLD_DIAGNOSTIC
1.1 rvb 888: if (CTOV(cp)->v_usecount) {
1.3 rvb 889: panic("coda_inactive: nonzero reference count");
1.1 rvb 890: }
891: if (cp->c_ovp != NULL) {
1.3 rvb 892: panic("coda_inactive: cp->ovp != NULL");
1.1 rvb 893: }
894: #endif
1.2 rvb 895: VOP_UNLOCK(vp, 0);
1.1 rvb 896: vgone(vp);
897: }
898:
1.3 rvb 899: MARK_INT_SAT(CODA_INACTIVE_STATS);
1.1 rvb 900: return(0);
901: }
902:
903: /*
904: * Remote file system operations having to do with directory manipulation.
905: */
906:
907: /*
908: * It appears that in NetBSD, lookup is supposed to return the vnode locked
909: */
910: int
1.3 rvb 911: coda_lookup(v)
1.1 rvb 912: void *v;
913: {
914: /* true args */
915: struct vop_lookup_args *ap = v;
916: struct vnode *dvp = ap->a_dvp;
917: struct cnode *dcp = VTOC(dvp);
918: struct vnode **vpp = ap->a_vpp;
919: /*
920: * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest
921: * of the string to xlate, and that we must try to get at least
922: * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I
923: * could be wrong.
924: */
925: struct componentname *cnp = ap->a_cnp;
926: struct ucred *cred = cnp->cn_cred;
927: struct proc *p = cnp->cn_proc;
928: /* locals */
929: struct cnode *cp;
930: const char *nm = cnp->cn_nameptr;
931: int len = cnp->cn_namelen;
932: ViceFid VFid;
933: int vtype;
934: int error = 0;
935:
1.10 wrstuden 936: cnp->cn_flags &= ~PDIRUNLOCK;
937:
1.3 rvb 938: MARK_ENTRY(CODA_LOOKUP_STATS);
1.1 rvb 939:
1.3 rvb 940: CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %lx.%lx.%lx\n",
1.1 rvb 941: nm, dcp->c_fid.Volume,
942: dcp->c_fid.Vnode, dcp->c_fid.Unique)););
943:
944: /* Check for lookup of control object. */
945: if (IS_CTL_NAME(dvp, nm, len)) {
1.3 rvb 946: *vpp = coda_ctlvp;
1.1 rvb 947: vref(*vpp);
1.3 rvb 948: MARK_INT_SAT(CODA_LOOKUP_STATS);
1.1 rvb 949: goto exit;
950: }
951:
1.3 rvb 952: if (len+1 > CODA_MAXNAMLEN) {
953: MARK_INT_FAIL(CODA_LOOKUP_STATS);
954: CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, %lx.%lx.%lx(%s)\n",
1.1 rvb 955: dcp->c_fid.Volume, dcp->c_fid.Vnode,
956: dcp->c_fid.Unique, nm)););
957: *vpp = (struct vnode *)0;
958: error = EINVAL;
959: goto exit;
960: }
961: /* First try to look the file up in the cfs name cache */
962: /* lock the parent vnode? */
1.3 rvb 963: cp = coda_nc_lookup(dcp, nm, len, cred);
1.1 rvb 964: if (cp) {
965: *vpp = CTOV(cp);
966: vref(*vpp);
1.3 rvb 967: CODADEBUG(CODA_LOOKUP,
1.1 rvb 968: myprintf(("lookup result %d vpp %p\n",error,*vpp));)
969: } else {
970:
971: /* The name wasn't cached, so we need to contact Venus */
972: error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, p, &VFid, &vtype);
973:
974: if (error) {
1.3 rvb 975: MARK_INT_FAIL(CODA_LOOKUP_STATS);
976: CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %lx.%lx.%lx(%s)%d\n",
1.1 rvb 977: dcp->c_fid.Volume, dcp->c_fid.Vnode, dcp->c_fid.Unique, nm, error));)
978: *vpp = (struct vnode *)0;
979: } else {
1.3 rvb 980: MARK_INT_SAT(CODA_LOOKUP_STATS);
981: CODADEBUG(CODA_LOOKUP,
1.1 rvb 982: myprintf(("lookup: vol %lx vno %lx uni %lx type %o result %d\n",
983: VFid.Volume, VFid.Vnode, VFid.Unique, vtype,
984: error)); )
985:
1.3 rvb 986: cp = make_coda_node(&VFid, dvp->v_mount, vtype);
1.1 rvb 987: *vpp = CTOV(cp);
988:
989: /* enter the new vnode in the Name Cache only if the top bit isn't set */
990: /* And don't enter a new vnode for an invalid one! */
1.3 rvb 991: if (!(vtype & CODA_NOCACHE))
992: coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp));
1.1 rvb 993: }
994: }
995:
996: exit:
997: /*
998: * If we are creating, and this was the last name to be looked up,
999: * and the error was ENOENT, then there really shouldn't be an
1000: * error and we can make the leaf NULL and return success. Since
1001: * this is supposed to work under Mach as well as NetBSD, we're
1002: * leaving this fn wrapped. We also must tell lookup/namei that
1003: * we need to save the last component of the name. (Create will
1004: * have to free the name buffer later...lucky us...)
1005: */
1006: if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME))
1007: && (cnp->cn_flags & ISLASTCN)
1008: && (error == ENOENT))
1009: {
1010: error = EJUSTRETURN;
1011: cnp->cn_flags |= SAVENAME;
1012: *ap->a_vpp = NULL;
1013: }
1014:
1015: /*
1016: * If we are removing, and we are at the last element, and we
1017: * found it, then we need to keep the name around so that the
1018: * removal will go ahead as planned. Unfortunately, this will
1019: * probably also lock the to-be-removed vnode, which may or may
1020: * not be a good idea. I'll have to look at the bits of
1.3 rvb 1021: * coda_remove to make sure. We'll only save the name if we did in
1022: * fact find the name, otherwise coda_remove won't have a chance
1.1 rvb 1023: * to free the pathname.
1024: */
1025: if ((cnp->cn_nameiop == DELETE)
1026: && (cnp->cn_flags & ISLASTCN)
1027: && !error)
1028: {
1029: cnp->cn_flags |= SAVENAME;
1030: }
1031:
1032: /*
1033: * If the lookup went well, we need to (potentially?) unlock the
1034: * parent, and lock the child. We are only responsible for
1035: * checking to see if the parent is supposed to be unlocked before
1036: * we return. We must always lock the child (provided there is
1037: * one, and (the parent isn't locked or it isn't the same as the
1038: * parent.) Simple, huh? We can never leave the parent locked unless
1039: * we are ISLASTCN
1040: */
1041: if (!error || (error == EJUSTRETURN)) {
1042: if (!(cnp->cn_flags & LOCKPARENT) || !(cnp->cn_flags & ISLASTCN)) {
1.2 rvb 1043: if ((error = VOP_UNLOCK(dvp, 0))) {
1.1 rvb 1044: return error;
1045: }
1.10 wrstuden 1046: cnp->cn_flags |= PDIRUNLOCK;
1.1 rvb 1047: /*
1048: * The parent is unlocked. As long as there is a child,
1049: * lock it without bothering to check anything else.
1050: */
1051: if (*ap->a_vpp) {
1.2 rvb 1052: if ((error = vn_lock(*ap->a_vpp, LK_EXCLUSIVE))) {
1.3 rvb 1053: printf("coda_lookup: ");
1.1 rvb 1054: panic("unlocked parent but couldn't lock child");
1055: }
1056: }
1057: } else {
1058: /* The parent is locked, and may be the same as the child */
1059: if (*ap->a_vpp && (*ap->a_vpp != dvp)) {
1060: /* Different, go ahead and lock it. */
1.2 rvb 1061: if ((error = vn_lock(*ap->a_vpp, LK_EXCLUSIVE))) {
1.3 rvb 1062: printf("coda_lookup: ");
1.1 rvb 1063: panic("unlocked parent but couldn't lock child");
1064: }
1065: }
1066: }
1067: } else {
1068: /* If the lookup failed, we need to ensure that the leaf is NULL */
1069: /* Don't change any locking? */
1070: *ap->a_vpp = NULL;
1071: }
1072: return(error);
1073: }
1074:
1075: /*ARGSUSED*/
1076: int
1.3 rvb 1077: coda_create(v)
1.1 rvb 1078: void *v;
1079: {
1080: /* true args */
1081: struct vop_create_args *ap = v;
1082: struct vnode *dvp = ap->a_dvp;
1083: struct cnode *dcp = VTOC(dvp);
1084: struct vattr *va = ap->a_vap;
1085: int exclusive = 1;
1086: int mode = ap->a_vap->va_mode;
1087: struct vnode **vpp = ap->a_vpp;
1088: struct componentname *cnp = ap->a_cnp;
1089: struct ucred *cred = cnp->cn_cred;
1090: struct proc *p = cnp->cn_proc;
1091: /* locals */
1092: int error;
1093: struct cnode *cp;
1094: const char *nm = cnp->cn_nameptr;
1095: int len = cnp->cn_namelen;
1096: ViceFid VFid;
1097: struct vattr attr;
1098:
1.3 rvb 1099: MARK_ENTRY(CODA_CREATE_STATS);
1.1 rvb 1100:
1101: /* All creates are exclusive XXX */
1102: /* I'm assuming the 'mode' argument is the file mode bits XXX */
1103:
1104: /* Check for create of control object. */
1105: if (IS_CTL_NAME(dvp, nm, len)) {
1106: *vpp = (struct vnode *)0;
1.3 rvb 1107: MARK_INT_FAIL(CODA_CREATE_STATS);
1.1 rvb 1108: return(EACCES);
1109: }
1110:
1111: error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, mode, va, cred, p, &VFid, &attr);
1112:
1113: if (!error) {
1114:
1115: /* If this is an exclusive create, panic if the file already exists. */
1116: /* Venus should have detected the file and reported EEXIST. */
1117:
1118: if ((exclusive == 1) &&
1.3 rvb 1119: (coda_find(&VFid) != NULL))
1.1 rvb 1120: panic("cnode existed for newly created file!");
1121:
1.3 rvb 1122: cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type);
1.1 rvb 1123: *vpp = CTOV(cp);
1124:
1125: /* Update va to reflect the new attributes. */
1126: (*va) = attr;
1127:
1128: /* Update the attribute cache and mark it as valid */
1.3 rvb 1129: if (coda_attr_cache) {
1.1 rvb 1130: VTOC(*vpp)->c_vattr = attr;
1131: VTOC(*vpp)->c_flags |= C_VATTR;
1132: }
1133:
1134: /* Invalidate the parent's attr cache, the modification time has changed */
1135: VTOC(dvp)->c_flags &= ~C_VATTR;
1136:
1137: /* enter the new vnode in the Name Cache */
1.3 rvb 1138: coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp));
1.1 rvb 1139:
1.3 rvb 1140: CODADEBUG(CODA_CREATE,
1.1 rvb 1141: myprintf(("create: (%lx.%lx.%lx), result %d\n",
1142: VFid.Volume, VFid.Vnode, VFid.Unique, error)); )
1143: } else {
1144: *vpp = (struct vnode *)0;
1.3 rvb 1145: CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", error));)
1.1 rvb 1146: }
1147:
1148: /* Locking strategy. */
1149: /*
1150: * In NetBSD, all creates must explicitly vput their dvp's. We'll
1151: * go ahead and use the LOCKLEAF flag of the cnp argument.
1152: * However, I'm pretty sure that create must return the leaf
1153: * locked; so there is a DIAGNOSTIC check to ensure that this is
1154: * true.
1155: */
1156: vput(dvp);
1157: if (!error) {
1158: if (cnp->cn_flags & LOCKLEAF) {
1.2 rvb 1159: if ((error = vn_lock(*ap->a_vpp, LK_EXCLUSIVE))) {
1.3 rvb 1160: printf("coda_create: ");
1.1 rvb 1161: panic("unlocked parent but couldn't lock child");
1162: }
1163: }
1.7 rvb 1164: #ifdef OLD_DIAGNOSTIC
1.1 rvb 1165: else {
1.3 rvb 1166: printf("coda_create: LOCKLEAF not set!\n");
1.1 rvb 1167: }
1.5 rvb 1168: #endif
1.1 rvb 1169: }
1170: /* Have to free the previously saved name */
1171: /*
1172: * This condition is stolen from ufs_makeinode. I have no idea
1173: * why it's here, but what the hey...
1174: */
1175: if ((cnp->cn_flags & SAVESTART) == 0) {
1.20 thorpej 1176: PNBUF_PUT(cnp->cn_pnbuf);
1.1 rvb 1177: }
1178: return(error);
1179: }
1180:
1181: int
1.3 rvb 1182: coda_remove(v)
1.1 rvb 1183: void *v;
1184: {
1185: /* true args */
1186: struct vop_remove_args *ap = v;
1187: struct vnode *dvp = ap->a_dvp;
1188: struct cnode *cp = VTOC(dvp);
1189: struct componentname *cnp = ap->a_cnp;
1190: struct ucred *cred = cnp->cn_cred;
1191: struct proc *p = cnp->cn_proc;
1192: /* locals */
1193: int error;
1194: const char *nm = cnp->cn_nameptr;
1195: int len = cnp->cn_namelen;
1196: struct cnode *tp;
1197:
1.3 rvb 1198: MARK_ENTRY(CODA_REMOVE_STATS);
1.1 rvb 1199:
1.3 rvb 1200: CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %lx.%lx.%lx\n",
1.1 rvb 1201: nm, cp->c_fid.Volume, cp->c_fid.Vnode,
1202: cp->c_fid.Unique)););
1203:
1.3 rvb 1204: /* Remove the file's entry from the CODA Name Cache */
1.1 rvb 1205: /* We're being conservative here, it might be that this person
1206: * doesn't really have sufficient access to delete the file
1207: * but we feel zapping the entry won't really hurt anyone -- dcs
1208: */
1209: /* I'm gonna go out on a limb here. If a file and a hardlink to it
1210: * exist, and one is removed, the link count on the other will be
1211: * off by 1. We could either invalidate the attrs if cached, or
1212: * fix them. I'll try to fix them. DCS 11/8/94
1213: */
1.3 rvb 1214: tp = coda_nc_lookup(VTOC(dvp), nm, len, cred);
1.1 rvb 1215: if (tp) {
1216: if (VALID_VATTR(tp)) { /* If attrs are cached */
1217: if (tp->c_vattr.va_nlink > 1) { /* If it's a hard link */
1218: tp->c_vattr.va_nlink--;
1219: }
1220: }
1221:
1.3 rvb 1222: coda_nc_zapfile(VTOC(dvp), nm, len);
1.1 rvb 1223: /* No need to flush it if it doesn't exist! */
1224: }
1225: /* Invalidate the parent's attr cache, the modification time has changed */
1226: VTOC(dvp)->c_flags &= ~C_VATTR;
1227:
1228: /* Check for remove of control object. */
1229: if (IS_CTL_NAME(dvp, nm, len)) {
1.3 rvb 1230: MARK_INT_FAIL(CODA_REMOVE_STATS);
1.1 rvb 1231: return(ENOENT);
1232: }
1233:
1234: error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, p);
1235:
1.3 rvb 1236: CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error)); )
1.1 rvb 1237:
1238: /*
1239: * Regardless of what happens, we have to unconditionally drop
1240: * locks/refs on parent and child. (I hope). This is based on
1241: * what ufs_remove seems to be doing.
1242: */
1243: if (dvp == ap->a_vp) {
1244: vrele(ap->a_vp);
1245: } else {
1246: vput(ap->a_vp);
1247: }
1248: vput(dvp);
1249:
1250: if ((cnp->cn_flags & SAVESTART) == 0) {
1.20 thorpej 1251: PNBUF_PUT(cnp->cn_pnbuf);
1.1 rvb 1252: }
1253: return(error);
1254: }
1255:
1256: int
1.3 rvb 1257: coda_link(v)
1.1 rvb 1258: void *v;
1259: {
1260: /* true args */
1261: struct vop_link_args *ap = v;
1262: struct vnode *vp = ap->a_vp;
1263: struct cnode *cp = VTOC(vp);
1264: struct vnode *tdvp = ap->a_dvp;
1265: struct cnode *tdcp = VTOC(tdvp);
1266: struct componentname *cnp = ap->a_cnp;
1267: struct ucred *cred = cnp->cn_cred;
1268: struct proc *p = cnp->cn_proc;
1269: /* locals */
1270: int error;
1271: const char *nm = cnp->cn_nameptr;
1272: int len = cnp->cn_namelen;
1273:
1.3 rvb 1274: MARK_ENTRY(CODA_LINK_STATS);
1.1 rvb 1275:
1.3 rvb 1276: if (codadebug & CODADBGMSK(CODA_LINK)) {
1.1 rvb 1277:
1278: myprintf(("nb_link: vp fid: (%lx.%lx.%lx)\n",
1279: cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique));
1280: myprintf(("nb_link: tdvp fid: (%lx.%lx.%lx)\n",
1281: tdcp->c_fid.Volume, tdcp->c_fid.Vnode, tdcp->c_fid.Unique));
1282:
1283: }
1.3 rvb 1284: if (codadebug & CODADBGMSK(CODA_LINK)) {
1.1 rvb 1285: myprintf(("link: vp fid: (%lx.%lx.%lx)\n",
1286: cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique));
1287: myprintf(("link: tdvp fid: (%lx.%lx.%lx)\n",
1288: tdcp->c_fid.Volume, tdcp->c_fid.Vnode, tdcp->c_fid.Unique));
1289:
1290: }
1291:
1292: /* Check for link to/from control object. */
1293: if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) {
1.3 rvb 1294: MARK_INT_FAIL(CODA_LINK_STATS);
1.1 rvb 1295: return(EACCES);
1296: }
1297:
1298: /*
1299: * According to the ufs_link operation here's the locking situation:
1300: * We enter with the thing called "dvp" (the directory) locked.
1301: * We must unconditionally drop locks on "dvp"
1302: *
1303: * We enter with the thing called "vp" (the linked-to) unlocked,
1304: * but ref'd (?)
1.3 rvb 1305: * We seem to need to lock it before calling coda_link, and
1.1 rvb 1306: * unconditionally unlock it after.
1307: */
1308:
1.2 rvb 1309: if ((ap->a_vp != tdvp) && (error = vn_lock(ap->a_vp, LK_EXCLUSIVE))) {
1.1 rvb 1310: goto exit;
1311: }
1312:
1313: error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, cred, p);
1314:
1315: /* Invalidate the parent's attr cache, the modification time has changed */
1316: VTOC(tdvp)->c_flags &= ~C_VATTR;
1317: VTOC(vp)->c_flags &= ~C_VATTR;
1318:
1.3 rvb 1319: CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error)); )
1.1 rvb 1320:
1321: exit:
1322:
1323: if (ap->a_vp != tdvp) {
1.2 rvb 1324: VOP_UNLOCK(ap->a_vp, 0);
1.1 rvb 1325: }
1326: vput(tdvp);
1327:
1328: /* Drop the name buffer if we don't need to SAVESTART */
1329: if ((cnp->cn_flags & SAVESTART) == 0) {
1.20 thorpej 1330: PNBUF_PUT(cnp->cn_pnbuf);
1.1 rvb 1331: }
1332: return(error);
1333: }
1334:
1335: int
1.3 rvb 1336: coda_rename(v)
1.1 rvb 1337: void *v;
1338: {
1339: /* true args */
1340: struct vop_rename_args *ap = v;
1341: struct vnode *odvp = ap->a_fdvp;
1342: struct cnode *odcp = VTOC(odvp);
1343: struct componentname *fcnp = ap->a_fcnp;
1344: struct vnode *ndvp = ap->a_tdvp;
1345: struct cnode *ndcp = VTOC(ndvp);
1346: struct componentname *tcnp = ap->a_tcnp;
1347: struct ucred *cred = fcnp->cn_cred;
1348: struct proc *p = fcnp->cn_proc;
1349: /* true args */
1350: int error;
1351: const char *fnm = fcnp->cn_nameptr;
1352: int flen = fcnp->cn_namelen;
1353: const char *tnm = tcnp->cn_nameptr;
1354: int tlen = tcnp->cn_namelen;
1355:
1.3 rvb 1356: MARK_ENTRY(CODA_RENAME_STATS);
1.1 rvb 1357:
1358: /* Hmmm. The vnodes are already looked up. Perhaps they are locked?
1359: This could be Bad. XXX */
1.5 rvb 1360: #ifdef OLD_DIAGNOSTIC
1.1 rvb 1361: if ((fcnp->cn_cred != tcnp->cn_cred)
1362: || (fcnp->cn_proc != tcnp->cn_proc))
1363: {
1.3 rvb 1364: panic("coda_rename: component names don't agree");
1.1 rvb 1365: }
1.5 rvb 1366: #endif
1.1 rvb 1367:
1368: /* Check for rename involving control object. */
1369: if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) {
1.3 rvb 1370: MARK_INT_FAIL(CODA_RENAME_STATS);
1.1 rvb 1371: return(EACCES);
1372: }
1373:
1374: /* Problem with moving directories -- need to flush entry for .. */
1375: if (odvp != ndvp) {
1.3 rvb 1376: struct cnode *ovcp = coda_nc_lookup(VTOC(odvp), fnm, flen, cred);
1.1 rvb 1377: if (ovcp) {
1378: struct vnode *ovp = CTOV(ovcp);
1379: if ((ovp) &&
1380: (ovp->v_type == VDIR)) /* If it's a directory */
1.3 rvb 1381: coda_nc_zapfile(VTOC(ovp),"..", 2);
1.1 rvb 1382: }
1383: }
1384:
1385: /* Remove the entries for both source and target files */
1.3 rvb 1386: coda_nc_zapfile(VTOC(odvp), fnm, flen);
1387: coda_nc_zapfile(VTOC(ndvp), tnm, tlen);
1.1 rvb 1388:
1389: /* Invalidate the parent's attr cache, the modification time has changed */
1390: VTOC(odvp)->c_flags &= ~C_VATTR;
1391: VTOC(ndvp)->c_flags &= ~C_VATTR;
1392:
1.3 rvb 1393: if (flen+1 > CODA_MAXNAMLEN) {
1394: MARK_INT_FAIL(CODA_RENAME_STATS);
1.1 rvb 1395: error = EINVAL;
1396: goto exit;
1397: }
1398:
1.3 rvb 1399: if (tlen+1 > CODA_MAXNAMLEN) {
1400: MARK_INT_FAIL(CODA_RENAME_STATS);
1.1 rvb 1401: error = EINVAL;
1402: goto exit;
1403: }
1404:
1405: error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, flen, tnm, tlen, cred, p);
1406:
1407: exit:
1.3 rvb 1408: CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));)
1.1 rvb 1409: /* XXX - do we need to call cache pureg on the moved vnode? */
1410: cache_purge(ap->a_fvp);
1411:
1412: /* It seems to be incumbent on us to drop locks on all four vnodes */
1413: /* From-vnodes are not locked, only ref'd. To-vnodes are locked. */
1414:
1415: vrele(ap->a_fvp);
1416: vrele(odvp);
1417:
1418: if (ap->a_tvp) {
1419: if (ap->a_tvp == ndvp) {
1420: vrele(ap->a_tvp);
1421: } else {
1422: vput(ap->a_tvp);
1423: }
1424: }
1425:
1426: vput(ndvp);
1427: return(error);
1428: }
1429:
1430: int
1.3 rvb 1431: coda_mkdir(v)
1.1 rvb 1432: void *v;
1433: {
1434: /* true args */
1435: struct vop_mkdir_args *ap = v;
1436: struct vnode *dvp = ap->a_dvp;
1437: struct cnode *dcp = VTOC(dvp);
1438: struct componentname *cnp = ap->a_cnp;
1.17 augustss 1439: struct vattr *va = ap->a_vap;
1.1 rvb 1440: struct vnode **vpp = ap->a_vpp;
1441: struct ucred *cred = cnp->cn_cred;
1442: struct proc *p = cnp->cn_proc;
1443: /* locals */
1444: int error;
1445: const char *nm = cnp->cn_nameptr;
1446: int len = cnp->cn_namelen;
1447: struct cnode *cp;
1448: ViceFid VFid;
1449: struct vattr ova;
1450:
1.3 rvb 1451: MARK_ENTRY(CODA_MKDIR_STATS);
1.1 rvb 1452:
1453: /* Check for mkdir of target object. */
1454: if (IS_CTL_NAME(dvp, nm, len)) {
1455: *vpp = (struct vnode *)0;
1.3 rvb 1456: MARK_INT_FAIL(CODA_MKDIR_STATS);
1.1 rvb 1457: return(EACCES);
1458: }
1459:
1.3 rvb 1460: if (len+1 > CODA_MAXNAMLEN) {
1.1 rvb 1461: *vpp = (struct vnode *)0;
1.3 rvb 1462: MARK_INT_FAIL(CODA_MKDIR_STATS);
1.1 rvb 1463: return(EACCES);
1464: }
1465:
1466: error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, p, &VFid, &ova);
1467:
1468: if (!error) {
1.3 rvb 1469: if (coda_find(&VFid) != NULL)
1.1 rvb 1470: panic("cnode existed for newly created directory!");
1471:
1472:
1.3 rvb 1473: cp = make_coda_node(&VFid, dvp->v_mount, va->va_type);
1.1 rvb 1474: *vpp = CTOV(cp);
1475:
1476: /* enter the new vnode in the Name Cache */
1.3 rvb 1477: coda_nc_enter(VTOC(dvp), nm, len, cred, VTOC(*vpp));
1.1 rvb 1478:
1479: /* as a side effect, enter "." and ".." for the directory */
1.3 rvb 1480: coda_nc_enter(VTOC(*vpp), ".", 1, cred, VTOC(*vpp));
1481: coda_nc_enter(VTOC(*vpp), "..", 2, cred, VTOC(dvp));
1.1 rvb 1482:
1.3 rvb 1483: if (coda_attr_cache) {
1.1 rvb 1484: VTOC(*vpp)->c_vattr = ova; /* update the attr cache */
1485: VTOC(*vpp)->c_flags |= C_VATTR; /* Valid attributes in cnode */
1486: }
1487:
1488: /* Invalidate the parent's attr cache, the modification time has changed */
1489: VTOC(dvp)->c_flags &= ~C_VATTR;
1490:
1.3 rvb 1491: CODADEBUG( CODA_MKDIR, myprintf(("mkdir: (%lx.%lx.%lx) result %d\n",
1.1 rvb 1492: VFid.Volume, VFid.Vnode, VFid.Unique, error)); )
1493: } else {
1494: *vpp = (struct vnode *)0;
1.3 rvb 1495: CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));)
1.1 rvb 1496: }
1497:
1498: /*
1499: * Currently, all mkdirs explicitly vput their dvp's.
1500: * It also appears that we *must* lock the vpp, since
1501: * lockleaf isn't set, but someone down the road is going
1502: * to try to unlock the new directory.
1503: */
1504: vput(dvp);
1505: if (!error) {
1.2 rvb 1506: if ((error = vn_lock(*ap->a_vpp, LK_EXCLUSIVE))) {
1.3 rvb 1507: panic("coda_mkdir: couldn't lock child");
1.1 rvb 1508: }
1509: }
1510:
1511: /* Have to free the previously saved name */
1512: /*
1513: * ufs_mkdir doesn't check for SAVESTART before freeing the
1514: * pathname buffer, but ufs_create does. For the moment, I'll
1515: * follow their lead, but this seems like it is probably
1516: * incorrect.
1517: */
1.20 thorpej 1518: PNBUF_PUT(cnp->cn_pnbuf);
1.1 rvb 1519: return(error);
1520: }
1521:
1522: int
1.3 rvb 1523: coda_rmdir(v)
1.1 rvb 1524: void *v;
1525: {
1526: /* true args */
1527: struct vop_rmdir_args *ap = v;
1528: struct vnode *dvp = ap->a_dvp;
1529: struct cnode *dcp = VTOC(dvp);
1530: struct componentname *cnp = ap->a_cnp;
1531: struct ucred *cred = cnp->cn_cred;
1532: struct proc *p = cnp->cn_proc;
1533: /* true args */
1534: int error;
1535: const char *nm = cnp->cn_nameptr;
1536: int len = cnp->cn_namelen;
1537: struct cnode *cp;
1538:
1.3 rvb 1539: MARK_ENTRY(CODA_RMDIR_STATS);
1.1 rvb 1540:
1541: /* Check for rmdir of control object. */
1542: if (IS_CTL_NAME(dvp, nm, len)) {
1.3 rvb 1543: MARK_INT_FAIL(CODA_RMDIR_STATS);
1.1 rvb 1544: return(ENOENT);
1545: }
1546:
1547: /* We're being conservative here, it might be that this person
1548: * doesn't really have sufficient access to delete the file
1549: * but we feel zapping the entry won't really hurt anyone -- dcs
1550: */
1551: /*
1552: * As a side effect of the rmdir, remove any entries for children of
1553: * the directory, especially "." and "..".
1554: */
1.3 rvb 1555: cp = coda_nc_lookup(dcp, nm, len, cred);
1556: if (cp) coda_nc_zapParentfid(&(cp->c_fid), NOT_DOWNCALL);
1.1 rvb 1557:
1.3 rvb 1558: /* Remove the file's entry from the CODA Name Cache */
1559: coda_nc_zapfile(dcp, nm, len);
1.1 rvb 1560:
1561: /* Invalidate the parent's attr cache, the modification time has changed */
1562: dcp->c_flags &= ~C_VATTR;
1563:
1564: error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, p);
1565:
1.3 rvb 1566: CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error)); )
1.1 rvb 1567:
1568: /*
1569: * regardless of what happens, we need to drop locks/refs on the
1570: * parent and child. I think.
1571: */
1572: if (dvp == ap->a_vp) {
1573: vrele(ap->a_vp);
1574: } else {
1575: vput(ap->a_vp);
1576: }
1577: vput(dvp);
1578:
1579: if ((cnp->cn_flags & SAVESTART) == 0) {
1.20 thorpej 1580: PNBUF_PUT(cnp->cn_pnbuf);
1.1 rvb 1581: }
1582: return(error);
1583: }
1584:
1585: int
1.3 rvb 1586: coda_symlink(v)
1.1 rvb 1587: void *v;
1588: {
1589: /* true args */
1590: struct vop_symlink_args *ap = v;
1591: struct vnode *tdvp = ap->a_dvp;
1592: struct cnode *tdcp = VTOC(tdvp);
1593: struct componentname *cnp = ap->a_cnp;
1594: struct vattr *tva = ap->a_vap;
1595: char *path = ap->a_target;
1596: struct ucred *cred = cnp->cn_cred;
1597: struct proc *p = cnp->cn_proc;
1598: /* locals */
1599: int error;
1600: /*
1.3 rvb 1601: * XXX I'm assuming the following things about coda_symlink's
1.1 rvb 1602: * arguments:
1603: * t(foo) is the new name/parent/etc being created.
1604: * lname is the contents of the new symlink.
1605: */
1.2 rvb 1606: const char *nm = cnp->cn_nameptr;
1.1 rvb 1607: int len = cnp->cn_namelen;
1608: int plen = strlen(path);
1609:
1610: /* XXX What about the vpp argument? Do we need it? */
1611: /*
1612: * Here's the strategy for the moment: perform the symlink, then
1613: * do a lookup to grab the resulting vnode. I know this requires
1614: * two communications with Venus for a new sybolic link, but
1615: * that's the way the ball bounces. I don't yet want to change
1616: * the way the Mach symlink works. When Mach support is
1617: * deprecated, we should change symlink so that the common case
1618: * returns the resultant vnode in a vpp argument.
1619: */
1620:
1.3 rvb 1621: MARK_ENTRY(CODA_SYMLINK_STATS);
1.1 rvb 1622:
1623: /* Check for symlink of control object. */
1624: if (IS_CTL_NAME(tdvp, nm, len)) {
1.3 rvb 1625: MARK_INT_FAIL(CODA_SYMLINK_STATS);
1.1 rvb 1626: return(EACCES);
1627: }
1628:
1.3 rvb 1629: if (plen+1 > CODA_MAXPATHLEN) {
1630: MARK_INT_FAIL(CODA_SYMLINK_STATS);
1.1 rvb 1631: return(EINVAL);
1632: }
1633:
1.3 rvb 1634: if (len+1 > CODA_MAXNAMLEN) {
1635: MARK_INT_FAIL(CODA_SYMLINK_STATS);
1.1 rvb 1636: error = EINVAL;
1637: goto exit;
1638: }
1639:
1640: error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, tva, cred, p);
1641:
1642: /* Invalidate the parent's attr cache, the modification time has changed */
1643: tdcp->c_flags &= ~C_VATTR;
1644:
1645: if (!error)
1646: {
1647: struct nameidata nd;
1648: NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, nm, p);
1649: nd.ni_cnd.cn_cred = cred;
1650: nd.ni_loopcnt = 0;
1651: nd.ni_startdir = tdvp;
1652: nd.ni_cnd.cn_pnbuf = (char *)nm;
1653: nd.ni_cnd.cn_nameptr = nd.ni_cnd.cn_pnbuf;
1654: nd.ni_pathlen = len;
1655: vput(tdvp);
1656: error = lookup(&nd);
1657: *ap->a_vpp = nd.ni_vp;
1658: }
1659:
1660: /*
1661: * Free the name buffer
1662: */
1663: if ((cnp->cn_flags & SAVESTART) == 0) {
1.20 thorpej 1664: PNBUF_PUT(cnp->cn_pnbuf);
1.1 rvb 1665: }
1666:
1667: exit:
1.3 rvb 1668: CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error)); )
1.1 rvb 1669: return(error);
1670: }
1671:
1672: /*
1673: * Read directory entries.
1674: */
1675: int
1.3 rvb 1676: coda_readdir(v)
1.1 rvb 1677: void *v;
1678: {
1679: /* true args */
1680: struct vop_readdir_args *ap = v;
1681: struct vnode *vp = ap->a_vp;
1682: struct cnode *cp = VTOC(vp);
1.17 augustss 1683: struct uio *uiop = ap->a_uio;
1.1 rvb 1684: struct ucred *cred = ap->a_cred;
1685: int *eofflag = ap->a_eofflag;
1686: off_t **cookies = ap->a_cookies;
1687: int *ncookies = ap->a_ncookies;
1688: struct proc *p = ap->a_uio->uio_procp;
1689: /* upcall decl */
1690: /* locals */
1691: int error = 0;
1692:
1.3 rvb 1693: MARK_ENTRY(CODA_READDIR_STATS);
1.1 rvb 1694:
1.12 matt 1695: CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %lu, %lld, %d)\n", uiop->uio_iov->iov_base, (unsigned long) uiop->uio_resid, (long long) uiop->uio_offset, uiop->uio_segflg)); )
1.1 rvb 1696:
1697: /* Check for readdir of control object. */
1698: if (IS_CTL_VP(vp)) {
1.3 rvb 1699: MARK_INT_FAIL(CODA_READDIR_STATS);
1.1 rvb 1700: return(ENOENT);
1701: }
1702:
1.2 rvb 1703: {
1.1 rvb 1704: /* Redirect the request to UFS. */
1705:
1706: /* If directory is not already open do an "internal open" on it. */
1707: int opened_internally = 0;
1708: if (cp->c_ovp == NULL) {
1709: opened_internally = 1;
1.3 rvb 1710: MARK_INT_GEN(CODA_OPEN_STATS);
1.1 rvb 1711: error = VOP_OPEN(vp, FREAD, cred, p);
1.18 phil 1712: #ifdef CODA_VERBOSE
1.3 rvb 1713: printf("coda_readdir: Internally Opening %p\n", vp);
1.18 phil 1714: #endif
1.1 rvb 1715: if (error) return(error);
1716: }
1717:
1718: /* Have UFS handle the call. */
1.22 chs 1719: CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = (%lx.%lx.%lx), refcnt = %d\n",cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique, vp->v_usecount)); )
1.1 rvb 1720: error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, cookies,
1721: ncookies);
1722: if (error)
1.3 rvb 1723: MARK_INT_FAIL(CODA_READDIR_STATS);
1.1 rvb 1724: else
1.3 rvb 1725: MARK_INT_SAT(CODA_READDIR_STATS);
1.1 rvb 1726:
1727: /* Do an "internal close" if necessary. */
1728: if (opened_internally) {
1.3 rvb 1729: MARK_INT_GEN(CODA_CLOSE_STATS);
1.1 rvb 1730: (void)VOP_CLOSE(vp, FREAD, cred, p);
1731: }
1732: }
1733:
1734: return(error);
1735: }
1736:
1737: /*
1738: * Convert from file system blocks to device blocks
1739: */
1740: int
1.3 rvb 1741: coda_bmap(v)
1.1 rvb 1742: void *v;
1743: {
1744: /* XXX on the global proc */
1745: /* true args */
1746: struct vop_bmap_args *ap = v;
1747: struct vnode *vp __attribute__((unused)) = ap->a_vp; /* file's vnode */
1748: daddr_t bn __attribute__((unused)) = ap->a_bn; /* fs block number */
1749: struct vnode **vpp = ap->a_vpp; /* RETURN vp of device */
1750: daddr_t *bnp __attribute__((unused)) = ap->a_bnp; /* RETURN device block number */
1751: struct proc *p __attribute__((unused)) = curproc;
1752: /* upcall decl */
1753: /* locals */
1754:
1755: *vpp = (struct vnode *)0;
1.3 rvb 1756: myprintf(("coda_bmap called!\n"));
1.1 rvb 1757: return(EINVAL);
1758: }
1759:
1760: /*
1761: * I don't think the following two things are used anywhere, so I've
1762: * commented them out
1763: *
1764: * struct buf *async_bufhead;
1765: * int async_daemon_count;
1766: */
1767: int
1.3 rvb 1768: coda_strategy(v)
1.1 rvb 1769: void *v;
1770: {
1771: /* true args */
1772: struct vop_strategy_args *ap = v;
1.17 augustss 1773: struct buf *bp __attribute__((unused)) = ap->a_bp;
1.1 rvb 1774: struct proc *p __attribute__((unused)) = curproc;
1775: /* upcall decl */
1776: /* locals */
1777:
1.3 rvb 1778: myprintf(("coda_strategy called! "));
1.1 rvb 1779: return(EINVAL);
1780: }
1781:
1782: int
1.3 rvb 1783: coda_reclaim(v)
1.1 rvb 1784: void *v;
1785: {
1786: /* true args */
1787: struct vop_reclaim_args *ap = v;
1788: struct vnode *vp = ap->a_vp;
1789: struct cnode *cp = VTOC(vp);
1790: /* upcall decl */
1791: /* locals */
1792:
1793: /*
1794: * Forced unmount/flush will let vnodes with non zero use be destroyed!
1795: */
1796: ENTRY;
1797:
1798: if (IS_UNMOUNTING(cp)) {
1799: #ifdef DEBUG
1800: if (VTOC(vp)->c_ovp) {
1801: if (IS_UNMOUNTING(cp))
1.3 rvb 1802: printf("coda_reclaim: c_ovp not void: vp %p, cp %p\n", vp, cp);
1.1 rvb 1803: }
1804: #endif
1805: } else {
1.5 rvb 1806: #ifdef OLD_DIAGNOSTIC
1.1 rvb 1807: if (vp->v_usecount != 0)
1.5 rvb 1808: print("coda_reclaim: pushing active %p\n", vp);
1.1 rvb 1809: if (VTOC(vp)->c_ovp) {
1.3 rvb 1810: panic("coda_reclaim: c_ovp not void");
1.2 rvb 1811: }
1.5 rvb 1812: #endif
1.1 rvb 1813: }
1814: cache_purge(vp);
1.3 rvb 1815: coda_free(VTOC(vp));
1.25.2.2 thorpej 1816: SET_VTOC(vp) = NULL;
1.1 rvb 1817: return (0);
1818: }
1819:
1820: int
1.3 rvb 1821: coda_lock(v)
1.1 rvb 1822: void *v;
1823: {
1824: /* true args */
1825: struct vop_lock_args *ap = v;
1826: struct vnode *vp = ap->a_vp;
1827: struct cnode *cp = VTOC(vp);
1828: /* upcall decl */
1829: /* locals */
1830:
1831: ENTRY;
1832:
1.3 rvb 1833: if (coda_lockdebug) {
1.1 rvb 1834: myprintf(("Attempting lock on %lx.%lx.%lx\n",
1835: cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique));
1836: }
1837:
1.10 wrstuden 1838: return (lockmgr(&vp->v_lock, ap->a_flags, &vp->v_interlock));
1.1 rvb 1839: }
1840:
1841: int
1.3 rvb 1842: coda_unlock(v)
1.1 rvb 1843: void *v;
1844: {
1845: /* true args */
1846: struct vop_unlock_args *ap = v;
1847: struct vnode *vp = ap->a_vp;
1848: struct cnode *cp = VTOC(vp);
1849: /* upcall decl */
1850: /* locals */
1851:
1852: ENTRY;
1.3 rvb 1853: if (coda_lockdebug) {
1.1 rvb 1854: myprintf(("Attempting unlock on %lx.%lx.%lx\n",
1855: cp->c_fid.Volume, cp->c_fid.Vnode, cp->c_fid.Unique));
1856: }
1857:
1.10 wrstuden 1858: return (lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock));
1.1 rvb 1859: }
1860:
1861: int
1.3 rvb 1862: coda_islocked(v)
1.1 rvb 1863: void *v;
1864: {
1865: /* true args */
1866: struct vop_islocked_args *ap = v;
1867: ENTRY;
1868:
1.10 wrstuden 1869: return (lockstatus(&ap->a_vp->v_lock));
1.1 rvb 1870: }
1871:
1872: /* How one looks up a vnode given a device/inode pair: */
1873: int
1.3 rvb 1874: coda_grab_vnode(dev_t dev, ino_t ino, struct vnode **vpp)
1.1 rvb 1875: {
1876: /* This is like VFS_VGET() or igetinode()! */
1877: int error;
1878: struct mount *mp;
1879:
1880: if (!(mp = devtomp(dev))) {
1.3 rvb 1881: myprintf(("coda_grab_vnode: devtomp(%d) returns NULL\n", dev));
1.1 rvb 1882: return(ENXIO);
1883: }
1884:
1885: /* XXX - ensure that nonzero-return means failure */
1886: error = VFS_VGET(mp,ino,vpp);
1887: if (error) {
1.3 rvb 1888: myprintf(("coda_grab_vnode: iget/vget(%d, %d) returns %p, err %d\n",
1.1 rvb 1889: dev, ino, *vpp, error));
1890: return(ENOENT);
1891: }
1892: return(0);
1893: }
1894:
1895: void
1896: print_vattr( attr )
1897: struct vattr *attr;
1898: {
1899: char *typestr;
1900:
1901: switch (attr->va_type) {
1902: case VNON:
1903: typestr = "VNON";
1904: break;
1905: case VREG:
1906: typestr = "VREG";
1907: break;
1908: case VDIR:
1909: typestr = "VDIR";
1910: break;
1911: case VBLK:
1912: typestr = "VBLK";
1913: break;
1914: case VCHR:
1915: typestr = "VCHR";
1916: break;
1917: case VLNK:
1918: typestr = "VLNK";
1919: break;
1920: case VSOCK:
1921: typestr = "VSCK";
1922: break;
1923: case VFIFO:
1924: typestr = "VFFO";
1925: break;
1926: case VBAD:
1927: typestr = "VBAD";
1928: break;
1929: default:
1930: typestr = "????";
1931: break;
1932: }
1933:
1934:
1935: myprintf(("attr: type %s mode %d uid %d gid %d fsid %d rdev %d\n",
1936: typestr, (int)attr->va_mode, (int)attr->va_uid,
1937: (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev));
1938:
1939: myprintf((" fileid %d nlink %d size %d blocksize %d bytes %d\n",
1940: (int)attr->va_fileid, (int)attr->va_nlink,
1941: (int)attr->va_size,
1942: (int)attr->va_blocksize,(int)attr->va_bytes));
1943: myprintf((" gen %ld flags %ld vaflags %d\n",
1944: attr->va_gen, attr->va_flags, attr->va_vaflags));
1945: myprintf((" atime sec %d nsec %d\n",
1946: (int)attr->va_atime.tv_sec, (int)attr->va_atime.tv_nsec));
1947: myprintf((" mtime sec %d nsec %d\n",
1948: (int)attr->va_mtime.tv_sec, (int)attr->va_mtime.tv_nsec));
1949: myprintf((" ctime sec %d nsec %d\n",
1950: (int)attr->va_ctime.tv_sec, (int)attr->va_ctime.tv_nsec));
1951: }
1952:
1953: /* How to print a ucred */
1954: void
1955: print_cred(cred)
1956: struct ucred *cred;
1957: {
1958:
1959: int i;
1960:
1961: myprintf(("ref %d\tuid %d\n",cred->cr_ref,cred->cr_uid));
1962:
1963: for (i=0; i < cred->cr_ngroups; i++)
1964: myprintf(("\tgroup %d: (%d)\n",i,cred->cr_groups[i]));
1965: myprintf(("\n"));
1966:
1967: }
1968:
1969: /*
1970: * Return a vnode for the given fid.
1971: * If no cnode exists for this fid create one and put it
1972: * in a table hashed by fid.Volume and fid.Vnode. If the cnode for
1973: * this fid is already in the table return it (ref count is
1.3 rvb 1974: * incremented by coda_find. The cnode will be flushed from the
1975: * table when coda_inactive calls coda_unsave.
1.1 rvb 1976: */
1977: struct cnode *
1.3 rvb 1978: make_coda_node(fid, vfsp, type)
1.1 rvb 1979: ViceFid *fid; struct mount *vfsp; short type;
1980: {
1981: struct cnode *cp;
1982: int err;
1983:
1.3 rvb 1984: if ((cp = coda_find(fid)) == NULL) {
1.1 rvb 1985: struct vnode *vp;
1986:
1.3 rvb 1987: cp = coda_alloc();
1.1 rvb 1988: cp->c_fid = *fid;
1989:
1.3 rvb 1990: err = getnewvnode(VT_CODA, vfsp, coda_vnodeop_p, &vp);
1.1 rvb 1991: if (err) {
1.3 rvb 1992: panic("coda: getnewvnode returned error %d\n", err);
1.1 rvb 1993: }
1994: vp->v_data = cp;
1995: vp->v_type = type;
1996: cp->c_vnode = vp;
1.3 rvb 1997: coda_save(cp);
1.1 rvb 1998:
1999: } else {
2000: vref(CTOV(cp));
2001: }
2002:
2003: return cp;
1.25 chs 2004: }
2005:
2006: int
2007: coda_getpages(v)
2008: void *v;
2009: {
2010: struct vop_getpages_args /* {
2011: struct vnode *a_vp;
2012: voff_t a_offset;
2013: struct vm_page **a_m;
2014: int *a_count;
2015: int a_centeridx;
2016: vm_prot_t a_access_type;
2017: int a_advice;
2018: int a_flags;
2019: } */ *ap = v;
2020: struct vnode *vp = ap->a_vp;
2021: struct cnode *cp = VTOC(vp);
2022: struct proc *p = curproc;
2023: struct ucred *cred = p->p_ucred;
2024: int error;
2025:
2026: /* Check for control object. */
2027: if (IS_CTL_VP(vp)) {
2028: return(EINVAL);
2029: }
2030:
2031: error = VOP_OPEN(vp, FREAD, cred, p);
2032: if (error) {
2033: return error;
2034: }
2035: ap->a_vp = cp->c_ovp;
2036: error = VOCALL(ap->a_vp->v_op, VOFFSET(vop_getpages), ap);
2037: (void) VOP_CLOSE(vp, FREAD, cred, p);
2038: return error;
2039: }
2040:
2041: int
2042: coda_putpages(v)
2043: void *v;
2044: {
2045: struct vop_putpages_args /* {
2046: struct vnode *a_vp;
2047: voff_t a_offlo;
2048: voff_t a_offhi;
2049: int a_flags;
2050: } */ *ap = v;
2051: struct vnode *vp = ap->a_vp;
1.25.2.2 thorpej 2052:
2053: simple_unlock(&vp->v_interlock);
1.25 chs 2054:
2055: /* Check for control object. */
2056: if (IS_CTL_VP(vp)) {
2057: return(EINVAL);
2058: }
2059:
2060: /*
2061: * XXX
2062: * we'd like to do something useful here for msync(),
2063: * but that turns out to be hard.
2064: */
2065:
2066: return 0;
1.1 rvb 2067: }
CVSweb <webmaster@jp.NetBSD.org>