diff mbox series

cifs: add ioctl for SRV_COPYCHUNK range

Message ID 20180903065733.28037-1-lsahlber@redhat.com (mailing list archive)
State New, archived
Headers show
Series cifs: add ioctl for SRV_COPYCHUNK range | expand

Commit Message

Ronnie Sahlberg Sept. 3, 2018, 6:57 a.m. UTC
Add a new ioctl for COPYCHUNK that copies a region. The existing
COPYCHUNK can only be used to copy a whole file.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/cifs_ioctl.h |  8 ++++++++
 fs/cifs/ioctl.c      | 53 ++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 55 insertions(+), 6 deletions(-)

Comments

Steve French Sept. 3, 2018, 2:20 p.m. UTC | #1
Maybe should update David Disseldorp's test tool as well so user space
code to experiment with this easily
On Mon, Sep 3, 2018 at 1:57 AM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
>
> Add a new ioctl for COPYCHUNK that copies a region. The existing
> COPYCHUNK can only be used to copy a whole file.
>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/cifs_ioctl.h |  8 ++++++++
>  fs/cifs/ioctl.c      | 53 ++++++++++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 55 insertions(+), 6 deletions(-)
>
> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
> index 57ff0756e30c..b40b9b608dde 100644
> --- a/fs/cifs/cifs_ioctl.h
> +++ b/fs/cifs/cifs_ioctl.h
> @@ -43,8 +43,16 @@ struct smb_snapshot_array {
>         /*      snapshots[]; */
>  } __packed;
>
> +struct smb_srv_copychunk {
> +       __u32   src_fd;
> +       __u32   length;
> +       __u64   src_offset;
> +       __u64   dst_offset;
> +} __packed;
> +
>  #define CIFS_IOCTL_MAGIC       0xCF
>  #define CIFS_IOC_COPYCHUNK_FILE        _IOW(CIFS_IOCTL_MAGIC, 3, int)
>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
> +#define CIFS_IOC_COPYCHUNK _IOW(CIFS_IOCTL_MAGIC, 7, struct smb_srv_copychunk)
> diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
> index 54f32f9143a9..91f87ea01be0 100644
> --- a/fs/cifs/ioctl.c
> +++ b/fs/cifs/ioctl.c
> @@ -34,14 +34,13 @@
>  #include "cifs_ioctl.h"
>  #include <linux/btrfs.h>
>
> -static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> -                       unsigned long srcfd)
> +static long _cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> +                                 struct smb_srv_copychunk *cc)
>  {
>         int rc;
>         struct fd src_file;
>         struct inode *src_inode;
>
> -       cifs_dbg(FYI, "ioctl copychunk range\n");
>         /* the destination must be opened for writing */
>         if (!(dst_file->f_mode & FMODE_WRITE)) {
>                 cifs_dbg(FYI, "file target not open for write\n");
> @@ -55,7 +54,7 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>                 return rc;
>         }
>
> -       src_file = fdget(srcfd);
> +       src_file = fdget(cc->src_fd);
>         if (!src_file.file) {
>                 rc = -EBADF;
>                 goto out_drop_write;
> @@ -72,8 +71,9 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>         if (S_ISDIR(src_inode->i_mode))
>                 goto out_fput;
>
> -       rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
> -                                       src_inode->i_size, 0);
> +       rc = cifs_file_copychunk_range(xid, src_file.file, cc->src_offset,
> +                                      dst_file, cc->dst_offset,
> +                                      cc->length, 0);
>         if (rc > 0)
>                 rc = 0;
>  out_fput:
> @@ -83,6 +83,44 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>         return rc;
>  }
>
> +static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> +                                unsigned long p)
> +{
> +       void __user *arg = (void __user *)p;
> +       struct smb_srv_copychunk cc;
> +
> +       cifs_dbg(FYI, "ioctl copychunk range\n");
> +
> +       if (copy_from_user(&cc, arg, sizeof(cc)))
> +               return -EFAULT;
> +
> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
> +}
> +
> +static long cifs_ioctl_copychunk_file(unsigned int xid, struct file *dst_file,
> +                                     unsigned long srcfd)
> +{
> +       struct smb_srv_copychunk cc;
> +       struct fd src_file;
> +       struct inode *src_inode;
> +
> +       cifs_dbg(FYI, "ioctl copychunk file\n");
> +
> +       src_file = fdget(srcfd);
> +       if (!src_file.file) {
> +               mnt_drop_write_file(dst_file);
> +               return -EBADF;
> +       }
> +       src_inode = file_inode(src_file.file);
> +
> +       memset(&cc, 0, sizeof(struct smb_srv_copychunk));
> +       cc.src_fd = srcfd;
> +       cc.length = src_inode->i_size;
> +       fdput(src_file);
> +
> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
> +}
> +
>  static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
>                                 void __user *arg)
>  {
> @@ -194,6 +232,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
>                         }
>                         break;
>                 case CIFS_IOC_COPYCHUNK_FILE:
> +                       rc = cifs_ioctl_copychunk_file(xid, filep, arg);
> +                       break;
> +               case CIFS_IOC_COPYCHUNK:
>                         rc = cifs_ioctl_copychunk(xid, filep, arg);
>                         break;
>                 case CIFS_IOC_SET_INTEGRITY:
> --
> 2.13.3
>
Steve French Sept. 3, 2018, 2:23 p.m. UTC | #2
tentatively merged into cifs-2.6.git for-next (along with the updated
compounding series)
On Mon, Sep 3, 2018 at 1:57 AM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
>
> Add a new ioctl for COPYCHUNK that copies a region. The existing
> COPYCHUNK can only be used to copy a whole file.
>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/cifs_ioctl.h |  8 ++++++++
>  fs/cifs/ioctl.c      | 53 ++++++++++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 55 insertions(+), 6 deletions(-)
>
> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
> index 57ff0756e30c..b40b9b608dde 100644
> --- a/fs/cifs/cifs_ioctl.h
> +++ b/fs/cifs/cifs_ioctl.h
> @@ -43,8 +43,16 @@ struct smb_snapshot_array {
>         /*      snapshots[]; */
>  } __packed;
>
> +struct smb_srv_copychunk {
> +       __u32   src_fd;
> +       __u32   length;
> +       __u64   src_offset;
> +       __u64   dst_offset;
> +} __packed;
> +
>  #define CIFS_IOCTL_MAGIC       0xCF
>  #define CIFS_IOC_COPYCHUNK_FILE        _IOW(CIFS_IOCTL_MAGIC, 3, int)
>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
> +#define CIFS_IOC_COPYCHUNK _IOW(CIFS_IOCTL_MAGIC, 7, struct smb_srv_copychunk)
> diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
> index 54f32f9143a9..91f87ea01be0 100644
> --- a/fs/cifs/ioctl.c
> +++ b/fs/cifs/ioctl.c
> @@ -34,14 +34,13 @@
>  #include "cifs_ioctl.h"
>  #include <linux/btrfs.h>
>
> -static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> -                       unsigned long srcfd)
> +static long _cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> +                                 struct smb_srv_copychunk *cc)
>  {
>         int rc;
>         struct fd src_file;
>         struct inode *src_inode;
>
> -       cifs_dbg(FYI, "ioctl copychunk range\n");
>         /* the destination must be opened for writing */
>         if (!(dst_file->f_mode & FMODE_WRITE)) {
>                 cifs_dbg(FYI, "file target not open for write\n");
> @@ -55,7 +54,7 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>                 return rc;
>         }
>
> -       src_file = fdget(srcfd);
> +       src_file = fdget(cc->src_fd);
>         if (!src_file.file) {
>                 rc = -EBADF;
>                 goto out_drop_write;
> @@ -72,8 +71,9 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>         if (S_ISDIR(src_inode->i_mode))
>                 goto out_fput;
>
> -       rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
> -                                       src_inode->i_size, 0);
> +       rc = cifs_file_copychunk_range(xid, src_file.file, cc->src_offset,
> +                                      dst_file, cc->dst_offset,
> +                                      cc->length, 0);
>         if (rc > 0)
>                 rc = 0;
>  out_fput:
> @@ -83,6 +83,44 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>         return rc;
>  }
>
> +static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> +                                unsigned long p)
> +{
> +       void __user *arg = (void __user *)p;
> +       struct smb_srv_copychunk cc;
> +
> +       cifs_dbg(FYI, "ioctl copychunk range\n");
> +
> +       if (copy_from_user(&cc, arg, sizeof(cc)))
> +               return -EFAULT;
> +
> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
> +}
> +
> +static long cifs_ioctl_copychunk_file(unsigned int xid, struct file *dst_file,
> +                                     unsigned long srcfd)
> +{
> +       struct smb_srv_copychunk cc;
> +       struct fd src_file;
> +       struct inode *src_inode;
> +
> +       cifs_dbg(FYI, "ioctl copychunk file\n");
> +
> +       src_file = fdget(srcfd);
> +       if (!src_file.file) {
> +               mnt_drop_write_file(dst_file);
> +               return -EBADF;
> +       }
> +       src_inode = file_inode(src_file.file);
> +
> +       memset(&cc, 0, sizeof(struct smb_srv_copychunk));
> +       cc.src_fd = srcfd;
> +       cc.length = src_inode->i_size;
> +       fdput(src_file);
> +
> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
> +}
> +
>  static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
>                                 void __user *arg)
>  {
> @@ -194,6 +232,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
>                         }
>                         break;
>                 case CIFS_IOC_COPYCHUNK_FILE:
> +                       rc = cifs_ioctl_copychunk_file(xid, filep, arg);
> +                       break;
> +               case CIFS_IOC_COPYCHUNK:
>                         rc = cifs_ioctl_copychunk(xid, filep, arg);
>                         break;
>                 case CIFS_IOC_SET_INTEGRITY:
> --
> 2.13.3
>
ronnie sahlberg Sept. 3, 2018, 9:58 p.m. UTC | #3
I updated cloner that is part of xfstest.
Once this goes in I will submit a change to xfstest..

On Tue, Sep 4, 2018 at 12:23 AM, Steve French <smfrench@gmail.com> wrote:
> tentatively merged into cifs-2.6.git for-next (along with the updated
> compounding series)
> On Mon, Sep 3, 2018 at 1:57 AM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
>>
>> Add a new ioctl for COPYCHUNK that copies a region. The existing
>> COPYCHUNK can only be used to copy a whole file.
>>
>> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
>> ---
>>  fs/cifs/cifs_ioctl.h |  8 ++++++++
>>  fs/cifs/ioctl.c      | 53 ++++++++++++++++++++++++++++++++++++++++++++++------
>>  2 files changed, 55 insertions(+), 6 deletions(-)
>>
>> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
>> index 57ff0756e30c..b40b9b608dde 100644
>> --- a/fs/cifs/cifs_ioctl.h
>> +++ b/fs/cifs/cifs_ioctl.h
>> @@ -43,8 +43,16 @@ struct smb_snapshot_array {
>>         /*      snapshots[]; */
>>  } __packed;
>>
>> +struct smb_srv_copychunk {
>> +       __u32   src_fd;
>> +       __u32   length;
>> +       __u64   src_offset;
>> +       __u64   dst_offset;
>> +} __packed;
>> +
>>  #define CIFS_IOCTL_MAGIC       0xCF
>>  #define CIFS_IOC_COPYCHUNK_FILE        _IOW(CIFS_IOCTL_MAGIC, 3, int)
>>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
>>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
>>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
>> +#define CIFS_IOC_COPYCHUNK _IOW(CIFS_IOCTL_MAGIC, 7, struct smb_srv_copychunk)
>> diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
>> index 54f32f9143a9..91f87ea01be0 100644
>> --- a/fs/cifs/ioctl.c
>> +++ b/fs/cifs/ioctl.c
>> @@ -34,14 +34,13 @@
>>  #include "cifs_ioctl.h"
>>  #include <linux/btrfs.h>
>>
>> -static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>> -                       unsigned long srcfd)
>> +static long _cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>> +                                 struct smb_srv_copychunk *cc)
>>  {
>>         int rc;
>>         struct fd src_file;
>>         struct inode *src_inode;
>>
>> -       cifs_dbg(FYI, "ioctl copychunk range\n");
>>         /* the destination must be opened for writing */
>>         if (!(dst_file->f_mode & FMODE_WRITE)) {
>>                 cifs_dbg(FYI, "file target not open for write\n");
>> @@ -55,7 +54,7 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>>                 return rc;
>>         }
>>
>> -       src_file = fdget(srcfd);
>> +       src_file = fdget(cc->src_fd);
>>         if (!src_file.file) {
>>                 rc = -EBADF;
>>                 goto out_drop_write;
>> @@ -72,8 +71,9 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>>         if (S_ISDIR(src_inode->i_mode))
>>                 goto out_fput;
>>
>> -       rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
>> -                                       src_inode->i_size, 0);
>> +       rc = cifs_file_copychunk_range(xid, src_file.file, cc->src_offset,
>> +                                      dst_file, cc->dst_offset,
>> +                                      cc->length, 0);
>>         if (rc > 0)
>>                 rc = 0;
>>  out_fput:
>> @@ -83,6 +83,44 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>>         return rc;
>>  }
>>
>> +static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>> +                                unsigned long p)
>> +{
>> +       void __user *arg = (void __user *)p;
>> +       struct smb_srv_copychunk cc;
>> +
>> +       cifs_dbg(FYI, "ioctl copychunk range\n");
>> +
>> +       if (copy_from_user(&cc, arg, sizeof(cc)))
>> +               return -EFAULT;
>> +
>> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
>> +}
>> +
>> +static long cifs_ioctl_copychunk_file(unsigned int xid, struct file *dst_file,
>> +                                     unsigned long srcfd)
>> +{
>> +       struct smb_srv_copychunk cc;
>> +       struct fd src_file;
>> +       struct inode *src_inode;
>> +
>> +       cifs_dbg(FYI, "ioctl copychunk file\n");
>> +
>> +       src_file = fdget(srcfd);
>> +       if (!src_file.file) {
>> +               mnt_drop_write_file(dst_file);
>> +               return -EBADF;
>> +       }
>> +       src_inode = file_inode(src_file.file);
>> +
>> +       memset(&cc, 0, sizeof(struct smb_srv_copychunk));
>> +       cc.src_fd = srcfd;
>> +       cc.length = src_inode->i_size;
>> +       fdput(src_file);
>> +
>> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
>> +}
>> +
>>  static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
>>                                 void __user *arg)
>>  {
>> @@ -194,6 +232,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
>>                         }
>>                         break;
>>                 case CIFS_IOC_COPYCHUNK_FILE:
>> +                       rc = cifs_ioctl_copychunk_file(xid, filep, arg);
>> +                       break;
>> +               case CIFS_IOC_COPYCHUNK:
>>                         rc = cifs_ioctl_copychunk(xid, filep, arg);
>>                         break;
>>                 case CIFS_IOC_SET_INTEGRITY:
>> --
>> 2.13.3
>>
>
>
> --
> Thanks,
>
> Steve
Steve French Sept. 3, 2018, 10:13 p.m. UTC | #4
thx
On Mon, Sep 3, 2018 at 4:58 PM ronnie sahlberg <ronniesahlberg@gmail.com> wrote:
>
> I updated cloner that is part of xfstest.
> Once this goes in I will submit a change to xfstest..
>
> On Tue, Sep 4, 2018 at 12:23 AM, Steve French <smfrench@gmail.com> wrote:
> > tentatively merged into cifs-2.6.git for-next (along with the updated
> > compounding series)
> > On Mon, Sep 3, 2018 at 1:57 AM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
> >>
> >> Add a new ioctl for COPYCHUNK that copies a region. The existing
> >> COPYCHUNK can only be used to copy a whole file.
> >>
> >> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> >> ---
> >>  fs/cifs/cifs_ioctl.h |  8 ++++++++
> >>  fs/cifs/ioctl.c      | 53 ++++++++++++++++++++++++++++++++++++++++++++++------
> >>  2 files changed, 55 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
> >> index 57ff0756e30c..b40b9b608dde 100644
> >> --- a/fs/cifs/cifs_ioctl.h
> >> +++ b/fs/cifs/cifs_ioctl.h
> >> @@ -43,8 +43,16 @@ struct smb_snapshot_array {
> >>         /*      snapshots[]; */
> >>  } __packed;
> >>
> >> +struct smb_srv_copychunk {
> >> +       __u32   src_fd;
> >> +       __u32   length;
> >> +       __u64   src_offset;
> >> +       __u64   dst_offset;
> >> +} __packed;
> >> +
> >>  #define CIFS_IOCTL_MAGIC       0xCF
> >>  #define CIFS_IOC_COPYCHUNK_FILE        _IOW(CIFS_IOCTL_MAGIC, 3, int)
> >>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
> >>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
> >>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
> >> +#define CIFS_IOC_COPYCHUNK _IOW(CIFS_IOCTL_MAGIC, 7, struct smb_srv_copychunk)
> >> diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
> >> index 54f32f9143a9..91f87ea01be0 100644
> >> --- a/fs/cifs/ioctl.c
> >> +++ b/fs/cifs/ioctl.c
> >> @@ -34,14 +34,13 @@
> >>  #include "cifs_ioctl.h"
> >>  #include <linux/btrfs.h>
> >>
> >> -static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> >> -                       unsigned long srcfd)
> >> +static long _cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> >> +                                 struct smb_srv_copychunk *cc)
> >>  {
> >>         int rc;
> >>         struct fd src_file;
> >>         struct inode *src_inode;
> >>
> >> -       cifs_dbg(FYI, "ioctl copychunk range\n");
> >>         /* the destination must be opened for writing */
> >>         if (!(dst_file->f_mode & FMODE_WRITE)) {
> >>                 cifs_dbg(FYI, "file target not open for write\n");
> >> @@ -55,7 +54,7 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> >>                 return rc;
> >>         }
> >>
> >> -       src_file = fdget(srcfd);
> >> +       src_file = fdget(cc->src_fd);
> >>         if (!src_file.file) {
> >>                 rc = -EBADF;
> >>                 goto out_drop_write;
> >> @@ -72,8 +71,9 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> >>         if (S_ISDIR(src_inode->i_mode))
> >>                 goto out_fput;
> >>
> >> -       rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
> >> -                                       src_inode->i_size, 0);
> >> +       rc = cifs_file_copychunk_range(xid, src_file.file, cc->src_offset,
> >> +                                      dst_file, cc->dst_offset,
> >> +                                      cc->length, 0);
> >>         if (rc > 0)
> >>                 rc = 0;
> >>  out_fput:
> >> @@ -83,6 +83,44 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> >>         return rc;
> >>  }
> >>
> >> +static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
> >> +                                unsigned long p)
> >> +{
> >> +       void __user *arg = (void __user *)p;
> >> +       struct smb_srv_copychunk cc;
> >> +
> >> +       cifs_dbg(FYI, "ioctl copychunk range\n");
> >> +
> >> +       if (copy_from_user(&cc, arg, sizeof(cc)))
> >> +               return -EFAULT;
> >> +
> >> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
> >> +}
> >> +
> >> +static long cifs_ioctl_copychunk_file(unsigned int xid, struct file *dst_file,
> >> +                                     unsigned long srcfd)
> >> +{
> >> +       struct smb_srv_copychunk cc;
> >> +       struct fd src_file;
> >> +       struct inode *src_inode;
> >> +
> >> +       cifs_dbg(FYI, "ioctl copychunk file\n");
> >> +
> >> +       src_file = fdget(srcfd);
> >> +       if (!src_file.file) {
> >> +               mnt_drop_write_file(dst_file);
> >> +               return -EBADF;
> >> +       }
> >> +       src_inode = file_inode(src_file.file);
> >> +
> >> +       memset(&cc, 0, sizeof(struct smb_srv_copychunk));
> >> +       cc.src_fd = srcfd;
> >> +       cc.length = src_inode->i_size;
> >> +       fdput(src_file);
> >> +
> >> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
> >> +}
> >> +
> >>  static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
> >>                                 void __user *arg)
> >>  {
> >> @@ -194,6 +232,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
> >>                         }
> >>                         break;
> >>                 case CIFS_IOC_COPYCHUNK_FILE:
> >> +                       rc = cifs_ioctl_copychunk_file(xid, filep, arg);
> >> +                       break;
> >> +               case CIFS_IOC_COPYCHUNK:
> >>                         rc = cifs_ioctl_copychunk(xid, filep, arg);
> >>                         break;
> >>                 case CIFS_IOC_SET_INTEGRITY:
> >> --
> >> 2.13.3
> >>
> >
> >
> > --
> > Thanks,
> >
> > Steve
Ronnie Sahlberg Sept. 4, 2018, 11:10 a.m. UTC | #5
Tiny patch to generate copychunk ioctl's




----- Original Message -----
From: "ronnie sahlberg" <ronniesahlberg@gmail.com>
To: "Steve French" <smfrench@gmail.com>
Cc: "Ronnie Sahlberg" <lsahlber@redhat.com>, "CIFS" <linux-cifs@vger.kernel.org>
Sent: Tuesday, 4 September, 2018 7:58:29 AM
Subject: Re: [PATCH] cifs: add ioctl for SRV_COPYCHUNK range

I updated cloner that is part of xfstest.
Once this goes in I will submit a change to xfstest..

On Tue, Sep 4, 2018 at 12:23 AM, Steve French <smfrench@gmail.com> wrote:
> tentatively merged into cifs-2.6.git for-next (along with the updated
> compounding series)
> On Mon, Sep 3, 2018 at 1:57 AM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
>>
>> Add a new ioctl for COPYCHUNK that copies a region. The existing
>> COPYCHUNK can only be used to copy a whole file.
>>
>> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
>> ---
>>  fs/cifs/cifs_ioctl.h |  8 ++++++++
>>  fs/cifs/ioctl.c      | 53 ++++++++++++++++++++++++++++++++++++++++++++++------
>>  2 files changed, 55 insertions(+), 6 deletions(-)
>>
>> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
>> index 57ff0756e30c..b40b9b608dde 100644
>> --- a/fs/cifs/cifs_ioctl.h
>> +++ b/fs/cifs/cifs_ioctl.h
>> @@ -43,8 +43,16 @@ struct smb_snapshot_array {
>>         /*      snapshots[]; */
>>  } __packed;
>>
>> +struct smb_srv_copychunk {
>> +       __u32   src_fd;
>> +       __u32   length;
>> +       __u64   src_offset;
>> +       __u64   dst_offset;
>> +} __packed;
>> +
>>  #define CIFS_IOCTL_MAGIC       0xCF
>>  #define CIFS_IOC_COPYCHUNK_FILE        _IOW(CIFS_IOCTL_MAGIC, 3, int)
>>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
>>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
>>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
>> +#define CIFS_IOC_COPYCHUNK _IOW(CIFS_IOCTL_MAGIC, 7, struct smb_srv_copychunk)
>> diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
>> index 54f32f9143a9..91f87ea01be0 100644
>> --- a/fs/cifs/ioctl.c
>> +++ b/fs/cifs/ioctl.c
>> @@ -34,14 +34,13 @@
>>  #include "cifs_ioctl.h"
>>  #include <linux/btrfs.h>
>>
>> -static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>> -                       unsigned long srcfd)
>> +static long _cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>> +                                 struct smb_srv_copychunk *cc)
>>  {
>>         int rc;
>>         struct fd src_file;
>>         struct inode *src_inode;
>>
>> -       cifs_dbg(FYI, "ioctl copychunk range\n");
>>         /* the destination must be opened for writing */
>>         if (!(dst_file->f_mode & FMODE_WRITE)) {
>>                 cifs_dbg(FYI, "file target not open for write\n");
>> @@ -55,7 +54,7 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>>                 return rc;
>>         }
>>
>> -       src_file = fdget(srcfd);
>> +       src_file = fdget(cc->src_fd);
>>         if (!src_file.file) {
>>                 rc = -EBADF;
>>                 goto out_drop_write;
>> @@ -72,8 +71,9 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>>         if (S_ISDIR(src_inode->i_mode))
>>                 goto out_fput;
>>
>> -       rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
>> -                                       src_inode->i_size, 0);
>> +       rc = cifs_file_copychunk_range(xid, src_file.file, cc->src_offset,
>> +                                      dst_file, cc->dst_offset,
>> +                                      cc->length, 0);
>>         if (rc > 0)
>>                 rc = 0;
>>  out_fput:
>> @@ -83,6 +83,44 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>>         return rc;
>>  }
>>
>> +static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>> +                                unsigned long p)
>> +{
>> +       void __user *arg = (void __user *)p;
>> +       struct smb_srv_copychunk cc;
>> +
>> +       cifs_dbg(FYI, "ioctl copychunk range\n");
>> +
>> +       if (copy_from_user(&cc, arg, sizeof(cc)))
>> +               return -EFAULT;
>> +
>> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
>> +}
>> +
>> +static long cifs_ioctl_copychunk_file(unsigned int xid, struct file *dst_file,
>> +                                     unsigned long srcfd)
>> +{
>> +       struct smb_srv_copychunk cc;
>> +       struct fd src_file;
>> +       struct inode *src_inode;
>> +
>> +       cifs_dbg(FYI, "ioctl copychunk file\n");
>> +
>> +       src_file = fdget(srcfd);
>> +       if (!src_file.file) {
>> +               mnt_drop_write_file(dst_file);
>> +               return -EBADF;
>> +       }
>> +       src_inode = file_inode(src_file.file);
>> +
>> +       memset(&cc, 0, sizeof(struct smb_srv_copychunk));
>> +       cc.src_fd = srcfd;
>> +       cc.length = src_inode->i_size;
>> +       fdput(src_file);
>> +
>> +       return _cifs_ioctl_copychunk(xid, dst_file, &cc);
>> +}
>> +
>>  static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
>>                                 void __user *arg)
>>  {
>> @@ -194,6 +232,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
>>                         }
>>                         break;
>>                 case CIFS_IOC_COPYCHUNK_FILE:
>> +                       rc = cifs_ioctl_copychunk_file(xid, filep, arg);
>> +                       break;
>> +               case CIFS_IOC_COPYCHUNK:
>>                         rc = cifs_ioctl_copychunk(xid, filep, arg);
>>                         break;
>>                 case CIFS_IOC_SET_INTEGRITY:
>> --
>> 2.13.3
>>
>
>
> --
> Thanks,
>
> Steve
From c324ff8b759e1733e23cfcd299028f924521f158 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <lsahlber@redhat.com>
Date: Tue, 4 Sep 2018 20:56:04 +1000
Subject: [PATCH] cifs: copychunk range support

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 src/cloner.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/cloner.c b/src/cloner.c
index ffad82f0..8274dcaf 100644
--- a/src/cloner.c
+++ b/src/cloner.c
@@ -40,9 +40,18 @@ struct btrfs_ioctl_clone_range_args {
 
 #define CIFS_IOCTL_MAGIC 0xCF
 #define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
-
 #endif
 
+struct smb_srv_copychunk {
+	uint32_t src_fd;
+	uint32_t length;
+	uint64_t src_offset;
+	uint64_t dst_offset;
+};
+
+#define CIFS_IOC_COPYCHUNK      _IOW(CIFS_IOCTL_MAGIC, 7, \
+				     struct smb_srv_copychunk)
+
 #ifndef BTRFS_SUPER_MAGIC
 #define BTRFS_SUPER_MAGIC    0x9123683E
 #endif
@@ -120,6 +129,24 @@ clone_file_range_btrfs(int src_fd, int dst_fd, uint64_t src_off,
 }
 
 static int
+clone_file_range_cifs(int src_fd, int dst_fd, uint64_t src_off,
+		      uint64_t dst_off, uint64_t len)
+{
+	struct smb_srv_copychunk cc_args;
+	int ret;
+
+	memset(&cc_args, 0, sizeof(cc_args));
+	cc_args.src_fd = src_fd;
+	cc_args.src_offset = src_off;
+	cc_args.length = len;
+	cc_args.dst_offset = dst_off;
+	ret = ioctl(dst_fd, CIFS_IOC_COPYCHUNK, &cc_args);
+	if (ret != 0)
+		ret = errno;
+	return ret;
+}
+
+static int
 clone_file_range(unsigned int fs_type, int src_fd, int dst_fd, uint64_t src_off,
 		 uint64_t dst_off, uint64_t len)
 {
@@ -128,7 +155,10 @@ clone_file_range(unsigned int fs_type, int src_fd, int dst_fd, uint64_t src_off,
 		return clone_file_range_btrfs(src_fd, dst_fd, src_off, dst_off,
 					      len);
 		break;
-	case CIFS_MAGIC_NUMBER:	/* only supports full file server-side copies */
+	case CIFS_MAGIC_NUMBER:
+		return clone_file_range_cifs(src_fd, dst_fd, src_off, dst_off,
+					     len);
+		break;
 	default:
 		return ENOTSUP;
 		break;
Christoph Hellwig Sept. 4, 2018, 2:11 p.m. UTC | #6
On Mon, Sep 03, 2018 at 04:57:33PM +1000, Ronnie Sahlberg wrote:
> Add a new ioctl for COPYCHUNK that copies a region. The existing
> COPYCHUNK can only be used to copy a whole file.

Please don't add magic ioctls and reuse the existing kernel copy
offload functionality.
Steve French Sept. 5, 2018, 2:30 p.m. UTC | #7
On Tue, Sep 4, 2018 at 9:11 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> On Mon, Sep 03, 2018 at 04:57:33PM +1000, Ronnie Sahlberg wrote:
> > Add a new ioctl for COPYCHUNK that copies a region. The existing
> > COPYCHUNK can only be used to copy a whole file.
>
> Please don't add magic ioctls and reuse the existing kernel copy
> offload functionality.

The existing kernel copy offload syscall does overlap the proposed
ioctl, so until
additional feature rich SMB3 copy offload mechanisms are added  (ODX might
be a good example) require interface features not supported by the syscall
(and thus require a cifs specific ioctl), we might as well avoid confusion
and drop this patch.

Now if any useful copy tools (rsync, gio copy etc.) actually used the copy
syscall that would be even better - but that is a different problem ...
Steve French Sept. 6, 2018, 5:58 p.m. UTC | #8
patch removed
On Wed, Sep 5, 2018 at 9:30 AM Steve French <smfrench@gmail.com> wrote:
>
> On Tue, Sep 4, 2018 at 9:11 AM Christoph Hellwig <hch@infradead.org> wrote:
> >
> > On Mon, Sep 03, 2018 at 04:57:33PM +1000, Ronnie Sahlberg wrote:
> > > Add a new ioctl for COPYCHUNK that copies a region. The existing
> > > COPYCHUNK can only be used to copy a whole file.
> >
> > Please don't add magic ioctls and reuse the existing kernel copy
> > offload functionality.
>
> The existing kernel copy offload syscall does overlap the proposed
> ioctl, so until
> additional feature rich SMB3 copy offload mechanisms are added  (ODX might
> be a good example) require interface features not supported by the syscall
> (and thus require a cifs specific ioctl), we might as well avoid confusion
> and drop this patch.
>
> Now if any useful copy tools (rsync, gio copy etc.) actually used the copy
> syscall that would be even better - but that is a different problem ...
> --
> Thanks,
>
> Steve
diff mbox series

Patch

diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
index 57ff0756e30c..b40b9b608dde 100644
--- a/fs/cifs/cifs_ioctl.h
+++ b/fs/cifs/cifs_ioctl.h
@@ -43,8 +43,16 @@  struct smb_snapshot_array {
 	/*	snapshots[]; */
 } __packed;
 
+struct smb_srv_copychunk {
+	__u32   src_fd;
+	__u32   length;
+	__u64   src_offset;
+	__u64   dst_offset;
+} __packed;
+
 #define CIFS_IOCTL_MAGIC	0xCF
 #define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
 #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
 #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
 #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
+#define CIFS_IOC_COPYCHUNK _IOW(CIFS_IOCTL_MAGIC, 7, struct smb_srv_copychunk)
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 54f32f9143a9..91f87ea01be0 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -34,14 +34,13 @@ 
 #include "cifs_ioctl.h"
 #include <linux/btrfs.h>
 
-static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
-			unsigned long srcfd)
+static long _cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
+				  struct smb_srv_copychunk *cc)
 {
 	int rc;
 	struct fd src_file;
 	struct inode *src_inode;
 
-	cifs_dbg(FYI, "ioctl copychunk range\n");
 	/* the destination must be opened for writing */
 	if (!(dst_file->f_mode & FMODE_WRITE)) {
 		cifs_dbg(FYI, "file target not open for write\n");
@@ -55,7 +54,7 @@  static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 		return rc;
 	}
 
-	src_file = fdget(srcfd);
+	src_file = fdget(cc->src_fd);
 	if (!src_file.file) {
 		rc = -EBADF;
 		goto out_drop_write;
@@ -72,8 +71,9 @@  static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 	if (S_ISDIR(src_inode->i_mode))
 		goto out_fput;
 
-	rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
-					src_inode->i_size, 0);
+	rc = cifs_file_copychunk_range(xid, src_file.file, cc->src_offset,
+				       dst_file, cc->dst_offset,
+				       cc->length, 0);
 	if (rc > 0)
 		rc = 0;
 out_fput:
@@ -83,6 +83,44 @@  static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 	return rc;
 }
 
+static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
+				 unsigned long p)
+{
+	void __user *arg = (void __user *)p;
+	struct smb_srv_copychunk cc;
+
+	cifs_dbg(FYI, "ioctl copychunk range\n");
+
+	if (copy_from_user(&cc, arg, sizeof(cc)))
+		return -EFAULT;
+
+	return _cifs_ioctl_copychunk(xid, dst_file, &cc);
+}
+
+static long cifs_ioctl_copychunk_file(unsigned int xid, struct file *dst_file,
+				      unsigned long srcfd)
+{
+	struct smb_srv_copychunk cc;
+	struct fd src_file;
+	struct inode *src_inode;
+
+	cifs_dbg(FYI, "ioctl copychunk file\n");
+
+	src_file = fdget(srcfd);
+	if (!src_file.file) {
+		mnt_drop_write_file(dst_file);
+		return -EBADF;
+	}
+	src_inode = file_inode(src_file.file);
+
+	memset(&cc, 0, sizeof(struct smb_srv_copychunk));
+	cc.src_fd = srcfd;
+	cc.length = src_inode->i_size;
+	fdput(src_file);
+
+	return _cifs_ioctl_copychunk(xid, dst_file, &cc);
+}
+
 static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
 				void __user *arg)
 {
@@ -194,6 +232,9 @@  long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
 			}
 			break;
 		case CIFS_IOC_COPYCHUNK_FILE:
+			rc = cifs_ioctl_copychunk_file(xid, filep, arg);
+			break;
+		case CIFS_IOC_COPYCHUNK:
 			rc = cifs_ioctl_copychunk(xid, filep, arg);
 			break;
 		case CIFS_IOC_SET_INTEGRITY: