summaryrefslogtreecommitdiffstats
path: root/sys/boot/zfs/zfsimpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/zfs/zfsimpl.c')
-rw-r--r--sys/boot/zfs/zfsimpl.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c
index c37d7a5..a770e01 100644
--- a/sys/boot/zfs/zfsimpl.c
+++ b/sys/boot/zfs/zfsimpl.c
@@ -49,6 +49,13 @@ struct zfsmount {
*/
static vdev_list_t zfs_vdevs;
+ /*
+ * List of ZFS features supported for read
+ */
+static const char *features_for_read[] = {
+ NULL
+};
+
/*
* List of all pools, chained through spa_link.
*/
@@ -198,6 +205,57 @@ nvlist_find(const unsigned char *nvlist, const char *name, int type,
return (EIO);
}
+static int
+nvlist_check_features_for_read(const unsigned char *nvlist)
+{
+ const unsigned char *p, *pair;
+ int junk;
+ int encoded_size, decoded_size;
+ int rc;
+
+ rc = 0;
+
+ p = nvlist;
+ xdr_int(&p, &junk);
+ xdr_int(&p, &junk);
+
+ pair = p;
+ xdr_int(&p, &encoded_size);
+ xdr_int(&p, &decoded_size);
+ while (encoded_size && decoded_size) {
+ int namelen, pairtype;
+ const char *pairname;
+ int i, found;
+
+ found = 0;
+
+ xdr_int(&p, &namelen);
+ pairname = (const char*) p;
+ p += roundup(namelen, 4);
+ xdr_int(&p, &pairtype);
+
+ for (i = 0; features_for_read[i] != NULL; i++) {
+ if (!memcmp(pairname, features_for_read[i], namelen)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ printf("ZFS: unsupported feature: %s\n", pairname);
+ rc = EIO;
+ }
+
+ p = pair + encoded_size;
+
+ pair = p;
+ xdr_int(&p, &encoded_size);
+ xdr_int(&p, &decoded_size);
+ }
+
+ return (rc);
+}
+
/*
* Return the next nvlist in an nvlist array.
*/
@@ -788,6 +846,7 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap)
uint64_t is_log;
const char *pool_name;
const unsigned char *vdevs;
+ const unsigned char *features;
int i, rc, is_newer;
char *upbuf;
const struct uberblock *up;
@@ -822,12 +881,18 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap)
return (EIO);
}
- if (val > SPA_VERSION) {
+ if (!SPA_VERSION_IS_SUPPORTED(val)) {
printf("ZFS: unsupported ZFS version %u (should be %u)\n",
(unsigned) val, (unsigned) SPA_VERSION);
return (EIO);
}
+ /* Check ZFS features for read */
+ rc = nvlist_find(nvlist, ZPOOL_CONFIG_FEATURES_FOR_READ,
+ DATA_TYPE_NVLIST, 0, &features);
+ if (nvlist_check_features_for_read(features) != 0)
+ return (EIO);
+
if (nvlist_find(nvlist,
ZPOOL_CONFIG_POOL_STATE,
DATA_TYPE_UINT64, 0, &val)) {
OpenPOWER on IntegriCloud