source: grub-pc/trunk/fuentes/grub-core/fs/zfs/zfsinfo.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 11.0 KB
Line 
1/*
2 *  GRUB  --  GRand Unified Bootloader
3 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009  Free Software Foundation, Inc.
4 *  Copyright 2008  Sun Microsystems, Inc.
5 *
6 *  GRUB is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation; either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  GRUB is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <grub/zfs/zfs.h>
21#include <grub/device.h>
22#include <grub/file.h>
23#include <grub/command.h>
24#include <grub/misc.h>
25#include <grub/mm.h>
26#include <grub/dl.h>
27#include <grub/env.h>
28#include <grub/i18n.h>
29
30GRUB_MOD_LICENSE ("GPLv3+");
31
32static inline void
33print_tabs (int n)
34{
35  int i;
36
37  for (i = 0; i < n; i++)
38    grub_printf (" ");
39}
40
41static grub_err_t
42print_state (char *nvlist, int tab)
43{
44  grub_uint64_t ival;
45  int isok = 1;
46
47  print_tabs (tab);
48
49  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival))
50    {
51      grub_puts_ (N_("Virtual device is removed"));
52      isok = 0;
53    }
54
55  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
56    {
57      grub_puts_ (N_("Virtual device is faulted"));
58      isok = 0;
59    }
60
61  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival))
62    {
63      grub_puts_ (N_("Virtual device is offline"));
64      isok = 0;
65    }
66
67  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
68    /* TRANSLATORS: degraded doesn't mean broken but that some of
69       component are missing but virtual device as whole is still usable.  */
70    grub_puts_ (N_("Virtual device is degraded"));
71
72  if (isok)
73    grub_puts_ (N_("Virtual device is online"));
74  grub_xputs ("\n");
75
76  return GRUB_ERR_NONE;
77}
78
79static grub_err_t
80print_vdev_info (char *nvlist, int tab)
81{
82  char *type = 0;
83
84  type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
85
86  if (!type)
87    {
88      print_tabs (tab);
89      grub_puts_ (N_("Incorrect virtual device: no type available"));
90      return grub_errno;
91    }
92
93  if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
94    {
95      char *bootpath = 0;
96      char *path = 0;
97      char *devid = 0;
98
99      print_tabs (tab);
100      /* TRANSLATORS: The virtual devices form a tree (in graph-theoretical
101         sense). The nodes like mirror or raidz have children: member devices.
102         The "real" devices which actually store data are called "leafs"
103         (again borrowed from graph theory) and can be either disks
104         (or partitions) or files.  */
105      grub_puts_ (N_("Leaf virtual device (file or disk)"));
106
107      print_state (nvlist, tab);
108
109      bootpath =
110        grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_PHYS_PATH);
111      print_tabs (tab);
112      if (!bootpath)
113        grub_puts_ (N_("Bootpath: unavailable\n"));
114      else
115        grub_printf_ (N_("Bootpath: %s\n"), bootpath);
116
117      path = grub_zfs_nvlist_lookup_string (nvlist, "path");
118      print_tabs (tab);
119      if (!path)
120        grub_puts_ (N_("Path: unavailable"));
121      else
122        grub_printf_ (N_("Path: %s\n"), path);
123
124      devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
125      print_tabs (tab);
126      if (!devid)
127        grub_puts_ (N_("Devid: unavailable"));
128      else
129        grub_printf_ (N_("Devid: %s\n"), devid);
130      grub_free (bootpath);
131      grub_free (devid);
132      grub_free (path);
133      return GRUB_ERR_NONE;
134    }
135  char is_mirror=(grub_strcmp(type,VDEV_TYPE_MIRROR) == 0);
136  char is_raidz=(grub_strcmp(type,VDEV_TYPE_RAIDZ) == 0);
137
138  if (is_mirror || is_raidz)
139    {
140      int nelm, i;
141
142      nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
143        (nvlist, ZPOOL_CONFIG_CHILDREN);
144
145      if(is_mirror){
146         grub_puts_ (N_("This VDEV is a mirror"));
147      }
148      else if(is_raidz){
149         grub_uint64_t parity;
150         grub_zfs_nvlist_lookup_uint64(nvlist,"nparity",&parity);
151         grub_printf_ (N_("This VDEV is a RAIDZ%llu\n"),(unsigned long long)parity);
152      }
153      print_tabs (tab);
154      if (nelm <= 0)
155        {
156          grub_puts_ (N_("Incorrect VDEV"));
157          return GRUB_ERR_NONE;
158        }
159      grub_printf_ (N_("VDEV with %d children\n"), nelm);
160      print_state (nvlist, tab);
161      for (i = 0; i < nelm; i++)
162        {
163          char *child;
164
165          child = grub_zfs_nvlist_lookup_nvlist_array
166            (nvlist, ZPOOL_CONFIG_CHILDREN, i);
167
168          print_tabs (tab);
169          if (!child)
170            {
171              /* TRANSLATORS: it's the element carying the number %d, not
172                 total element number. And the number itself is fine,
173                 only the element isn't.
174              */
175              grub_printf_ (N_("VDEV element number %d isn't correct\n"), i);
176              continue;
177            }
178
179          /* TRANSLATORS: it's the element carying the number %d, not
180             total element number. This is used in enumeration
181             "Element number 1", "Element number 2", ... */
182          grub_printf_ (N_("VDEV element number %d:\n"), i);
183          print_vdev_info (child, tab + 1);
184
185          grub_free (child);
186        }
187      return GRUB_ERR_NONE;
188    }
189
190  print_tabs (tab);
191  grub_printf_ (N_("Unknown virtual device type: %s\n"), type);
192
193  return GRUB_ERR_NONE;
194}
195
196static grub_err_t
197get_bootpath (char *nvlist, char **bootpath, char **devid)
198{
199  char *type = 0;
200
201  type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
202
203  if (!type)
204    return grub_errno;
205
206  if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
207    {
208      *bootpath = grub_zfs_nvlist_lookup_string (nvlist,
209                                                 ZPOOL_CONFIG_PHYS_PATH);
210      *devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
211      if (!*bootpath || !*devid)
212        {
213          grub_free (*bootpath);
214          grub_free (*devid);
215          *bootpath = 0;
216          *devid = 0;
217        }
218      return GRUB_ERR_NONE;
219    }
220
221  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
222    {
223      int nelm, i;
224
225      nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
226        (nvlist, ZPOOL_CONFIG_CHILDREN);
227
228      for (i = 0; i < nelm; i++)
229        {
230          char *child;
231
232          child = grub_zfs_nvlist_lookup_nvlist_array (nvlist,
233                                                       ZPOOL_CONFIG_CHILDREN,
234                                                       i);
235
236          get_bootpath (child, bootpath, devid);
237
238          grub_free (child);
239
240          if (*bootpath && *devid)
241            return GRUB_ERR_NONE;
242        }
243    }
244
245  return GRUB_ERR_NONE;
246}
247
248static const char *poolstates[] = {
249  /* TRANSLATORS: Here we speak about ZFS pools it's semi-marketing,
250     semi-technical term by Sun/Oracle and should be translated in sync with
251     other ZFS-related software and documentation.  */
252  [POOL_STATE_ACTIVE] = N_("Pool state: active"),
253  [POOL_STATE_EXPORTED] = N_("Pool state: exported"),
254  [POOL_STATE_DESTROYED] = N_("Pool state: destroyed"),
255  [POOL_STATE_SPARE] = N_("Pool state: reserved for hot spare"),
256  [POOL_STATE_L2CACHE] = N_("Pool state: level 2 ARC device"),
257  [POOL_STATE_UNINITIALIZED] = N_("Pool state: uninitialized"),
258  [POOL_STATE_UNAVAIL] = N_("Pool state: unavailable"),
259  [POOL_STATE_POTENTIALLY_ACTIVE] = N_("Pool state: potentially active")
260};
261
262static grub_err_t
263grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc,
264                  char **args)
265{
266  grub_device_t dev;
267  char *devname;
268  grub_err_t err;
269  char *nvlist = 0;
270  char *nv = 0;
271  char *poolname;
272  grub_uint64_t guid;
273  grub_uint64_t pool_state;
274  int found;
275
276  if (argc < 1)
277    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
278
279  if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
280    {
281      devname = grub_strdup (args[0] + 1);
282      if (devname)
283        devname[grub_strlen (devname) - 1] = 0;
284    }
285  else
286    devname = grub_strdup (args[0]);
287  if (!devname)
288    return grub_errno;
289
290  dev = grub_device_open (devname);
291  grub_free (devname);
292  if (!dev)
293    return grub_errno;
294
295  err = grub_zfs_fetch_nvlist (dev, &nvlist);
296
297  grub_device_close (dev);
298
299  if (err)
300    return err;
301
302  poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
303  if (!poolname)
304    grub_puts_ (N_("Pool name: unavailable"));
305  else
306    grub_printf_ (N_("Pool name: %s\n"), poolname);
307
308  found =
309    grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
310  if (!found)
311    grub_puts_ (N_("Pool GUID: unavailable"));
312  else
313    grub_printf_ (N_("Pool GUID: %016llx\n"), (long long unsigned) guid);
314
315  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
316                                         &pool_state);
317  if (!found)
318    grub_puts_ (N_("Unable to retrieve pool state"));
319  else if (pool_state >= ARRAY_SIZE (poolstates))
320    grub_puts_ (N_("Unrecognized pool state"));
321  else
322    grub_puts_ (poolstates[pool_state]);
323
324  nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
325
326  if (!nv)
327    /* TRANSLATORS: There are undetermined number of virtual devices
328       in a device tree, not just one.
329     */
330    grub_puts_ (N_("No virtual device tree available"));
331  else
332    print_vdev_info (nv, 1);
333
334  grub_free (nv);
335  grub_free (nvlist);
336
337  return GRUB_ERR_NONE;
338}
339
340static grub_err_t
341grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
342                     char **args)
343{
344  grub_device_t dev;
345  char *devname;
346  grub_err_t err;
347  char *nvlist = 0;
348  char *nv = 0;
349  char *bootpath = 0, *devid = 0;
350  char *fsname;
351  char *bootfs;
352  char *poolname;
353  grub_uint64_t mdnobj;
354
355  if (argc < 1)
356    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
357
358  devname = grub_file_get_device_name (args[0]);
359  if (grub_errno)
360    return grub_errno;
361
362  dev = grub_device_open (devname);
363  grub_free (devname);
364  if (!dev)
365    return grub_errno;
366
367  err = grub_zfs_fetch_nvlist (dev, &nvlist);
368
369  fsname = grub_strchr (args[0], ')');
370  if (fsname)
371    fsname++;
372  else
373    fsname = args[0];
374
375  if (!err)
376    err = grub_zfs_getmdnobj (dev, fsname, &mdnobj);
377
378  grub_device_close (dev);
379
380  if (err)
381    return err;
382
383  poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
384  if (!poolname)
385    {
386      if (!grub_errno)
387        grub_error (GRUB_ERR_BAD_FS, "No poolname found");
388      return grub_errno;
389    }
390
391  nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
392
393  if (nv)
394    get_bootpath (nv, &bootpath, &devid);
395
396  grub_free (nv);
397  grub_free (nvlist);
398
399  bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu%s%s%s%s%s%s",
400                           poolname, (unsigned long long) mdnobj,
401                           bootpath ? ",bootpath=\"" : "",
402                           bootpath ? : "",
403                           bootpath ? "\"" : "",
404                           devid ? ",diskdevid=\"" : "",
405                           devid ? : "",
406                           devid ? "\"" : "");
407  if (!bootfs)
408    return grub_errno;
409  if (argc >= 2)
410    grub_env_set (args[1], bootfs);
411  else
412    grub_printf ("%s\n", bootfs);
413
414  grub_free (bootfs);
415  grub_free (poolname);
416  grub_free (bootpath);
417  grub_free (devid);
418
419  return GRUB_ERR_NONE;
420}
421
422
423static grub_command_t cmd_info, cmd_bootfs;
424
425GRUB_MOD_INIT (zfsinfo)
426{
427  cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
428                                    N_("DEVICE"),
429                                    N_("Print ZFS info about DEVICE."));
430  cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
431                                      N_("FILESYSTEM [VARIABLE]"),
432                                      N_("Print ZFS-BOOTFSOBJ or store it into VARIABLE"));
433}
434
435GRUB_MOD_FINI (zfsinfo)
436{
437  grub_unregister_command (cmd_info);
438  grub_unregister_command (cmd_bootfs);
439}
Note: See TracBrowser for help on using the repository browser.