Every time btrfs mounts a image that it's already mounted (cloned
images), it will assign a new random UUID to it to avoid conflicts.
However, for some internal kernel usage, it's important to access the
original UUID of a given image.
For instance, overlayfs' "index" feature keeps track of the UUID of the
mounted filesystem on it's upper layer, to avoid being remounted with a
different filesystem. However, overlayfs uses the same random UUID
exposed to userspace, so the "index" check will fail when trying to
remount the very same filesystem.
Implement export operation get_disk_uuid() to export the real image
UUID.
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
fs/btrfs/export.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index 230d9326b685..09f9ef8c1b1e 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -8,6 +8,7 @@
#include "export.h"
#include "accessors.h"
#include "super.h"
+#include "volumes.h"
#define BTRFS_FID_SIZE_NON_CONNECTABLE (offsetof(struct btrfs_fid, \
parent_objectid) / 4)
@@ -298,10 +299,29 @@ static int btrfs_get_name(struct dentry *parent, char *name,
return 0;
}
+static int btrfs_get_disk_uuid(struct super_block *sb, u8 *buf, u32 *len,
+ u64 *offset)
+{
+ struct btrfs_fs_devices *fs_dev = btrfs_sb(sb)->fs_devices;
+
+ if (fs_dev->temp_fsid)
+ return -ENODATA;
+
+ if (*len < sizeof(uuid_t))
+ return -EINVAL;
+
+ memcpy(buf, &fs_dev->metadata_uuid, sizeof(uuid_t));
+ *offset = offsetof(struct btrfs_fs_devices, metadata_uuid);
+ *len = sizeof(uuid_t);
+
+ return 0;
+}
+
const struct export_operations btrfs_export_ops = {
.encode_fh = btrfs_encode_fh,
.fh_to_dentry = btrfs_fh_to_dentry,
.fh_to_parent = btrfs_fh_to_parent,
.get_parent = btrfs_get_parent,
.get_name = btrfs_get_name,
+ .get_disk_uuid = btrfs_get_disk_uuid,
};
--
2.52.0