grub-extras/lua: add fs label to grub.enum_device
[grub-extras.git] / disabled / zfs / zfsinfo.c
bloba9a13507e318d836c0ad8f71289ba8ad41698291
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
4 * Copyright 2008 Sun Microsystems, Inc.
5 * Copyright (C) 2009 Vladimir Serbinenko <phcoder@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <grub/zfs/zfs.h>
23 #include <grub/device.h>
24 #include <grub/file.h>
25 #include <grub/command.h>
26 #include <grub/misc.h>
27 #include <grub/mm.h>
28 #include <grub/dl.h>
29 #include <grub/env.h>
31 static inline void
32 print_tabs (int n)
34 int i;
36 for (i = 0; i < n; i++)
37 grub_printf (" ");
40 static grub_err_t
41 print_state (char *nvlist, int tab)
43 grub_uint64_t ival;
44 int isok = 1;
46 print_tabs (tab);
47 grub_printf ("State: ");
49 if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival))
51 grub_printf ("removed ");
52 isok = 0;
55 if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
57 grub_printf ("faulted ");
58 isok = 0;
61 if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival))
63 grub_printf ("offline ");
64 isok = 0;
67 if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
68 grub_printf ("degraded ");
70 if (isok)
71 grub_printf ("online");
72 grub_printf ("\n");
74 return GRUB_ERR_NONE;
77 static grub_err_t
78 print_vdev_info (char *nvlist, int tab)
80 char *type = 0;
82 type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
84 if (!type)
86 print_tabs (tab);
87 grub_printf ("Incorrect VDEV: no type available\n");
88 return grub_errno;
91 if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
93 char *bootpath = 0;
94 char *path = 0;
95 char *devid = 0;
97 print_tabs (tab);
98 grub_printf ("Leaf VDEV\n");
100 print_state (nvlist, tab);
102 bootpath =
103 grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_PHYS_PATH);
104 print_tabs (tab);
105 if (!bootpath)
106 grub_printf ("Bootpath: unavailable\n");
107 else
108 grub_printf ("Bootpath: %s\n", bootpath);
110 path = grub_zfs_nvlist_lookup_string (nvlist, "path");
111 print_tabs (tab);
112 if (!path)
113 grub_printf ("Path: unavailable\n");
114 else
115 grub_printf ("Path: %s\n", path);
117 devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
118 print_tabs (tab);
119 if (!devid)
120 grub_printf ("Devid: unavailable\n");
121 else
122 grub_printf ("Devid: %s\n", devid);
123 grub_free (bootpath);
124 grub_free (devid);
125 grub_free (path);
126 return GRUB_ERR_NONE;
129 if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
131 int nelm, i;
133 nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
134 (nvlist, ZPOOL_CONFIG_CHILDREN);
136 print_tabs (tab);
137 if (nelm <= 0)
139 grub_printf ("Incorrect mirror VDEV\n");
140 return GRUB_ERR_NONE;
142 grub_printf ("Mirror VDEV with %d children\n", nelm);
143 print_state (nvlist, tab);
145 for (i = 0; i < nelm; i++)
147 char *child;
149 child = grub_zfs_nvlist_lookup_nvlist_array
150 (nvlist, ZPOOL_CONFIG_CHILDREN, i);
152 print_tabs (tab);
153 if (!child)
155 grub_printf ("Mirror VDEV element %d isn't correct\n", i);
156 continue;
159 grub_printf ("Mirror VDEV element %d:\n", i);
160 print_vdev_info (child, tab + 1);
162 grub_free (child);
166 print_tabs (tab);
167 grub_printf ("Unknown VDEV type: %s\n", type);
169 return GRUB_ERR_NONE;
172 static grub_err_t
173 get_bootpath (char *nvlist, char **bootpath, char **devid)
175 char *type = 0;
177 type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
179 if (!type)
180 return grub_errno;
182 if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
184 *bootpath = grub_zfs_nvlist_lookup_string (nvlist,
185 ZPOOL_CONFIG_PHYS_PATH);
186 *devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
187 if (!*bootpath || !*devid)
189 grub_free (*bootpath);
190 grub_free (*devid);
191 *bootpath = 0;
192 *devid = 0;
194 return GRUB_ERR_NONE;
197 if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
199 int nelm, i;
201 nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
202 (nvlist, ZPOOL_CONFIG_CHILDREN);
204 for (i = 0; i < nelm; i++)
206 char *child;
208 child = grub_zfs_nvlist_lookup_nvlist_array (nvlist,
209 ZPOOL_CONFIG_CHILDREN,
212 get_bootpath (child, bootpath, devid);
214 grub_free (child);
216 if (*bootpath && *devid)
217 return GRUB_ERR_NONE;
221 return GRUB_ERR_NONE;
224 static char *poolstates[] = {
225 [POOL_STATE_ACTIVE] = "active",
226 [POOL_STATE_EXPORTED] = "exported",
227 [POOL_STATE_DESTROYED] = "destroyed",
228 [POOL_STATE_SPARE] = "reserved for hot spare",
229 [POOL_STATE_L2CACHE] = "level 2 ARC device",
230 [POOL_STATE_UNINITIALIZED] = "uninitialized",
231 [POOL_STATE_UNAVAIL] = "unavailable",
232 [POOL_STATE_POTENTIALLY_ACTIVE] = "potentially active"
235 static grub_err_t
236 grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc,
237 char **args)
239 grub_device_t dev;
240 char *devname;
241 grub_err_t err;
242 char *nvlist = 0;
243 char *nv = 0;
244 char *poolname;
245 grub_uint64_t guid;
246 grub_uint64_t pool_state;
247 int found;
249 if (argc < 1)
250 return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
252 if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
254 devname = grub_strdup (args[0] + 1);
255 if (devname)
256 devname[grub_strlen (devname) - 1] = 0;
258 else
259 devname = grub_strdup (args[0]);
260 if (!devname)
261 return grub_errno;
263 dev = grub_device_open (devname);
264 grub_free (devname);
265 if (!dev)
266 return grub_errno;
268 err = grub_zfs_fetch_nvlist (dev, &nvlist);
270 grub_device_close (dev);
272 if (err)
273 return err;
275 poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
276 if (!poolname)
277 grub_printf ("Pool name: unavailable\n");
278 else
279 grub_printf ("Pool name: %s\n", poolname);
281 found =
282 grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
283 if (!found)
284 grub_printf ("Pool GUID: unavailable\n");
285 else
286 grub_printf ("Pool GUID: %016llx\n", (long long unsigned) guid);
288 found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
289 &pool_state);
290 if (!found)
291 grub_printf ("Unable to retrieve pool state\n");
292 else if (pool_state >= ARRAY_SIZE (poolstates))
293 grub_printf ("Unrecognized pool state\n");
294 else
295 grub_printf ("Pool state: %s\n", poolstates[pool_state]);
297 nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
299 if (!nv)
300 grub_printf ("No vdev tree available\n");
301 else
302 print_vdev_info (nv, 1);
304 grub_free (nv);
305 grub_free (nvlist);
307 return GRUB_ERR_NONE;
310 static grub_err_t
311 grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
312 char **args)
314 grub_device_t dev;
315 char *devname;
316 grub_err_t err;
317 char *nvlist = 0;
318 char *nv = 0;
319 char *bootpath = 0, *devid = 0;
320 char *fsname;
321 char *bootfs;
322 char *poolname;
323 grub_uint64_t mdnobj;
325 if (argc < 1)
326 return grub_error (GRUB_ERR_BAD_ARGUMENT, "filesystem name required");
328 devname = grub_file_get_device_name (args[0]);
329 if (grub_errno)
330 return grub_errno;
332 dev = grub_device_open (devname);
333 grub_free (devname);
334 if (!dev)
335 return grub_errno;
337 err = grub_zfs_fetch_nvlist (dev, &nvlist);
339 fsname = grub_strchr (args[0], ')');
340 if (fsname)
341 fsname++;
342 else
343 fsname = args[0];
345 if (!err)
346 err = grub_zfs_getmdnobj (dev, fsname, &mdnobj);
348 grub_device_close (dev);
350 if (err)
351 return err;
353 poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
354 if (!poolname)
356 if (!grub_errno)
357 grub_error (GRUB_ERR_BAD_FS, "No poolname found");
358 return grub_errno;
361 nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
363 if (nv)
364 get_bootpath (nv, &bootpath, &devid);
366 grub_free (nv);
367 grub_free (nvlist);
369 if (bootpath && devid)
371 bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu bootpath=%s diskdevid=%s",
372 poolname, (unsigned long long) mdnobj,
373 bootpath, devid);
374 if (!bootfs)
375 return grub_errno;
377 else
379 bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu",
380 poolname, (unsigned long long) mdnobj);
381 if (!bootfs)
382 return grub_errno;
384 if (argc >= 2)
385 grub_env_set (args[1], bootfs);
386 else
387 grub_printf ("%s\n", bootfs);
389 grub_free (bootfs);
390 grub_free (poolname);
391 grub_free (bootpath);
392 grub_free (devid);
394 return GRUB_ERR_NONE;
398 static grub_command_t cmd_info, cmd_bootfs;
400 GRUB_MOD_INIT (zfsinfo)
402 cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
403 "zfsinfo DEVICE",
404 "Print ZFS info about DEVICE.");
405 cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
406 "zfs-bootfs FILESYSTEM [VARIABLE]",
407 "Print ZFS-BOOTFSOBJ or set it to VARIABLE");
410 GRUB_MOD_FINI (zfsinfo)
412 grub_unregister_command (cmd_info);
413 grub_unregister_command (cmd_bootfs);