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

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

CVSweb <webmaster@jp.NetBSD.org>