Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS fixes from Steve French:
"A set of cifs fixes most important of which is Pavel's fix for some
problems with handling Windows reparse points and also the security
fix for setfacl over a cifs mount to Samba removing part of the ACL.
Both of these fixes are for stable as well.

Also added most of copychunk (copy offload) support to cifs although I
expect a final patch in that series (to fix handling of larger files)
in a few days (had to hold off on that in order to incorporate some
additional code review feedback).

Also added support for O_DIRECT on forcedirectio mounts (needed in
order to run some of the server benchmarks over cifs and smb2/smb3
mounts)"

* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6:
[CIFS] Warn if SMB3 encryption required by server
setfacl removes part of ACL when setting POSIX ACLs to Samba
[CIFS] Set copychunk defaults
CIFS: SMB2/SMB3 Copy offload support (refcopy) phase 1
cifs: Use data structures to compute NTLMv2 response offsets
[CIFS] O_DIRECT opens should work on directio mounts
cifs: don't spam the logs on unexpected lookup errors
cifs: change ERRnomem error mapping from ENOMEM to EREMOTEIO
CIFS: Fix symbolic links usage

+358 -74
+24 -16
fs/cifs/cifsencrypt.c
··· 548 548 CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) 549 549 { 550 550 int rc; 551 - unsigned int offset = CIFS_SESS_KEY_SIZE + 8; 551 + struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *) 552 + (ses->auth_key.response + CIFS_SESS_KEY_SIZE); 553 + unsigned int hash_len; 554 + 555 + /* The MD5 hash starts at challenge_key.key */ 556 + hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE + 557 + offsetof(struct ntlmv2_resp, challenge.key[0])); 552 558 553 559 if (!ses->server->secmech.sdeschmacmd5) { 554 560 cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__); ··· 562 556 } 563 557 564 558 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, 565 - ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); 559 + ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); 566 560 if (rc) { 567 561 cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n", 568 562 __func__); ··· 576 570 } 577 571 578 572 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) 579 - memcpy(ses->auth_key.response + offset, 580 - ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); 573 + memcpy(ntlmv2->challenge.key, 574 + ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); 581 575 else 582 - memcpy(ses->auth_key.response + offset, 583 - ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); 576 + memcpy(ntlmv2->challenge.key, 577 + ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); 584 578 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, 585 - ses->auth_key.response + offset, ses->auth_key.len - offset); 579 + ntlmv2->challenge.key, hash_len); 586 580 if (rc) { 587 581 cifs_dbg(VFS, "%s: Could not update with response\n", __func__); 588 582 return rc; 589 583 } 590 584 585 + /* Note that the MD5 digest over writes anon.challenge_key.key */ 591 586 rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, 592 - ses->auth_key.response + CIFS_SESS_KEY_SIZE); 587 + ntlmv2->ntlmv2_hash); 593 588 if (rc) 594 589 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); 595 590 ··· 634 627 int rc; 635 628 int baselen; 636 629 unsigned int tilen; 637 - struct ntlmv2_resp *buf; 630 + struct ntlmv2_resp *ntlmv2; 638 631 char ntlmv2_hash[16]; 639 632 unsigned char *tiblob = NULL; /* target info blob */ 640 633 ··· 667 660 } 668 661 ses->auth_key.len += baselen; 669 662 670 - buf = (struct ntlmv2_resp *) 663 + ntlmv2 = (struct ntlmv2_resp *) 671 664 (ses->auth_key.response + CIFS_SESS_KEY_SIZE); 672 - buf->blob_signature = cpu_to_le32(0x00000101); 673 - buf->reserved = 0; 674 - buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 675 - get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 676 - buf->reserved2 = 0; 665 + ntlmv2->blob_signature = cpu_to_le32(0x00000101); 666 + ntlmv2->reserved = 0; 667 + /* Must be within 5 minutes of the server */ 668 + ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 669 + get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal)); 670 + ntlmv2->reserved2 = 0; 677 671 678 672 memcpy(ses->auth_key.response + baselen, tiblob, tilen); 679 673 ··· 714 706 } 715 707 716 708 rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, 717 - ses->auth_key.response + CIFS_SESS_KEY_SIZE, 709 + ntlmv2->ntlmv2_hash, 718 710 CIFS_HMAC_MD5_HASH_SIZE); 719 711 if (rc) { 720 712 cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
+7 -1
fs/cifs/cifsglob.h
··· 261 261 /* query path data from the server */ 262 262 int (*query_path_info)(const unsigned int, struct cifs_tcon *, 263 263 struct cifs_sb_info *, const char *, 264 - FILE_ALL_INFO *, bool *); 264 + FILE_ALL_INFO *, bool *, bool *); 265 265 /* query file data from the server */ 266 266 int (*query_file_info)(const unsigned int, struct cifs_tcon *, 267 267 struct cifs_fid *, FILE_ALL_INFO *); ··· 381 381 char * (*create_lease_buf)(u8 *, u8); 382 382 /* parse lease context buffer and return oplock/epoch info */ 383 383 __u8 (*parse_lease_buf)(void *, unsigned int *); 384 + int (*clone_range)(const unsigned int, struct cifsFileInfo *src_file, 385 + struct cifsFileInfo *target_file, u64 src_off, u64 len, 386 + u64 dest_off); 384 387 }; 385 388 386 389 struct smb_version_values { ··· 858 855 __le64 vol_create_time; 859 856 __u32 ss_flags; /* sector size flags */ 860 857 __u32 perf_sector_size; /* best sector size for perf */ 858 + __u32 max_chunks; 859 + __u32 max_bytes_chunk; 860 + __u32 max_bytes_copy; 861 861 #endif /* CONFIG_CIFS_SMB2 */ 862 862 #ifdef CONFIG_CIFS_FSCACHE 863 863 u64 resource_id; /* server resource id */
+7 -1
fs/cifs/cifspdu.h
··· 697 697 } __attribute__((packed)); 698 698 699 699 struct ntlmv2_resp { 700 - char ntlmv2_hash[CIFS_ENCPWD_SIZE]; 700 + union { 701 + char ntlmv2_hash[CIFS_ENCPWD_SIZE]; 702 + struct { 703 + __u8 reserved[8]; 704 + __u8 key[CIFS_SERVER_CHALLENGE_SIZE]; 705 + } __attribute__((packed)) challenge; 706 + } __attribute__((packed)); 701 707 __le32 blob_signature; 702 708 __u32 reserved; 703 709 __le64 time;
+5 -3
fs/cifs/cifssmb.c
··· 3369 3369 return 0; 3370 3370 } 3371 3371 cifs_acl->version = cpu_to_le16(1); 3372 - if (acl_type == ACL_TYPE_ACCESS) 3372 + if (acl_type == ACL_TYPE_ACCESS) { 3373 3373 cifs_acl->access_entry_count = cpu_to_le16(count); 3374 - else if (acl_type == ACL_TYPE_DEFAULT) 3374 + cifs_acl->default_entry_count = __constant_cpu_to_le16(0xFFFF); 3375 + } else if (acl_type == ACL_TYPE_DEFAULT) { 3375 3376 cifs_acl->default_entry_count = cpu_to_le16(count); 3376 - else { 3377 + cifs_acl->access_entry_count = __constant_cpu_to_le16(0xFFFF); 3378 + } else { 3377 3379 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type); 3378 3380 return 0; 3379 3381 }
+1 -1
fs/cifs/dir.c
··· 756 756 /* if it was once a directory (but how can we tell?) we could do 757 757 shrink_dcache_parent(direntry); */ 758 758 } else if (rc != -EACCES) { 759 - cifs_dbg(VFS, "Unexpected lookup error %d\n", rc); 759 + cifs_dbg(FYI, "Unexpected lookup error %d\n", rc); 760 760 /* We special case check for Access Denied - since that 761 761 is a common return code */ 762 762 }
+22
fs/cifs/file.c
··· 3663 3663 } 3664 3664 } 3665 3665 3666 + /* 3667 + * The presence of cifs_direct_io() in the address space ops vector 3668 + * allowes open() O_DIRECT flags which would have failed otherwise. 3669 + * 3670 + * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests 3671 + * so this method should never be called. 3672 + * 3673 + * Direct IO is not yet supported in the cached mode. 3674 + */ 3675 + static ssize_t 3676 + cifs_direct_io(int rw, struct kiocb *iocb, const struct iovec *iov, 3677 + loff_t pos, unsigned long nr_segs) 3678 + { 3679 + /* 3680 + * FIXME 3681 + * Eventually need to support direct IO for non forcedirectio mounts 3682 + */ 3683 + return -EINVAL; 3684 + } 3685 + 3686 + 3666 3687 const struct address_space_operations cifs_addr_ops = { 3667 3688 .readpage = cifs_readpage, 3668 3689 .readpages = cifs_readpages, ··· 3693 3672 .write_end = cifs_write_end, 3694 3673 .set_page_dirty = __set_page_dirty_nobuffers, 3695 3674 .releasepage = cifs_release_page, 3675 + .direct_IO = cifs_direct_io, 3696 3676 .invalidatepage = cifs_invalidate_page, 3697 3677 .launder_page = cifs_launder_page, 3698 3678 };
+13 -10
fs/cifs/inode.c
··· 542 542 /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ 543 543 static void 544 544 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, 545 - struct cifs_sb_info *cifs_sb, bool adjust_tz) 545 + struct cifs_sb_info *cifs_sb, bool adjust_tz, 546 + bool symlink) 546 547 { 547 548 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 548 549 ··· 570 569 fattr->cf_createtime = le64_to_cpu(info->CreationTime); 571 570 572 571 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); 573 - if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 572 + 573 + if (symlink) { 574 + fattr->cf_mode = S_IFLNK; 575 + fattr->cf_dtype = DT_LNK; 576 + } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 574 577 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; 575 578 fattr->cf_dtype = DT_DIR; 576 579 /* ··· 583 578 */ 584 579 if (!tcon->unix_ext) 585 580 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; 586 - } else if (fattr->cf_cifsattrs & ATTR_REPARSE) { 587 - fattr->cf_mode = S_IFLNK; 588 - fattr->cf_dtype = DT_LNK; 589 - fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); 590 581 } else { 591 582 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; 592 583 fattr->cf_dtype = DT_REG; ··· 627 626 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data); 628 627 switch (rc) { 629 628 case 0: 630 - cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false); 629 + cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false, 630 + false); 631 631 break; 632 632 case -EREMOTE: 633 633 cifs_create_dfs_fattr(&fattr, inode->i_sb); ··· 675 673 bool adjust_tz = false; 676 674 struct cifs_fattr fattr; 677 675 struct cifs_search_info *srchinf = NULL; 676 + bool symlink = false; 678 677 679 678 tlink = cifs_sb_tlink(cifs_sb); 680 679 if (IS_ERR(tlink)) ··· 705 702 } 706 703 data = (FILE_ALL_INFO *)buf; 707 704 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, 708 - data, &adjust_tz); 705 + data, &adjust_tz, &symlink); 709 706 } 710 707 711 708 if (!rc) { 712 - cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb, 713 - adjust_tz); 709 + cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz, 710 + symlink); 714 711 } else if (rc == -EREMOTE) { 715 712 cifs_create_dfs_fattr(&fattr, sb); 716 713 rc = 0;
+111
fs/cifs/ioctl.c
··· 22 22 */ 23 23 24 24 #include <linux/fs.h> 25 + #include <linux/file.h> 26 + #include <linux/mount.h> 27 + #include <linux/mm.h> 28 + #include <linux/pagemap.h> 29 + #include <linux/btrfs.h> 25 30 #include "cifspdu.h" 26 31 #include "cifsglob.h" 27 32 #include "cifsproto.h" 28 33 #include "cifs_debug.h" 29 34 #include "cifsfs.h" 35 + 36 + static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, 37 + unsigned long srcfd, u64 off, u64 len, u64 destoff) 38 + { 39 + int rc; 40 + struct cifsFileInfo *smb_file_target = dst_file->private_data; 41 + struct inode *target_inode = file_inode(dst_file); 42 + struct cifs_tcon *target_tcon; 43 + struct fd src_file; 44 + struct cifsFileInfo *smb_file_src; 45 + struct inode *src_inode; 46 + struct cifs_tcon *src_tcon; 47 + 48 + cifs_dbg(FYI, "ioctl clone range\n"); 49 + /* the destination must be opened for writing */ 50 + if (!(dst_file->f_mode & FMODE_WRITE)) { 51 + cifs_dbg(FYI, "file target not open for write\n"); 52 + return -EINVAL; 53 + } 54 + 55 + /* check if target volume is readonly and take reference */ 56 + rc = mnt_want_write_file(dst_file); 57 + if (rc) { 58 + cifs_dbg(FYI, "mnt_want_write failed with rc %d\n", rc); 59 + return rc; 60 + } 61 + 62 + src_file = fdget(srcfd); 63 + if (!src_file.file) { 64 + rc = -EBADF; 65 + goto out_drop_write; 66 + } 67 + 68 + if ((!src_file.file->private_data) || (!dst_file->private_data)) { 69 + rc = -EBADF; 70 + cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); 71 + goto out_fput; 72 + } 73 + 74 + rc = -EXDEV; 75 + smb_file_target = dst_file->private_data; 76 + smb_file_src = src_file.file->private_data; 77 + src_tcon = tlink_tcon(smb_file_src->tlink); 78 + target_tcon = tlink_tcon(smb_file_target->tlink); 79 + 80 + /* check if source and target are on same tree connection */ 81 + if (src_tcon != target_tcon) { 82 + cifs_dbg(VFS, "file copy src and target on different volume\n"); 83 + goto out_fput; 84 + } 85 + 86 + src_inode = src_file.file->f_dentry->d_inode; 87 + 88 + /* 89 + * Note: cifs case is easier than btrfs since server responsible for 90 + * checks for proper open modes and file type and if it wants 91 + * server could even support copy of range where source = target 92 + */ 93 + 94 + /* so we do not deadlock racing two ioctls on same files */ 95 + if (target_inode < src_inode) { 96 + mutex_lock_nested(&target_inode->i_mutex, I_MUTEX_PARENT); 97 + mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD); 98 + } else { 99 + mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_PARENT); 100 + mutex_lock_nested(&target_inode->i_mutex, I_MUTEX_CHILD); 101 + } 102 + 103 + /* determine range to clone */ 104 + rc = -EINVAL; 105 + if (off + len > src_inode->i_size || off + len < off) 106 + goto out_unlock; 107 + if (len == 0) 108 + len = src_inode->i_size - off; 109 + 110 + cifs_dbg(FYI, "about to flush pages\n"); 111 + /* should we flush first and last page first */ 112 + truncate_inode_pages_range(&target_inode->i_data, destoff, 113 + PAGE_CACHE_ALIGN(destoff + len)-1); 114 + 115 + if (target_tcon->ses->server->ops->clone_range) 116 + rc = target_tcon->ses->server->ops->clone_range(xid, 117 + smb_file_src, smb_file_target, off, len, destoff); 118 + 119 + /* force revalidate of size and timestamps of target file now 120 + that target is updated on the server */ 121 + CIFS_I(target_inode)->time = 0; 122 + out_unlock: 123 + /* although unlocking in the reverse order from locking is not 124 + strictly necessary here it is a little cleaner to be consistent */ 125 + if (target_inode < src_inode) { 126 + mutex_unlock(&src_inode->i_mutex); 127 + mutex_unlock(&target_inode->i_mutex); 128 + } else { 129 + mutex_unlock(&target_inode->i_mutex); 130 + mutex_unlock(&src_inode->i_mutex); 131 + } 132 + out_fput: 133 + fdput(src_file); 134 + out_drop_write: 135 + mnt_drop_write_file(dst_file); 136 + return rc; 137 + } 30 138 31 139 long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) 32 140 { ··· 212 104 xid, tcon, pSMBFile); 213 105 cifs_dbg(FYI, "set compress flag rc %d\n", rc); 214 106 } 107 + break; 108 + case BTRFS_IOC_CLONE: 109 + rc = cifs_ioctl_clone(xid, filep, arg, 0, 0, 0); 215 110 break; 216 111 default: 217 112 cifs_dbg(FYI, "unsupported ioctl\n");
+1 -1
fs/cifs/netmisc.c
··· 51 51 {ERRnoaccess, -EACCES}, 52 52 {ERRbadfid, -EBADF}, 53 53 {ERRbadmcb, -EIO}, 54 - {ERRnomem, -ENOMEM}, 54 + {ERRnomem, -EREMOTEIO}, 55 55 {ERRbadmem, -EFAULT}, 56 56 {ERRbadenv, -EFAULT}, 57 57 {ERRbadformat, -EINVAL},
+8 -32
fs/cifs/readdir.c
··· 134 134 dput(dentry); 135 135 } 136 136 137 - /* 138 - * Is it possible that this directory might turn out to be a DFS referral 139 - * once we go to try and use it? 140 - */ 141 - static bool 142 - cifs_dfs_is_possible(struct cifs_sb_info *cifs_sb) 143 - { 144 - #ifdef CONFIG_CIFS_DFS_UPCALL 145 - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 146 - 147 - if (tcon->Flags & SMB_SHARE_IS_IN_DFS) 148 - return true; 149 - #endif 150 - return false; 151 - } 152 - 153 137 static void 154 138 cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) 155 139 { ··· 143 159 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 144 160 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; 145 161 fattr->cf_dtype = DT_DIR; 146 - /* 147 - * Windows CIFS servers generally make DFS referrals look 148 - * like directories in FIND_* responses with the reparse 149 - * attribute flag also set (since DFS junctions are 150 - * reparse points). We must revalidate at least these 151 - * directory inodes before trying to use them (if 152 - * they are DFS we will get PATH_NOT_COVERED back 153 - * when queried directly and can then try to connect 154 - * to the DFS target) 155 - */ 156 - if (cifs_dfs_is_possible(cifs_sb) && 157 - (fattr->cf_cifsattrs & ATTR_REPARSE)) 158 - fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; 159 - } else if (fattr->cf_cifsattrs & ATTR_REPARSE) { 160 - fattr->cf_mode = S_IFLNK; 161 - fattr->cf_dtype = DT_LNK; 162 162 } else { 163 163 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; 164 164 fattr->cf_dtype = DT_REG; 165 165 } 166 + 167 + /* 168 + * We need to revalidate it further to make a decision about whether it 169 + * is a symbolic link, DFS referral or a reparse point with a direct 170 + * access like junctions, deduplicated files, NFS symlinks. 171 + */ 172 + if (fattr->cf_cifsattrs & ATTR_REPARSE) 173 + fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; 166 174 167 175 /* non-unix readdir doesn't provide nlink */ 168 176 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
+20 -1
fs/cifs/smb1ops.c
··· 534 534 static int 535 535 cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 536 536 struct cifs_sb_info *cifs_sb, const char *full_path, 537 - FILE_ALL_INFO *data, bool *adjustTZ) 537 + FILE_ALL_INFO *data, bool *adjustTZ, bool *symlink) 538 538 { 539 539 int rc; 540 + 541 + *symlink = false; 540 542 541 543 /* could do find first instead but this returns more info */ 542 544 rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */, ··· 556 554 CIFS_MOUNT_MAP_SPECIAL_CHR); 557 555 *adjustTZ = true; 558 556 } 557 + 558 + if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { 559 + int tmprc; 560 + int oplock = 0; 561 + __u16 netfid; 562 + 563 + /* Need to check if this is a symbolic link or not */ 564 + tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, 565 + FILE_READ_ATTRIBUTES, 0, &netfid, &oplock, 566 + NULL, cifs_sb->local_nls, 567 + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 568 + if (tmprc == -EOPNOTSUPP) 569 + *symlink = true; 570 + else 571 + CIFSSMBClose(xid, tcon, netfid); 572 + } 573 + 559 574 return rc; 560 575 } 561 576
+12 -4
fs/cifs/smb2inode.c
··· 123 123 int 124 124 smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 125 125 struct cifs_sb_info *cifs_sb, const char *full_path, 126 - FILE_ALL_INFO *data, bool *adjust_tz) 126 + FILE_ALL_INFO *data, bool *adjust_tz, bool *symlink) 127 127 { 128 128 int rc; 129 129 struct smb2_file_all_info *smb2_data; 130 130 131 131 *adjust_tz = false; 132 + *symlink = false; 132 133 133 134 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, 134 135 GFP_KERNEL); ··· 137 136 return -ENOMEM; 138 137 139 138 rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path, 140 - FILE_READ_ATTRIBUTES, FILE_OPEN, 141 - OPEN_REPARSE_POINT, smb2_data, 142 - SMB2_OP_QUERY_INFO); 139 + FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 140 + smb2_data, SMB2_OP_QUERY_INFO); 141 + if (rc == -EOPNOTSUPP) { 142 + *symlink = true; 143 + /* Failed on a symbolic link - query a reparse point info */ 144 + rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path, 145 + FILE_READ_ATTRIBUTES, FILE_OPEN, 146 + OPEN_REPARSE_POINT, smb2_data, 147 + SMB2_OP_QUERY_INFO); 148 + } 143 149 if (rc) 144 150 goto out; 145 151
+1 -1
fs/cifs/smb2maperror.c
··· 306 306 {STATUS_NONEXISTENT_SECTOR, -EIO, "STATUS_NONEXISTENT_SECTOR"}, 307 307 {STATUS_MORE_PROCESSING_REQUIRED, -EIO, 308 308 "STATUS_MORE_PROCESSING_REQUIRED"}, 309 - {STATUS_NO_MEMORY, -ENOMEM, "STATUS_NO_MEMORY"}, 309 + {STATUS_NO_MEMORY, -EREMOTEIO, "STATUS_NO_MEMORY"}, 310 310 {STATUS_CONFLICTING_ADDRESSES, -EADDRINUSE, 311 311 "STATUS_CONFLICTING_ADDRESSES"}, 312 312 {STATUS_NOT_MAPPED_VIEW, -EIO, "STATUS_NOT_MAPPED_VIEW"},
+82
fs/cifs/smb2ops.c
··· 494 494 } 495 495 496 496 static int 497 + SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, 498 + u64 persistent_fid, u64 volatile_fid, 499 + struct copychunk_ioctl *pcchunk) 500 + { 501 + int rc; 502 + unsigned int ret_data_len; 503 + struct resume_key_req *res_key; 504 + 505 + rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, 506 + FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */, 507 + NULL, 0 /* no input */, 508 + (char **)&res_key, &ret_data_len); 509 + 510 + if (rc) { 511 + cifs_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc); 512 + goto req_res_key_exit; 513 + } 514 + if (ret_data_len < sizeof(struct resume_key_req)) { 515 + cifs_dbg(VFS, "Invalid refcopy resume key length\n"); 516 + rc = -EINVAL; 517 + goto req_res_key_exit; 518 + } 519 + memcpy(pcchunk->SourceKey, res_key->ResumeKey, COPY_CHUNK_RES_KEY_SIZE); 520 + 521 + req_res_key_exit: 522 + kfree(res_key); 523 + return rc; 524 + } 525 + 526 + static int 527 + smb2_clone_range(const unsigned int xid, 528 + struct cifsFileInfo *srcfile, 529 + struct cifsFileInfo *trgtfile, u64 src_off, 530 + u64 len, u64 dest_off) 531 + { 532 + int rc; 533 + unsigned int ret_data_len; 534 + struct copychunk_ioctl *pcchunk; 535 + char *retbuf = NULL; 536 + 537 + pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL); 538 + 539 + if (pcchunk == NULL) 540 + return -ENOMEM; 541 + 542 + cifs_dbg(FYI, "in smb2_clone_range - about to call request res key\n"); 543 + /* Request a key from the server to identify the source of the copy */ 544 + rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink), 545 + srcfile->fid.persistent_fid, 546 + srcfile->fid.volatile_fid, pcchunk); 547 + 548 + /* Note: request_res_key sets res_key null only if rc !=0 */ 549 + if (rc) 550 + return rc; 551 + 552 + /* For now array only one chunk long, will make more flexible later */ 553 + pcchunk->ChunkCount = __constant_cpu_to_le32(1); 554 + pcchunk->Reserved = 0; 555 + pcchunk->SourceOffset = cpu_to_le64(src_off); 556 + pcchunk->TargetOffset = cpu_to_le64(dest_off); 557 + pcchunk->Length = cpu_to_le32(len); 558 + pcchunk->Reserved2 = 0; 559 + 560 + /* Request that server copy to target from src file identified by key */ 561 + rc = SMB2_ioctl(xid, tlink_tcon(trgtfile->tlink), 562 + trgtfile->fid.persistent_fid, 563 + trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE, 564 + true /* is_fsctl */, (char *)pcchunk, 565 + sizeof(struct copychunk_ioctl), &retbuf, &ret_data_len); 566 + 567 + /* BB need to special case rc = EINVAL to alter chunk size */ 568 + 569 + cifs_dbg(FYI, "rc %d data length out %d\n", rc, ret_data_len); 570 + 571 + kfree(pcchunk); 572 + return rc; 573 + } 574 + 575 + static int 497 576 smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon, 498 577 struct cifs_fid *fid) 499 578 { ··· 1096 1017 .set_oplock_level = smb2_set_oplock_level, 1097 1018 .create_lease_buf = smb2_create_lease_buf, 1098 1019 .parse_lease_buf = smb2_parse_lease_buf, 1020 + .clone_range = smb2_clone_range, 1099 1021 }; 1100 1022 1101 1023 struct smb_version_operations smb21_operations = { ··· 1170 1090 .set_oplock_level = smb21_set_oplock_level, 1171 1091 .create_lease_buf = smb2_create_lease_buf, 1172 1092 .parse_lease_buf = smb2_parse_lease_buf, 1093 + .clone_range = smb2_clone_range, 1173 1094 }; 1174 1095 1175 1096 struct smb_version_operations smb30_operations = { ··· 1246 1165 .set_oplock_level = smb3_set_oplock_level, 1247 1166 .create_lease_buf = smb3_create_lease_buf, 1248 1167 .parse_lease_buf = smb3_parse_lease_buf, 1168 + .clone_range = smb2_clone_range, 1249 1169 }; 1250 1170 1251 1171 struct smb_version_values smb20_values = {
+11 -1
fs/cifs/smb2pdu.c
··· 630 630 goto ssetup_exit; 631 631 632 632 ses->session_flags = le16_to_cpu(rsp->SessionFlags); 633 + if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) 634 + cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); 633 635 ssetup_exit: 634 636 free_rsp_buf(resp_buftype, rsp); 635 637 ··· 718 716 } 719 717 720 718 #define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */) 719 + 720 + /* These are similar values to what Windows uses */ 721 + static inline void init_copy_chunk_defaults(struct cifs_tcon *tcon) 722 + { 723 + tcon->max_chunks = 256; 724 + tcon->max_bytes_chunk = 1048576; 725 + tcon->max_bytes_copy = 16777216; 726 + } 721 727 722 728 int 723 729 SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ··· 828 818 if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && 829 819 ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) 830 820 cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); 831 - 821 + init_copy_chunk_defaults(tcon); 832 822 tcon_exit: 833 823 free_rsp_buf(resp_buftype, rsp); 834 824 kfree(unc_path);
+32 -1
fs/cifs/smb2pdu.h
··· 122 122 __le16 StructureSize2; /* size of wct area (varies, request specific) */ 123 123 } __packed; 124 124 125 + struct smb2_transform_hdr { 126 + __be32 smb2_buf_length; /* big endian on wire */ 127 + /* length is only two or three bytes - with 128 + one or two byte type preceding it that MBZ */ 129 + __u8 ProtocolId[4]; /* 0xFD 'S' 'M' 'B' */ 130 + __u8 Signature[16]; 131 + __u8 Nonce[11]; 132 + __u8 Reserved[5]; 133 + __le32 OriginalMessageSize; 134 + __u16 Reserved1; 135 + __le16 EncryptionAlgorithm; 136 + __u64 SessionId; 137 + } __packed; 138 + 139 + /* Encryption Algorithms */ 140 + #define SMB2_ENCRYPTION_AES128_CCM __constant_cpu_to_le16(0x0001) 141 + 125 142 /* 126 143 * SMB2 flag definitions 127 144 */ ··· 254 237 /* Currently defined SessionFlags */ 255 238 #define SMB2_SESSION_FLAG_IS_GUEST 0x0001 256 239 #define SMB2_SESSION_FLAG_IS_NULL 0x0002 240 + #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004 257 241 struct smb2_sess_setup_rsp { 258 242 struct smb2_hdr hdr; 259 243 __le16 StructureSize; /* Must be 9 */ ··· 552 534 } Data; 553 535 } __packed; 554 536 537 + #define COPY_CHUNK_RES_KEY_SIZE 24 538 + struct resume_key_req { 539 + char ResumeKey[COPY_CHUNK_RES_KEY_SIZE]; 540 + __le32 ContextLength; /* MBZ */ 541 + char Context[0]; /* ignored, Windows sets to 4 bytes of zero */ 542 + } __packed; 543 + 555 544 /* this goes in the ioctl buffer when doing a copychunk request */ 556 545 struct copychunk_ioctl { 557 - char SourceKey[24]; 546 + char SourceKey[COPY_CHUNK_RES_KEY_SIZE]; 558 547 __le32 ChunkCount; /* we are only sending 1 */ 559 548 __le32 Reserved; 560 549 /* array will only be one chunk long for us */ ··· 569 544 __le64 TargetOffset; 570 545 __le32 Length; /* how many bytes to copy */ 571 546 __u32 Reserved2; 547 + } __packed; 548 + 549 + struct copychunk_ioctl_rsp { 550 + __le32 ChunksWritten; 551 + __le32 ChunkBytesWritten; 552 + __le32 TotalBytesWritten; 572 553 } __packed; 573 554 574 555 /* Response and Request are the same format */
+1 -1
fs/cifs/smb2proto.h
··· 61 61 extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 62 62 struct cifs_sb_info *cifs_sb, 63 63 const char *full_path, FILE_ALL_INFO *data, 64 - bool *adjust_tz); 64 + bool *adjust_tz, bool *symlink); 65 65 extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, 66 66 const char *full_path, __u64 size, 67 67 struct cifs_sb_info *cifs_sb, bool set_alloc);