[PATCH 04/51] xfs_io: unshare blocks via fallocate

Darrick J. Wong
2015-10-07T05:05:44Z

Try to unshare copy-on-write blocks via fallocate.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
io/prealloc.c | 41 +++++++++++++++++++++++++++++++++++++++--
man/man8/xfs_io.8 | 5 +++++
2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/io/prealloc.c b/io/prealloc.c
index 713ea7b..5b77768 100644
--- a/io/prealloc.c
+++ b/io/prealloc.c
@@ -40,6 +40,10 @@
#define FALLOC_FL_INSERT_RANGE 0x20
#endif

+#ifndef FALLOC_FL_UNSHARE_RANGE
+#define FALLOC_FL_UNSHARE_RANGE 0x40
+#endif
+
static cmdinfo_t allocsp_cmd;
static cmdinfo_t freesp_cmd;
static cmdinfo_t resvsp_cmd;
@@ -173,7 +177,7 @@ fallocate_f(
int mode = 0;
int c;

- while ((c = getopt(argc, argv, "cikp")) != EOF) {
+ while ((c = getopt(argc, argv, "cikpu")) != EOF) {
switch (c) {
case 'c':
mode = FALLOC_FL_COLLAPSE_RANGE;
@@ -187,6 +191,9 @@ fallocate_f(
case 'p':
mode = FALLOC_FL_PUNCH_HOLE;
break;
+ case 'u':
+ mode = FALLOC_FL_UNSHARE_RANGE;
+ break;
default:
command_usage(&falloc_cmd);
}
@@ -286,6 +293,26 @@ fzero_f(
}
return 0;
}
+
+static int
+funshare_f(
+ int argc,
+ char **argv)
+{
+ xfs_flock64_t segment;
+ int mode = FALLOC_FL_UNSHARE_RANGE;
+ int index = 1;
+
+ if (!offset_length(argv[index], argv[index + 1], &segment))
+ return 0;
+
+ if (fallocate(file->fd, mode,
+ segment.l_start, segment.l_len)) {
+ perror("fallocate");
+ return 0;
+ }
+ return 0;
+}
#endif /* HAVE_FALLOCATE */

void
@@ -346,7 +373,7 @@ prealloc_init(void)
falloc_cmd.argmin = 2;
falloc_cmd.argmax = -1;
falloc_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
- falloc_cmd.args = _("[-c] [-k] [-p] off len");
+ falloc_cmd.args = _("[-c] [-k] [-p] [-u] off len");
falloc_cmd.oneline =
_("allocates space associated with part of a file via fallocate");
add_command(&falloc_cmd);
@@ -390,5 +417,15 @@ prealloc_init(void)
fzero_cmd.oneline =
_("zeroes space and eliminates holes by preallocating");
add_command(&fzero_cmd);
+
+ fzero_cmd.name = "funshare";
+ fzero_cmd.cfunc = funshare_f;
+ fzero_cmd.argmin = 2;
+ fzero_cmd.argmax = 2;
+ fzero_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
+ fzero_cmd.args = _("off len");
+ fzero_cmd.oneline =
+ _("unshares shared blocks within the range");
+ add_command(&fzero_cmd);
#endif /* HAVE_FALLOCATE */
}
diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
index e0a901f..d66dfbf 100644
--- a/man/man8/xfs_io.8
+++ b/man/man8/xfs_io.8
@@ -415,6 +415,11 @@ the FALLOC_FL_PUNCH_HOLE flag as described in the
.BR fallocate (2)
manual page.
.TP
+.BI funshare " offset length"
+Call fallocate with FALLOC_FL_UNSHARE_RANGE flag as described in the
+.BR fallocate (2)
+manual page to unshare all shared blocks within the range.
+.TP
.BI fzero " offset length"
Call fallocate with FALLOC_FL_ZERO_RANGE flag as described in the
.BR fallocate (2)