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