summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Swartzendruber <[email protected]>2014-08-29 15:12:21 -0400
committerBrian Behlendorf <[email protected]>2014-09-03 09:17:14 -0700
commit287be44f536e27d377518badd2bd8e2758db2be6 (patch)
tree70d096920cf17ad445e0e08cf687b6adcdc51942
parentbcd9624d0f941bebf732f61bcb7bdbd223b0d396 (diff)
Improve handling of filesystem versions
Change mount code to diagnose filesystem versions that are not supported by the current implementation. Change upgrade code to do likewise and refuse to upgrade a pool if any filesystems on it are a version which is not supported by the current implementation. Signed-off-by: Brian Behlendorf <[email protected]> Signed-off-by: Dan Swartzendruber <[email protected]> Closes: #2616
-rw-r--r--cmd/mount_zfs/mount_zfs.c57
-rw-r--r--cmd/zpool/zpool_main.c32
-rw-r--r--module/zfs/zfs_vfsops.c7
3 files changed, 75 insertions, 21 deletions
diff --git a/cmd/mount_zfs/mount_zfs.c b/cmd/mount_zfs/mount_zfs.c
index 6cb23d1c6..b168f719a 100644
--- a/cmd/mount_zfs/mount_zfs.c
+++ b/cmd/mount_zfs/mount_zfs.c
@@ -363,6 +363,7 @@ main(int argc, char **argv)
{
zfs_handle_t *zhp;
char prop[ZFS_MAXPROPLEN];
+ uint64_t zfs_version = 0;
char mntopts[MNT_LINE_MAX] = { '\0' };
char badopt[MNT_LINE_MAX] = { '\0' };
char mtabopt[MNT_LINE_MAX] = { '\0' };
@@ -515,6 +516,18 @@ main(int argc, char **argv)
(void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop,
sizeof (prop), NULL, NULL, 0, B_FALSE);
+ /*
+ * Fetch the max supported zfs version in case we get ENOTSUP
+ * back from the mount command, since we need the zfs handle
+ * to do so.
+ */
+ zfs_version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
+ if (zfs_version == 0) {
+ fprintf(stderr, gettext("unable to fetch "
+ "ZFS version for filesystem '%s'\n"), dataset);
+ return (MOUNT_SYSERR);
+ }
+
zfs_close(zhp);
libzfs_fini(g_zfs);
@@ -551,22 +564,36 @@ main(int argc, char **argv)
if (!fake) {
error = mount(dataset, mntpoint, MNTTYPE_ZFS,
mntflags, mntopts);
- if (error) {
- switch (errno) {
- case ENOENT:
- (void) fprintf(stderr, gettext("mount point "
- "'%s' does not exist\n"), mntpoint);
- return (MOUNT_SYSERR);
- case EBUSY:
- (void) fprintf(stderr, gettext("filesystem "
- "'%s' is already mounted\n"), dataset);
- return (MOUNT_BUSY);
- default:
- (void) fprintf(stderr, gettext("filesystem "
- "'%s' can not be mounted due to error "
- "%d\n"), dataset, errno);
- return (MOUNT_USAGE);
+ }
+
+ if (error) {
+ switch (errno) {
+ case ENOENT:
+ (void) fprintf(stderr, gettext("mount point "
+ "'%s' does not exist\n"), mntpoint);
+ return (MOUNT_SYSERR);
+ case EBUSY:
+ (void) fprintf(stderr, gettext("filesystem "
+ "'%s' is already mounted\n"), dataset);
+ return (MOUNT_BUSY);
+ case ENOTSUP:
+ if (zfs_version > ZPL_VERSION) {
+ (void) fprintf(stderr,
+ gettext("filesystem '%s' (v%d) is not "
+ "supported by this implementation of "
+ "ZFS (max v%d).\n"), dataset,
+ (int) zfs_version, (int) ZPL_VERSION);
+ } else {
+ (void) fprintf(stderr,
+ gettext("filesystem '%s' mount "
+ "failed for unknown reason.\n"), dataset);
}
+ return (MOUNT_SYSERR);
+ default:
+ (void) fprintf(stderr, gettext("filesystem "
+ "'%s' can not be mounted due to error "
+ "%d\n"), dataset, errno);
+ return (MOUNT_USAGE);
}
}
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c
index 952645ea5..1086f9555 100644
--- a/cmd/zpool/zpool_main.c
+++ b/cmd/zpool/zpool_main.c
@@ -4602,11 +4602,32 @@ typedef struct upgrade_cbdata {
} upgrade_cbdata_t;
static int
+check_unsupp_fs(zfs_handle_t *zhp, void *unsupp_fs)
+{
+ int zfs_version = (int) zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
+ int *count = (int *)unsupp_fs;
+
+ if (zfs_version > ZPL_VERSION) {
+ (void) printf(gettext("%s (v%d) is not supported by this "
+ "implementation of ZFS.\n"),
+ zfs_get_name(zhp), zfs_version);
+ (*count)++;
+ }
+
+ zfs_iter_filesystems(zhp, check_unsupp_fs, unsupp_fs);
+
+ zfs_close(zhp);
+
+ return (0);
+}
+
+static int
upgrade_version(zpool_handle_t *zhp, uint64_t version)
{
int ret;
nvlist_t *config;
uint64_t oldversion;
+ int unsupp_fs = 0;
config = zpool_get_config(zhp, NULL);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
@@ -4615,6 +4636,17 @@ upgrade_version(zpool_handle_t *zhp, uint64_t version)
assert(SPA_VERSION_IS_SUPPORTED(oldversion));
assert(oldversion < version);
+ ret = zfs_iter_root(zpool_get_handle(zhp), check_unsupp_fs, &unsupp_fs);
+ if (ret != 0)
+ return (ret);
+
+ if (unsupp_fs) {
+ (void) printf(gettext("Upgrade not performed due to %d "
+ "unsupported filesystems (max v%d).\n"),
+ unsupp_fs, (int) ZPL_VERSION);
+ return (1);
+ }
+
ret = zpool_upgrade(zhp, version);
if (ret != 0)
return (ret);
diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c
index a27ac694d..eea78417a 100644
--- a/module/zfs/zfs_vfsops.c
+++ b/module/zfs/zfs_vfsops.c
@@ -679,12 +679,7 @@ zfs_sb_create(const char *osname, zfs_sb_t **zsbp)
error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zsb->z_version);
if (error) {
goto out;
- } else if (zsb->z_version >
- zfs_zpl_version_map(spa_version(dmu_objset_spa(os)))) {
- (void) printk("Can't mount a version %lld file system "
- "on a version %lld pool\n. Pool must be upgraded to mount "
- "this file system.", (u_longlong_t)zsb->z_version,
- (u_longlong_t)spa_version(dmu_objset_spa(os)));
+ } else if (zsb->z_version > ZPL_VERSION) {
error = SET_ERROR(ENOTSUP);
goto out;
}