6940770 panic in sa_find_idx_tab() after receiving into pool when version shouldn't have allowed it
--- a/usr/src/lib/libzfs/common/libzfs_mount.c Sat Apr 03 14:24:23 2010 -0400
+++ b/usr/src/lib/libzfs/common/libzfs_mount.c Sun Apr 04 17:04:46 2010 -0600
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -316,13 +315,15 @@
"Insufficient privileges"));
} else if (errno == ENOTSUP) {
char buf[256];
+ int spa_version;
+ VERIFY(zfs_spa_version(zhp, &spa_version) == 0);
(void) snprintf(buf, sizeof (buf),
- dgettext(TEXT_DOMAIN, "Mismatched versions: File "
- "system is version %llu on-disk format, which is "
- "incompatible with this software version %lld!"),
+ dgettext(TEXT_DOMAIN, "Can't mount a version %lld "
+ "file system on a version %d pool. Pool must be"
+ " upgraded to mount this file system."),
(u_longlong_t)zfs_prop_get_int(zhp,
- ZFS_PROP_VERSION), ZPL_VERSION);
+ ZFS_PROP_VERSION), spa_version);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, buf));
} else {
zfs_error_aux(hdl, strerror(errno));
--- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c Sat Apr 03 14:24:23 2010 -0400
+++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c Sun Apr 04 17:04:46 2010 -0600
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <assert.h>
@@ -2683,6 +2682,11 @@
"invalid stream (checksum mismatch)"));
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
+ case ENOTSUP:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "pool must be upgraded to receive this stream."));
+ (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
+ break;
default:
(void) zfs_standard_error(hdl, ioctl_errno, errbuf);
}
--- a/usr/src/uts/common/fs/zfs/dmu_send.c Sat Apr 03 14:24:23 2010 -0400
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c Sun Apr 04 17:04:46 2010 -0600
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/dmu.h>
@@ -39,6 +38,7 @@
#include <sys/zfs_ioctl.h>
#include <sys/zap.h>
#include <sys/zio_checksum.h>
+#include <sys/zfs_znode.h>
#include <sys/avl.h>
#include <sys/ddt.h>
@@ -419,6 +419,20 @@
drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
DMU_SET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo,
DMU_SUBSTREAM);
+
+#ifdef _KERNEL
+ if (dmu_objset_type(tosnap) == DMU_OST_ZFS) {
+ uint64_t version;
+ if (zfs_get_zplprop(tosnap, ZFS_PROP_VERSION, &version) != 0)
+ return (EINVAL);
+ if (version == ZPL_VERSION_SA) {
+ DMU_SET_FEATUREFLAGS(
+ drr->drr_u.drr_begin.drr_versioninfo,
+ DMU_BACKUP_FEATURE_SA_SPILL);
+ }
+ }
+#endif
+
drr->drr_u.drr_begin.drr_creation_time =
ds->ds_phys->ds_creation_time;
drr->drr_u.drr_begin.drr_type = tosnap->os_phys->os_type;
@@ -645,6 +659,19 @@
dp->dp_spa, tx, cr, "dataset = %lld", dsobj);
}
+
+static boolean_t
+dmu_recv_verify_features(dsl_dataset_t *ds, struct drr_begin *drrb)
+{
+ int featureflags;
+
+ featureflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
+
+ /* Verify pool version supports SA if SA_SPILL feature set */
+ return ((featureflags & DMU_BACKUP_FEATURE_SA_SPILL) &&
+ (spa_version(dsl_dataset_get_spa(ds)) < SPA_VERSION_SA));
+}
+
/*
* NB: callers *MUST* call dmu_recv_stream() if dmu_recv_begin()
* succeeds; otherwise we will leak the holds on the datasets.
@@ -705,6 +732,10 @@
/* open the dataset we are logically receiving into */
err = dsl_dataset_hold(tofs, dmu_recv_tag, &ds);
if (err == 0) {
+ if (dmu_recv_verify_features(ds, drrb)) {
+ dsl_dataset_rele(ds, dmu_recv_tag);
+ return (ENOTSUP);
+ }
/* target fs already exists; recv into temp clone */
/* Can't recv a clone into an existing fs */
@@ -751,6 +782,11 @@
if (err)
return (err);
+ if (dmu_recv_verify_features(ds, drrb)) {
+ dsl_dataset_rele(ds, dmu_recv_tag);
+ return (ENOTSUP);
+ }
+
err = dsl_sync_task_do(ds->ds_dir->dd_pool,
recv_new_check, recv_new_sync, ds->ds_dir, &rbsa, 5);
dsl_dataset_rele(ds, FTAG);
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c Sat Apr 03 14:24:23 2010 -0400
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c Sun Apr 04 17:04:46 2010 -0600
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -862,7 +861,6 @@
return (zfs_fuid_overquota(zfsvfs, isgroup, fuid));
}
-
int
zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
{
@@ -898,15 +896,15 @@
error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version);
if (error) {
goto out;
- } else if (zfsvfs->z_version > ZPL_VERSION) {
- (void) printf("Mismatched versions: File system "
- "is version %llu on-disk format, which is "
- "incompatible with this software version %lld!",
- (u_longlong_t)zfsvfs->z_version, ZPL_VERSION);
+ } else if (zfsvfs->z_version >
+ zfs_zpl_version_map(spa_version(dmu_objset_spa(os)))) {
+ (void) printf("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)zfsvfs->z_version,
+ (u_longlong_t)spa_version(dmu_objset_spa(os)));
error = ENOTSUP;
goto out;
}
-
if ((error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &zval)) != 0)
goto out;
zfsvfs->z_norm = (int)zval;