---- 在 星期五, 2019-10-04 21:20:30 Chengguang Xu <cgxu519@xxxxxxxxxxxx> 撰写 ---- > 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> > --- Any better idea or suggestion for this? Thanks, Chengguang > 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 > > >