[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/7] Add support for special envblk functions in GRUB
From: |
Paul Dagnelie |
Subject: |
[PATCH 2/7] Add support for special envblk functions in GRUB |
Date: |
Wed, 11 Mar 2020 10:37:10 -0700 |
This patch introducces the idea of envblk functions to GRUB. These functions
are used to interact with a grubenv file stored not in the usual grub tree,
but instead in a special filesystem-managed region that can more easily be
accessed at boot time. These functions interface between calling code and the
per-fs logic, an interface for which is also added as part of this patch.
Signed-off-by: Paul Dagnelie <address@hidden>
---
grub-core/kern/file.c | 30 ++++++++++++++++++++++++++++--
include/grub/file.h | 10 ++++++++++
include/grub/fs.h | 12 ++++++++++++
3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index 75eb5e2fa..f929f61a0 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -149,6 +149,27 @@ grub_file_open (const char *name, enum grub_file_type type)
return 0;
}
+grub_file_t
+grub_file_envblk_open (grub_fs_t fs, grub_device_t device, enum grub_file_type
type)
+{
+ grub_file_t file = NULL;
+ file = (grub_file_t) grub_zalloc (sizeof (*file));
+ if (! file)
+ return NULL;
+ file->device = device;
+ file->special = 1;
+
+ if ((fs->fs_envblk_open) (file) != GRUB_ERR_NONE) {
+ grub_free(file);
+ return NULL;
+ }
+
+ file->fs = fs;
+ grub_errno = GRUB_ERR_NONE;
+
+ return grub_apply_file_filters(file, type, NULL);
+}
+
grub_disk_read_hook_t grub_file_progress_hook;
grub_ssize_t
@@ -185,7 +206,10 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t
len)
file->read_hook_data = file;
file->progress_offset = file->offset;
}
- res = (file->fs->fs_read) (file, buf, len);
+ if (grub_file_envblk (file))
+ res = (file->fs->fs_envblk_read) (file, buf, len);
+ else
+ res = (file->fs->fs_read) (file, buf, len);
file->read_hook = read_hook;
file->read_hook_data = read_hook_data;
if (res > 0)
@@ -197,7 +221,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t
len)
grub_err_t
grub_file_close (grub_file_t file)
{
- if (file->fs->fs_close)
+ if (grub_file_envblk (file) && file->fs->fs_envblk_close)
+ (file->fs->fs_envblk_close) (file);
+ else if (file->fs->fs_close)
(file->fs->fs_close) (file);
if (file->device)
diff --git a/include/grub/file.h b/include/grub/file.h
index 31567483c..1cc688f55 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -170,6 +170,9 @@ struct grub_file
/* Caller-specific data passed to the read hook. */
void *read_hook_data;
+
+ /* If the file is an FS's special file, which uses separate functions for
interaction. */
+ int special;
};
typedef struct grub_file *grub_file_t;
@@ -211,6 +214,7 @@ grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file,
void *buf,
grub_size_t len);
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
+grub_file_t EXPORT_FUNC(grub_file_envblk_open) (grub_fs_t fs, grub_device_t
device, enum grub_file_type type);
/* Return value of grub_file_size() in case file size is unknown. */
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL
@@ -233,6 +237,12 @@ grub_file_seekable (const grub_file_t file)
return !file->not_easily_seekable;
}
+static inline int
+grub_file_envblk (const grub_file_t file)
+{
+ return file->special;
+}
+
grub_file_t
grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
grub_off_t start, grub_off_t size);
diff --git a/include/grub/fs.h b/include/grub/fs.h
index 302e48d4b..ec1a7a50e 100644
--- a/include/grub/fs.h
+++ b/include/grub/fs.h
@@ -96,6 +96,18 @@ struct grub_fs
/* Whether blocklist installs have a chance to work. */
int blocklist_install;
#endif
+
+ /*
+ * The envblk functions are defined on filesystems that need to handle
+ * grub-writable files in a special way. This is most commonly the case for
+ * CoW filesystems like btrfs and ZFS. The normal read and close functions
+ * should detect that they are being called on a special file and act
+ * appropriately.
+ */
+ grub_err_t (*fs_envblk_open) (struct grub_file *file);
+ grub_ssize_t (*fs_envblk_read) (struct grub_file *file, char *buf,
grub_size_t len);
+ grub_err_t (*fs_envblk_write) (struct grub_file *file, char *buf,
grub_size_t len);
+ grub_err_t (*fs_envblk_close) (struct grub_file *file);
};
typedef struct grub_fs *grub_fs_t;
--
2.19.0
- [PATCH 0/7] ZFS/other CoW FS save_env support, Paul Dagnelie, 2020/03/11
- [PATCH 1/7] Factor out file filter function for reuse, Paul Dagnelie, 2020/03/11
- [PATCH 2/7] Add support for special envblk functions in GRUB,
Paul Dagnelie <=
- [PATCH 3/7] Factor out envblk buffer creation for reuse, Paul Dagnelie, 2020/03/11
- [PATCH 4/7] Use envblk file and fs functions to implement reading the grubenv file from special FS regions, Paul Dagnelie, 2020/03/11
- [PATCH 5/7] Add ZFS envblock functions, Paul Dagnelie, 2020/03/11
- [PATCH 6/7] Refactor default envblk size out for reuse, Paul Dagnelie, 2020/03/11
- [PATCH 7/7] Update editenv to support editing zfs envblock, fix whitespace, and autodetect bootenv support in libzfs, Paul Dagnelie, 2020/03/11
- Re: [PATCH 0/7] ZFS/other CoW FS save_env support, Daniel Kiper, 2020/03/25