263
274
grub_size_t keysize,
264
275
grub_uint64_t salt,
265
276
grub_uint64_t algo) = NULL;
278
* List of pool features that the grub implementation of ZFS supports for
279
* read. Note that features that are only required for write do not need
280
* to be listed here since grub opens pools in read-only mode.
282
#define MAX_SUPPORTED_FEATURE_STRLEN 50
283
static const char *spa_feature_names[] = {
284
"org.illumos:lz4_compress",NULL
288
check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx);
290
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data );
267
292
static grub_err_t
268
293
zlib_decompress (void *s, void *d,
269
294
grub_size_t slen, grub_size_t dlen)
271
if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0)
273
return GRUB_ERR_NONE;
296
if (grub_zlib_decompress (s, slen, 0, d, dlen) == (grub_ssize_t) dlen)
297
return GRUB_ERR_NONE;
300
grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
301
"premature end of compressed");
276
305
static grub_err_t
793
* For a given XDR packed nvlist, verify the first 4 bytes and move on.
795
* An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
797
* encoding method/host endian (4 bytes)
798
* nvl_version (4 bytes)
799
* nvl_nvflag (4 bytes)
801
* encoded size of the nvpair (4 bytes)
802
* decoded size of the nvpair (4 bytes)
803
* name string size (4 bytes)
804
* name string data (sizeof(NV_ALIGN4(string))
805
* data type (4 bytes)
806
* # of elements in the nvpair (4 bytes)
808
* 2 zero's for the last nvpair
809
* (end of the entire list) (8 bytes)
814
* The nvlist_next_nvpair() function returns a handle to the next nvpair in the
815
* list following nvpair. If nvpair is NULL, the first pair is returned. If
816
* nvpair is the last pair in the nvlist, NULL is returned.
819
nvlist_next_nvpair (const char *nvl, const char *nvpair)
829
/* skip over header, nvl_version and nvl_nvflag */
830
nvpair = nvl + 4 * 3;
834
/* skip to the next nvpair */
835
encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
836
nvpair += encode_size;
837
/*If encode_size equals 0 nvlist_next_nvpair would return
838
* the same pair received in input, leading to an infinite loop.
839
* If encode_size is less than 0, this will move the pointer
840
* backwards, *possibly* examinining two times the same nvpair
841
* and potentially getting into an infinite loop. */
844
grub_dprintf ("zfs", "nvpair with size <= 0\n");
845
grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
849
/* 8 bytes of 0 marks the end of the list */
850
if (grub_get_unaligned64 (nvpair) == 0)
852
/*consistency checks*/
853
if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE)
855
grub_dprintf ("zfs", "nvlist overflow\n");
856
grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
859
encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
862
name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
865
nvp = nvp + ((name_len + 3) & ~3); // align
866
if (nvp + 4 >= nvl + VDEV_PHYS_SIZE
868
|| nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE)
870
grub_dprintf ("zfs", "nvlist overflow\n");
871
grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
874
/* end consistency checks */
880
* This function returns 0 on success and 1 on failure. On success, a string
881
* containing the name of nvpair is saved in buf.
884
nvpair_name (const char *nvp, char **buf, grub_size_t *buflen)
886
/* skip over encode/decode size */
889
*buf = (char *) (nvp + 4);
890
*buflen = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
896
* This function retrieves the value of the nvpair in the form of enumerated
900
nvpair_type (const char *nvp)
904
/* skip over encode/decode size */
907
/* skip over name_len */
908
name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
912
nvp = nvp + ((name_len + 3) & ~3); /* align */
914
type = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
920
nvpair_value (const char *nvp,char **val,
921
grub_size_t *size_out, grub_size_t *nelm_out)
923
int name_len,nelm,encode_size;
925
/* skip over encode/decode size */
926
encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvp));
929
/* skip over name_len */
930
name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
934
nvp = nvp + ((name_len + 3) & ~3); /* align */
938
nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
942
grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
946
*size_out = encode_size;
763
954
* Check the disk label information and retrieve needed vdev name-value pairs.
891
1107
grub_dprintf ("zfs", "check 10 passed\n");
1108
features = grub_zfs_nvlist_lookup_nvlist(nvlist,
1109
ZPOOL_CONFIG_FEATURES_FOR_READ);
1112
const char *nvp=NULL;
1113
char name[MAX_SUPPORTED_FEATURE_STRLEN + 1];
1115
grub_size_t namelen;
1116
while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL)
1118
nvpair_name (nvp, &nameptr, &namelen);
1119
if(namelen > MAX_SUPPORTED_FEATURE_STRLEN)
1120
namelen = MAX_SUPPORTED_FEATURE_STRLEN;
1121
grub_memcpy (name, nameptr, namelen);
1122
name[namelen] = '\0';
1123
grub_dprintf("zfs","str=%s\n",name);
1124
if (check_feature(name,1, NULL) != 0)
1126
grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name);
1127
err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name);
1132
grub_dprintf ("zfs", "check 12 passed (feature flags)\n");
893
1133
grub_free (nvlist);
895
1135
return GRUB_ERR_NONE;
2113
2363
for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++)
2116
struct zap_leaf_entry *le;
2118
grub_size_t val_length;
2119
le = ZAP_LEAF_ENTRY (l, blksft, chunk);
2121
/* Verify the chunk entry */
2122
if (le->le_type != ZAP_CHUNK_ENTRY)
2125
buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
2126
* name_elem_length + 1);
2127
if (zap_leaf_array_get (l, endian, blksft,
2128
grub_zfs_to_cpu16 (le->le_name_chunk,
2130
grub_zfs_to_cpu16 (le->le_name_length,
2132
* name_elem_length, buf))
2137
buf[le->le_name_length * name_elem_length] = 0;
2139
val_length = ((int) le->le_value_length
2140
* (int) le->le_int_size);
2141
val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
2142
if (zap_leaf_array_get (l, endian, blksft,
2143
grub_zfs_to_cpu16 (le->le_value_chunk,
2152
if (hook (buf, le->le_name_length,
2153
val, le->le_value_length, le->le_int_size))
2366
struct zap_leaf_entry *le;
2368
grub_size_t val_length;
2369
le = ZAP_LEAF_ENTRY (l, blksft, chunk);
2371
/* Verify the chunk entry */
2372
if (le->le_type != ZAP_CHUNK_ENTRY)
2375
buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
2376
* name_elem_length + 1);
2377
if (zap_leaf_array_get (l, endian, blksft,
2378
grub_zfs_to_cpu16 (le->le_name_chunk,
2380
grub_zfs_to_cpu16 (le->le_name_length,
2382
* name_elem_length, buf))
2387
buf[le->le_name_length * name_elem_length] = 0;
2389
val_length = ((int) le->le_value_length
2390
* (int) le->le_int_size);
2391
val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
2392
if (zap_leaf_array_get (l, endian, blksft,
2393
grub_zfs_to_cpu16 (le->le_value_chunk,
2402
if (hook (buf, le->le_name_length,
2403
val, le->le_value_length, le->le_int_size, hook_data))
2213
2463
return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
2466
/* Context for zap_iterate_u64. */
2467
struct zap_iterate_u64_ctx
2469
int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *);
2470
struct grub_zfs_dir_ctx *dir_ctx;
2473
/* Helper for zap_iterate_u64. */
2475
zap_iterate_u64_transform (const void *name,
2476
grub_size_t namelen __attribute__ ((unused)),
2479
grub_size_t elemsize,
2482
struct zap_iterate_u64_ctx *ctx = data;
2484
if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
2486
return ctx->hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in),
2217
2491
zap_iterate_u64 (dnode_end_t * zap_dnode,
2218
int NESTED_FUNC_ATTR (*hook) (const char *name,
2220
struct grub_zfs_data *data)
2492
int (*hook) (const char *name, grub_uint64_t val,
2493
struct grub_zfs_dir_ctx *ctx),
2494
struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx)
2222
2496
grub_uint64_t block_type;
2818
3081
return GRUB_ERR_NONE;
3084
/* Context for dnode_get_fullpath. */
3085
struct dnode_get_fullpath_ctx
3087
struct subvolume *subvol;
3092
/* Helper for dnode_get_fullpath. */
3094
count_zap_keys (const void *name __attribute__ ((unused)),
3095
grub_size_t namelen __attribute__ ((unused)),
3096
const void *val_in __attribute__ ((unused)),
3097
grub_size_t nelem __attribute__ ((unused)),
3098
grub_size_t elemsize __attribute__ ((unused)),
3101
struct dnode_get_fullpath_ctx *ctx = data;
3103
ctx->subvol->nkeys++;
3107
/* Helper for dnode_get_fullpath. */
3109
load_zap_key (const void *name, grub_size_t namelen, const void *val_in,
3110
grub_size_t nelem, grub_size_t elemsize, void *data)
3112
struct dnode_get_fullpath_ctx *ctx = data;
3116
grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
3123
grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
3128
ctx->subvol->keyring[ctx->keyn].txg =
3129
grub_be_to_cpu64 (*(grub_uint64_t *) name);
3130
ctx->subvol->keyring[ctx->keyn].algo =
3131
grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
3132
ctx->subvol->keyring[ctx->keyn].cipher =
3133
grub_zfs_load_key (val_in, nelem, ctx->salt,
3134
ctx->subvol->keyring[ctx->keyn].algo);
2821
3139
static grub_err_t
2822
3140
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
2823
3141
dnode_end_t * dn, int *isfs,
2827
3145
const char *ptr_at, *filename;
2828
3146
grub_uint64_t headobj;
2829
3147
grub_uint64_t keychainobj;
2831
3148
grub_err_t err;
2834
auto int NESTED_FUNC_ATTR count_zap_keys (const void *name,
2835
grub_size_t namelen,
2838
grub_size_t elemsize);
2839
int NESTED_FUNC_ATTR count_zap_keys (const void *name __attribute__ ((unused)),
2840
grub_size_t namelen __attribute__ ((unused)),
2841
const void *val_in __attribute__ ((unused)),
2842
grub_size_t nelem __attribute__ ((unused)),
2843
grub_size_t elemsize __attribute__ ((unused)))
2849
auto int NESTED_FUNC_ATTR load_zap_key (const void *name,
2850
grub_size_t namelen,
2853
grub_size_t elemsize);
2854
int NESTED_FUNC_ATTR load_zap_key (const void *name,
2855
grub_size_t namelen,
2858
grub_size_t elemsize)
2862
grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
2869
grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
2874
subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name);
2875
subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
2876
subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt,
2877
subvol->keyring[keyn].algo);
2882
3150
ptr_at = grub_strchr (fullpath, '@');
3034
* For a given XDR packed nvlist, verify the first 4 bytes and move on.
3036
* An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
3038
* encoding method/host endian (4 bytes)
3039
* nvl_version (4 bytes)
3040
* nvl_nvflag (4 bytes)
3042
* encoded size of the nvpair (4 bytes)
3043
* decoded size of the nvpair (4 bytes)
3044
* name string size (4 bytes)
3045
* name string data (sizeof(NV_ALIGN4(string))
3046
* data type (4 bytes)
3047
* # of elements in the nvpair (4 bytes)
3049
* 2 zero's for the last nvpair
3050
* (end of the entire list) (8 bytes)
3055
3306
nvlist_find_value (const char *nvlist_in, const char *name,
3056
3307
int valtype, char **val,
3057
3308
grub_size_t *size_out, grub_size_t *nelm_out)
3059
int name_len, type, encode_size;
3060
const char *nvpair, *nvp_name, *nvlist = nvlist_in;
3310
grub_size_t nvp_name_len, name_len = grub_strlen(name);
3312
const char *nvpair=NULL,*nvlist=nvlist_in;
3062
3315
/* Verify if the 1st and 2nd byte in the nvlist are valid. */
3063
3316
/* NOTE: independently of what endianness header announces all
3073
/* skip the header, nvl_version, and nvl_nvflag */
3074
nvlist = nvlist + 4 * 3;
3076
3327
* Loop thru the nvpair list
3077
3328
* The XDR representation of an integer is in big-endian byte order.
3079
while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist))))
3330
while ((nvpair=nvlist_next_nvpair(nvlist,nvpair)))
3083
if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE)
3085
grub_dprintf ("zfs", "nvlist overflow\n");
3086
grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
3090
nvpair = nvlist + 4 * 2; /* skip the encode/decode size */
3092
name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
3096
nvpair = nvpair + ((name_len + 3) & ~3); /* align */
3098
if (nvpair + 8 >= nvlist_in + VDEV_PHYS_SIZE
3100
|| nvpair + 8 + encode_size > nvlist_in + VDEV_PHYS_SIZE)
3102
grub_dprintf ("zfs", "nvlist overflow\n");
3103
grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
3107
type = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
3110
nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
3113
grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
3119
if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype)
3121
*val = (char *) nvpair;
3122
*size_out = encode_size;
3128
nvlist += encode_size; /* goto the next nvpair */
3332
nvpair_name(nvpair,&nvp_name, &nvp_name_len);
3333
type = nvpair_type(nvpair);
3335
&& (nvp_name_len == name_len
3336
|| (nvp_name_len > name_len && nvp_name[name_len] == '\0'))
3337
&& grub_memcmp (nvp_name, name, name_len) == 0)
3339
return nvpair_value(nvpair,val,size_out,nelm_out);
3737
3956
info->mtimeset = 1;
3738
3957
info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
3962
/* Helper for grub_zfs_dir. */
3964
iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
3967
struct grub_dirhook_info info;
3970
grub_memset (&info, 0, sizeof (info));
3972
dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
3974
if (dn.dn.dn_bonustype == DMU_OT_SA)
3979
if (dn.dn.dn_bonuslen != 0)
3981
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn);
3983
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
3985
blkptr_t *bp = &dn.dn.dn_spill;
3987
err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data);
3990
grub_print_error ();
3996
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
3997
grub_print_error ();
4001
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
4003
info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
4004
info.case_insensitive = ctx->data->subvol.case_insensitive;
4007
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
4010
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
4013
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
4014
grub_dprintf ("zfs", "type=%d, name=%s\n",
4015
(int)dn.dn.dn_type, (char *)name);
4016
return ctx->hook (name, &info, ctx->hook_data);
4019
/* Helper for grub_zfs_dir. */
4021
iterate_zap_fs (const char *name, grub_uint64_t val,
4022
struct grub_zfs_dir_ctx *ctx)
4025
struct grub_dirhook_info info;
4028
err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
4034
if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
4037
err = fill_fs_info (&info, mdn, ctx->data);
4043
return ctx->hook (name, &info, ctx->hook_data);
4046
/* Helper for grub_zfs_dir. */
4048
iterate_zap_snap (const char *name, grub_uint64_t val,
4049
struct grub_zfs_dir_ctx *ctx)
4052
struct grub_dirhook_info info;
4058
err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
4065
if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
4068
err = fill_fs_info (&info, mdn, ctx->data);
4075
name2 = grub_malloc (grub_strlen (name) + 2);
4077
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
4078
ret = ctx->hook (name2, &info, ctx->hook_data);
3743
4083
static grub_err_t
3744
4084
grub_zfs_dir (grub_device_t device, const char *path,
3745
int (*hook) (const char *, const struct grub_dirhook_info *))
4085
grub_fs_dir_hook_t hook, void *hook_data)
4087
struct grub_zfs_dir_ctx ctx = {
4089
.hook_data = hook_data
3747
4091
struct grub_zfs_data *data;
3748
4092
grub_err_t err;
3750
auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val);
3751
auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name,
3753
auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name,
3756
int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val)
3758
struct grub_dirhook_info info;
3760
grub_memset (&info, 0, sizeof (info));
3762
dnode_get (&(data->subvol.mdn), val, 0, &dn, data);
3764
if (dn.dn.dn_bonustype == DMU_OT_SA)
3769
if (dn.dn.dn_bonuslen != 0)
3771
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn);
3773
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
3775
blkptr_t *bp = &dn.dn.dn_spill;
3777
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
3780
grub_print_error ();
3786
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
3787
grub_print_error ();
3791
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
3793
info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
3794
info.case_insensitive = data->subvol.case_insensitive;
3797
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
3800
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
3803
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
3804
grub_dprintf ("zfs", "type=%d, name=%s\n",
3805
(int)dn.dn.dn_type, (char *)name);
3806
return hook (name, &info);
3809
int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val)
3811
struct grub_dirhook_info info;
3813
err = dnode_get (&(data->mos), val, 0, &mdn, data);
3816
if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
3819
fill_fs_info (&info, mdn, data);
3820
return hook (name, &info);
3822
int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val)
3824
struct grub_dirhook_info info;
3829
err = dnode_get (&(data->mos), val, 0, &mdn, data);
3833
if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
3836
fill_fs_info (&info, mdn, data);
3838
name2 = grub_malloc (grub_strlen (name) + 2);
3840
grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
3841
ret = hook (name2, &info);
3846
4095
data = zfs_mount (device);
3900
4160
zfs_unmount (data);
3901
4161
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
3903
zap_iterate_u64 (&(data->dnode), iterate_zap, data);
4163
zap_iterate_u64 (&(data->dnode), iterate_zap, data, &ctx);
3905
4165
zfs_unmount (data);
3906
4166
return grub_errno;
4170
check_feature (const char *name, grub_uint64_t val,
4171
struct grub_zfs_dir_ctx *ctx __attribute__((unused)))
4178
for (i = 0; spa_feature_names[i] != NULL; i++)
4179
if (grub_strcmp (name, spa_feature_names[i]) == 0)
4185
* Checks whether the MOS features that are active are supported by this
4186
* (GRUB's) implementation of ZFS.
4194
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data )
4196
grub_uint64_t objnum;
4197
grub_uint8_t errnum = 0;
4198
dnode_end_t dn,mosmdn;
4200
grub_zfs_endian_t endianzap;
4202
grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t));
4203
mosmdn.endian=endian;
4204
errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT,
4205
DMU_OT_OBJECT_DIRECTORY, &dn,data);
4210
* Find the object number for 'features_for_read' and retrieve its
4211
* corresponding dnode. Note that we don't check features_for_write
4212
* because GRUB is not opening the pool for write.
4214
errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0);
4218
errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data);
4222
errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data);
4226
size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT;
4227
return mzap_iterate (mzp,endianzap, size, check_feature,NULL);
3909
4231
#ifdef GRUB_UTIL
3910
4232
static grub_err_t
3911
4233
grub_zfs_embed (grub_device_t device __attribute__ ((unused)),