Re: [Ocfs2-devel] [PATCH 6/6] ocfs2: implement the VFS clone_range, copy_range, and dedupe_range features
On Fri, Nov 11, 2016 at 02:45:54PM +0800, Eric Ren wrote: > On 11/11/2016 02:20 PM, Darrick J. Wong wrote: > >On Fri, Nov 11, 2016 at 01:49:48PM +0800, Eric Ren wrote: > >>Hi, > >> > >>A few issues obvious to me: > >> > >>On 11/10/2016 06:51 AM, Darrick J. Wong wrote: > >>>Connect the new VFS clone_range, copy_range, and dedupe_range features > >>>to the existing reflink capability of ocfs2. Compared to the existing > >>>ocfs2 reflink ioctl We have to do things a little differently to support > >>>the VFS semantics (we can clone subranges of a file but we don't clone > >>>xattrs), but the VFS ioctls are more broadly supported. > >>How can I test the new ocfs2 reflink (with this patch) manually? What > >>commands should I use to do xxx_range things? > >See the 'reflink', 'dedupe', and 'copy_range' commands in xfs_io. > > > >The first two were added in xfsprogs 4.3, and copy_range in 4.7. > > OK, thanks. I think you are missing the following two inline comments: > > >>>+ spin_lock(_I(dest)->ip_lock); > >>>+ if (newlen > i_size_read(dest)) { > >>>+ i_size_write(dest, newlen); > >>>+ di->i_size = newlen; > >>di->i_size = cpu_to_le64(newlen); Good catch! > >>>+ } > >>>+ spin_unlock(_I(dest)->ip_lock); > >>>+ > >>Add ocfs2_update_inode_fsync_trans() here? Looks this function was > >>introduced by you to improve efficiency. > >>Just want to awake your memory about this, though I don't know about the > >>details why it should be. D'oh! Yes, I did miss that. The function updates the destination inode's information. Specifically, it updates i_size if we reflinked blocks into the file past EOF. Looking at it some more, I also need to update i_blocks or the stat(2) info will be wrong, and I also need to convert inline data to extents prior to reflinking. --D > >> > >>Eric > Thanks, > Eric ___ Ocfs2-devel mailing list Ocfs2-devel@oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel
Re: [Ocfs2-devel] [PATCH 6/6] ocfs2: implement the VFS clone_range, copy_range, and dedupe_range features
On 11/11/2016 02:20 PM, Darrick J. Wong wrote: > On Fri, Nov 11, 2016 at 01:49:48PM +0800, Eric Ren wrote: >> Hi, >> >> A few issues obvious to me: >> >> On 11/10/2016 06:51 AM, Darrick J. Wong wrote: >>> Connect the new VFS clone_range, copy_range, and dedupe_range features >>> to the existing reflink capability of ocfs2. Compared to the existing >>> ocfs2 reflink ioctl We have to do things a little differently to support >>> the VFS semantics (we can clone subranges of a file but we don't clone >>> xattrs), but the VFS ioctls are more broadly supported. >> How can I test the new ocfs2 reflink (with this patch) manually? What >> commands should I use to do xxx_range things? > See the 'reflink', 'dedupe', and 'copy_range' commands in xfs_io. > > The first two were added in xfsprogs 4.3, and copy_range in 4.7. OK, thanks. I think you are missing the following two inline comments: >>> + spin_lock(_I(dest)->ip_lock); >>> + if (newlen > i_size_read(dest)) { >>> + i_size_write(dest, newlen); >>> + di->i_size = newlen; >> di->i_size = cpu_to_le64(newlen); >> >>> + } >>> + spin_unlock(_I(dest)->ip_lock); >>> + >> Add ocfs2_update_inode_fsync_trans() here? Looks this function was >> introduced by you to improve efficiency. >> Just want to awake your memory about this, though I don't know about the >> details why it should be. >> >> Eric Thanks, Eric ___ Ocfs2-devel mailing list Ocfs2-devel@oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel
Re: [Ocfs2-devel] [PATCH 6/6] ocfs2: implement the VFS clone_range, copy_range, and dedupe_range features
On Fri, Nov 11, 2016 at 01:49:48PM +0800, Eric Ren wrote: > Hi, > > A few issues obvious to me: > > On 11/10/2016 06:51 AM, Darrick J. Wong wrote: > >Connect the new VFS clone_range, copy_range, and dedupe_range features > >to the existing reflink capability of ocfs2. Compared to the existing > >ocfs2 reflink ioctl We have to do things a little differently to support > >the VFS semantics (we can clone subranges of a file but we don't clone > >xattrs), but the VFS ioctls are more broadly supported. > > How can I test the new ocfs2 reflink (with this patch) manually? What > commands should I use to do xxx_range things? See the 'reflink', 'dedupe', and 'copy_range' commands in xfs_io. The first two were added in xfsprogs 4.3, and copy_range in 4.7. --D > > > > >Signed-off-by: Darrick J. Wong> >--- > > fs/ocfs2/file.c | 62 - > > fs/ocfs2/file.h |3 > > fs/ocfs2/refcounttree.c | 619 > > +++ > > fs/ocfs2/refcounttree.h |7 + > > 4 files changed, 688 insertions(+), 3 deletions(-) > > > > > >diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c > >index 000c234..d5a022d 100644 > >--- a/fs/ocfs2/file.c > >+++ b/fs/ocfs2/file.c > >@@ -1667,9 +1667,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode, > > *done = ret; > > } > >-static int ocfs2_remove_inode_range(struct inode *inode, > >-struct buffer_head *di_bh, u64 byte_start, > >-u64 byte_len) > >+int ocfs2_remove_inode_range(struct inode *inode, > >+ struct buffer_head *di_bh, u64 byte_start, > >+ u64 byte_len) > > { > > int ret = 0, flags = 0, done = 0, i; > > u32 trunc_start, trunc_len, trunc_end, trunc_cpos, phys_cpos; > >@@ -2440,6 +2440,56 @@ static loff_t ocfs2_file_llseek(struct file *file, > >loff_t offset, int whence) > > return offset; > > } > >+static ssize_t ocfs2_file_copy_range(struct file *file_in, > >+ loff_t pos_in, > >+ struct file *file_out, > >+ loff_t pos_out, > >+ size_t len, > >+ unsigned int flags) > >+{ > >+int error; > >+ > >+error = ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, > >+ len, false); > >+if (error) > >+return error; > >+return len; > >+} > >+ > >+static int ocfs2_file_clone_range(struct file *file_in, > >+ loff_t pos_in, > >+ struct file *file_out, > >+ loff_t pos_out, > >+ u64 len) > >+{ > >+return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, > >+ len, false); > >+} > >+ > >+#define OCFS2_MAX_DEDUPE_LEN(16 * 1024 * 1024) > >+static ssize_t ocfs2_file_dedupe_range(struct file *src_file, > >+ u64 loff, > >+ u64 len, > >+ struct file *dst_file, > >+ u64 dst_loff) > >+{ > >+int error; > >+ > >+/* > >+ * Limit the total length we will dedupe for each operation. > >+ * This is intended to bound the total time spent in this > >+ * ioctl to something sane. > >+ */ > >+if (len > OCFS2_MAX_DEDUPE_LEN) > >+len = OCFS2_MAX_DEDUPE_LEN; > >+ > >+error = ocfs2_reflink_remap_range(src_file, loff, dst_file, dst_loff, > >+ len, true); > >+if (error) > >+return error; > >+return len; > >+} > >+ > > const struct inode_operations ocfs2_file_iops = { > > .setattr= ocfs2_setattr, > > .getattr= ocfs2_getattr, > >@@ -2479,6 +2529,9 @@ const struct file_operations ocfs2_fops = { > > .splice_read= generic_file_splice_read, > > .splice_write = iter_file_splice_write, > > .fallocate = ocfs2_fallocate, > >+.copy_file_range = ocfs2_file_copy_range, > >+.clone_file_range = ocfs2_file_clone_range, > >+.dedupe_file_range = ocfs2_file_dedupe_range, > > }; > > const struct file_operations ocfs2_dops = { > >@@ -2524,6 +2577,9 @@ const struct file_operations ocfs2_fops_no_plocks = { > > .splice_read= generic_file_splice_read, > > .splice_write = iter_file_splice_write, > > .fallocate = ocfs2_fallocate, > >+.copy_file_range = ocfs2_file_copy_range, > >+.clone_file_range = ocfs2_file_clone_range, > >+.dedupe_file_range = ocfs2_file_dedupe_range, > > }; > > const struct file_operations ocfs2_dops_no_plocks = { > >diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h > >index e8c62f2..897fd9a 100644 > >--- a/fs/ocfs2/file.h > >+++ b/fs/ocfs2/file.h > >@@ -82,4 +82,7 @@ int
Re: [Ocfs2-devel] [PATCH 6/6] ocfs2: implement the VFS clone_range, copy_range, and dedupe_range features
Hi, A few issues obvious to me: On 11/10/2016 06:51 AM, Darrick J. Wong wrote: > Connect the new VFS clone_range, copy_range, and dedupe_range features > to the existing reflink capability of ocfs2. Compared to the existing > ocfs2 reflink ioctl We have to do things a little differently to support > the VFS semantics (we can clone subranges of a file but we don't clone > xattrs), but the VFS ioctls are more broadly supported. How can I test the new ocfs2 reflink (with this patch) manually? What commands should I use to do xxx_range things? > > Signed-off-by: Darrick J. Wong> --- > fs/ocfs2/file.c | 62 - > fs/ocfs2/file.h |3 > fs/ocfs2/refcounttree.c | 619 > +++ > fs/ocfs2/refcounttree.h |7 + > 4 files changed, 688 insertions(+), 3 deletions(-) > > > diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c > index 000c234..d5a022d 100644 > --- a/fs/ocfs2/file.c > +++ b/fs/ocfs2/file.c > @@ -1667,9 +1667,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode, > *done = ret; > } > > -static int ocfs2_remove_inode_range(struct inode *inode, > - struct buffer_head *di_bh, u64 byte_start, > - u64 byte_len) > +int ocfs2_remove_inode_range(struct inode *inode, > + struct buffer_head *di_bh, u64 byte_start, > + u64 byte_len) > { > int ret = 0, flags = 0, done = 0, i; > u32 trunc_start, trunc_len, trunc_end, trunc_cpos, phys_cpos; > @@ -2440,6 +2440,56 @@ static loff_t ocfs2_file_llseek(struct file *file, > loff_t offset, int whence) > return offset; > } > > +static ssize_t ocfs2_file_copy_range(struct file *file_in, > + loff_t pos_in, > + struct file *file_out, > + loff_t pos_out, > + size_t len, > + unsigned int flags) > +{ > + int error; > + > + error = ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, > + len, false); > + if (error) > + return error; > + return len; > +} > + > +static int ocfs2_file_clone_range(struct file *file_in, > + loff_t pos_in, > + struct file *file_out, > + loff_t pos_out, > + u64 len) > +{ > + return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, > + len, false); > +} > + > +#define OCFS2_MAX_DEDUPE_LEN (16 * 1024 * 1024) > +static ssize_t ocfs2_file_dedupe_range(struct file *src_file, > +u64 loff, > +u64 len, > +struct file *dst_file, > +u64 dst_loff) > +{ > + int error; > + > + /* > + * Limit the total length we will dedupe for each operation. > + * This is intended to bound the total time spent in this > + * ioctl to something sane. > + */ > + if (len > OCFS2_MAX_DEDUPE_LEN) > + len = OCFS2_MAX_DEDUPE_LEN; > + > + error = ocfs2_reflink_remap_range(src_file, loff, dst_file, dst_loff, > + len, true); > + if (error) > + return error; > + return len; > +} > + > const struct inode_operations ocfs2_file_iops = { > .setattr= ocfs2_setattr, > .getattr= ocfs2_getattr, > @@ -2479,6 +2529,9 @@ const struct file_operations ocfs2_fops = { > .splice_read= generic_file_splice_read, > .splice_write = iter_file_splice_write, > .fallocate = ocfs2_fallocate, > + .copy_file_range = ocfs2_file_copy_range, > + .clone_file_range = ocfs2_file_clone_range, > + .dedupe_file_range = ocfs2_file_dedupe_range, > }; > > const struct file_operations ocfs2_dops = { > @@ -2524,6 +2577,9 @@ const struct file_operations ocfs2_fops_no_plocks = { > .splice_read= generic_file_splice_read, > .splice_write = iter_file_splice_write, > .fallocate = ocfs2_fallocate, > + .copy_file_range = ocfs2_file_copy_range, > + .clone_file_range = ocfs2_file_clone_range, > + .dedupe_file_range = ocfs2_file_dedupe_range, > }; > > const struct file_operations ocfs2_dops_no_plocks = { > diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h > index e8c62f2..897fd9a 100644 > --- a/fs/ocfs2/file.h > +++ b/fs/ocfs2/file.h > @@ -82,4 +82,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int > cmd, > > int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos, > size_t count); > +int ocfs2_remove_inode_range(struct inode *inode, > +
[Ocfs2-devel] [PATCH 6/6] ocfs2: implement the VFS clone_range, copy_range, and dedupe_range features
Connect the new VFS clone_range, copy_range, and dedupe_range features to the existing reflink capability of ocfs2. Compared to the existing ocfs2 reflink ioctl We have to do things a little differently to support the VFS semantics (we can clone subranges of a file but we don't clone xattrs), but the VFS ioctls are more broadly supported. Signed-off-by: Darrick J. Wong--- fs/ocfs2/file.c | 62 - fs/ocfs2/file.h |3 fs/ocfs2/refcounttree.c | 619 +++ fs/ocfs2/refcounttree.h |7 + 4 files changed, 688 insertions(+), 3 deletions(-) diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 000c234..d5a022d 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1667,9 +1667,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode, *done = ret; } -static int ocfs2_remove_inode_range(struct inode *inode, - struct buffer_head *di_bh, u64 byte_start, - u64 byte_len) +int ocfs2_remove_inode_range(struct inode *inode, +struct buffer_head *di_bh, u64 byte_start, +u64 byte_len) { int ret = 0, flags = 0, done = 0, i; u32 trunc_start, trunc_len, trunc_end, trunc_cpos, phys_cpos; @@ -2440,6 +2440,56 @@ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence) return offset; } +static ssize_t ocfs2_file_copy_range(struct file *file_in, +loff_t pos_in, +struct file *file_out, +loff_t pos_out, +size_t len, +unsigned int flags) +{ + int error; + + error = ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, + len, false); + if (error) + return error; + return len; +} + +static int ocfs2_file_clone_range(struct file *file_in, + loff_t pos_in, + struct file *file_out, + loff_t pos_out, + u64 len) +{ + return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, +len, false); +} + +#define OCFS2_MAX_DEDUPE_LEN (16 * 1024 * 1024) +static ssize_t ocfs2_file_dedupe_range(struct file *src_file, + u64 loff, + u64 len, + struct file *dst_file, + u64 dst_loff) +{ + int error; + + /* +* Limit the total length we will dedupe for each operation. +* This is intended to bound the total time spent in this +* ioctl to something sane. +*/ + if (len > OCFS2_MAX_DEDUPE_LEN) + len = OCFS2_MAX_DEDUPE_LEN; + + error = ocfs2_reflink_remap_range(src_file, loff, dst_file, dst_loff, + len, true); + if (error) + return error; + return len; +} + const struct inode_operations ocfs2_file_iops = { .setattr= ocfs2_setattr, .getattr= ocfs2_getattr, @@ -2479,6 +2529,9 @@ const struct file_operations ocfs2_fops = { .splice_read= generic_file_splice_read, .splice_write = iter_file_splice_write, .fallocate = ocfs2_fallocate, + .copy_file_range = ocfs2_file_copy_range, + .clone_file_range = ocfs2_file_clone_range, + .dedupe_file_range = ocfs2_file_dedupe_range, }; const struct file_operations ocfs2_dops = { @@ -2524,6 +2577,9 @@ const struct file_operations ocfs2_fops_no_plocks = { .splice_read= generic_file_splice_read, .splice_write = iter_file_splice_write, .fallocate = ocfs2_fallocate, + .copy_file_range = ocfs2_file_copy_range, + .clone_file_range = ocfs2_file_clone_range, + .dedupe_file_range = ocfs2_file_dedupe_range, }; const struct file_operations ocfs2_dops_no_plocks = { diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index e8c62f2..897fd9a 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -82,4 +82,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos, size_t count); +int ocfs2_remove_inode_range(struct inode *inode, +struct buffer_head *di_bh, u64 byte_start, +u64 byte_len); #endif /* OCFS2_FILE_H */ diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index d92b6c6..3e2198c 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -34,6 +34,7 @@ #include "xattr.h" #include "namei.h" #include