[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.58

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

CVSweb <webmaster@jp.NetBSD.org>