summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2013-06-11 19:22:20 +0000
committerdelphij <delphij@FreeBSD.org>2013-06-11 19:22:20 +0000
commit72c35861484e95b3490dbdca4076835c0abca906 (patch)
treeb6a0a899c7a58d2c8ed31d06d4eb2a181f8029c4
parent051062c8add5c68ceb7d29cd80b68fd58b7099a8 (diff)
downloadFreeBSD-src-72c35861484e95b3490dbdca4076835c0abca906.zip
FreeBSD-src-72c35861484e95b3490dbdca4076835c0abca906.tar.gz
MFV r251622:
ZFS shouldn't ignore errors unmounting snapshots Illumos ZFS issues: 3744 zfs shouldn't ignore errors unmounting snapshots MFC after: 2 weeks
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c50
3 files changed, 33 insertions, 21 deletions
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 fa9d937..568bba3 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 b27f115..af2def2 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 88bf336..2411beb 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));
}
OpenPOWER on IntegriCloud