[BACK]Return to coda_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / coda

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>