[PATCH] ovl: improving copy-up efficiency for sparse file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Current copy-up is not efficient for sparse file,
It's not only slow but also wasting more disk space
when the target lower file has huge hole inside.
This patch tries to recognize file hole and skip it
during copy-up.

In detail, this optimization checks the hole according
to copy-up chunk size so it may not recognize all kind
of holes in the file. However, it is easy to implement
and will be enough for most of the time.

Additionally, this optimization relies on lseek(2)
SEEK_DATA implementation, so for some specific
filesystems which do not support this feature
will behave as before on copy-up.

Signed-off-by: Chengguang Xu <cgxu519@xxxxxxxxxxxx>
---
 fs/overlayfs/copy_up.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index b801c6353100..028033c9f021 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -144,10 +144,11 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
 		goto out;
 	/* Couldn't clone, so now we try to copy the data */
 
-	/* FIXME: copy up sparse files efficiently */
 	while (len) {
 		size_t this_len = OVL_COPY_UP_CHUNK_SIZE;
 		long bytes;
+		loff_t old_next_data_pos;
+		loff_t hole_len;
 
 		if (len < this_len)
 			this_len = len;
@@ -157,6 +158,18 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
 			break;
 		}
 
+		old_next_data_pos = vfs_llseek(old_file, old_pos, SEEK_DATA);
+		if (old_next_data_pos >= old_pos + OVL_COPY_UP_CHUNK_SIZE) {
+			hole_len = (old_next_data_pos - old_pos) /
+				OVL_COPY_UP_CHUNK_SIZE * OVL_COPY_UP_CHUNK_SIZE;
+			old_pos += hole_len;
+			new_pos += hole_len;
+			len -= hole_len;
+			continue;
+		} else if (old_next_data_pos == -ENXIO) {
+			break;
+		}
+
 		bytes = do_splice_direct(old_file, &old_pos,
 					 new_file, &new_pos,
 					 this_len, SPLICE_F_MOVE);
-- 
2.21.0







[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux