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