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