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 <behlendorf1@llnl.gov>
Signed-off-by: Dan Swartzendruber <dswartz@druber.com>
Closes: #2616
This commit is contained in:
Dan Swartzendruber 2014-08-29 15:12:21 -04:00 committed by Brian Behlendorf
parent bcd9624d0f
commit 287be44f53
3 changed files with 75 additions and 21 deletions

View File

@ -363,6 +363,7 @@ main(int argc, char **argv)
{ {
zfs_handle_t *zhp; zfs_handle_t *zhp;
char prop[ZFS_MAXPROPLEN]; char prop[ZFS_MAXPROPLEN];
uint64_t zfs_version = 0;
char mntopts[MNT_LINE_MAX] = { '\0' }; char mntopts[MNT_LINE_MAX] = { '\0' };
char badopt[MNT_LINE_MAX] = { '\0' }; char badopt[MNT_LINE_MAX] = { '\0' };
char mtabopt[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, (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop,
sizeof (prop), NULL, NULL, 0, B_FALSE); 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); zfs_close(zhp);
libzfs_fini(g_zfs); libzfs_fini(g_zfs);
@ -551,6 +564,8 @@ main(int argc, char **argv)
if (!fake) { if (!fake) {
error = mount(dataset, mntpoint, MNTTYPE_ZFS, error = mount(dataset, mntpoint, MNTTYPE_ZFS,
mntflags, mntopts); mntflags, mntopts);
}
if (error) { if (error) {
switch (errno) { switch (errno) {
case ENOENT: case ENOENT:
@ -561,6 +576,19 @@ main(int argc, char **argv)
(void) fprintf(stderr, gettext("filesystem " (void) fprintf(stderr, gettext("filesystem "
"'%s' is already mounted\n"), dataset); "'%s' is already mounted\n"), dataset);
return (MOUNT_BUSY); 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: default:
(void) fprintf(stderr, gettext("filesystem " (void) fprintf(stderr, gettext("filesystem "
"'%s' can not be mounted due to error " "'%s' can not be mounted due to error "
@ -568,7 +596,6 @@ main(int argc, char **argv)
return (MOUNT_USAGE); return (MOUNT_USAGE);
} }
} }
}
if (!nomtab && mtab_is_writeable()) { if (!nomtab && mtab_is_writeable()) {
error = mtab_update(dataset, mntpoint, MNTTYPE_ZFS, mtabopt); error = mtab_update(dataset, mntpoint, MNTTYPE_ZFS, mtabopt);

View File

@ -4601,12 +4601,33 @@ typedef struct upgrade_cbdata {
char **cb_argv; char **cb_argv;
} upgrade_cbdata_t; } 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 static int
upgrade_version(zpool_handle_t *zhp, uint64_t version) upgrade_version(zpool_handle_t *zhp, uint64_t version)
{ {
int ret; int ret;
nvlist_t *config; nvlist_t *config;
uint64_t oldversion; uint64_t oldversion;
int unsupp_fs = 0;
config = zpool_get_config(zhp, NULL); config = zpool_get_config(zhp, NULL);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 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(SPA_VERSION_IS_SUPPORTED(oldversion));
assert(oldversion < version); 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); ret = zpool_upgrade(zhp, version);
if (ret != 0) if (ret != 0)
return (ret); return (ret);

View File

@ -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); error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zsb->z_version);
if (error) { if (error) {
goto out; goto out;
} else if (zsb->z_version > } else if (zsb->z_version > ZPL_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)));
error = SET_ERROR(ENOTSUP); error = SET_ERROR(ENOTSUP);
goto out; goto out;
} }