[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC][PATCH][cp] btrfs, nocow and cp --reflink
From: |
Goffredo Baroncelli |
Subject: |
[RFC][PATCH][cp] btrfs, nocow and cp --reflink |
Date: |
Wed, 25 May 2022 19:05:19 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.1 |
Hi All,
recently I discovered that BTRFS allow to reflink a file only if the flag
FS_NOCOW_FL is the same on both source and destination.
In the end of this email I added a patch to "cp" to set the FS_NOCOW_FL flag
according to the source.
Even tough this works, I am wondering if this is the expected/the least
surprise behavior by/for any user. This is the reason why this email is tagged
as RFC.
Without reflink, the default behavior is that the new file has the FS_NOCOW_FL
flag set according to the parent directory; with this patch the flag would be
the same as the source.
I am not sure that this is the correct behviour without warning the user of
this change.
Another possibility, is to flip the NOCOW flag only if --reflink=always is
passed.
Thoughts ?
BR
G.Baroncelli
-----
diff --git a/src/copy.c b/src/copy.c
index b15d91990..41df45cd5 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -22,6 +22,8 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <selinux/selinux.h>
+#include <sys/vfs.h>
+#include <linux/magic.h>
#if HAVE_HURD_H
# include <hurd.h>
@@ -399,6 +401,32 @@ static inline int
clone_file (int dest_fd, int src_fd)
{
#ifdef FICLONE
+# ifdef __linux__
+ /* BTRFS requires that both source and dest have the same setting
+ about FS_NOCOW_FL */
+ int src_flags, dst_flags, r;
+ struct statfs sbuf;
+
+ r = fstatfs(dest_fd, &sbuf);
+ if (r < 0)
+ return r;
+ if (sbuf.f_type == BTRFS_SUPER_MAGIC || sbuf.f_type == BTRFS_TEST_MAGIC)
+ {
+ r = ioctl(src_fd, FS_IOC_GETFLAGS, &src_flags);
+ if (r < 0)
+ return r;
+ r = ioctl(dest_fd, FS_IOC_GETFLAGS, &dst_flags);
+ if (r < 0)
+ return r;
+ if ((src_flags ^ dst_flags) & FS_NOCOW_FL)
+ {
+ dst_flags ^= FS_NOCOW_FL;
+ r = ioctl(dest_fd, FS_IOC_SETFLAGS, &dst_flags);
+ if (r < 0)
+ return r;
+ }
+ }
+# endif
return ioctl (dest_fd, FICLONE, src_fd);
#else
(void) dest_fd;
--
gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it>
Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5
- [RFC][PATCH][cp] btrfs, nocow and cp --reflink,
Goffredo Baroncelli <=