Add support for /boot on btrfs
This commit is contained in:
parent
e0fe64ca89
commit
7d47e62c2e
143
0001-Change-return-type-in-getRootSpecifier.patch
Normal file
143
0001-Change-return-type-in-getRootSpecifier.patch
Normal file
@ -0,0 +1,143 @@
|
||||
From c1c46d21182974181f5b4c2ed0a02288b4bfd880 Mon Sep 17 00:00:00 2001
|
||||
From: Nathaniel McCallum <npmccallum@redhat.com>
|
||||
Date: Fri, 2 Mar 2018 14:59:32 -0500
|
||||
Subject: [PATCH 1/3] Change return type in getRootSpecifier()
|
||||
|
||||
Rather than returning a new allocation of the prefix, just return the
|
||||
length of the prefix. This change accomplishes a couple things. First,
|
||||
it reduces some memory leaks since the return value was often never
|
||||
freed. Second, it simplifies the caller who is usually only interested
|
||||
in the length of the prefix.
|
||||
---
|
||||
grubby.c | 54 +++++++++++++++++++++++++++---------------------------
|
||||
1 file changed, 27 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/grubby.c b/grubby.c
|
||||
index d4ebb86..a062ef8 100644
|
||||
--- a/grubby.c
|
||||
+++ b/grubby.c
|
||||
@@ -675,7 +675,7 @@ static int lineWrite(FILE * out, struct singleLine * line,
|
||||
struct configFileInfo * cfi);
|
||||
static int getNextLine(char ** bufPtr, struct singleLine * line,
|
||||
struct configFileInfo * cfi);
|
||||
-static char * getRootSpecifier(char * str);
|
||||
+static size_t getRootSpecifier(const char *str);
|
||||
static void requote(struct singleLine *line, struct configFileInfo * cfi);
|
||||
static void insertElement(struct singleLine * line,
|
||||
const char * item, int insertHere,
|
||||
@@ -1840,7 +1840,7 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix,
|
||||
char * fullName;
|
||||
int i;
|
||||
char * dev;
|
||||
- char * rootspec;
|
||||
+ size_t rs;
|
||||
char * rootdev;
|
||||
|
||||
if (skipRemoved && entry->skip) {
|
||||
@@ -1866,12 +1866,11 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix,
|
||||
|
||||
fullName = alloca(strlen(bootPrefix) +
|
||||
strlen(line->elements[1].item) + 1);
|
||||
- rootspec = getRootSpecifier(line->elements[1].item);
|
||||
- int rootspec_offset = rootspec ? strlen(rootspec) : 0;
|
||||
+ rs = getRootSpecifier(line->elements[1].item);
|
||||
int hasslash = endswith(bootPrefix, '/') ||
|
||||
- beginswith(line->elements[1].item + rootspec_offset, '/');
|
||||
+ beginswith(line->elements[1].item + rs, '/');
|
||||
sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
|
||||
- line->elements[1].item + rootspec_offset);
|
||||
+ line->elements[1].item + rs);
|
||||
if (access(fullName, R_OK)) {
|
||||
notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
|
||||
return 0;
|
||||
@@ -1952,7 +1951,6 @@ struct singleEntry * findEntryByPath(struct grubConfig * config,
|
||||
struct singleLine * line;
|
||||
int i;
|
||||
char * chptr;
|
||||
- char * rootspec = NULL;
|
||||
enum lineType_e checkType = LT_KERNEL;
|
||||
|
||||
if (isdigit(*kernel)) {
|
||||
@@ -2044,11 +2042,10 @@ struct singleEntry * findEntryByPath(struct grubConfig * config,
|
||||
|
||||
if (line && line->type != LT_MENUENTRY &&
|
||||
line->numElements >= 2) {
|
||||
- rootspec = getRootSpecifier(line->elements[1].item);
|
||||
- if (!strcmp(line->elements[1].item +
|
||||
- ((rootspec != NULL) ? strlen(rootspec) : 0),
|
||||
- kernel + strlen(prefix)))
|
||||
- break;
|
||||
+ if (!strcmp(line->elements[1].item +
|
||||
+ getRootSpecifier(line->elements[1].item),
|
||||
+ kernel + strlen(prefix)))
|
||||
+ break;
|
||||
}
|
||||
if(line->type == LT_MENUENTRY &&
|
||||
!strcmp(line->elements[1].item, kernel))
|
||||
@@ -2797,11 +2794,11 @@ struct singleLine * addLineTmpl(struct singleEntry * entry,
|
||||
|
||||
/* but try to keep the rootspec from the template... sigh */
|
||||
if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD|LT_KERNEL_EFI|LT_INITRD_EFI|LT_KERNEL_16|LT_INITRD_16)) {
|
||||
- char * rootspec = getRootSpecifier(tmplLine->elements[1].item);
|
||||
- if (rootspec != NULL) {
|
||||
- free(newLine->elements[1].item);
|
||||
- newLine->elements[1].item =
|
||||
- sdupprintf("%s%s", rootspec, val);
|
||||
+ size_t rs = getRootSpecifier(tmplLine->elements[1].item);
|
||||
+ if (rs > 0) {
|
||||
+ free(newLine->elements[1].item);
|
||||
+ newLine->elements[1].item = sdupprintf("%.*s%s", (int) rs,
|
||||
+ tmplLine->elements[1].item, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3729,15 +3726,19 @@ int checkForElilo(struct grubConfig * config) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static char * getRootSpecifier(char * str) {
|
||||
- char * idx, * rootspec = NULL;
|
||||
+static size_t getRootSpecifier(const char *str)
|
||||
+{
|
||||
+ size_t rs = 0;
|
||||
|
||||
if (*str == '(') {
|
||||
- idx = rootspec = strdup(str);
|
||||
- while(*idx && (*idx != ')') && (!isspace(*idx))) idx++;
|
||||
- *(++idx) = '\0';
|
||||
+ for (; str[rs] != ')' && !isspace(str[rs]); rs++) {
|
||||
+ if (!str[rs])
|
||||
+ return rs;
|
||||
+ }
|
||||
+ rs++;
|
||||
}
|
||||
- return rootspec;
|
||||
+
|
||||
+ return rs;
|
||||
}
|
||||
|
||||
static char * getInitrdVal(struct grubConfig * config,
|
||||
@@ -4616,7 +4617,7 @@ int main(int argc, const char ** argv) {
|
||||
if (displayDefault) {
|
||||
struct singleLine * line;
|
||||
struct singleEntry * entry;
|
||||
- char * rootspec;
|
||||
+ size_t rs;
|
||||
|
||||
if (config->defaultImage == -1) return 0;
|
||||
if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
|
||||
@@ -4629,9 +4630,8 @@ int main(int argc, const char ** argv) {
|
||||
line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
|
||||
if (!line) return 0;
|
||||
|
||||
- rootspec = getRootSpecifier(line->elements[1].item);
|
||||
- printf("%s%s\n", bootPrefix, line->elements[1].item +
|
||||
- ((rootspec != NULL) ? strlen(rootspec) : 0));
|
||||
+ rs = getRootSpecifier(line->elements[1].item);
|
||||
+ printf("%s%s\n", bootPrefix, line->elements[1].item + rs);
|
||||
|
||||
return 0;
|
||||
|
||||
--
|
||||
2.14.3
|
||||
|
209
0002-Add-btrfs-subvolume-support-for-grub2.patch
Normal file
209
0002-Add-btrfs-subvolume-support-for-grub2.patch
Normal file
@ -0,0 +1,209 @@
|
||||
From 5dec033b19bb5b07a0a136a7357e16c8ca9f5dd6 Mon Sep 17 00:00:00 2001
|
||||
From: Nathaniel McCallum <npmccallum@redhat.com>
|
||||
Date: Fri, 2 Mar 2018 08:40:18 -0500
|
||||
Subject: [PATCH 2/3] Add btrfs subvolume support for grub2
|
||||
|
||||
In order to find the subvolume prefix from a given path, we parse
|
||||
/proc/mounts. In cases where /proc/mounts doesn't contain the
|
||||
filesystem, the caller can use the --mounts option to specify his own
|
||||
mounts file.
|
||||
|
||||
Btrfs subvolumes are already supported by grub2 and by grub2-mkconfig.
|
||||
|
||||
Fixes #22
|
||||
---
|
||||
grubby.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 143 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grubby.c b/grubby.c
|
||||
index a062ef8..96d252a 100644
|
||||
--- a/grubby.c
|
||||
+++ b/grubby.c
|
||||
@@ -68,6 +68,8 @@ int isEfi = 0;
|
||||
|
||||
char *saved_command_line = NULL;
|
||||
|
||||
+const char *mounts = "/proc/mounts";
|
||||
+
|
||||
/* comments get lumped in with indention */
|
||||
struct lineElement {
|
||||
char * item;
|
||||
@@ -1834,6 +1836,129 @@ static int endswith(const char *s, char c)
|
||||
return s[slen] == c;
|
||||
}
|
||||
|
||||
+typedef struct {
|
||||
+ const char *start;
|
||||
+ size_t chars;
|
||||
+} field;
|
||||
+
|
||||
+static int iscomma(int c)
|
||||
+{
|
||||
+ return c == ',';
|
||||
+}
|
||||
+
|
||||
+static int isequal(int c)
|
||||
+{
|
||||
+ return c == '=';
|
||||
+}
|
||||
+
|
||||
+static field findField(const field *in, typeof(isspace) *isdelim, field *out)
|
||||
+{
|
||||
+ field nxt = {};
|
||||
+ size_t off = 0;
|
||||
+
|
||||
+ while (off < in->chars && isdelim(in->start[off]))
|
||||
+ off++;
|
||||
+
|
||||
+ if (off == in->chars)
|
||||
+ return nxt;
|
||||
+
|
||||
+ out->start = &in->start[off];
|
||||
+ out->chars = 0;
|
||||
+
|
||||
+ while (off + out->chars < in->chars && !isdelim(out->start[out->chars]))
|
||||
+ out->chars++;
|
||||
+
|
||||
+ nxt.start = out->start + out->chars;
|
||||
+ nxt.chars = in->chars - off - out->chars;
|
||||
+ return nxt;
|
||||
+}
|
||||
+
|
||||
+static int fieldEquals(const field *in, const char *str)
|
||||
+{
|
||||
+ return in->chars == strlen(str) &&
|
||||
+ strncmp(in->start, str, in->chars) == 0;
|
||||
+}
|
||||
+
|
||||
+/* Parse /proc/mounts to determine the subvolume prefix. */
|
||||
+static size_t subvolPrefix(const char *str)
|
||||
+{
|
||||
+ FILE *file = NULL;
|
||||
+ char *line = NULL;
|
||||
+ size_t prfx = 0;
|
||||
+ size_t size = 0;
|
||||
+
|
||||
+ file = fopen(mounts, "r");
|
||||
+ if (!file)
|
||||
+ return 0;
|
||||
+
|
||||
+ for (ssize_t s; (s = getline(&line, &size, file)) >= 0; ) {
|
||||
+ field nxt = { line, s };
|
||||
+ field dev = {};
|
||||
+ field path = {};
|
||||
+ field type = {};
|
||||
+ field opts = {};
|
||||
+ field opt = {};
|
||||
+
|
||||
+ nxt = findField(&nxt, isspace, &dev);
|
||||
+ if (!nxt.start)
|
||||
+ continue;
|
||||
+
|
||||
+ nxt = findField(&nxt, isspace, &path);
|
||||
+ if (!nxt.start)
|
||||
+ continue;
|
||||
+
|
||||
+ nxt = findField(&nxt, isspace, &type);
|
||||
+ if (!nxt.start)
|
||||
+ continue;
|
||||
+
|
||||
+ nxt = findField(&nxt, isspace, &opts);
|
||||
+ if (!nxt.start)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!fieldEquals(&type, "btrfs"))
|
||||
+ continue;
|
||||
+
|
||||
+ /* We have found a btrfs mount point. */
|
||||
+
|
||||
+ nxt = opts;
|
||||
+ while ((nxt = findField(&nxt, iscomma, &opt)).start) {
|
||||
+ field key = {};
|
||||
+ field val = {};
|
||||
+
|
||||
+ opt = findField(&opt, isequal, &key);
|
||||
+ if (!opt.start)
|
||||
+ continue;
|
||||
+
|
||||
+ opt = findField(&opt, isequal, &val);
|
||||
+ if (!opt.start)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!fieldEquals(&key, "subvol"))
|
||||
+ continue;
|
||||
+
|
||||
+ /* We have found a btrfs subvolume mount point. */
|
||||
+
|
||||
+ if (strncmp(val.start, str, val.chars))
|
||||
+ continue;
|
||||
+
|
||||
+ if (val.start[val.chars - 1] != '/' &&
|
||||
+ str[val.chars] != '/')
|
||||
+ continue;
|
||||
+
|
||||
+ /* The subvolume mount point matches our input. */
|
||||
+
|
||||
+ if (prfx < val.chars)
|
||||
+ prfx = val.chars;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dbgPrintf("%s(): str: '%s', prfx: '%s'\n", __FUNCTION__, str, prfx);
|
||||
+
|
||||
+ fclose(file);
|
||||
+ free(line);
|
||||
+ return prfx;
|
||||
+}
|
||||
+
|
||||
int suitableImage(struct singleEntry * entry, const char * bootPrefix,
|
||||
int skipRemoved, int flags) {
|
||||
struct singleLine * line;
|
||||
@@ -2794,12 +2919,22 @@ struct singleLine * addLineTmpl(struct singleEntry * entry,
|
||||
|
||||
/* but try to keep the rootspec from the template... sigh */
|
||||
if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD|LT_KERNEL_EFI|LT_INITRD_EFI|LT_KERNEL_16|LT_INITRD_16)) {
|
||||
- size_t rs = getRootSpecifier(tmplLine->elements[1].item);
|
||||
+ const char *prfx = tmplLine->elements[1].item;
|
||||
+ size_t rs = getRootSpecifier(prfx);
|
||||
+ if (isinitrd(tmplLine->type)) {
|
||||
+ for (struct singleLine *l = entry->lines;
|
||||
+ rs == 0 && l; l = l->next) {
|
||||
+ if (iskernel(l->type)) {
|
||||
+ prfx = l->elements[1].item;
|
||||
+ rs = getRootSpecifier(prfx);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
if (rs > 0) {
|
||||
free(newLine->elements[1].item);
|
||||
- newLine->elements[1].item = sdupprintf("%.*s%s", (int) rs,
|
||||
- tmplLine->elements[1].item, val);
|
||||
- }
|
||||
+ newLine->elements[1].item = sdupprintf("%.*s%s",
|
||||
+ (int) rs, prfx, val);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3738,7 +3873,7 @@ static size_t getRootSpecifier(const char *str)
|
||||
rs++;
|
||||
}
|
||||
|
||||
- return rs;
|
||||
+ return rs + subvolPrefix(str + rs);
|
||||
}
|
||||
|
||||
static char * getInitrdVal(struct grubConfig * config,
|
||||
@@ -4253,6 +4388,9 @@ int main(int argc, const char ** argv) {
|
||||
{ "mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0,
|
||||
_("default arguments for the new multiboot kernel or "
|
||||
"new arguments for multiboot kernel being updated"), NULL },
|
||||
+ { "mounts", 0, POPT_ARG_STRING, &mounts, 0,
|
||||
+ _("path to fake /proc/mounts file (for testing only)"),
|
||||
+ _("mounts") },
|
||||
{ "bad-image-okay", 0, 0, &badImageOkay, 0,
|
||||
_("don't sanity check images in boot entries (for testing only)"),
|
||||
NULL },
|
||||
--
|
||||
2.14.3
|
||||
|
1871
0003-Add-tests-for-btrfs-support.patch
Normal file
1871
0003-Add-tests-for-btrfs-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
Name: grubby
|
||||
Version: 8.40
|
||||
Release: 9%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Summary: Command line tool for updating bootloader configs
|
||||
License: GPLv2+
|
||||
URL: https://github.com/rhinstaller/grubby
|
||||
@ -10,6 +10,9 @@ URL: https://github.com/rhinstaller/grubby
|
||||
# Source0: %%{name}-%%{version}.tar.bz2
|
||||
Source0: https://github.com/rhboot/grubby/archive/%{version}-1.tar.gz
|
||||
Patch1: drop-uboot-uImage-creation.patch
|
||||
Patch2: 0001-Change-return-type-in-getRootSpecifier.patch
|
||||
Patch3: 0002-Add-btrfs-subvolume-support-for-grub2.patch
|
||||
Patch4: 0003-Add-tests-for-btrfs-support.patch
|
||||
|
||||
BuildRequires: pkgconfig glib2-devel popt-devel
|
||||
BuildRequires: libblkid-devel git-core
|
||||
@ -62,6 +65,9 @@ make install DESTDIR=$RPM_BUILD_ROOT mandir=%{_mandir}
|
||||
%{_mandir}/man8/*.8*
|
||||
|
||||
%changelog
|
||||
* Sat Mar 03 2018 Nathaniel McCallum <npmccallum@redhat.com> - 8.40-10
|
||||
- Add support for /boot on btrfs subvolumes
|
||||
|
||||
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user