diff options
-rw-r--r-- | usr/src/uts/common/fs/zfs/dsl_userhold.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_ioctl.c | 48 |
3 files changed, 32 insertions, 20 deletions
diff --git a/usr/src/uts/common/fs/zfs/dsl_userhold.c b/usr/src/uts/common/fs/zfs/dsl_userhold.c index fa9d937085..568bba33b5 100644 --- a/usr/src/uts/common/fs/zfs/dsl_userhold.c +++ b/usr/src/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/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h index 874d422568..9422177023 100644 --- a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h +++ b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h @@ -344,7 +344,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/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c index 33990c243d..e2abe5f942 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c @@ -3356,41 +3356,44 @@ 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. */ (void) dounmount(vfsp, MS_FORCE, kcred); + 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)); } /* @@ -3413,7 +3416,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); } @@ -3431,7 +3434,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; @@ -3452,7 +3455,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); } return (dsl_destroy_snapshots_nvl(snaps, defer, outnvl)); @@ -3470,8 +3475,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); @@ -3517,8 +3526,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)); } /* @@ -4977,14 +4985,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)); } |