void 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, ctx); vn->sc_vp = NULL; } if (vn->sc_shadow_vp != NULL) { /* release long-term reference */ (void)vn_close(vn->sc_shadow_vp, FREAD | FWRITE, ctx); vn->sc_shadow_vp = NULL; } if (vn->sc_shadow_map != NULL) { shadow_map_free(vn->sc_shadow_map); vn->sc_shadow_map = NULL; } vn->sc_flags &= ~(VNF_INITED | VNF_READONLY); if (vn->sc_cred) { kauth_cred_unref(&vn->sc_cred); } vn->sc_size = 0; vn->sc_fsize = 0; if (vn->sc_cdev) { devfs_remove(vn->sc_cdev); vn->sc_cdev = NULL; } }
/* * Accounting system call. Written based on the specification and * previous implementation done by Mark Tinguely. */ int sys_acct(struct proc *p, void *v, register_t *retval) { struct sys_acct_args /* { syscallarg(const char *) path; } */ *uap = v; struct nameidata nd; int error; /* Make sure that the caller is root. */ if ((error = suser(p, 0)) != 0) return (error); /* * If accounting is to be started to a file, open that file for * writing and make sure it's 'normal'. */ if (SCARG(uap, path) != NULL) { NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = vn_open(&nd, FWRITE|O_APPEND, 0)) != 0) return (error); VOP_UNLOCK(nd.ni_vp, 0); if (nd.ni_vp->v_type != VREG) { vn_close(nd.ni_vp, FWRITE, p->p_ucred, p); return (EACCES); } } /* * If accounting was previously enabled, kill the old space-watcher, * close the file, and (if no new file was specified, leave). */ if (acctp != NULL || savacctp != NULL) { wakeup(&acct_proc); error = vn_close((acctp != NULL ? acctp : savacctp), FWRITE, p->p_ucred, p); acctp = savacctp = NULL; } if (SCARG(uap, path) == NULL) return (0); /* * Save the new accounting file vnode, and schedule the new * free space watcher. */ acctp = nd.ni_vp; if ((error = acct_start()) != 0) { acctp = NULL; (void)vn_close(nd.ni_vp, FWRITE, p->p_ucred, p); return (error); } return (0); }
static int vniocattach_shadow(struct vn_softc *vn, struct vn_ioctl_64 *vniop, __unused dev_t dev, int in_kernel, proc_t p) { vfs_context_t ctx = vfs_context_current(); struct nameidata nd; int error, flags; shadow_map_t * map; off_t file_size; flags = FREAD|FWRITE; if (in_kernel) { NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, UIO_SYSSPACE, vniop->vn_file, ctx); } else { NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), 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! */ return (error); } if (nd.ni_vp->v_type != VREG || (error = vnode_size(nd.ni_vp, &file_size, ctx))) { (void)vn_close(nd.ni_vp, flags, ctx); vnode_put(nd.ni_vp); 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, ctx); vnode_put(nd.ni_vp); vn->sc_shadow_vp = NULL; return (ENOMEM); } vn->sc_shadow_vp = nd.ni_vp; vn->sc_shadow_vid = vnode_vid(nd.ni_vp); vn->sc_shadow_vp->v_flag |= VNOCACHE_DATA; vn->sc_shadow_map = map; vn->sc_flags &= ~VNF_READONLY; /* we're now read/write */ /* lose the short-term reference */ vnode_put(nd.ni_vp); return(0); }
void vdsp_close(void *arg1) { struct vdsp_softc *sc = arg1; struct proc *p = curproc; sc->sc_seq_no = 0; if (sc->sc_vd) { free(sc->sc_vd, M_DEVBUF, 0); sc->sc_vd = NULL; } if (sc->sc_vd_ring != NULL) { free(sc->sc_vd_ring, M_DEVBUF, sc->sc_num_descriptors * sizeof(*sc->sc_vd_ring)); sc->sc_vd_ring = NULL; } if (sc->sc_label) { free(sc->sc_label, M_DEVBUF, 0); sc->sc_label = NULL; } if (sc->sc_vp) { vn_close(sc->sc_vp, FREAD | FWRITE, p->p_ucred, p); sc->sc_vp = NULL; } }
/* ARGSUSED */ static int cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l) { struct dk_softc *dksc = &cs->sc_dksc; if (!DK_ATTACHED(dksc)) return ENXIO; /* Delete all of our wedges. */ dkwedge_delall(&dksc->sc_dkdev); /* Kill off any queued buffers. */ dk_drain(dksc); bufq_free(dksc->sc_bufq); (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred); cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv); free(cs->sc_tpath, M_DEVBUF); free(cs->sc_data, M_DEVBUF); cs->sc_data_used = 0; dk_detach(dksc); disk_detach(&dksc->sc_dkdev); return 0; }
static void kobj_close_vfs(kobj_t ko) { VOP_UNLOCK(ko->ko_source); vn_close(ko->ko_source, FREAD, kauth_cred_get()); }
/* * Enable an EA using the passed filesystem, backing vnode, attribute name, * namespace, and proc. Will perform a VOP_OPEN() on the vp, so expects vp * to be locked when passed in. The vnode will be returned unlocked, * regardless of success/failure of the function. As a result, the caller * will always need to vrele(), but not vput(). */ static int ufs_extattr_enable_with_open(struct ufsmount *ump, struct vnode *vp, int attrnamespace, const char *attrname, struct thread *td) { int error; error = VOP_OPEN(vp, FREAD|FWRITE, td->td_ucred, td, NULL); if (error) { printf("ufs_extattr_enable_with_open.VOP_OPEN(): failed " "with %d\n", error); VOP_UNLOCK(vp, 0); return (error); } error = VOP_ADD_WRITECOUNT(vp, 1); if (error != 0) { VOP_CLOSE(vp, FREAD | FWRITE, td->td_ucred, td); VOP_UNLOCK(vp, 0); return (error); } CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d", __func__, vp, vp->v_writecount); vref(vp); VOP_UNLOCK(vp, 0); error = ufs_extattr_enable(ump, attrnamespace, attrname, vp, td); if (error != 0) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); return (error); }
static void alq_shutdown(struct alq *alq) { ALQ_LOCK(alq); /* Stop any new writers. */ alq->aq_flags |= AQ_SHUTDOWN; /* * If the ALQ isn't active but has unwritten data (possible if * the ALQ_NOACTIVATE flag has been used), explicitly activate the * ALQ here so that the pending data gets flushed by the ald_daemon. */ if (!(alq->aq_flags & AQ_ACTIVE) && HAS_PENDING_DATA(alq)) { alq->aq_flags |= AQ_ACTIVE; ALQ_UNLOCK(alq); ALD_LOCK(); ald_activate(alq); ALD_UNLOCK(); ALQ_LOCK(alq); } /* Drain IO */ while (alq->aq_flags & AQ_ACTIVE) { alq->aq_flags |= AQ_WANTED; msleep_spin(alq, &alq->aq_mtx, "aldclose", 0); } ALQ_UNLOCK(alq); vn_close(alq->aq_vp, FWRITE, alq->aq_cred, curthread); crfree(alq->aq_cred); }
/* * Enable an EA using the passed filesystem, backing vnode, attribute name, * namespace, and proc. Will perform a VOP_OPEN() on the vp, so expects vp * to be locked when passed in. The vnode will be returned unlocked, * regardless of success/failure of the function. As a result, the caller * will always need to vrele(), but not vput(). */ static int ufs_extattr_enable_with_open(struct myfs_ufsmount *ump, struct vnode *vp, int attrnamespace, const char *attrname, struct thread *td) { int error; error = VOP_OPEN(vp, FREAD|FWRITE, td->td_ucred, td, NULL); if (error) { printf("ufs_extattr_enable_with_open.VOP_OPEN(): failed " "with %d\n", error); VOP_UNLOCK(vp, 0); return (error); } vp->v_writecount++; vref(vp); VOP_UNLOCK(vp, 0); error = ufs_extattr_enable(ump, attrnamespace, attrname, vp, td); if (error != 0) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); return (error); }
/* * Disable extended attribute support on an FS. */ static int ufs_extattr_disable(struct ufsmount *ump, int attrnamespace, const char *attrname, struct thread *td) { struct ufs_extattr_list_entry *uele; int error = 0; if (!ufs_extattr_valid_attrname(attrnamespace, attrname)) return (EINVAL); uele = ufs_extattr_find_attr(ump, attrnamespace, attrname); if (!uele) return (ENOATTR); LIST_REMOVE(uele, uele_entries); vn_lock(uele->uele_backing_vnode, LK_SHARED | LK_RETRY); ASSERT_VOP_LOCKED(uele->uele_backing_vnode, "ufs_extattr_disable"); VOP_UNLOCK(uele->uele_backing_vnode, 0); error = vn_close(uele->uele_backing_vnode, FREAD|FWRITE, td->td_ucred, td); free(uele, M_UFS_EXTATTR); return (error); }
static int vfs_mountroot_readconf(struct thread *td, struct sbuf *sb) { static char buf[128]; struct nameidata nd; off_t ofs; ssize_t resid; int error, flags, len; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/.mount.conf", td); flags = FREAD; error = vn_open(&nd, &flags, 0, NULL); if (error) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); ofs = 0; len = sizeof(buf) - 1; while (1) { error = vn_rdwr(UIO_READ, nd.ni_vp, buf, len, ofs, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); if (error) break; if (resid == len) break; buf[len - resid] = 0; sbuf_printf(sb, "%s", buf); ofs += len - resid; } VOP_UNLOCK(nd.ni_vp, 0); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); return (error); }
int randomdev_write_file(const char *filename, void *buf, size_t length) { struct nameidata nd; struct thread* td = curthread; int error; ssize_t resid; int flags; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); flags = FWRITE | O_CREAT | O_TRUNC; error = vn_open(&nd, &flags, 0, NULL); if (error == 0) { NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_vp->v_type != VREG) error = ENOEXEC; else error = vn_rdwr(UIO_WRITE, nd.ni_vp, buf, length, 0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); VOP_UNLOCK(nd.ni_vp, 0); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); } return (error); }
/* * Lookup the provided name in the filesystem. If the file exists, * is a valid block device, and isn't being used by anyone else, * set *vpp to the file's vnode. */ int dk_lookup(struct pathbuf *pb, struct lwp *l, struct vnode **vpp) { struct nameidata nd; struct vnode *vp; int error; if (l == NULL) return ESRCH; /* Is ESRCH the best choice? */ NDINIT(&nd, LOOKUP, FOLLOW, pb); if ((error = vn_open(&nd, FREAD | FWRITE, 0)) != 0) { DPRINTF((DKDB_FOLLOW|DKDB_INIT), ("%s: vn_open error = %d\n", __func__, error)); return error; } vp = nd.ni_vp; if (vp->v_type != VBLK) { error = ENOTBLK; goto out; } /* Reopen as anonymous vnode to protect against forced unmount. */ if ((error = bdevvp(vp->v_rdev, vpp)) != 0) goto out; VOP_UNLOCK(vp); if ((error = vn_close(vp, FREAD | FWRITE, l->l_cred)) != 0) { vrele(*vpp); return error; } if ((error = VOP_OPEN(*vpp, FREAD | FWRITE, l->l_cred)) != 0) { vrele(*vpp); return error; } mutex_enter((*vpp)->v_interlock); (*vpp)->v_writecount++; mutex_exit((*vpp)->v_interlock); IFDEBUG(DKDB_VNODE, vprint("dk_lookup: vnode info", *vpp)); return 0; out: VOP_UNLOCK(vp); (void) vn_close(vp, FREAD | FWRITE, l->l_cred); return error; }
void kobj_close_file(struct _buf *file) { if (file->mounted) vn_close(file->ptr, FREAD, curthread->td_ucred, curthread); kmem_free(file, sizeof(*file)); }
/* * Lookup the provided name in the filesystem. If the file exists, * is a valid block device, and isn't being used by anyone else, * set *vpp to the file's vnode. */ int ccdlookup(char *path, struct proc *p, struct vnode **vpp) { struct nameidata nd; struct vnode *vp; struct vattr va; int error; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p); if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) { CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, ("ccdlookup: vn_open error = %d\n", error)); return (error); } vp = nd.ni_vp; if (vp->v_usecount > 1) { VOP_UNLOCK(vp, 0, p); (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); return (EBUSY); } if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) { CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, ("ccdlookup: getattr error = %d\n", error)); VOP_UNLOCK(vp, 0, p); (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); return (error); } /* XXX: eventually we should handle VREG, too. */ if (va.va_type != VBLK) { VOP_UNLOCK(vp, 0, p); (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); return (ENOTBLK); } #ifdef DIAGNOSTIC CCD_DCALL(CCDB_VNODE, vprint("ccdlookup: vnode info", vp)); #endif VOP_UNLOCK(vp, 0, p); *vpp = vp; return (0); }
/* * MPSAFE */ static int vn_closefile(struct file *fp) { int error; fp->f_ops = &badfileops; error = vn_close(((struct vnode *)fp->f_data), fp->f_flag); return (error); }
void vdsp_close(void *arg1, void *arg2) { struct vdsp_softc *sc = arg1; struct proc *p = curproc; if (sc->sc_vp) { vn_close(sc->sc_vp, FREAD | FWRITE, p->p_ucred, p); sc->sc_vp = NULL; } }
static int devfs_fo_close(struct file *fp) { struct vnode *vp = (struct vnode *)fp->f_data; int error; fp->f_ops = &badfileops; error = vn_close(vp, fp->f_flag, fp); devfs_clear_cdevpriv(fp); return (error); }
static void swap_file_close(struct chip_swap *swap) { if (swap == NULL) return; if (swap->swap_vp == NULL) return; vn_close(swap->swap_vp, FWRITE, swap->swap_cred, curthread); crfree(swap->swap_cred); }
void kobj_close_file(struct _buf *file) { if (file->mounted) { struct vnode *vp = file->ptr; struct thread *td = curthread; int vfslocked; vfslocked = VFS_LOCK_GIANT(vp->v_mount); vn_close(vp, FREAD, td->td_ucred, td); VFS_UNLOCK_GIANT(vfslocked); } kmem_free(file, sizeof(*file)); }
char * linker_search_path(const char *name) { struct nameidata nd; struct proc *p = curproc; /* XXX */ char *cp, *ep, *result; int error; enum vtype type; /* qualified at all? */ if (index(name, '/')) return(linker_strdup(name)); /* traverse the linker path */ cp = linker_path; for (;;) { /* find the end of this component */ for (ep = cp; (*ep != 0) && (*ep != ';'); ep++) ; result = malloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK); if (result == NULL) /* actually ENOMEM */ return(NULL); strncpy(result, cp, ep - cp); strcpy(result + (ep - cp), name); /* * Attempt to open the file, and return the path if we succeed and it's * a regular file. */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, p); error = vn_open(&nd, FREAD, 0); if (error == 0) { type = nd.ni_vp->v_type; VOP_UNLOCK(nd.ni_vp, 0, p); vn_close(nd.ni_vp, FREAD, p->p_ucred, p); if (type == VREG) return(result); } free(result, M_LINKER); if (*ep == 0) break; cp = ep + 1; } return(NULL); }
/* * File table vnode close routine. */ int vn_closefile(struct file *fp, struct proc *p) { struct vnode *vp = fp->f_data; struct flock lf; if ((fp->f_iflags & FIF_HASLOCK)) { lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; lf.l_type = F_UNLCK; (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); } return (vn_close(vp, fp->f_flag, fp->f_cred, p)); }
void vndclear(struct vnd_softc *sc) { struct vnode *vp = sc->sc_vp; struct proc *p = curproc; /* XXX */ DNPRINTF(VDB_FOLLOW, "vndclear(%p): vp %p\n", sc, vp); if (vp == NULL) panic("vndioctl: null vp"); (void) vn_close(vp, VNDRW(sc), sc->sc_cred, p); crfree(sc->sc_cred); sc->sc_flags = 0; sc->sc_vp = NULL; sc->sc_cred = NULL; sc->sc_size = 0; memset(sc->sc_file, 0, sizeof(sc->sc_file)); }
static void alq_shutdown(struct alq *alq) { ALQ_LOCK(alq); /* Stop any new writers. */ alq->aq_flags |= AQ_SHUTDOWN; /* Drain IO */ while (alq->aq_flags & (AQ_FLUSHING|AQ_ACTIVE)) { alq->aq_flags |= AQ_WANTED; msleep_spin(alq, &alq->aq_mtx, "aldclose", 0); } ALQ_UNLOCK(alq); vn_close(alq->aq_vp, FWRITE, alq->aq_cred, curthread); crfree(alq->aq_cred); }
/* * Cleanup a nlookupdata structure after we are through with it. This may * be called on any nlookupdata structure initialized with nlookup_init(). * Calling nlookup_done() is mandatory in all cases except where nlookup_init() * returns an error, even if as a consumer you believe you have taken all * dynamic elements out of the nlookupdata structure. */ void nlookup_done(struct nlookupdata *nd) { if (nd->nl_nch.ncp) { if (nd->nl_flags & NLC_NCPISLOCKED) { nd->nl_flags &= ~NLC_NCPISLOCKED; cache_unlock(&nd->nl_nch); } if (nd->nl_flags & NLC_NCDIR) { cache_drop_ncdir(&nd->nl_nch); nd->nl_flags &= ~NLC_NCDIR; } else { cache_drop(&nd->nl_nch); /* NULL's out the nch */ } } if (nd->nl_rootnch.ncp) cache_drop_and_cache(&nd->nl_rootnch); if (nd->nl_jailnch.ncp) cache_drop_and_cache(&nd->nl_jailnch); if ((nd->nl_flags & NLC_HASBUF) && nd->nl_path) { objcache_put(namei_oc, nd->nl_path); nd->nl_path = NULL; } if (nd->nl_cred) { if ((nd->nl_flags & NLC_BORROWCRED) == 0) crfree(nd->nl_cred); nd->nl_cred = NULL; nd->nl_flags &= ~NLC_BORROWCRED; } if (nd->nl_open_vp) { if (nd->nl_flags & NLC_LOCKVP) { vn_unlock(nd->nl_open_vp); nd->nl_flags &= ~NLC_LOCKVP; } vn_close(nd->nl_open_vp, nd->nl_vp_fmode, NULL); nd->nl_open_vp = NULL; } if (nd->nl_dvp) { vrele(nd->nl_dvp); nd->nl_dvp = NULL; } nd->nl_flags = 0; /* clear remaining flags (just clear everything) */ }
/* * Lookup the provided name in the filesystem. If the file exists, * is a valid block device, and isn't being used by anyone else, * set *vpp to the file's vnode. */ int dk_lookup(const char *path, struct lwp *l, struct vnode **vpp, enum uio_seg segflg) { struct nameidata nd; struct vnode *vp; struct vattr va; int error; if (l == NULL) return ESRCH; /* Is ESRCH the best choice? */ NDINIT(&nd, LOOKUP, FOLLOW, segflg, path); if ((error = vn_open(&nd, FREAD | FWRITE, 0)) != 0) { DPRINTF((DKDB_FOLLOW|DKDB_INIT), ("dk_lookup: vn_open error = %d\n", error)); return error; } vp = nd.ni_vp; if ((error = VOP_GETATTR(vp, &va, l->l_cred)) != 0) { DPRINTF((DKDB_FOLLOW|DKDB_INIT), ("dk_lookup: getattr error = %d\n", error)); goto out; } /* XXX: eventually we should handle VREG, too. */ if (va.va_type != VBLK) { error = ENOTBLK; goto out; } IFDEBUG(DKDB_VNODE, vprint("dk_lookup: vnode info", vp)); VOP_UNLOCK(vp, 0); *vpp = vp; return 0; out: VOP_UNLOCK(vp, 0); (void) vn_close(vp, FREAD | FWRITE, l->l_cred); return error; }
/* * Enable an EA using the passed file system, backing vnode, attribute name, * namespace, and proc. Will perform a VOP_OPEN() on the vp, so expects vp * to be locked when passed in. The vnode will be returned unlocked, * regardless of success/failure of the function. As a result, the caller * will always need to vrele(), but not vput(). */ static int ufs_extattr_enable_with_open(struct ufsmount *ump, struct vnode *vp, int attrnamespace, const char *attrname, struct proc *p) { int error; error = VOP_OPEN(vp, FREAD|FWRITE, p->p_ucred, p); if (error) { printf("ufs_extattr_enable_with_open.VOP_OPEN(): failed " "with %d\n", error); VOP_UNLOCK(vp, 0, p); return (error); } #if 0 /* - XXX */ /* * XXX: Note, should VOP_CLOSE() if vfs_object_create() fails, but due * to a similar piece of code in vn_open(), we don't. */ if (vn_canvmio(vp) == TRUE) if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0) { /* * XXX: bug replicated from vn_open(): should * VOP_CLOSE() here. */ VOP_UNLOCK(vp, 0, p); return (error); } #endif vp->v_writecount++; vref(vp); VOP_UNLOCK(vp, 0, p); error = ufs_extattr_enable(ump, attrnamespace, attrname, vp, p); if (error != 0) vn_close(vp, FREAD|FWRITE, p->p_ucred, p); return (error); }
/* * kobj_close: * * Close an open ELF object. */ static void kobj_close(kobj_t ko) { if (ko->ko_source == NULL) { return; } switch (ko->ko_type) { case KT_VNODE: VOP_UNLOCK(ko->ko_source, 0); vn_close(ko->ko_source, FREAD, kauth_cred_get()); break; case KT_MEMORY: /* nothing */ break; default: panic("kobj_close: unknown type"); break; } ko->ko_source = NULL; }
/* * Disable extended attribute support on an FS. */ static int ufs_extattr_disable(struct ufsmount *ump, int attrnamespace, const char *attrname, struct proc *p) { struct ufs_extattr_list_entry *uele; int error = 0; if (!ufs_extattr_valid_attrname(attrnamespace, attrname)) return (EINVAL); uele = ufs_extattr_find_attr(ump, attrnamespace, attrname); if (!uele) return (ENOENT); LIST_REMOVE(uele, uele_entries); uele->uele_backing_vnode->v_flag &= ~VSYSTEM; error = vn_close(uele->uele_backing_vnode, FREAD|FWRITE, p->p_ucred, p); FREE(uele, M_UFS_EXTATTR); return (error); }
/* * Delete a snapshot. */ static int fss_delete_snapshot(struct fss_softc *sc, struct lwp *l) { if ((sc->sc_flags & FSS_PERSISTENT) == 0) fscow_disestablish(sc->sc_mount, fss_copy_on_write, sc); mutex_enter(&sc->sc_slock); sc->sc_flags &= ~(FSS_ACTIVE|FSS_ERROR); sc->sc_mount = NULL; sc->sc_bdev = NODEV; mutex_exit(&sc->sc_slock); fss_softc_free(sc); if (sc->sc_flags & FSS_PERSISTENT) vrele(sc->sc_bs_vp); else vn_close(sc->sc_bs_vp, FREAD|FWRITE, l->l_cred); sc->sc_bs_vp = NULL; sc->sc_flags &= ~FSS_PERSISTENT; return 0; }