1*53838Spendry /* 2*53838Spendry * Copyright (c) 1992 The Regents of the University of California 3*53838Spendry * Copyright (c) 1990, 1992 Jan-Simon Pendry 4*53838Spendry * All rights reserved. 5*53838Spendry * 6*53838Spendry * This code is derived from software donated to Berkeley by 7*53838Spendry * Jan-Simon Pendry. 8*53838Spendry * 9*53838Spendry * %sccs.include.redist.c% 10*53838Spendry * 11*53838Spendry * @(#)fdesc_vnops.c 1.1 (Berkeley) 06/03/92 12*53838Spendry * 13*53838Spendry * $Id: fdesc_vnops.c,v 1.7 1992/05/30 10:05:34 jsp Exp jsp $ 14*53838Spendry */ 15*53838Spendry 16*53838Spendry /* 17*53838Spendry * /dev/fd Filesystem 18*53838Spendry */ 19*53838Spendry 20*53838Spendry #include <sys/param.h> 21*53838Spendry #include <sys/systm.h> 22*53838Spendry #include <sys/types.h> 23*53838Spendry #include <sys/time.h> 24*53838Spendry #include <sys/proc.h> 25*53838Spendry #include <sys/resourcevar.h> 26*53838Spendry #include <sys/filedesc.h> 27*53838Spendry #include <sys/vnode.h> 28*53838Spendry #include <sys/malloc.h> 29*53838Spendry #include <sys/file.h> 30*53838Spendry #include <sys/stat.h> 31*53838Spendry #include <sys/mount.h> 32*53838Spendry #include <sys/namei.h> 33*53838Spendry #include <sys/buf.h> 34*53838Spendry #include <fdesc/fdesc.h> 35*53838Spendry 36*53838Spendry /* 37*53838Spendry * vp is the current namei directory 38*53838Spendry * ndp is the name to locate in that directory... 39*53838Spendry */ 40*53838Spendry fdesc_lookup (ap) 41*53838Spendry struct vop_lookup_args *ap; 42*53838Spendry { 43*53838Spendry /*USES_VOP_LOCK;*/ 44*53838Spendry char *pname; 45*53838Spendry struct proc *p; 46*53838Spendry int nfiles; 47*53838Spendry unsigned fd; 48*53838Spendry int error; 49*53838Spendry struct vnode *fvp; 50*53838Spendry 51*53838Spendry #ifdef FDESC_DIAGNOSTIC 52*53838Spendry printf("fdesc_lookup(%x)\n", ap); 53*53838Spendry printf("fdesc_lookup(dp = %x, vpp = %x, cnp = %x)\n", ap->a_dvp, ap->a_vpp, ap->a_cnp); 54*53838Spendry #endif 55*53838Spendry pname = ap->a_cnp->cn_nameptr; 56*53838Spendry #ifdef FDESC_DIAGNOSTIC 57*53838Spendry printf("fdesc_lookup(%s)\n", pname); 58*53838Spendry #endif 59*53838Spendry if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { 60*53838Spendry *ap->a_vpp = ap->a_dvp; 61*53838Spendry VREF(ap->a_dvp); 62*53838Spendry /*VOP_LOCK(ap->a_dvp);*/ 63*53838Spendry return (0); 64*53838Spendry } 65*53838Spendry 66*53838Spendry p = ap->a_cnp->cn_proc; 67*53838Spendry nfiles = p->p_fd->fd_nfiles; 68*53838Spendry 69*53838Spendry fd = 0; 70*53838Spendry while (*pname >= '0' && *pname <= '9') { 71*53838Spendry fd = 10 * fd + *pname++ - '0'; 72*53838Spendry if (fd >= nfiles) 73*53838Spendry break; 74*53838Spendry } 75*53838Spendry 76*53838Spendry #ifdef FDESC_DIAGNOSTIC 77*53838Spendry printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname); 78*53838Spendry #endif 79*53838Spendry if (*pname == '/') { 80*53838Spendry error = ENOTDIR; 81*53838Spendry goto bad; 82*53838Spendry } 83*53838Spendry 84*53838Spendry if (*pname != '\0') { 85*53838Spendry error = ENOENT; 86*53838Spendry goto bad; 87*53838Spendry } 88*53838Spendry 89*53838Spendry if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { 90*53838Spendry error = EBADF; 91*53838Spendry goto bad; 92*53838Spendry } 93*53838Spendry 94*53838Spendry #ifdef FDESC_DIAGNOSTIC 95*53838Spendry printf("fdesc_lookup: allocate new vnode\n"); 96*53838Spendry #endif 97*53838Spendry error = getnewvnode(VT_UFS, ap->a_dvp->v_mount, fdesc_vnodeop_p, &fvp); 98*53838Spendry if (error) 99*53838Spendry goto bad; 100*53838Spendry MALLOC(fvp->v_data, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); 101*53838Spendry VTOFDESC(fvp)->f_fd = fd; 102*53838Spendry /*VTOFDESC(fvp)->f_isroot = 0;*/ 103*53838Spendry *ap->a_vpp = fvp; 104*53838Spendry #ifdef FDESC_DIAGNOSTIC 105*53838Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 106*53838Spendry #endif 107*53838Spendry return (0); 108*53838Spendry 109*53838Spendry bad:; 110*53838Spendry *ap->a_vpp = NULL; 111*53838Spendry #ifdef FDESC_DIAGNOSTIC 112*53838Spendry printf("fdesc_lookup: error = %d\n", error); 113*53838Spendry #endif 114*53838Spendry return (error); 115*53838Spendry } 116*53838Spendry 117*53838Spendry fdesc_open (ap) 118*53838Spendry struct vop_open_args *ap; 119*53838Spendry { 120*53838Spendry /* 121*53838Spendry * Can always open the root (modulo perms) 122*53838Spendry */ 123*53838Spendry if (ap->a_vp->v_flag & VROOT) 124*53838Spendry return (0); 125*53838Spendry 126*53838Spendry /* 127*53838Spendry * XXX Kludge: set ap->a_p->p_dupfd to contain the value of the 128*53838Spendry * the file descriptor being sought for duplication. The error 129*53838Spendry * return ensures that the vnode for this device will be released 130*53838Spendry * by vn_open. Open will detect this special error and take the 131*53838Spendry * actions in dupfdopen. Other callers of vn_open or VOP_OPEN 132*53838Spendry * will simply report the error. 133*53838Spendry */ 134*53838Spendry ap->a_p->p_dupfd = VTOFDESC(ap->a_vp)->f_fd; /* XXX */ 135*53838Spendry return (ENODEV); 136*53838Spendry } 137*53838Spendry 138*53838Spendry static int 139*53838Spendry fdesc_attr(fd, vap, cred, p) 140*53838Spendry int fd; 141*53838Spendry struct vattr *vap; 142*53838Spendry struct ucred *cred; 143*53838Spendry struct proc *p; 144*53838Spendry { 145*53838Spendry USES_VOP_GETATTR; 146*53838Spendry struct filedesc *fdp = p->p_fd; 147*53838Spendry struct file *fp; 148*53838Spendry int error; 149*53838Spendry 150*53838Spendry #ifdef FDESC_DIAGNOSTIC 151*53838Spendry printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 152*53838Spendry #endif 153*53838Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 154*53838Spendry #ifdef FDESC_DIAGNOSTIC 155*53838Spendry printf("fdesc_attr: fp = %x (EBADF)\n", fp); 156*53838Spendry #endif 157*53838Spendry return (EBADF); 158*53838Spendry } 159*53838Spendry 160*53838Spendry /* 161*53838Spendry * Can stat the underlying vnode, but not sockets because 162*53838Spendry * they don't use struct vattrs. Well, we could convert from 163*53838Spendry * a struct stat back to a struct vattr, later... 164*53838Spendry */ 165*53838Spendry switch (fp->f_type) { 166*53838Spendry case DTYPE_VNODE: 167*53838Spendry error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); 168*53838Spendry break; 169*53838Spendry 170*53838Spendry case DTYPE_SOCKET: 171*53838Spendry error = EOPNOTSUPP; 172*53838Spendry break; 173*53838Spendry 174*53838Spendry default: 175*53838Spendry panic("fdesc attr"); 176*53838Spendry break; 177*53838Spendry } 178*53838Spendry 179*53838Spendry #ifdef FDESC_DIAGNOSTIC 180*53838Spendry printf("fdesc_attr: returns error %d\n", error); 181*53838Spendry #endif 182*53838Spendry return (error); 183*53838Spendry } 184*53838Spendry 185*53838Spendry fdesc_getattr (ap) 186*53838Spendry struct vop_getattr_args *ap; 187*53838Spendry { 188*53838Spendry unsigned fd; 189*53838Spendry int error; 190*53838Spendry 191*53838Spendry if (ap->a_vp->v_flag & VROOT) { 192*53838Spendry #ifdef FDESC_DIAGNOSTIC 193*53838Spendry printf("fdesc_getattr: stat rootdir\n"); 194*53838Spendry #endif 195*53838Spendry bzero((caddr_t) ap->a_vap, sizeof(*ap->a_vap)); 196*53838Spendry vattr_null(ap->a_vap); 197*53838Spendry ap->a_vap->va_type = VDIR; 198*53838Spendry ap->a_vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 199*53838Spendry ap->a_vap->va_nlink = 2; 200*53838Spendry ap->a_vap->va_uid = 0; 201*53838Spendry ap->a_vap->va_gid = 0; 202*53838Spendry ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 203*53838Spendry ap->a_vap->va_fileid = 2; 204*53838Spendry /* ap->a_vap->va_qsize = 0; */ 205*53838Spendry ap->a_vap->va_size = DEV_BSIZE; 206*53838Spendry ap->a_vap->va_blocksize = DEV_BSIZE; 207*53838Spendry microtime(&ap->a_vap->va_atime); 208*53838Spendry ap->a_vap->va_mtime = ap->a_vap->va_atime; 209*53838Spendry ap->a_vap->va_ctime = ap->a_vap->va_ctime; 210*53838Spendry ap->a_vap->va_gen = 0; 211*53838Spendry ap->a_vap->va_flags = 0; 212*53838Spendry ap->a_vap->va_rdev = 0; 213*53838Spendry /* ap->a_vap->va_qbytes = 0; */ 214*53838Spendry ap->a_vap->va_bytes = 0; 215*53838Spendry return (0); 216*53838Spendry } 217*53838Spendry 218*53838Spendry fd = VTOFDESC(ap->a_vp)->f_fd; 219*53838Spendry error = fdesc_attr(fd, ap->a_vap, ap->a_cred, ap->a_p); 220*53838Spendry if (error == 0) 221*53838Spendry ap->a_vp->v_type = ap->a_vap->va_type; 222*53838Spendry return (error); 223*53838Spendry } 224*53838Spendry 225*53838Spendry fdesc_setattr (ap) 226*53838Spendry struct vop_setattr_args *ap; 227*53838Spendry { 228*53838Spendry USES_VOP_SETATTR; 229*53838Spendry struct filedesc *fdp = ap->a_p->p_fd; 230*53838Spendry struct file *fp; 231*53838Spendry unsigned fd; 232*53838Spendry int error; 233*53838Spendry 234*53838Spendry /* 235*53838Spendry * Can't mess with the root vnode 236*53838Spendry */ 237*53838Spendry if (ap->a_vp->v_flag & VROOT) 238*53838Spendry return (EACCES); 239*53838Spendry 240*53838Spendry fd = VTOFDESC(ap->a_vp)->f_fd; 241*53838Spendry #ifdef FDESC_DIAGNOSTIC 242*53838Spendry printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 243*53838Spendry #endif 244*53838Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 245*53838Spendry #ifdef FDESC_DIAGNOSTIC 246*53838Spendry printf("fdesc_setattr: fp = %x (EBADF)\n", fp); 247*53838Spendry #endif 248*53838Spendry return (EBADF); 249*53838Spendry } 250*53838Spendry 251*53838Spendry /* 252*53838Spendry * Can setattr the underlying vnode, but not sockets! 253*53838Spendry */ 254*53838Spendry switch (fp->f_type) { 255*53838Spendry case DTYPE_VNODE: 256*53838Spendry error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); 257*53838Spendry break; 258*53838Spendry 259*53838Spendry case DTYPE_SOCKET: 260*53838Spendry error = EOPNOTSUPP; 261*53838Spendry break; 262*53838Spendry 263*53838Spendry default: 264*53838Spendry panic("fdesc setattr"); 265*53838Spendry break; 266*53838Spendry } 267*53838Spendry 268*53838Spendry #ifdef FDESC_DIAGNOSTIC 269*53838Spendry printf("fdesc_setattr: returns error %d\n", error); 270*53838Spendry #endif 271*53838Spendry return (error); 272*53838Spendry } 273*53838Spendry 274*53838Spendry fdesc_readdir (ap) 275*53838Spendry struct vop_readdir_args *ap; 276*53838Spendry { 277*53838Spendry struct filedesc *fdp; 278*53838Spendry int i; 279*53838Spendry int error; 280*53838Spendry 281*53838Spendry #define UIO_MX 16 282*53838Spendry 283*53838Spendry fdp = ap->a_uio->uio_procp->p_fd; 284*53838Spendry i = ap->a_uio->uio_offset / UIO_MX; 285*53838Spendry error = 0; 286*53838Spendry while (ap->a_uio->uio_resid > 0) { 287*53838Spendry if (i >= fdp->fd_nfiles) { 288*53838Spendry *ap->a_eofflagp = 1; 289*53838Spendry break; 290*53838Spendry } 291*53838Spendry if (fdp->fd_ofiles[i] != NULL) { 292*53838Spendry struct readdir d; 293*53838Spendry struct readdir *dp = &d; 294*53838Spendry char *cp = dp->d_name; 295*53838Spendry #ifdef FDESC_FILEID 296*53838Spendry struct vattr va; 297*53838Spendry #endif 298*53838Spendry bzero((caddr_t) dp, UIO_MX); 299*53838Spendry 300*53838Spendry dp->d_namlen = sprintf(dp->d_name, "%d", i); 301*53838Spendry /* 302*53838Spendry * Fill in the remaining fields 303*53838Spendry */ 304*53838Spendry dp->d_reclen = UIO_MX; 305*53838Spendry dp->d_ino = i + 3; 306*53838Spendry #ifdef FDESC_FILEID 307*53838Spendry /* 308*53838Spendry * If we want the file ids to match the 309*53838Spendry * we must call getattr on the underlying file. 310*53838Spendry * fdesc_attr may return an error, in which case 311*53838Spendry * we ignore the returned file id. 312*53838Spendry */ 313*53838Spendry error = fdesc_attr(i, &va, ap->a_cred, p); 314*53838Spendry if (error == 0) 315*53838Spendry dp->d_ino = va.va_fileid; 316*53838Spendry #endif 317*53838Spendry /* 318*53838Spendry * And ship to userland 319*53838Spendry */ 320*53838Spendry error = uiomove((caddr_t) dp, UIO_MX, ap->a_uio); 321*53838Spendry if (error) 322*53838Spendry break; 323*53838Spendry } 324*53838Spendry i++; 325*53838Spendry } 326*53838Spendry 327*53838Spendry ap->a_uio->uio_offset = i * UIO_MX; 328*53838Spendry return (error); 329*53838Spendry } 330*53838Spendry 331*53838Spendry fdesc_inactive (ap) 332*53838Spendry struct vop_inactive_args *ap; 333*53838Spendry { 334*53838Spendry /* 335*53838Spendry * Clear out the v_type field to avoid 336*53838Spendry * nasty things happening in vgone(). 337*53838Spendry */ 338*53838Spendry ap->a_vp->v_type = VNON; 339*53838Spendry #ifdef FDESC_DIAGNOSTIC 340*53838Spendry printf("fdesc_inactive(%x)\n", ap->a_vp); 341*53838Spendry #endif 342*53838Spendry return (0); 343*53838Spendry } 344*53838Spendry 345*53838Spendry fdesc_reclaim (ap) 346*53838Spendry struct vop_reclaim_args *ap; 347*53838Spendry { 348*53838Spendry struct vnode *vp = ap->a_vp; 349*53838Spendry printf("fdesc_reclaim(%x)\n", vp); 350*53838Spendry if (vp->v_data) { 351*53838Spendry FREE(vp->v_data, M_TEMP); 352*53838Spendry vp->v_data = 0; 353*53838Spendry } 354*53838Spendry return (0); 355*53838Spendry } 356*53838Spendry 357*53838Spendry /* 358*53838Spendry * Print out the contents of a /dev/fd vnode. 359*53838Spendry */ 360*53838Spendry /* ARGSUSED */ 361*53838Spendry fdesc_print (ap) 362*53838Spendry struct vop_print_args *ap; 363*53838Spendry { 364*53838Spendry printf("tag VT_NON, fdesc vnode\n"); 365*53838Spendry } 366*53838Spendry 367*53838Spendry /*void*/ 368*53838Spendry fdesc_vfree (ap) 369*53838Spendry struct vop_vfree_args *ap; 370*53838Spendry { 371*53838Spendry 372*53838Spendry return; 373*53838Spendry } 374*53838Spendry 375*53838Spendry /* 376*53838Spendry * /dev/fd vnode unsupported operation 377*53838Spendry */ 378*53838Spendry fdesc_enotsupp() 379*53838Spendry { 380*53838Spendry return (EOPNOTSUPP); 381*53838Spendry } 382*53838Spendry 383*53838Spendry /* 384*53838Spendry * /dev/fd "should never get here" operation 385*53838Spendry */ 386*53838Spendry fdesc_badop() 387*53838Spendry { 388*53838Spendry panic("fdesc: bad op"); 389*53838Spendry /* NOTREACHED */ 390*53838Spendry } 391*53838Spendry 392*53838Spendry /* 393*53838Spendry * /dev/fd vnode null operation 394*53838Spendry */ 395*53838Spendry fdesc_nullop() 396*53838Spendry { 397*53838Spendry return (0); 398*53838Spendry } 399*53838Spendry 400*53838Spendry #define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp) 401*53838Spendry #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp) 402*53838Spendry #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) 403*53838Spendry #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) 404*53838Spendry #define fdesc_read ((int (*) __P((struct vop_read_args *)))fdesc_enotsupp) 405*53838Spendry #define fdesc_write ((int (*) __P((struct vop_write_args *)))fdesc_enotsupp) 406*53838Spendry #define fdesc_ioctl ((int (*) __P((struct vop_ioctl_args *)))fdesc_enotsupp) 407*53838Spendry #define fdesc_select ((int (*) __P((struct vop_select_args *)))fdesc_enotsupp) 408*53838Spendry #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp) 409*53838Spendry #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 410*53838Spendry #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) 411*53838Spendry #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp) 412*53838Spendry #define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp) 413*53838Spendry #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp) 414*53838Spendry #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp) 415*53838Spendry #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp) 416*53838Spendry #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp) 417*53838Spendry #define fdesc_readlink ((int (*) __P((struct vop_readlink_args *)))fdesc_enotsupp) 418*53838Spendry #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 419*53838Spendry #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop) 420*53838Spendry #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 421*53838Spendry #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) 422*53838Spendry #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) 423*53838Spendry #define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 424*53838Spendry #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp) 425*53838Spendry #define fdesc_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp) 426*53838Spendry #define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp) 427*53838Spendry #define fdesc_valloc ((int(*) __P(( \ 428*53838Spendry struct vnode *pvp, \ 429*53838Spendry int mode, \ 430*53838Spendry struct ucred *cred, \ 431*53838Spendry struct vnode **vpp))) fdesc_enotsupp) 432*53838Spendry #define fdesc_truncate ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp) 433*53838Spendry #define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp) 434*53838Spendry #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp) 435*53838Spendry 436*53838Spendry int (**fdesc_vnodeop_p)(); 437*53838Spendry struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { 438*53838Spendry { &vop_default_desc, vn_default_error }, 439*53838Spendry { &vop_lookup_desc, fdesc_lookup }, /* lookup */ 440*53838Spendry { &vop_create_desc, fdesc_create }, /* create */ 441*53838Spendry { &vop_mknod_desc, fdesc_mknod }, /* mknod */ 442*53838Spendry { &vop_open_desc, fdesc_open }, /* open */ 443*53838Spendry { &vop_close_desc, fdesc_close }, /* close */ 444*53838Spendry { &vop_access_desc, fdesc_access }, /* access */ 445*53838Spendry { &vop_getattr_desc, fdesc_getattr }, /* getattr */ 446*53838Spendry { &vop_setattr_desc, fdesc_setattr }, /* setattr */ 447*53838Spendry { &vop_read_desc, fdesc_read }, /* read */ 448*53838Spendry { &vop_write_desc, fdesc_write }, /* write */ 449*53838Spendry { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ 450*53838Spendry { &vop_select_desc, fdesc_select }, /* select */ 451*53838Spendry { &vop_mmap_desc, fdesc_mmap }, /* mmap */ 452*53838Spendry { &vop_fsync_desc, fdesc_fsync }, /* fsync */ 453*53838Spendry { &vop_seek_desc, fdesc_seek }, /* seek */ 454*53838Spendry { &vop_remove_desc, fdesc_remove }, /* remove */ 455*53838Spendry { &vop_link_desc, fdesc_link }, /* link */ 456*53838Spendry { &vop_rename_desc, fdesc_rename }, /* rename */ 457*53838Spendry { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ 458*53838Spendry { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ 459*53838Spendry { &vop_symlink_desc, fdesc_symlink }, /* symlink */ 460*53838Spendry { &vop_readdir_desc, fdesc_readdir }, /* readdir */ 461*53838Spendry { &vop_readlink_desc, fdesc_readlink }, /* readlink */ 462*53838Spendry { &vop_abortop_desc, fdesc_abortop }, /* abortop */ 463*53838Spendry { &vop_inactive_desc, fdesc_inactive }, /* inactive */ 464*53838Spendry { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ 465*53838Spendry { &vop_lock_desc, fdesc_lock }, /* lock */ 466*53838Spendry { &vop_unlock_desc, fdesc_unlock }, /* unlock */ 467*53838Spendry { &vop_bmap_desc, fdesc_bmap }, /* bmap */ 468*53838Spendry { &vop_strategy_desc, fdesc_strategy }, /* strategy */ 469*53838Spendry { &vop_print_desc, fdesc_print }, /* print */ 470*53838Spendry { &vop_islocked_desc, fdesc_islocked }, /* islocked */ 471*53838Spendry { &vop_advlock_desc, fdesc_advlock }, /* advlock */ 472*53838Spendry { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ 473*53838Spendry { &vop_vget_desc, fdesc_vget }, /* vget */ 474*53838Spendry { &vop_valloc_desc, fdesc_valloc }, /* valloc */ 475*53838Spendry { &vop_vfree_desc, fdesc_vfree }, /* vfree */ 476*53838Spendry { &vop_truncate_desc, fdesc_truncate }, /* truncate */ 477*53838Spendry { &vop_update_desc, fdesc_update }, /* update */ 478*53838Spendry { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ 479*53838Spendry { (struct vnodeop_desc*)NULL, (int(*)())NULL } 480*53838Spendry }; 481*53838Spendry struct vnodeopv_desc fdesc_vnodeop_opv_desc = 482*53838Spendry { &fdesc_vnodeop_p, fdesc_vnodeop_entries }; 483