diff options
author | avg <avg@FreeBSD.org> | 2016-07-13 09:40:53 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2016-07-13 09:40:53 +0000 |
commit | 39571e4eceeef9408be5ff772014803a167f8f2c (patch) | |
tree | affec798a5afbd339c220feb4373cdf6b2a2480f | |
parent | 0f651ac9a72ba1b7cd7b5d4ce88dff602cf339bf (diff) | |
download | FreeBSD-src-39571e4eceeef9408be5ff772014803a167f8f2c.zip FreeBSD-src-39571e4eceeef9408be5ff772014803a167f8f2c.tar.gz |
MFC r299902,299938: mount_snapshot: consolidate all error handling
-rw-r--r-- | sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c | 38 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c | 1 |
2 files changed, 22 insertions, 17 deletions
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c index 03e8e5f..6af1e8b 100644 --- a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c +++ b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c @@ -121,34 +121,39 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath, struct ucred *cr; int error; + ASSERT_VOP_ELOCKED(*vpp, "mount_snapshot"); + + vp = *vpp; + *vpp = NULL; + error = 0; + /* * Be ultra-paranoid about making sure the type and fspath * variables will fit in our mp buffers, including the * terminating NUL. */ if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN) - return (ENAMETOOLONG); - - vfsp = vfs_byname_kld(fstype, td, &error); - if (vfsp == NULL) - return (ENODEV); - - vp = *vpp; - if (vp->v_type != VDIR) - return (ENOTDIR); + error = ENAMETOOLONG; + if (error == 0 && (vfsp = vfs_byname_kld(fstype, td, &error)) == NULL) + error = ENODEV; + if (error == 0 && vp->v_type != VDIR) + error = ENOTDIR; /* * We need vnode lock to protect v_mountedhere and vnode interlock * to protect v_iflag. */ - vn_lock(vp, LK_SHARED | LK_RETRY); - VI_LOCK(vp); - if ((vp->v_iflag & VI_MOUNT) != 0 || vp->v_mountedhere != NULL) { + if (error == 0) { + VI_LOCK(vp); + if ((vp->v_iflag & VI_MOUNT) == 0 && vp->v_mountedhere == NULL) + vp->v_iflag |= VI_MOUNT; + else + error = EBUSY; VI_UNLOCK(vp); - VOP_UNLOCK(vp, 0); - return (EBUSY); } - vp->v_iflag |= VI_MOUNT; - VI_UNLOCK(vp); + if (error != 0) { + vput(vp); + return (error); + } VOP_UNLOCK(vp, 0); /* @@ -198,7 +203,6 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath, vfs_unbusy(mp); vfs_freeopts(mp->mnt_optnew); vfs_mount_destroy(mp); - *vpp = NULL; return (error); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c index a51e453..1c20aee 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c @@ -1112,6 +1112,7 @@ domount: (void) snprintf(mountpoint, mountpoint_len, "%s/" ZFS_CTLDIR_NAME "/snapshot/%s", dvp->v_vfsp->mnt_stat.f_mntonname, nm); + VERIFY0(vn_lock(*vpp, LK_EXCLUSIVE)); err = mount_snapshot(curthread, vpp, "zfs", mountpoint, snapname, 0); kmem_free(mountpoint, mountpoint_len); if (err == 0) { |