From: Steve French Date: Sun, 28 Jun 2015 04:18:36 +0000 (-0700) Subject: Add reflink copy over SMB3.11 with new FSCTL_DUPLICATE_EXTENTS X-Git-Tag: omap-for-v4.2/fixes-rc1^2~67^2~4 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=02b1666544c08e245cb4e2253ed575f8128943d6;p=pandora-kernel.git Add reflink copy over SMB3.11 with new FSCTL_DUPLICATE_EXTENTS Getting fantastic copy performance with cp --reflink over SMB3.11 using the new FSCTL_DUPLICATE_EXTENTS. This FSCTL was added in the SMB3.11 dialect (testing was against REFS file system) so have put it as a 3.11 protocol specific operation ("vers=3.1.1" on the mount). Tested at the SMB3 plugfest in Redmond. It depends on the new FS Attribute (BLOCK_REFCOUNTING) which is used to advertise support for the ability to do this ioctl (if you can support multiple files pointing to the same block than this refcounting ability or equivalent is needed to support the new reflink-like duplicate extent SMB3 ioctl. Signed-off-by: Steve French --- diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a0212ec6f701..81194e6c7601 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -390,6 +390,9 @@ struct smb_version_operations { int (*clone_range)(const unsigned int, struct cifsFileInfo *src_file, struct cifsFileInfo *target_file, u64 src_off, u64 len, u64 dest_off); + int (*duplicate_extents)(const unsigned int, struct cifsFileInfo *src, + struct cifsFileInfo *target_file, u64 src_off, u64 len, + u64 dest_off); int (*validate_negotiate)(const unsigned int, struct cifs_tcon *); ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *, const unsigned char *, const unsigned char *, char *, diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 998a66ffe01e..47b030da0781 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -2255,6 +2255,8 @@ typedef struct { /* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */ +#define FILE_SUPPORTS_SPARSE_VDL 0x10000000 /* faster nonsparse extend */ +#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 /* allow ioctl dup extents */ #define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000 #define FILE_SUPPORTS_USN_JOURNAL 0x02000000 #define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000 diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 8b7898b7670f..7843b19ef5be 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -31,12 +31,14 @@ #include "cifsproto.h" #include "cifs_debug.h" #include "cifsfs.h" +#include #define CIFS_IOCTL_MAGIC 0xCF #define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, - unsigned long srcfd, u64 off, u64 len, u64 destoff) + unsigned long srcfd, u64 off, u64 len, u64 destoff, + bool dup_extents) { int rc; struct cifsFileInfo *smb_file_target = dst_file->private_data; @@ -109,9 +111,14 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, truncate_inode_pages_range(&target_inode->i_data, destoff, PAGE_CACHE_ALIGN(destoff + len)-1); - if (target_tcon->ses->server->ops->clone_range) + if (dup_extents && target_tcon->ses->server->ops->duplicate_extents) + rc = target_tcon->ses->server->ops->duplicate_extents(xid, + smb_file_src, smb_file_target, off, len, destoff); + else if (!dup_extents && target_tcon->ses->server->ops->clone_range) rc = target_tcon->ses->server->ops->clone_range(xid, smb_file_src, smb_file_target, off, len, destoff); + else + rc = -EOPNOTSUPP; /* force revalidate of size and timestamps of target file now that target is updated on the server */ @@ -205,7 +212,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) } break; case CIFS_IOC_COPYCHUNK_FILE: - rc = cifs_ioctl_clone(xid, filep, arg, 0, 0, 0); + rc = cifs_ioctl_clone(xid, filep, arg, 0, 0, 0, false); + break; + case BTRFS_IOC_CLONE: + rc = cifs_ioctl_clone(xid, filep, arg, 0, 0, 0, true); break; default: cifs_dbg(FYI, "unsupported ioctl\n"); Reading git-diff-tree failed