@@ -985,7 +985,8 @@ supported:
| fstype | string | Optional filesystem type to be created on the |
| | | partition. If no fstype key is given, no file |
| | | will be created on the corresponding partition. |
- | | | vfat / ext2 / ext3 /ext4 file system is supported |
+ | | | vfat / ext2 / ext3 /ext4 / btrfs |
+ | | | file system is supported |
+-------------+----------+----------------------------------------------------+
| partuuid | string | The partition UUID (GPT only). If omitted, a UUID |
| | | will be generated automatically. |
@@ -1152,6 +1153,30 @@ found on the device. It is a partition handler and it runs before any image is i
}
});
+BTRFS Handler
+-------------
+
+This handler is activated if support for BTRFS is on. It allows to created and delete subvolumes
+during an update.
+
+::
+
+ partitions: (
+ {
+ type = "btrfs";
+ device = "/dev/loop0p1";
+
+ properties: {
+ command = < one of create" or "delete" >
+ path = <path for the subvolume>;
+ mount = "true" or missing;
+ }
+ })
+
+
+If `mount` is set, SWUpdate will mount the device and the path is appenden to the
+mountpoint used with mount. If device is already mounted, path is the absolute path.
+
Delta Update Handler
--------------------
@@ -10,6 +10,7 @@
obj-y += dummy_handler.o chain_handler.o
obj-$(CONFIG_ARCHIVE) += archive_handler.o
obj-$(CONFIG_BOOTLOADERHANDLER) += boot_handler.o
+obj-$(CONFIG_BTRFS_FILESYSTEM) += btrfs_handler.o
obj-$(CONFIG_COPY) += copy_handler.o
obj-$(CONFIG_CFI) += flash_handler.o
obj-$(CONFIG_DELTA) += delta_handler.o delta_downloader.o zchunk_range.o
new file mode 100644
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2023
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <util.h>
+#include <blkid/blkid.h>
+#include <btrfsutil.h>
+#include "fs_interface.h"
+#include "progress.h"
+#include "swupdate_image.h"
+#include "handler.h"
+
+typedef enum {
+ BTRFS_UNKNOWN,
+ BTRFS_CREATE_SUBVOLUME,
+ BTRFS_DELETE_SUBVOLUME
+} btrfs_op_t;
+
+void btrfs_handler(void);
+
+static int btrfs(struct img_type *img,
+ void __attribute__ ((__unused__)) *data)
+{
+ int ret = 0;
+ btrfs_op_t op;
+ enum btrfs_util_error btrfs_error;
+
+ char *subvol_path = dict_get_value(&img->properties, "path");
+ char *cmd = dict_get_value(&img->properties, "command");
+ char *globalpath;
+ char *mountpoint;
+
+ op = IS_STR_EQUAL(cmd, "create") ? BTRFS_CREATE_SUBVOLUME :
+ IS_STR_EQUAL(cmd, "delete") ? BTRFS_DELETE_SUBVOLUME : BTRFS_UNKNOWN;
+
+ if (op == BTRFS_UNKNOWN) {
+ ERROR("Wrong operation of btrfs filesystem: %s", cmd);
+ return -EINVAL;
+ }
+ bool tomount = IS_STR_EQUAL(dict_get_value(&img->properties, "mount"), "true");
+ if (tomount) {
+ if (!strlen(img->device)) {
+ ERROR("btrfs must be mounted, no device set");
+ return -EINVAL;
+ }
+ globalpath = alloca(strlen(get_tmpdir()) +
+ strlen(DATADST_DIR_SUFFIX) + strlen(subvol_path) + 2);
+ sprintf(globalpath, "%s%s", get_tmpdir(), DATADST_DIR_SUFFIX);
+ mountpoint = strdupa(globalpath);
+ DEBUG("Try to mount %s as BTRFS", mountpoint);
+ ret = swupdate_mount(img->device, mountpoint, "btrfs");
+ if (ret) {
+ ERROR("%s cannot be mounted with btrfs", img->device);
+ return -1;
+ }
+ globalpath = strcat(globalpath, subvol_path);
+ } else
+ globalpath = subvol_path;
+
+ DEBUG("%s subvolume %s...", (op == BTRFS_CREATE_SUBVOLUME) ? "Creating" : "Deleting", subvol_path);
+ switch (op) {
+ case BTRFS_CREATE_SUBVOLUME:
+ btrfs_error = btrfs_util_create_subvolume(globalpath, 0, NULL, NULL);
+ break;
+ case BTRFS_DELETE_SUBVOLUME:
+ btrfs_error = btrfs_util_delete_subvolume(globalpath, BTRFS_UTIL_DELETE_SUBVOLUME_RECURSIVE);
+ break;
+ default:
+ btrfs_error = BTRFS_UTIL_ERROR_FS_INFO_FAILED;
+ break;
+ }
+
+ if (btrfs_error != BTRFS_UTIL_OK) {
+ ERROR("BTRFS %s failed with btrfs error : %s", cmd,
+ btrfs_util_strerror(btrfs_error));
+ ret = -1;
+ }
+
+ if (tomount) {
+ /*
+ * btrfs needs some time after creating a subvolume,
+ * so just delay here
+ */
+ sleep(1);
+ swupdate_umount(mountpoint);
+ }
+ /*
+ * Declare that handler has finished
+ */
+ swupdate_progress_update(100);
+
+ return ret;
+}
+
+__attribute__((constructor))
+void btrfs_handler(void)
+{
+ register_handler("btrfs", btrfs,
+ PARTITION_HANDLER | NO_DATA_HANDLER, NULL);
+}
Add an handler that works as wrapper for libbtrfsutil and add support to sw-description. Creation / deletion of subvolumes are supported. Signed-off-by: Stefano Babic <sbabic@denx.de> --- doc/source/handlers.rst | 27 +++++++++- handlers/Makefile | 1 + handlers/btrfs_handler.c | 105 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 handlers/btrfs_handler.c