ZFS on Linux Improvements 1. `zpool status` can output disk names which are under /dev/disk. 2. `zpool status` outputs the whole disk device for wholedisk pools, but GRUB needs the partition device. 3. Support native ZFS on Linux. Index: grub/util/getroot.c =================================================================== --- grub.orig/util/getroot.c 2012-02-03 05:54:39.540539000 -0600 +++ grub/util/getroot.c 2012-02-03 06:04:29.465275000 -0600 @@ -304,7 +304,87 @@ if (name[0] == '/') devices[ndevices++] = xstrdup (name); else +#ifdef __linux__ + { + /* The name returned by zpool isn't necessarily directly under /dev. */ + char *device = xasprintf ("/dev/%s", name); + struct stat sb; + char *real_device; + char *c; + char *partition; + + if (stat (device, &sb) != 0) + { + DIR *dev; + struct dirent *subdir; + + free (device); + device = NULL; + dev = opendir ("/dev/disk"); + if (dev) + { + while ((subdir = readdir (dev))) + { + if (subdir->d_name[0] == '.') + continue; + if (subdir->d_type == DT_UNKNOWN) + { + char *subdir_path = xasprintf ("/dev/disk/%s", subdir->d_name); + ret = stat (subdir_path, &sb); + free (subdir_path); + if (ret != 0) + continue; + if (!S_ISDIR (sb.st_mode)) + continue; + } + else if (subdir->d_type != DT_DIR) + continue; + device = xasprintf ("/dev/disk/%s/%s", subdir->d_name, name); + if (stat (device, &sb) == 0) + break; + else + { + free (device); + device = NULL; + } + } + closedir (dev); + if (! device) + grub_util_error (_("failed to find device %s"), device); + } + } + + /* Resolve the symlink to something like /dev/sda. */ + real_device = canonicalize_file_name (device); + if (! real_device) + grub_util_error (_("failed to get canonical path of %s"), device); + free(device); + + /* It ends in a number; assume it's a partition and stop. */ + for (c = real_device ; *(c+1) ; c++); + if (*c >= '0' && *c <= '9') + { + devices[ndevices++] = real_device; + break; + } + + /* Otherwise, it might be a partitioned wholedisk device. */ + partition = xasprintf ("%s1", real_device); + if (stat (partition, &sb) == 0) + { + free (real_device); + devices[ndevices++] = partition; + break; + } + free (partition); + + /* The device is not partitioned. */ + devices[ndevices++] = real_device; + break; + } +#else devices[ndevices++] = xasprintf ("/dev/%s", name); +#endif } break; } @@ -478,7 +558,8 @@ if (!*entries[i].device) continue; - if (grub_strcmp (entries[i].fstype, "fuse.zfs") == 0) + if (grub_strcmp (entries[i].fstype, "fuse.zfs") == 0 || + grub_strcmp (entries[i].fstype, "zfs") == 0) { char *slash; slash = strchr (entries[i].device, '/');