[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/5] Check for feature flags needed to read from the pool.
From: |
Massimo Maggi |
Subject: |
[PATCH 4/5] Check for feature flags needed to read from the pool. |
Date: |
Mon, 04 Feb 2013 12:09:49 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130128 Thunderbird/17.0.2 |
Ported to GRUB2 from IllumOS changeset 13700 2889e2596bd6
Author: Christopher Siden <address@hidden>
Ported-by: Massimo Maggi <address@hidden>
---
grub-core/fs/zfs/zfs.c | 102
++++++++++++++++++++++++++++++++++++++++++++++++-
include/grub/zfs/dmu.h | 46 +++++++++++++++++++++-
include/grub/zfs/zfs.h | 1 +
3 files changed, 146 insertions(+), 3 deletions(-)
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index 7f76445..cf10534 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -272,6 +272,19 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key)
(const struct grub_zfs_key *key
grub_size_t keysize,
grub_uint64_t salt,
grub_uint64_t algo) = NULL;
+/*
+ * List of pool features that the grub implementation of ZFS supports for
+ * read. Note that features that are only required for write do not need
+ * to be listed here since grub opens pools in read-only mode.
+ */
+static const char *spa_feature_names[] = {
+ "max.test:feat1",NULL
+};
+
+static int
+check_feature(const char *name, grub_uint64_t val, struct
grub_zfs_dir_ctx *ctx);
+static int
+check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t
endian,struct grub_zfs_data* data );
static grub_err_t zlib_decompress (void *s, void *d,
@@ -927,7 +940,7 @@ check_pool_label (struct grub_zfs_data *data,
int *inserted)
{
grub_uint64_t pool_state, txg = 0;
- char *nvlist;
+ char *nvlist,*features;
#if 0
char *nv;
#endif
@@ -1047,7 +1060,30 @@ check_pool_label (struct grub_zfs_data *data,
grub_free (nv);
}
grub_dprintf ("zfs", "check 10 passed\n");
-
+ if ((features=grub_zfs_nvlist_lookup_nvlist(nvlist,
ZPOOL_CONFIG_FEATURES_FOR_READ)))
+ {
+ const char *nvp=NULL;
+ char *name = grub_zalloc(51);
+ char *nameptr;
+ int namelen;
+ while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL)
+ {
+ nvpair_name(nvp, &nameptr,&namelen);
+ if(namelen > 50){namelen=50;}
+ grub_strncpy(name,nameptr,namelen);
+ name[namelen]=0;
+ grub_dprintf("zfs","namelen=%u str=%s\n",namelen,name);
+ if (check_feature(name,1, NULL) != 0)
+ {
+ grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name);
+ err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label
missing feature '%s' for read",name);
+ grub_free(name);
+ return err;
+ }
+ }
+ grub_free(name);
+ }
+ grub_dprintf ("zfs", "check 12 passed (feature flags)\n");
grub_free (nvlist);
return GRUB_ERR_NONE;
@@ -3502,6 +3538,10 @@ zfs_mount (grub_device_t dev)
return NULL;
}
+ if (ub->ub_version >= SPA_VERSION_FEATURES &&
+ check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian,
data) != 0)
+ return NULL;
+
/* Got the MOS. Save it at the memory addr MOS. */
grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode,
DNODE_SIZE);
@@ -4042,6 +4082,64 @@ grub_zfs_dir (grub_device_t device, const char *path,
return grub_errno;
}
+static int
+check_feature(const char *name, grub_uint64_t
val,__attribute__((unused)) struct grub_zfs_dir_ctx *ctx)
+{
+ int i;
+ if(val ==0) return 0;
+ if(*name==0) return 0;
+ for (i = 0; spa_feature_names[i] != NULL; i++) + {
+ if (grub_strcmp(name, spa_feature_names[i]) == 0) + return 0;
+ }
+ grub_printf("missing feature for read '%s'\n",name);
+ return 1;
+}
+
+/*
+ * Checks whether the MOS features that are active are supported by this
+ * (GRUB's) implementation of ZFS.
+ *
+ * Return:
+ * 0: Success.
+ * errnum: Failure.
+ */
+ +static int
+check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t
endian,struct grub_zfs_data* data )
+{
+ grub_uint64_t objnum;
+ grub_uint8_t errnum = 0;
+ dnode_end_t dn,mosmdn;
+ mzap_phys_t* mzp;
+ grub_zfs_endian_t endianzap;
+ int size;
+ grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t));
+ mosmdn.endian=endian;
+ if ((errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT,
+ DMU_OT_OBJECT_DIRECTORY, &dn,data)) != 0)
+ return (errnum);
+
+ /*
+ * Find the object number for 'features_for_read' and retrieve its
+ * corresponding dnode. Note that we don't check features_for_write
+ * because GRUB is not opening the pool for write.
+ */
+ if ((errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum,
data,0)) != 0)
+ return (errnum);
+ + if ((errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA,
&dn, data)) != 0)
+ return (errnum);
+
+ if ((errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data)) != 0)
+ return (errnum);
+
+ size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) <<
SPA_MINBLOCKSHIFT;
+ return (mzap_iterate(mzp,endianzap, size, check_feature,NULL));
+}
+
+
#ifdef GRUB_UTIL
static grub_err_t
grub_zfs_embed (grub_device_t device __attribute__ ((unused)),
diff --git a/include/grub/zfs/dmu.h b/include/grub/zfs/dmu.h
index 8fc6dc5..4ad616c 100644
--- a/include/grub/zfs/dmu.h
+++ b/include/grub/zfs/dmu.h
@@ -22,6 +22,39 @@
#ifndef _SYS_DMU_H
#define _SYS_DMU_H
+#define B_FALSE 0
+#define B_TRUE 1
+
+#define DMU_OT_NEWTYPE 0x80
+#define DMU_OT_METADATA 0x40
+#define DMU_OT_BYTESWAP_MASK 0x3f
+
+#define DMU_OT(byteswap, metadata) \
+ (DMU_OT_NEWTYPE | \
+ ((metadata) ? DMU_OT_METADATA : 0) | \
+ ((byteswap) & DMU_OT_BYTESWAP_MASK))
+
+#define DMU_OT_IS_VALID(ot) (((ot) & DMU_OT_NEWTYPE) ? \
+ ((ot) & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS : \
+ (ot) < DMU_OT_NUMTYPES)
+
+#define DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \
+ ((ot) & DMU_OT_METADATA) : \
+ dmu_ot[(ot)].ot_metadata)
+
+typedef enum dmu_object_byteswap {
+ DMU_BSWAP_UINT8,
+ DMU_BSWAP_UINT16,
+ DMU_BSWAP_UINT32,
+ DMU_BSWAP_UINT64,
+ DMU_BSWAP_ZAP,
+ DMU_BSWAP_DNODE,
+ DMU_BSWAP_OBJSET,
+ DMU_BSWAP_ZNODE,
+ DMU_BSWAP_OLDACL,
+ DMU_BSWAP_ACL,
+ DMU_BSWAP_NUMFUNCS
+} dmu_object_byteswap_t;
/*
* This file describes the interface that the DMU provides for its
@@ -89,7 +122,17 @@ typedef enum dmu_object_type {
DMU_OT_SA_ATTR_REGISTRATION, /* ZAP */
DMU_OT_SA_ATTR_LAYOUTS, /* ZAP */
DMU_OT_DSL_KEYCHAIN = 54,
- DMU_OT_NUMTYPES
+ DMU_OT_NUMTYPES,
+ DMU_OTN_UINT8_DATA = DMU_OT(DMU_BSWAP_UINT8, B_FALSE),
+ DMU_OTN_UINT8_METADATA = DMU_OT(DMU_BSWAP_UINT8, B_TRUE),
+ DMU_OTN_UINT16_DATA = DMU_OT(DMU_BSWAP_UINT16, B_FALSE),
+ DMU_OTN_UINT16_METADATA = DMU_OT(DMU_BSWAP_UINT16, B_TRUE),
+ DMU_OTN_UINT32_DATA = DMU_OT(DMU_BSWAP_UINT32, B_FALSE),
+ DMU_OTN_UINT32_METADATA = DMU_OT(DMU_BSWAP_UINT32, B_TRUE),
+ DMU_OTN_UINT64_DATA = DMU_OT(DMU_BSWAP_UINT64, B_FALSE),
+ DMU_OTN_UINT64_METADATA = DMU_OT(DMU_BSWAP_UINT64, B_TRUE),
+ DMU_OTN_ZAP_DATA = DMU_OT(DMU_BSWAP_ZAP, B_FALSE),
+ DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE),
} dmu_object_type_t;
typedef enum dmu_objset_type {
@@ -116,5 +159,6 @@ typedef enum dmu_objset_type {
#define DMU_POOL_HISTORY "history"
#define DMU_POOL_PROPS "pool_props"
#define DMU_POOL_L2CACHE "l2cache"
+#define DMU_POOL_FEATURES_FOR_READ "features_for_read"
#endif /* _SYS_DMU_H */
diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h
index 20b23b7..761ade7 100644
--- a/include/grub/zfs/zfs.h
+++ b/include/grub/zfs/zfs.h
@@ -81,6 +81,7 @@ typedef enum grub_zfs_endian
#define ZPOOL_CONFIG_DDT_HISTOGRAM "ddt_histogram"
#define ZPOOL_CONFIG_DDT_OBJ_STATS "ddt_object_stats"
#define ZPOOL_CONFIG_DDT_STATS "ddt_stats"
+#define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read"
/*
* The persistent vdev state is stored as separate values rather than a
single
* 'vdev_state' entry. This is because a device can be in multiple
states, such
--
1.8.1.1
Attached Message Part
Description: Text document
signature.asc
Description: OpenPGP digital signature
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH 4/5] Check for feature flags needed to read from the pool.,
Massimo Maggi <=