From: Richard Laager <rlaager@wiktel.com>
To: Zachary Bedell <pendorbound@gmail.com>
Cc: grub-devel@gnu.org
Subject: Re: [Patch] Robustly search for ZFS labels & uberblocks
Date: Fri, 27 Jan 2012 20:50:35 -0600 [thread overview]
Message-ID: <1327719035.9477.68.camel@watermelon.coderich.net> (raw)
In-Reply-To: <C2AFC8B8-54EC-4D2C-824D-C01B2070DBF6@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 665 bytes --]
On Fri, 2012-01-27 at 14:04 -0500, Zachary Bedell wrote:
> I've had to forward port the other changes necessary to support build on Linux.
Attached is the work I've done on this front. This includes the "allow
spaces in zpools" patch I previously submitted to grub-devel. And, the
changes in 10_linux.in are from dajhorn's Ubuntu packages.
I have not yet made anything boot on RAIDZ. I don't know if that's
caused by this patch.
If the changes to getroot.c are accepted upstream, I'd recommend moving
find_device_from_pool() higher up in that file, rather than using the
prototype, but the prototype keeps the patch smaller for now.
--
Richard
[-- Attachment #1.2: zfs-on-linux.patch --]
[-- Type: text/x-patch, Size: 6803 bytes --]
Index: grub/util/grub.d/10_linux.in
===================================================================
--- grub.orig/util/grub.d/10_linux.in 2012-01-24 23:44:10.530591000 -0600
+++ grub/util/grub.d/10_linux.in 2012-01-24 23:44:10.706928000 -0600
@@ -56,8 +56,10 @@
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
fi
-if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ] \
- || [ "x`stat -f --printf=%T /`" = xbtrfs ]; then
+LINUX_ROOT_FS=`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`
+LINUX_ROOT_STAT=`stat -f --printf=%T / || true`
+
+if [ "x${LINUX_ROOT_FS}" = xbtrfs -o "x${LINUX_ROOT_STAT}" = xbtrfs ]; then
rootsubvol="`make_system_path_relative_to_its_root /`"
rootsubvol="${rootsubvol#/}"
if [ "x${rootsubvol}" != x ]; then
@@ -76,6 +78,10 @@
GRUB_CMDLINE_EXTRA="$GRUB_CMDLINE_EXTRA crashkernel=384M-2G:64M,2G-:128M"
fi
+if [ "x${LINUX_ROOT_FS}" = xzfs ]; then
+ GRUB_CMDLINE_LINUX="boot=zfs \$bootfs ${GRUB_CMDLINE_LINUX}"
+fi
+
linux_entry ()
{
os="$1"
@@ -114,6 +120,12 @@
fi
printf '%s\n' "${prepare_boot_cache}"
fi
+ if [ "x${LINUX_ROOT_FS}" = xzfs ]; then
+ cat << EOF
+ insmod zfsinfo
+ zfs-bootfs (\$root) bootfs
+EOF
+ fi
if [ "x$5" != "xquiet" ]; then
message="$(gettext_printf "Loading Linux %s ..." ${version})"
cat << EOF
Index: grub/util/getroot.c
===================================================================
--- grub.orig/util/getroot.c 2012-01-24 23:44:04.105772000 -0600
+++ grub/util/getroot.c 2012-01-27 20:48:50.875006000 -0600
@@ -52,6 +52,8 @@
#endif
#ifdef __linux__
+# include <stdio.h>
+# include <mntent.h>
# include <sys/types.h>
# include <sys/wait.h>
#endif
@@ -115,6 +117,8 @@
return path;
}
+static char *find_device_from_pool (const char *poolname);
+
#ifdef __linux__
#define ESCAPED_PATH_MAX (4 * PATH_MAX)
@@ -263,7 +267,32 @@
if (!*entries[i].device)
continue;
- ret = strdup (entries[i].device);
+ if (strcmp (entries[i].fstype, "zfs") == 0)
+ {
+ char *poolname = entries[i].device;
+ char *poolname_i = poolname;
+ char *poolname_j = poolname;
+ /* Replace \040 with a space. Cut at the first slash. */
+ while (*poolname_j)
+ {
+ if (*poolname_j == '/')
+ break;
+ if (strncmp (poolname_j, "\\040", 4) == 0)
+ {
+ *poolname_i = ' ';
+ poolname_i++;
+ poolname_j += 4;
+ continue;
+ }
+ *poolname_i = *poolname_j;
+ poolname_i++;
+ poolname_j++;
+ }
+ *poolname_i = '\0';
+ ret = find_device_from_pool (poolname);
+ }
+ else
+ ret = strdup (entries[i].device);
if (relroot)
*relroot = strdup (entries[i].enc_root);
break;
@@ -280,13 +309,25 @@
static char *
find_root_device_from_libzfs (const char *dir)
{
- char *device = NULL;
+ char *device;
char *poolname;
char *poolfs;
grub_find_zpool_from_dir (dir, &poolname, &poolfs);
if (! poolname)
return NULL;
+ if (poolfs)
+ free (poolfs);
+
+ device = find_device_from_pool(poolname);
+ free(poolname);
+ return device;
+}
+
+static char *
+find_device_from_pool (const char *poolname)
+{
+ char *device = NULL;
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
{
@@ -357,7 +398,7 @@
char cksum[257], notes[257];
unsigned int dummy;
- cmd = xasprintf ("zpool status %s", poolname);
+ cmd = xasprintf ("zpool status \"%s\"", poolname);
fp = popen (cmd, "r");
free (cmd);
@@ -382,7 +423,10 @@
st++;
break;
case 1:
- if (!strcmp (name, poolname))
+ /* Use strncmp() because poolname can technically have trailing
+ spaces, which the sscanf() above will not catch. Since we've
+ asked about this pool specifically, this should be safe. */
+ if (!strncmp (name, poolname, strlen(name)))
st++;
break;
case 2:
@@ -395,17 +439,71 @@
free (line);
}
+
+#ifdef __linux__
+ /* The name returned by zpool isn't necessarily directly under /dev. */
+ {
+ const char *disk_naming_schemes[] = {
+ "/dev/disk/by-id/%s",
+ "/dev/disk/by-path/%s",
+ "/dev/disk/by-uuid/%s",
+ "/dev/disk/by-partuuid/%s",
+ "/dev/disk/by-label/%s",
+ "/dev/disk/by-partlabel/%s",
+ "/dev/%s",
+ NULL
+ };
+ const char **disk_naming_scheme = disk_naming_schemes;
+
+ for (; *disk_naming_scheme ; disk_naming_scheme++)
+ {
+ struct stat sb;
+ device = xasprintf (*disk_naming_scheme, name);
+ if (stat (device, &sb) == 0)
+ {
+ char *real_device;
+ const char *c;
+ char *first_partition;
+
+ /* Resolve the symlink to something like /dev/sda. */
+ real_device = realpath (device, NULL);
+ 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')
+ {
+ device = real_device;
+ break;
+ }
+
+ /* Otherwise, it might be a partitioned wholedisk vdev. */
+ first_partition = xasprintf ("%s1", real_device);
+ if (stat (first_partition, &sb) == 0)
+ {
+ free (real_device);
+ device = first_partition;
+ break;
+ }
+
+ /* The device is not partitioned. */
+ free (device);
+ device = real_device;
+ break;
+ }
+ free (device);
+ device = NULL;
+ }
+ }
+#else
device = xasprintf ("/dev/%s", name);
+#endif /* !__linux__ */
fail:
pclose (fp);
}
#endif
- free (poolname);
- if (poolfs)
- free (poolfs);
-
return device;
}
@@ -708,10 +806,10 @@
#ifdef __linux__
if (!os_dev)
os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
-#endif /* __linux__ */
-
+#else
if (!os_dev)
os_dev = find_root_device_from_libzfs (dir);
+#endif /* !__linux__ */
if (os_dev)
{
@@ -1484,6 +1582,37 @@
break;
}
}
+
+ fclose (mnttab);
+ }
+#elif defined(__linux__)
+ {
+ struct stat st;
+ struct mntent *mnt;
+ FILE *mnttab;
+
+ if (stat (dir, &st) != 0)
+ return;
+
+ mnttab = fopen ("/proc/mounts", "r");
+ if (! mnttab)
+ mnttab = fopen ("/etc/mtab", "r");
+ if (! mnttab)
+ return;
+
+ while ((mnt = getmntent (mnttab)) != NULL)
+ {
+ struct stat mnt_st;
+ if (strcmp (mnt->mnt_type, "zfs") != 0)
+ continue;
+ if (stat (mnt->mnt_dir, &mnt_st) != 0)
+ continue;
+ if (mnt_st.st_dev == st.st_dev)
+ {
+ *poolname = xstrdup (mnt->mnt_fsname);
+ break;
+ }
+ }
fclose (mnttab);
}
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
next prev parent reply other threads:[~2012-01-28 2:50 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-19 18:45 [Patch] Robustly search for ZFS labels & uberblocks Zachary Bedell
2011-09-28 21:20 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-19 11:36 ` Richard Laager
2012-01-22 14:18 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-22 20:31 ` Richard Laager
2012-01-24 7:12 ` Richard Laager
2012-01-27 19:04 ` Zachary Bedell
2012-01-27 22:22 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-28 2:50 ` Richard Laager [this message]
2012-01-28 12:51 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-28 16:50 ` Richard Laager
2012-01-28 17:06 ` Darik Horn
2012-01-28 17:39 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-28 18:33 ` Richard Laager
2012-01-28 19:21 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-29 22:42 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-31 8:45 ` Richard Laager
2012-02-02 11:13 ` Richard Laager
2012-02-03 10:02 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-02-03 9:52 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-02-03 11:20 ` Richard Laager
2012-01-28 18:40 ` Darik Horn
2012-01-28 19:27 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-01-30 1:22 ` Richard Laager
2012-01-30 1:43 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-11-03 14:45 ` Vladimir 'φ-coder/phcoder' Serbinenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1327719035.9477.68.camel@watermelon.coderich.net \
--to=rlaager@wiktel.com \
--cc=grub-devel@gnu.org \
--cc=pendorbound@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).