diff --git a/libcomposefs/lcfs-internal.h b/libcomposefs/lcfs-internal.h index 5c3d566a..9f3957e6 100644 --- a/libcomposefs/lcfs-internal.h +++ b/libcomposefs/lcfs-internal.h @@ -58,11 +58,13 @@ typedef int errint_t; #define OVERLAY_XATTR_ESCAPED_WHITEOUT OVERLAY_XATTR_ESCAPE_PREFIX "whiteout" #define OVERLAY_XATTR_ESCAPED_WHITEOUTS OVERLAY_XATTR_ESCAPE_PREFIX "whiteouts" +#define OVERLAY_XATTR_ESCAPED_OPAQUE OVERLAY_XATTR_ESCAPE_PREFIX "opaque" #define OVERLAY_XATTR_USERXATTR_WHITEOUT \ OVERLAY_XATTR_USERXATTR_PREFIX "whiteout" #define OVERLAY_XATTR_USERXATTR_WHITEOUTS \ OVERLAY_XATTR_USERXATTR_PREFIX "whiteouts" +#define OVERLAY_XATTR_USERXATTR_OPAQUE OVERLAY_XATTR_USERXATTR_PREFIX "opaque" #define ALIGN_TO(_offset, _align_size) \ (((_offset) + _align_size - 1) & ~(_align_size - 1)) diff --git a/libcomposefs/lcfs-writer-erofs.c b/libcomposefs/lcfs-writer-erofs.c index 52375b37..d24984c5 100644 --- a/libcomposefs/lcfs-writer-erofs.c +++ b/libcomposefs/lcfs-writer-erofs.c @@ -1067,7 +1067,7 @@ static int write_erofs_shared_xattrs(struct lcfs_ctx_s *ctx) return 0; } -static int add_overlayfs_xattrs(struct lcfs_node_s *node) +static int add_overlayfs_xattrs(struct lcfs_ctx_s *ctx, struct lcfs_node_s *node) { int type = node->inode.st_mode & S_IFMT; int ret; @@ -1148,6 +1148,18 @@ static int add_overlayfs_xattrs(struct lcfs_node_s *node) "", 0); if (ret < 0) return ret; + + /* Mark dir containing whiteouts with new format as of version 1 */ + if (ctx->options->version >= 1) { + ret = lcfs_node_set_xattr( + parent, OVERLAY_XATTR_ESCAPED_OPAQUE, "x", 1); + if (ret < 0) + return ret; + ret = lcfs_node_set_xattr( + parent, OVERLAY_XATTR_USERXATTR_OPAQUE, "x", 1); + if (ret < 0) + return ret; + } } return 0; @@ -1206,12 +1218,13 @@ static int add_overlay_whiteouts(struct lcfs_node_s *root) return 0; } -static int rewrite_tree_node_for_erofs(struct lcfs_node_s *node, +static int rewrite_tree_node_for_erofs(struct lcfs_ctx_s *ctx, + struct lcfs_node_s *node, struct lcfs_node_s *parent) { int ret; - ret = add_overlayfs_xattrs(node); + ret = add_overlayfs_xattrs(ctx, node); if (ret < 0) return ret; @@ -1256,7 +1269,7 @@ static int rewrite_tree_node_for_erofs(struct lcfs_node_s *node, continue; } - ret = rewrite_tree_node_for_erofs(child, node); + ret = rewrite_tree_node_for_erofs(ctx, child, node); if (ret < 0) { return -1; } @@ -1277,11 +1290,11 @@ static int set_overlay_opaque(struct lcfs_node_s *node) return 0; } -static int rewrite_tree_for_erofs(struct lcfs_node_s *root) +static int rewrite_tree_for_erofs(struct lcfs_ctx_s *ctx, struct lcfs_node_s *root) { int res; - res = rewrite_tree_node_for_erofs(root, root); + res = rewrite_tree_node_for_erofs(ctx, root, root); if (res < 0) return res; @@ -1320,7 +1333,7 @@ int lcfs_write_erofs_to(struct lcfs_ctx_s *ctx) root = ctx->root; /* After we cloned it */ /* Rewrite cloned tree as needed for erofs */ - ret = rewrite_tree_for_erofs(root); + ret = rewrite_tree_for_erofs(ctx, root); if (ret < 0) return ret; diff --git a/libcomposefs/lcfs-writer.h b/libcomposefs/lcfs-writer.h index df7f261c..0e585710 100644 --- a/libcomposefs/lcfs-writer.h +++ b/libcomposefs/lcfs-writer.h @@ -48,7 +48,11 @@ enum lcfs_flags_t { LCFS_FLAGS_MASK = 0, }; -#define LCFS_VERSION_MAX 0 +#define LCFS_VERSION_MAX 1 +/* Version history: + * 0 - Initial version + * 1 - Mark xwhitouts using the new opaque=x format as needed by Linux 6.8 + */ typedef ssize_t (*lcfs_read_cb)(void *file, void *buf, size_t count); typedef ssize_t (*lcfs_write_cb)(void *file, void *buf, size_t count); diff --git a/tests/Makefile.am b/tests/Makefile.am index f82c9b56..3d1b6222 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,5 @@ TEST_ASSETS_SMALL = \ - config.dump.gz config-with-hard-link.dump.gz special.dump + config.dump.gz config-with-hard-link.dump.gz special.dump special_v1.dump TEST_ASSETS = ${TEST_ASSETS_SMALL} \ cs9-x86_64-developer.dump.gz cs9-x86_64-minimal.dump.gz \ diff --git a/tests/assets/special.dump.sha256 b/tests/assets/special.dump.sha256 index ff898dc7..9776deb6 100644 --- a/tests/assets/special.dump.sha256 +++ b/tests/assets/special.dump.sha256 @@ -1 +1 @@ -d344782ff962ab7d1c5533755c19c5bf3c3485f55bfaf228fc89524c7e2ba61e \ No newline at end of file +d344782ff962ab7d1c5533755c19c5bf3c3485f55bfaf228fc89524c7e2ba61e diff --git a/tests/assets/special.dump.version b/tests/assets/special.dump.version new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/tests/assets/special.dump.version @@ -0,0 +1 @@ +0 diff --git a/tests/assets/special_v1.dump b/tests/assets/special_v1.dump new file mode 120000 index 00000000..9c50b02f --- /dev/null +++ b/tests/assets/special_v1.dump @@ -0,0 +1 @@ +special.dump \ No newline at end of file diff --git a/tests/assets/special_v1.dump.sha256 b/tests/assets/special_v1.dump.sha256 new file mode 100644 index 00000000..eeb1dd9a --- /dev/null +++ b/tests/assets/special_v1.dump.sha256 @@ -0,0 +1 @@ +ee8028939ca3151a50bbbbd377c52c46ab183013610c8909e624840bf496975f diff --git a/tests/assets/special_v1.dump.version b/tests/assets/special_v1.dump.version new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/tests/assets/special_v1.dump.version @@ -0,0 +1 @@ +1 diff --git a/tests/dumpdir b/tests/dumpdir index 3e2d4bd7..a60a2970 100755 --- a/tests/dumpdir +++ b/tests/dumpdir @@ -37,6 +37,8 @@ def dumpfile(file, root): if stat.S_ISDIR(st_mode) and has_whiteout_child(file): xattrs["trusted.overlay.overlay.whiteouts"] = b'' xattrs["user.overlay.whiteouts"] = b'' + xattrs["trusted.overlay.overlay.opaque"] = b'x' + xattrs["user.overlay.opaque"] = b'x' nlink = s.st_nlink; if args.no_nlink or (args.no_root_nlink and file == root):