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