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;
}
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;
}
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)
{
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;
+
+ 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;
+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"));
{
grub_unregister_command (cmd_info);
grub_unregister_command (cmd_bootfs);
+ grub_unregister_command (cmd_property);
}