diff options
Diffstat (limited to 'module/zfs/zfs_ioctl.c')
-rw-r--r-- | module/zfs/zfs_ioctl.c | 31 |
1 files changed, 7 insertions, 24 deletions
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 51382e8b6..ba695ddbe 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -3410,37 +3410,20 @@ 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). * - * XXX: This function should detect a failure to unmount a snapdir of a dataset - * and return the appropriate error code when it is mounted. Its Illumos and - * FreeBSD counterparts do this. We do not do this on Linux because there is no - * clear way to access the mount information that FreeBSD and Illumos use to - * distinguish between things with mounted snapshot directories, and things - * without mounted snapshot directories, which include zvols. Returning a - * failure for the latter causes `zfs destroy` to fail on zvol snapshots. + * 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. */ int zfs_unmount_snap(const char *snapname) { - zfs_sb_t *zsb = NULL; - char *dsname; - char *fullname; - char *ptr; + int err; - if ((ptr = strchr(snapname, '@')) == NULL) + if (strchr(snapname, '@') == NULL) return (0); - dsname = kmem_alloc(ptr - snapname + 1, KM_SLEEP); - strlcpy(dsname, snapname, ptr - snapname + 1); - fullname = strdup(snapname); - - if (zfs_sb_hold(dsname, FTAG, &zsb, B_FALSE) == 0) { - ASSERT(!dsl_pool_config_held(dmu_objset_pool(zsb->z_os))); - (void) zfsctl_unmount_snapshot(zsb, fullname, MNT_FORCE); - zfs_sb_rele(zsb, FTAG); - } - - kmem_free(dsname, ptr - snapname + 1); - strfree(fullname); + err = zfsctl_snapshot_unmount((char *)snapname, MNT_FORCE); + if (err != 0 && err != ENOENT) + return (SET_ERROR(err)); return (0); } |