X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4452a7af2eac33dbad800bcc91f2399d62c18f53..2d21ac55c334faf3a56e5634905ed6987fc787d4:/bsd/dev/vn/vn.c diff --git a/bsd/dev/vn/vn.c b/bsd/dev/vn/vn.c index f9a2212b9..4ac024c27 100644 --- a/bsd/dev/vn/vn.c +++ b/bsd/dev/vn/vn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -120,6 +120,8 @@ #include "shadow.h" +static void +vndevice_do_init(void) __attribute__((section("__TEXT, initcode"))); static ioctl_fcn_t vnioctl_chr; static ioctl_fcn_t vnioctl_blk; @@ -157,7 +159,7 @@ static struct cdevsw vn_cdevsw = { /* ioctl */ vnioctl_chr, /* stop */ eno_stop, /* reset */ eno_reset, - /* ttys */ 0, + /* ttys */ NULL, /* select */ eno_select, /* mmap */ eno_mmap, /* strategy */ eno_strat, @@ -177,7 +179,7 @@ struct vn_softc { struct vnode *sc_shadow_vp; /* shadow vnode if not NULL */ uint32_t sc_shadow_vid; shadow_map_t * sc_shadow_map; /* shadow map if not NULL */ - kauth_cred_t sc_cred; /* credentials */ + kauth_cred_t sc_cred; /* credentials */ u_int32_t sc_options; /* options */ void * sc_bdev; void * sc_cdev; @@ -194,9 +196,8 @@ static u_int32_t vn_options; #define IFOPT(vn,opt) if (((vn)->sc_options|vn_options) & (opt)) #define TESTOPT(vn,opt) (((vn)->sc_options|vn_options) & (opt)) -static int setcred(struct vnode * vp, struct proc * p, - kauth_cred_t cred); -static void vnclear (struct vn_softc *vn, struct proc * p); +static int setcred(struct vnode * vp, kauth_cred_t cred); +static void vnclear (struct vn_softc *vn, vfs_context_t ctx); static void vn_ioctl_to_64(struct vn_ioctl *from, struct user_vn_ioctl *to); void vndevice_init(void); int vndevice_root_image(char * path, char devname[], dev_t * dev_p); @@ -206,13 +207,13 @@ vniocattach_file(struct vn_softc *vn, struct user_vn_ioctl *vniop, dev_t dev, int in_kernel, - struct proc *p); + proc_t p); static int vniocattach_shadow(struct vn_softc * vn, struct user_vn_ioctl *vniop, dev_t dev, int in_kernel, - struct proc *p); + proc_t p); static __inline__ int vnunit(dev_t dev) { @@ -221,13 +222,13 @@ vnunit(dev_t dev) static int vnclose(__unused dev_t dev, __unused int flags, - __unused int devtype, __unused struct proc *p) + __unused int devtype, __unused proc_t p) { return (0); } static int -vnopen(dev_t dev, int flags, __unused int devtype, __unused struct proc *p) +vnopen(dev_t dev, int flags, __unused int devtype, __unused proc_t p) { struct vn_softc *vn; int unit; @@ -244,7 +245,7 @@ vnopen(dev_t dev, int flags, __unused int devtype, __unused struct proc *p) } static int -file_io(struct vnode * vp, struct vfs_context * context_p, +file_io(struct vnode * vp, vfs_context_t ctx, enum uio_rw op, char * base, off_t offset, user_ssize_t count, user_ssize_t * resid) { @@ -256,9 +257,9 @@ file_io(struct vnode * vp, struct vfs_context * context_p, &uio_buf[0], sizeof(uio_buf)); uio_addiov(auio, CAST_USER_ADDR_T(base), count); if (op == UIO_READ) - error = VNOP_READ(vp, auio, IO_SYNC, context_p); + error = VNOP_READ(vp, auio, IO_SYNC, ctx); else - error = VNOP_WRITE(vp, auio, IO_SYNC, context_p); + error = VNOP_WRITE(vp, auio, IO_SYNC, ctx); if (resid != NULL) { *resid = uio_resid(auio); @@ -286,7 +287,7 @@ block_remainder(off_t o, int blocksize) static int vnread_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, - struct vfs_context * context_p) + vfs_context_t ctx) { u_long blocksize = vn->sc_secsize; int error = 0; @@ -326,7 +327,7 @@ vnread_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, this_resid = resid; } uio_setresid(uio, this_resid); - error = VNOP_READ(vp, uio, ioflag, context_p); + error = VNOP_READ(vp, uio, ioflag, ctx); if (error) { break; } @@ -346,7 +347,7 @@ vnread_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, } static int -vncopy_block_to_shadow(struct vn_softc * vn, struct vfs_context * context_p, +vncopy_block_to_shadow(struct vn_softc * vn, vfs_context_t ctx, u_long file_block, u_long shadow_block) { int error; @@ -357,14 +358,14 @@ vncopy_block_to_shadow(struct vn_softc * vn, struct vfs_context * context_p, return (ENOMEM); } /* read one block from file at file_block offset */ - error = file_io(vn->sc_vp, context_p, UIO_READ, + error = file_io(vn->sc_vp, ctx, UIO_READ, tmpbuf, (off_t)file_block * vn->sc_secsize, vn->sc_secsize, NULL); if (error) { goto done; } /* write one block to shadow file at shadow_block offset */ - error = file_io(vn->sc_shadow_vp, context_p, UIO_WRITE, + error = file_io(vn->sc_shadow_vp, ctx, UIO_WRITE, tmpbuf, (off_t)shadow_block * vn->sc_secsize, vn->sc_secsize, NULL); done: @@ -379,7 +380,7 @@ enum { static int vnwrite_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, - struct vfs_context * context_p) + vfs_context_t ctx) { u_long blocksize = vn->sc_secsize; int error = 0; @@ -427,8 +428,7 @@ vnwrite_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, off_t size; size = (off_t)shadow_map_shadow_size(vn->sc_shadow_map) * vn->sc_secsize; - vnode_setsize(vn->sc_shadow_vp, size, IO_SYNC, - context_p); + vnode_setsize(vn->sc_shadow_vp, size, IO_SYNC, ctx); #endif 0 } /* write the blocks (or parts thereof) */ @@ -446,11 +446,10 @@ vnwrite_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, + resid_block_count - 1; d = shadow_block_number + shadow_block_count - 1; - error = vncopy_block_to_shadow(vn, context_p, - s, d); + error = vncopy_block_to_shadow(vn, ctx, s, d); if (error) { printf("vnwrite_shadow: failed to copy" - " block %d to shadow block %d\n", + " block %lu to shadow block %lu\n", s, d); break; } @@ -459,18 +458,18 @@ vnwrite_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, uio_setresid(uio, this_resid); if ((flags & FLAGS_FIRST_BLOCK_PARTIAL) != 0) { /* copy the first block to the shadow */ - error = vncopy_block_to_shadow(vn, context_p, + error = vncopy_block_to_shadow(vn, ctx, offset_block_number, shadow_block_number); if (error) { printf("vnwrite_shadow: failed to" - " copy block %d to shadow block %d\n", + " copy block %lu to shadow block %lu\n", offset_block_number, shadow_block_number); break; } } - error = VNOP_WRITE(vn->sc_shadow_vp, uio, ioflag, context_p); + error = VNOP_WRITE(vn->sc_shadow_vp, uio, ioflag, ctx); if (error) { break; } @@ -495,7 +494,7 @@ vnread(dev_t dev, struct uio *uio, int ioflag) int error = 0; boolean_t funnel_state; off_t offset; - struct proc * p; + proc_t p; user_ssize_t resid; struct vn_softc * vn; int unit; @@ -511,11 +510,15 @@ vnread(dev_t dev, struct uio *uio, int ioflag) error = ENXIO; goto done; } + + context.vc_thread = current_thread(); + context.vc_ucred = vn->sc_cred; + error = vnode_getwithvid(vn->sc_vp, vn->sc_vid); if (error != 0) { /* the vnode is no longer available, abort */ error = ENXIO; - vnclear(vn, p); + vnclear(vn, &context); goto done; } @@ -540,8 +543,6 @@ vnread(dev_t dev, struct uio *uio, int ioflag) uio_setresid(uio, resid); } - context.vc_proc = p; - context.vc_ucred = vn->sc_cred; if (vn->sc_shadow_vp != NULL) { error = vnode_getwithvid(vn->sc_shadow_vp, vn->sc_shadow_vid); @@ -549,7 +550,7 @@ vnread(dev_t dev, struct uio *uio, int ioflag) /* the vnode is no longer available, abort */ error = ENXIO; vnode_put(vn->sc_vp); - vnclear(vn, p); + vnclear(vn, &context); goto done; } error = vnread_shadow(vn, uio, ioflag, &context); @@ -570,7 +571,7 @@ vnwrite(dev_t dev, struct uio *uio, int ioflag) int error; boolean_t funnel_state; off_t offset; - struct proc * p; + proc_t p; user_ssize_t resid; struct vn_softc * vn; int unit; @@ -590,11 +591,15 @@ vnwrite(dev_t dev, struct uio *uio, int ioflag) error = EROFS; goto done; } + + context.vc_thread = current_thread(); + context.vc_ucred = vn->sc_cred; + error = vnode_getwithvid(vn->sc_vp, vn->sc_vid); if (error != 0) { /* the vnode is no longer available, abort */ error = ENXIO; - vnclear(vn, p); + vnclear(vn, &context); goto done; } resid = uio_resid(uio); @@ -618,9 +623,6 @@ vnwrite(dev_t dev, struct uio *uio, int ioflag) uio_setresid(uio, resid); } - context.vc_proc = p; - context.vc_ucred = vn->sc_cred; - if (vn->sc_shadow_vp != NULL) { error = vnode_getwithvid(vn->sc_shadow_vp, vn->sc_shadow_vid); @@ -628,7 +630,7 @@ vnwrite(dev_t dev, struct uio *uio, int ioflag) /* the vnode is no longer available, abort */ error = ENXIO; vnode_put(vn->sc_vp); - vnclear(vn, p); + vnclear(vn, &context); goto done; } error = vnwrite_shadow(vn, uio, ioflag, &context); @@ -643,18 +645,16 @@ vnwrite(dev_t dev, struct uio *uio, int ioflag) } static int -shadow_read(struct vn_softc * vn, struct buf * bp, char * base, struct proc * p) +shadow_read(struct vn_softc * vn, struct buf * bp, char * base, + vfs_context_t ctx) { u_long blocksize = vn->sc_secsize; - struct vfs_context context; int error = 0; u_long offset; boolean_t read_shadow; u_long resid; u_long start = 0; - context.vc_proc = p; - context.vc_ucred = vn->sc_cred; offset = buf_blkno(bp); resid = buf_resid(bp) / blocksize; while (resid > 0) { @@ -672,7 +672,7 @@ shadow_read(struct vn_softc * vn, struct buf * bp, char * base, struct proc * p) else { vp = vn->sc_vp; } - error = file_io(vp, &context, UIO_READ, base + start, + error = file_io(vp, ctx, UIO_READ, base + start, (off_t)this_offset * blocksize, (user_ssize_t)this_resid * blocksize, &temp_resid); @@ -694,18 +694,15 @@ shadow_read(struct vn_softc * vn, struct buf * bp, char * base, struct proc * p) static int shadow_write(struct vn_softc * vn, struct buf * bp, char * base, - struct proc * p) + vfs_context_t ctx) { u_long blocksize = vn->sc_secsize; - struct vfs_context context; int error = 0; u_long offset; boolean_t shadow_grew; u_long resid; u_long start = 0; - context.vc_proc = p; - context.vc_ucred = vn->sc_cred; offset = buf_blkno(bp); resid = buf_resid(bp) / blocksize; while (resid > 0) { @@ -722,11 +719,10 @@ shadow_write(struct vn_softc * vn, struct buf * bp, char * base, /* truncate the file to its new length before write */ size = (off_t)shadow_map_shadow_size(vn->sc_shadow_map) * blocksize; - vnode_setsize(vn->sc_shadow_vp, size, IO_SYNC, - &context); + vnode_setsize(vn->sc_shadow_vp, size, IO_SYNC, ctx); #endif } - error = file_io(vn->sc_shadow_vp, &context, UIO_WRITE, + error = file_io(vn->sc_shadow_vp, ctx, UIO_WRITE, base + start, (off_t)this_offset * blocksize, (user_ssize_t)this_resid * blocksize, @@ -748,25 +744,20 @@ shadow_write(struct vn_softc * vn, struct buf * bp, char * base, } static int -vn_readwrite_io(struct vn_softc * vn, struct buf * bp, struct proc * p) +vn_readwrite_io(struct vn_softc * vn, struct buf * bp, vfs_context_t ctx) { int error = 0; char * iov_base; caddr_t vaddr; - if (buf_map(bp, &vaddr)) panic("vn device: buf_map failed"); iov_base = (char *)vaddr; if (vn->sc_shadow_vp == NULL) { - struct vfs_context context; user_ssize_t temp_resid; - context.vc_proc = p; - context.vc_ucred = vn->sc_cred; - - error = file_io(vn->sc_vp, &context, + error = file_io(vn->sc_vp, ctx, buf_flags(bp) & B_READ ? UIO_READ : UIO_WRITE, iov_base, (off_t)buf_blkno(bp) * vn->sc_secsize, @@ -775,9 +766,9 @@ vn_readwrite_io(struct vn_softc * vn, struct buf * bp, struct proc * p) } else { if (buf_flags(bp) & B_READ) - error = shadow_read(vn, bp, iov_base, p); + error = shadow_read(vn, bp, iov_base, ctx); else - error = shadow_write(vn, bp, iov_base, p); + error = shadow_write(vn, bp, iov_base, ctx); } buf_unmap(bp); @@ -792,9 +783,9 @@ vnstrategy(struct buf *bp) long sz; /* in sc_secsize chunks */ daddr64_t blk_num; boolean_t funnel_state; - struct proc * p = current_proc(); struct vnode * shadow_vp = NULL; struct vnode * vp = NULL; + struct vfs_context context; funnel_state = thread_funnel_set(kernel_flock, TRUE); vn = vn_table + vnunit(buf_device(bp)); @@ -803,6 +794,9 @@ vnstrategy(struct buf *bp) goto done; } + context.vc_thread = current_thread(); + context.vc_ucred = vn->sc_cred; + buf_setresid(bp, buf_count(bp)); /* * Check for required alignment. Transfers must be a valid @@ -837,11 +831,12 @@ vnstrategy(struct buf *bp) error = ENXIO; goto done; } + error = vnode_getwithvid(vp, vn->sc_vid); if (error != 0) { /* the vnode is no longer available, abort */ error = ENXIO; - vnclear(vn, p); + vnclear(vn, &context); goto done; } shadow_vp = vn->sc_shadow_vp; @@ -852,11 +847,12 @@ vnstrategy(struct buf *bp) /* the vnode is no longer available, abort */ error = ENXIO; vnode_put(vn->sc_vp); - vnclear(vn, p); + vnclear(vn, &context); goto done; } } - error = vn_readwrite_io(vn, bp, p); + + error = vn_readwrite_io(vn, bp, &context); vnode_put(vp); if (shadow_vp != NULL) { vnode_put(shadow_vp); @@ -874,7 +870,7 @@ vnstrategy(struct buf *bp) /* ARGSUSED */ static int vnioctl(dev_t dev, u_long cmd, caddr_t data, - __unused int flag, struct proc *p, + __unused int flag, proc_t p, int is_char) { struct vn_softc *vn; @@ -886,6 +882,7 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, struct vfsioattr ioattr; struct user_vn_ioctl user_vnio; boolean_t funnel_state; + struct vfs_context context; unit = vnunit(dev); if (vnunit(dev) >= NVNDEVICE) { @@ -899,6 +896,9 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, goto done; } + context.vc_thread = current_thread(); + context.vc_ucred = vn->sc_cred; + viop = (struct user_vn_ioctl *)data; f = (u_int32_t *)data; o = (u_int64_t *)data; @@ -1054,7 +1054,7 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, * How are these problems handled for removable and failing * hardware devices? (Hint: They are not) */ - vnclear(vn, p); + vnclear(vn, &context); break; case VNIOCGSET: @@ -1087,13 +1087,13 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, } static int -vnioctl_chr(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +vnioctl_chr(dev_t dev, u_long cmd, caddr_t data, int flag, proc_t p) { return (vnioctl(dev, cmd, data, flag, p, TRUE)); } static int -vnioctl_blk(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +vnioctl_blk(dev_t dev, u_long cmd, caddr_t data, int flag, proc_t p) { return (vnioctl(dev, cmd, data, flag, p, FALSE)); } @@ -1110,47 +1110,42 @@ vniocattach_file(struct vn_softc *vn, struct user_vn_ioctl *vniop, dev_t dev, int in_kernel, - struct proc *p) + proc_t p) { dev_t cdev; - struct vfs_context context; + vfs_context_t ctx = vfs_context_current(); kauth_cred_t cred; struct nameidata nd; off_t file_size; int error, flags; - context.vc_proc = p; - context.vc_ucred = kauth_cred_proc_ref(p); - flags = FREAD|FWRITE; if (in_kernel) { - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE32, vniop->vn_file, &context); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE32, vniop->vn_file, ctx); } else { NDINIT(&nd, LOOKUP, FOLLOW, (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), - vniop->vn_file, &context); + vniop->vn_file, ctx); } /* vn_open gives both long- and short-term references */ error = vn_open(&nd, flags, 0); if (error) { if (error != EACCES && error != EPERM && error != EROFS) { - kauth_cred_unref(&context.vc_ucred); return (error); } flags &= ~FWRITE; if (in_kernel) { NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE32, - vniop->vn_file, &context); + vniop->vn_file, ctx); } else { NDINIT(&nd, LOOKUP, FOLLOW, (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), - vniop->vn_file, &context); + vniop->vn_file, ctx); } error = vn_open(&nd, flags, 0); if (error) { - kauth_cred_unref(&context.vc_ucred); return (error); } } @@ -1158,22 +1153,20 @@ vniocattach_file(struct vn_softc *vn, error = EINVAL; } else { - error = vnode_size(nd.ni_vp, &file_size, &context); + error = vnode_size(nd.ni_vp, &file_size, ctx); } if (error != 0) { - (void) vn_close(nd.ni_vp, flags, context.vc_ucred, p); + (void) vn_close(nd.ni_vp, flags, ctx); vnode_put(nd.ni_vp); - kauth_cred_unref(&context.vc_ucred); return (error); } cred = kauth_cred_proc_ref(p); nd.ni_vp->v_flag |= VNOCACHE_DATA; - error = setcred(nd.ni_vp, p, cred); + error = setcred(nd.ni_vp, cred); if (error) { - (void)vn_close(nd.ni_vp, flags, context.vc_ucred, p); + (void)vn_close(nd.ni_vp, flags, ctx); vnode_put(nd.ni_vp); kauth_cred_unref(&cred); - kauth_cred_unref(&context.vc_ucred); return(error); } vn->sc_secsize = DEV_BSIZE; @@ -1193,53 +1186,46 @@ vniocattach_file(struct vn_softc *vn, vn->sc_flags |= VNF_READONLY; /* lose the short-term reference */ vnode_put(nd.ni_vp); - kauth_cred_unref(&context.vc_ucred); return(0); } static int vniocattach_shadow(struct vn_softc *vn, struct user_vn_ioctl *vniop, - __unused int dev, int in_kernel, struct proc *p) + __unused int dev, int in_kernel, proc_t p) { - struct vfs_context context; + vfs_context_t ctx = vfs_context_current(); struct nameidata nd; int error, flags; shadow_map_t * map; off_t file_size; - context.vc_proc = p; - context.vc_ucred = kauth_cred_proc_ref(p); - flags = FREAD|FWRITE; if (in_kernel) { - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE32, vniop->vn_file, &context); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE32, vniop->vn_file, ctx); } else { NDINIT(&nd, LOOKUP, FOLLOW, (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), - vniop->vn_file, &context); + vniop->vn_file, ctx); } /* vn_open gives both long- and short-term references */ error = vn_open(&nd, flags, 0); if (error) { /* shadow MUST be writable! */ - kauth_cred_unref(&context.vc_ucred); return (error); } if (nd.ni_vp->v_type != VREG - || (error = vnode_size(nd.ni_vp, &file_size, &context))) { - (void)vn_close(nd.ni_vp, flags, context.vc_ucred, p); + || (error = vnode_size(nd.ni_vp, &file_size, ctx))) { + (void)vn_close(nd.ni_vp, flags, ctx); vnode_put(nd.ni_vp); - kauth_cred_unref(&context.vc_ucred); return (error ? error : EINVAL); } map = shadow_map_create(vn->sc_fsize, file_size, 0, vn->sc_secsize); if (map == NULL) { - (void)vn_close(nd.ni_vp, flags, context.vc_ucred, p); + (void)vn_close(nd.ni_vp, flags, ctx); vnode_put(nd.ni_vp); vn->sc_shadow_vp = NULL; - kauth_cred_unref(&context.vc_ucred); return (ENOMEM); } vn->sc_shadow_vp = nd.ni_vp; @@ -1250,7 +1236,6 @@ vniocattach_shadow(struct vn_softc *vn, struct user_vn_ioctl *vniop, /* lose the short-term reference */ vnode_put(nd.ni_vp); - kauth_cred_unref(&context.vc_ucred); return(0); } @@ -1267,7 +1252,7 @@ vndevice_root_image(char * path, char devname[], dev_t * dev_p) vn = vn_table + ROOT_IMAGE_UNIT; *dev_p = makedev(vndevice_bdev_major, ROOT_IMAGE_UNIT); - sprintf(devname, "vn%d", ROOT_IMAGE_UNIT); + snprintf(devname, 16, "vn%d", ROOT_IMAGE_UNIT); error = vniocattach_file(vn, &vnio, *dev_p, 1, current_proc()); return (error); } @@ -1279,7 +1264,7 @@ vndevice_root_image(char * path, char devname[], dev_t * dev_p) * if some other uid can write directly to the mapped file (NFS). */ static int -setcred(struct vnode * vp, struct proc * p, kauth_cred_t cred) +setcred(struct vnode * vp, kauth_cred_t cred) { char *tmpbuf; int error = 0; @@ -1288,7 +1273,7 @@ setcred(struct vnode * vp, struct proc * p, kauth_cred_t cred) /* * Horrible kludge to establish credentials for NFS XXX. */ - context.vc_proc = p; + context.vc_thread = current_thread(); context.vc_ucred = cred; tmpbuf = _MALLOC(DEV_BSIZE, M_TEMP, M_WAITOK); error = file_io(vp, &context, UIO_READ, tmpbuf, 0, DEV_BSIZE, NULL); @@ -1297,17 +1282,16 @@ setcred(struct vnode * vp, struct proc * p, kauth_cred_t cred) } void -vnclear(struct vn_softc *vn, struct proc * p) +vnclear(struct vn_softc *vn, vfs_context_t ctx) { if (vn->sc_vp != NULL) { /* release long-term reference */ - (void)vn_close(vn->sc_vp, vn->sc_open_flags, vn->sc_cred, p); + (void)vn_close(vn->sc_vp, vn->sc_open_flags, ctx); vn->sc_vp = NULL; } if (vn->sc_shadow_vp != NULL) { /* release long-term reference */ - (void)vn_close(vn->sc_shadow_vp, FREAD | FWRITE, - vn->sc_cred, p); + (void)vn_close(vn->sc_shadow_vp, FREAD | FWRITE, ctx); vn->sc_shadow_vp = NULL; } if (vn->sc_shadow_map != NULL) { @@ -1356,10 +1340,17 @@ static int vndevice_inited = 0; void vndevice_init(void) { - int i; - if (vndevice_inited) return; + + vndevice_do_init(); +} + +static void +vndevice_do_init( void ) +{ + int i; + vndevice_bdev_major = bdevsw_add(BDEV_MAJOR, &vn_bdevsw); if (vndevice_bdev_major < 0) {