From 0ee5cdfe9f9d576c95c35030ee25012545a3a294 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sun, 3 Nov 2013 16:40:32 +0100 Subject: [PATCH] Attempts at ZFS options --- grub-core/fs/zfs/zfs.c | 66 ++++++++++++++++++++++++++++++++++++-- grub-core/fs/zfs/zfsinfo.c | 61 ++++++++++++++++++++++++++++++++++- include/grub/zfs/zfs.h | 4 +++ util/grub-fstest.c | 4 ++- 4 files changed, 131 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index d0a4d9cc7..9bfaebb4c 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2604,7 +2604,8 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE); buf->endian = data->dnode_endian; if (type && buf->dn.dn_type != type) - return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type: %x, %x", + buf->dn.dn_type, type); return GRUB_ERR_NONE; } @@ -2635,7 +2636,8 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE); buf->endian = endian; if (type && buf->dn.dn_type != type) - return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type: %x, %x", + buf->dn.dn_type, type); return GRUB_ERR_NONE; } @@ -3771,6 +3773,66 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) return GRUB_ERR_NONE; } +#if 1 + +static int print_hook (const void *name, + grub_size_t namelen __attribute__ ((unused)), + const void *val_in __attribute__ ((unused)), + grub_size_t nelem __attribute__ ((unused)), + grub_size_t elemsize __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_printf ("<%s %u %u, %s>\n", (char *)name, + (unsigned) elemsize, (unsigned) nelem, + (char *) val_in); + return 0; +} + +#endif + +grub_err_t +grub_zfs_get_property (grub_device_t dev, + const char *fsfilename, const char *propname, + grub_uint64_t *property) +{ + struct grub_zfs_data *data; + grub_err_t err; + int isfs; + dnode_end_t props_dn; + grub_uint64_t propsobj; + + data = zfs_mount (dev); + if (! data) + return grub_errno; + + err = dnode_get_fullpath (fsfilename, &(data->subvol), + &(data->dnode), &isfs, data); + + propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_props_zapobj, data->dnode.endian); + + if (!err) + err = dnode_get (&(data->mos), propsobj, DMU_OT_DSL_PROPS, + &props_dn, data); + +#if 0 + if (!err) + err = zap_lookup (&props_dn, propname, + property, data, 0); +#else + (void) propname; + (void) property; +#endif + + zap_iterate (&props_dn, 1, + print_hook, + NULL, data); + + zfs_unmount (data); + + return err; +} + + static grub_ssize_t grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) { diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index c96bf2183..f8b915ebf 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -419,14 +419,72 @@ grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc, return GRUB_ERR_NONE; } +static grub_err_t +grub_cmd_zfs_property (grub_command_t cmd __attribute__ ((unused)), int argc, + char **args) +{ + grub_device_t device = 0; + char *device_name; + const char *file_name; + char *fs_name = NULL; + const char *name, *ptr; + grub_uint64_t property; + grub_err_t err; -static grub_command_t cmd_info, cmd_bootfs; + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); + + name = args[0]; + device_name = grub_file_get_device_name (name); + if (grub_errno) + return grub_errno; + + /* Get the file part of NAME. */ + file_name = (name[0] == '(') ? grub_strchr (name, ')') : NULL; + if (file_name) + file_name++; + else + file_name = name; + + device = grub_device_open (device_name); + grub_free (device_name); + if (! device) + return grub_errno; + + ptr = grub_strchr (file_name, '@'); + if (ptr) + { + fs_name = grub_strndup (file_name, ptr - file_name); + if (!fs_name) + { + grub_device_close (device); + return grub_errno; + } + } + + err = grub_zfs_get_property (device, fs_name ? : file_name, args[1], + &property); + grub_free (fs_name); + grub_device_close (device); + if (err) + return err; + + grub_printf ("0x%llx\n", (unsigned long long) property); + + return GRUB_ERR_NONE; +} + + +static grub_command_t cmd_info, cmd_bootfs, cmd_property; GRUB_MOD_INIT (zfsinfo) { cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo, N_("DEVICE"), N_("Print ZFS info about DEVICE.")); + cmd_property = grub_register_command ("zfsproperty", grub_cmd_zfs_property, + N_("SUBVOLUME PROPNAME"), + N_("Print ZFS property value.")); cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs, N_("FILESYSTEM [VARIABLE]"), N_("Print ZFS-BOOTFSOBJ or store it into VARIABLE")); @@ -436,4 +494,5 @@ GRUB_MOD_FINI (zfsinfo) { grub_unregister_command (cmd_info); grub_unregister_command (cmd_bootfs); + grub_unregister_command (cmd_property); } diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index 4ee513887..e059db690 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -153,6 +153,10 @@ extern grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_k grub_uint64_t salt, grub_uint64_t algo); +grub_err_t +grub_zfs_get_property (grub_device_t dev, + const char *fsfilename, const char *propname, + grub_uint64_t *property); #endif /* ! GRUB_ZFS_HEADER */ diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 802733963..cd39e6edd 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -417,9 +417,11 @@ fstest (int n) { case CMD_LS: execute_command ("ls", n, args); + grub_print_error (); break; case CMD_ZFSINFO: - execute_command ("zfsinfo", n, args); + execute_command ("zfsproperty", n, args); + grub_print_error (); break; case CMD_CP: cmd_cp (args[0], args[1]);