diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c index fa9d9370857b..568bba33b52e 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c @@ -433,7 +433,7 @@ dsl_dataset_user_release_tmp(dsl_pool_t *dp, uint64_t dsobj, const char *htag) dsl_dataset_name(ds, name); dsl_dataset_rele(ds, FTAG); dsl_pool_config_exit(dp, FTAG); - zfs_unmount_snap(name); + (void) zfs_unmount_snap(name); } else { dsl_pool_config_exit(dp, FTAG); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h index b27f11502812..af2def2da677 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h @@ -360,7 +360,7 @@ extern int zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr); extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr); extern int zfs_busy(void); -extern void zfs_unmount_snap(const char *); +extern int zfs_unmount_snap(const char *); extern void zfs_destroy_unmount_origin(const char *); /* diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 88bf3363d5cb..2411bebef034 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -3405,28 +3405,31 @@ zfs_ioc_log_history(const char *unused, nvlist_t *innvl, nvlist_t *outnvl) * * This function is best-effort. Callers must deal gracefully if it * remains mounted (or is remounted after this call). + * + * Returns 0 if the argument is not a snapshot, or it is not currently a + * filesystem, or we were able to unmount it. Returns error code otherwise. */ -void +int zfs_unmount_snap(const char *snapname) { vfs_t *vfsp; zfsvfs_t *zfsvfs; + int err; if (strchr(snapname, '@') == NULL) - return; + return (0); vfsp = zfs_get_vfs(snapname); if (vfsp == NULL) - return; + return (0); zfsvfs = vfsp->vfs_data; ASSERT(!dsl_pool_config_held(dmu_objset_pool(zfsvfs->z_os))); - if (vn_vfswlock(vfsp->vfs_vnodecovered) != 0) { - VFS_RELE(vfsp); - return; - } + err = vn_vfswlock(vfsp->vfs_vnodecovered); VFS_RELE(vfsp); + if (err != 0) + return (SET_ERROR(err)); /* * Always force the unmount for snapshots. @@ -3436,17 +3439,17 @@ zfs_unmount_snap(const char *snapname) (void) dounmount(vfsp, MS_FORCE, kcred); #else mtx_lock(&Giant); /* dounmount() */ - dounmount(vfsp, MS_FORCE, curthread); + (void) dounmount(vfsp, MS_FORCE, curthread); mtx_unlock(&Giant); /* dounmount() */ #endif + return (0); } /* ARGSUSED */ static int zfs_unmount_snap_cb(const char *snapname, void *arg) { - zfs_unmount_snap(snapname); - return (0); + return (zfs_unmount_snap(snapname)); } /* @@ -3469,7 +3472,7 @@ zfs_destroy_unmount_origin(const char *fsname) char originname[MAXNAMELEN]; dsl_dataset_name(ds->ds_prev, originname); dmu_objset_rele(os, FTAG); - zfs_unmount_snap(originname); + (void) zfs_unmount_snap(originname); } else { dmu_objset_rele(os, FTAG); } @@ -3487,7 +3490,7 @@ zfs_destroy_unmount_origin(const char *fsname) static int zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl) { - int poollen; + int error, poollen; nvlist_t *snaps; nvpair_t *pair; boolean_t defer; @@ -3508,7 +3511,9 @@ zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl) (name[poollen] != '/' && name[poollen] != '@')) return (SET_ERROR(EXDEV)); - zfs_unmount_snap(name); + error = zfs_unmount_snap(name); + if (error != 0) + return (error); (void) zvol_remove_minor(name); } @@ -3527,8 +3532,12 @@ static int zfs_ioc_destroy(zfs_cmd_t *zc) { int err; - if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) - zfs_unmount_snap(zc->zc_name); + + if (zc->zc_objset_type == DMU_OST_ZFS) { + err = zfs_unmount_snap(zc->zc_name); + if (err != 0) + return (err); + } if (strchr(zc->zc_name, '@')) err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy); @@ -3574,8 +3583,7 @@ recursive_unmount(const char *fsname, void *arg) char fullname[MAXNAMELEN]; (void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname); - zfs_unmount_snap(fullname); - return (0); + return (zfs_unmount_snap(fullname)); } /* @@ -5071,14 +5079,18 @@ static int zfs_ioc_release(const char *pool, nvlist_t *holds, nvlist_t *errlist) { nvpair_t *pair; + int err; /* * The release may cause the snapshot to be destroyed; make sure it * is not mounted. */ for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL; - pair = nvlist_next_nvpair(holds, pair)) - zfs_unmount_snap(nvpair_name(pair)); + pair = nvlist_next_nvpair(holds, pair)) { + err = zfs_unmount_snap(nvpair_name(pair)); + if (err != 0) + return (err); + } return (dsl_dataset_user_release(holds, errlist)); }