aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/Kconfig35
-rw-r--r--fs/cifs/cifsfs.c24
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h10
-rw-r--r--fs/cifs/cifspdu.h23
-rw-r--r--fs/cifs/connect.c2
-rw-r--r--fs/cifs/dir.c8
-rw-r--r--fs/cifs/file.c18
-rw-r--r--fs/cifs/inode.c11
-rw-r--r--fs/cifs/link.c12
-rw-r--r--fs/cifs/misc.c7
-rw-r--r--fs/cifs/netmisc.c20
-rw-r--r--fs/cifs/readdir.c6
-rw-r--r--fs/cifs/sess.c24
-rw-r--r--fs/cifs/smb1ops.c9
-rw-r--r--fs/cifs/smb2file.c2
-rw-r--r--fs/cifs/smb2inode.c2
-rw-r--r--fs/cifs/smb2maperror.c6
-rw-r--r--fs/cifs/smb2misc.c17
-rw-r--r--fs/cifs/smb2ops.c172
-rw-r--r--fs/cifs/smb2pdu.c23
-rw-r--r--fs/cifs/smb2pdu.h6
-rw-r--r--fs/cifs/smbfsctl.h2
23 files changed, 356 insertions, 85 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 603f18a65c12..a2172f3f69e3 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -22,6 +22,11 @@ config CIFS
22 support for OS/2 and Windows ME and similar servers is provided as 22 support for OS/2 and Windows ME and similar servers is provided as
23 well. 23 well.
24 24
25 The module also provides optional support for the followon
26 protocols for CIFS including SMB3, which enables
27 useful performance and security features (see the description
28 of CONFIG_CIFS_SMB2).
29
25 The cifs module provides an advanced network file system 30 The cifs module provides an advanced network file system
26 client for mounting to CIFS compliant servers. It includes 31 client for mounting to CIFS compliant servers. It includes
27 support for DFS (hierarchical name space), secure per-user 32 support for DFS (hierarchical name space), secure per-user
@@ -121,7 +126,8 @@ config CIFS_ACL
121 depends on CIFS_XATTR && KEYS 126 depends on CIFS_XATTR && KEYS
122 help 127 help
123 Allows fetching CIFS/NTFS ACL from the server. The DACL blob 128 Allows fetching CIFS/NTFS ACL from the server. The DACL blob
124 is handed over to the application/caller. 129 is handed over to the application/caller. See the man
130 page for getcifsacl for more information.
125 131
126config CIFS_DEBUG 132config CIFS_DEBUG
127 bool "Enable CIFS debugging routines" 133 bool "Enable CIFS debugging routines"
@@ -162,7 +168,7 @@ config CIFS_NFSD_EXPORT
162 Allows NFS server to export a CIFS mounted share (nfsd over cifs) 168 Allows NFS server to export a CIFS mounted share (nfsd over cifs)
163 169
164config CIFS_SMB2 170config CIFS_SMB2
165 bool "SMB2 network file system support" 171 bool "SMB2 and SMB3 network file system support"
166 depends on CIFS && INET 172 depends on CIFS && INET
167 select NLS 173 select NLS
168 select KEYS 174 select KEYS
@@ -170,16 +176,21 @@ config CIFS_SMB2
170 select DNS_RESOLVER 176 select DNS_RESOLVER
171 177
172 help 178 help
173 This enables experimental support for the SMB2 (Server Message Block 179 This enables support for the Server Message Block version 2
174 version 2) protocol. The SMB2 protocol is the successor to the 180 family of protocols, including SMB3. SMB3 support is
175 popular CIFS and SMB network file sharing protocols. SMB2 is the 181 enabled on mount by specifying "vers=3.0" in the mount
176 native file sharing mechanism for recent versions of Windows 182 options. These protocols are the successors to the popular
177 operating systems (since Vista). SMB2 enablement will eventually 183 CIFS and SMB network file sharing protocols. SMB3 is the
178 allow users better performance, security and features, than would be 184 native file sharing mechanism for the more recent
179 possible with cifs. Note that smb2 mount options also are simpler 185 versions of Windows (Windows 8 and Windows 2012 and
180 (compared to cifs) due to protocol improvements. 186 later) and Samba server and many others support SMB3 well.
181 187 In general SMB3 enables better performance, security
182 Unless you are a developer or tester, say N. 188 and features, than would be possible with CIFS (Note that
189 when mounting to Samba, due to the CIFS POSIX extensions,
190 CIFS mounts can provide slightly better POSIX compatibility
191 than SMB3 mounts do though). Note that SMB2/SMB3 mount
192 options are also slightly simpler (compared to CIFS) due
193 to protocol improvements.
183 194
184config CIFS_FSCACHE 195config CIFS_FSCACHE
185 bool "Provide CIFS client caching support" 196 bool "Provide CIFS client caching support"
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index ac4f260155c8..889b98455750 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -207,6 +207,19 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
207 return 0; 207 return 0;
208} 208}
209 209
210static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len)
211{
212 struct super_block *sb = file->f_path.dentry->d_sb;
213 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
214 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
215 struct TCP_Server_Info *server = tcon->ses->server;
216
217 if (server->ops->fallocate)
218 return server->ops->fallocate(file, tcon, mode, off, len);
219
220 return -EOPNOTSUPP;
221}
222
210static int cifs_permission(struct inode *inode, int mask) 223static int cifs_permission(struct inode *inode, int mask)
211{ 224{
212 struct cifs_sb_info *cifs_sb; 225 struct cifs_sb_info *cifs_sb;
@@ -812,8 +825,9 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
812 if (!(S_ISREG(inode->i_mode))) 825 if (!(S_ISREG(inode->i_mode)))
813 return -EINVAL; 826 return -EINVAL;
814 827
815 /* check if file is oplocked */ 828 /* Check if file is oplocked if this is request for new lease */
816 if (((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) || 829 if (arg == F_UNLCK ||
830 ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
817 ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode)))) 831 ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode))))
818 return generic_setlease(file, arg, lease); 832 return generic_setlease(file, arg, lease);
819 else if (tlink_tcon(cfile->tlink)->local_lease && 833 else if (tlink_tcon(cfile->tlink)->local_lease &&
@@ -908,6 +922,7 @@ const struct file_operations cifs_file_ops = {
908 .unlocked_ioctl = cifs_ioctl, 922 .unlocked_ioctl = cifs_ioctl,
909#endif /* CONFIG_CIFS_POSIX */ 923#endif /* CONFIG_CIFS_POSIX */
910 .setlease = cifs_setlease, 924 .setlease = cifs_setlease,
925 .fallocate = cifs_fallocate,
911}; 926};
912 927
913const struct file_operations cifs_file_strict_ops = { 928const struct file_operations cifs_file_strict_ops = {
@@ -927,6 +942,7 @@ const struct file_operations cifs_file_strict_ops = {
927 .unlocked_ioctl = cifs_ioctl, 942 .unlocked_ioctl = cifs_ioctl,
928#endif /* CONFIG_CIFS_POSIX */ 943#endif /* CONFIG_CIFS_POSIX */
929 .setlease = cifs_setlease, 944 .setlease = cifs_setlease,
945 .fallocate = cifs_fallocate,
930}; 946};
931 947
932const struct file_operations cifs_file_direct_ops = { 948const struct file_operations cifs_file_direct_ops = {
@@ -947,6 +963,7 @@ const struct file_operations cifs_file_direct_ops = {
947#endif /* CONFIG_CIFS_POSIX */ 963#endif /* CONFIG_CIFS_POSIX */
948 .llseek = cifs_llseek, 964 .llseek = cifs_llseek,
949 .setlease = cifs_setlease, 965 .setlease = cifs_setlease,
966 .fallocate = cifs_fallocate,
950}; 967};
951 968
952const struct file_operations cifs_file_nobrl_ops = { 969const struct file_operations cifs_file_nobrl_ops = {
@@ -965,6 +982,7 @@ const struct file_operations cifs_file_nobrl_ops = {
965 .unlocked_ioctl = cifs_ioctl, 982 .unlocked_ioctl = cifs_ioctl,
966#endif /* CONFIG_CIFS_POSIX */ 983#endif /* CONFIG_CIFS_POSIX */
967 .setlease = cifs_setlease, 984 .setlease = cifs_setlease,
985 .fallocate = cifs_fallocate,
968}; 986};
969 987
970const struct file_operations cifs_file_strict_nobrl_ops = { 988const struct file_operations cifs_file_strict_nobrl_ops = {
@@ -983,6 +1001,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
983 .unlocked_ioctl = cifs_ioctl, 1001 .unlocked_ioctl = cifs_ioctl,
984#endif /* CONFIG_CIFS_POSIX */ 1002#endif /* CONFIG_CIFS_POSIX */
985 .setlease = cifs_setlease, 1003 .setlease = cifs_setlease,
1004 .fallocate = cifs_fallocate,
986}; 1005};
987 1006
988const struct file_operations cifs_file_direct_nobrl_ops = { 1007const struct file_operations cifs_file_direct_nobrl_ops = {
@@ -1002,6 +1021,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
1002#endif /* CONFIG_CIFS_POSIX */ 1021#endif /* CONFIG_CIFS_POSIX */
1003 .llseek = cifs_llseek, 1022 .llseek = cifs_llseek,
1004 .setlease = cifs_setlease, 1023 .setlease = cifs_setlease,
1024 .fallocate = cifs_fallocate,
1005}; 1025};
1006 1026
1007const struct file_operations cifs_dir_ops = { 1027const struct file_operations cifs_dir_ops = {
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index b0fafa499505..002e0c173939 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -136,5 +136,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
136extern const struct export_operations cifs_export_ops; 136extern const struct export_operations cifs_export_ops;
137#endif /* CONFIG_CIFS_NFSD_EXPORT */ 137#endif /* CONFIG_CIFS_NFSD_EXPORT */
138 138
139#define CIFS_VERSION "2.04" 139#define CIFS_VERSION "2.05"
140#endif /* _CIFSFS_H */ 140#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 0012e1e291d4..25b8392bfdd2 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -70,11 +70,6 @@
70#define SERVER_NAME_LENGTH 40 70#define SERVER_NAME_LENGTH 40
71#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) 71#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
72 72
73/* used to define string lengths for reversing unicode strings */
74/* (256+1)*2 = 514 */
75/* (max path length + 1 for null) * 2 for unicode */
76#define MAX_NAME 514
77
78/* SMB echo "timeout" -- FIXME: tunable? */ 73/* SMB echo "timeout" -- FIXME: tunable? */
79#define SMB_ECHO_INTERVAL (60 * HZ) 74#define SMB_ECHO_INTERVAL (60 * HZ)
80 75
@@ -409,6 +404,10 @@ struct smb_version_operations {
409 /* get mtu credits */ 404 /* get mtu credits */
410 int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int, 405 int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int,
411 unsigned int *, unsigned int *); 406 unsigned int *, unsigned int *);
407 /* check if we need to issue closedir */
408 bool (*dir_needs_close)(struct cifsFileInfo *);
409 long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
410 loff_t);
412}; 411};
413 412
414struct smb_version_values { 413struct smb_version_values {
@@ -883,6 +882,7 @@ struct cifs_tcon {
883 for this mount even if server would support */ 882 for this mount even if server would support */
884 bool local_lease:1; /* check leases (only) on local system not remote */ 883 bool local_lease:1; /* check leases (only) on local system not remote */
885 bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ 884 bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
885 bool broken_sparse_sup; /* if server or share does not support sparse */
886 bool need_reconnect:1; /* connection reset, tid now invalid */ 886 bool need_reconnect:1; /* connection reset, tid now invalid */
887#ifdef CONFIG_CIFS_SMB2 887#ifdef CONFIG_CIFS_SMB2
888 bool print:1; /* set if connection to printer share */ 888 bool print:1; /* set if connection to printer share */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 33df36ef9d52..5f9822ac0245 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2253,6 +2253,29 @@ typedef struct {
2253/* minimum includes first three fields, and empty FS Name */ 2253/* minimum includes first three fields, and empty FS Name */
2254#define MIN_FS_ATTR_INFO_SIZE 12 2254#define MIN_FS_ATTR_INFO_SIZE 12
2255 2255
2256
2257/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
2258#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
2259#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
2260#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
2261#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
2262#define FILE_SUPPORTS_HARD_LINKS 0x00400000
2263#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
2264#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
2265#define FILE_READ_ONLY_VOLUME 0x00080000
2266#define FILE_NAMED_STREAMS 0x00040000
2267#define FILE_SUPPORTS_ENCRYPTION 0x00020000
2268#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
2269#define FILE_VOLUME_IS_COMPRESSED 0x00008000
2270#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
2271#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
2272#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
2273#define FILE_VOLUME_QUOTAS 0x00000020
2274#define FILE_FILE_COMPRESSION 0x00000010
2275#define FILE_PERSISTENT_ACLS 0x00000008
2276#define FILE_UNICODE_ON_DISK 0x00000004
2277#define FILE_CASE_PRESERVED_NAMES 0x00000002
2278#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
2256typedef struct { 2279typedef struct {
2257 __le32 Attributes; 2280 __le32 Attributes;
2258 __le32 MaxPathNameComponentLength; 2281 __le32 MaxPathNameComponentLength;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 03ed8a09581c..36ca2045009b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1600,6 +1600,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1600 tmp_end++; 1600 tmp_end++;
1601 if (!(tmp_end < end && tmp_end[1] == delim)) { 1601 if (!(tmp_end < end && tmp_end[1] == delim)) {
1602 /* No it is not. Set the password to NULL */ 1602 /* No it is not. Set the password to NULL */
1603 kfree(vol->password);
1603 vol->password = NULL; 1604 vol->password = NULL;
1604 break; 1605 break;
1605 } 1606 }
@@ -1637,6 +1638,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1637 options = end; 1638 options = end;
1638 } 1639 }
1639 1640
1641 kfree(vol->password);
1640 /* Now build new password string */ 1642 /* Now build new password string */
1641 temp_len = strlen(value); 1643 temp_len = strlen(value);
1642 vol->password = kzalloc(temp_len+1, GFP_KERNEL); 1644 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3db0c5fd9a11..6cbd9c688cfe 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -497,6 +497,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
497 goto out; 497 goto out;
498 } 498 }
499 499
500 if (file->f_flags & O_DIRECT &&
501 CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
502 if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
503 file->f_op = &cifs_file_direct_nobrl_ops;
504 else
505 file->f_op = &cifs_file_direct_ops;
506 }
507
500 file_info = cifs_new_fileinfo(&fid, file, tlink, oplock); 508 file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
501 if (file_info == NULL) { 509 if (file_info == NULL) {
502 if (server->ops->close) 510 if (server->ops->close)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 4ab2f79ffa7a..5f29354b072a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -467,6 +467,14 @@ int cifs_open(struct inode *inode, struct file *file)
467 cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n", 467 cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
468 inode, file->f_flags, full_path); 468 inode, file->f_flags, full_path);
469 469
470 if (file->f_flags & O_DIRECT &&
471 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
472 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
473 file->f_op = &cifs_file_direct_nobrl_ops;
474 else
475 file->f_op = &cifs_file_direct_ops;
476 }
477
470 if (server->oplocks) 478 if (server->oplocks)
471 oplock = REQ_OPLOCK; 479 oplock = REQ_OPLOCK;
472 else 480 else
@@ -762,7 +770,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
762 770
763 cifs_dbg(FYI, "Freeing private data in close dir\n"); 771 cifs_dbg(FYI, "Freeing private data in close dir\n");
764 spin_lock(&cifs_file_list_lock); 772 spin_lock(&cifs_file_list_lock);
765 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { 773 if (server->ops->dir_needs_close(cfile)) {
766 cfile->invalidHandle = true; 774 cfile->invalidHandle = true;
767 spin_unlock(&cifs_file_list_lock); 775 spin_unlock(&cifs_file_list_lock);
768 if (server->ops->close_dir) 776 if (server->ops->close_dir)
@@ -3560,15 +3568,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
3560 lru_cache_add_file(page); 3568 lru_cache_add_file(page);
3561 unlock_page(page); 3569 unlock_page(page);
3562 page_cache_release(page); 3570 page_cache_release(page);
3563 if (rc == -EAGAIN)
3564 list_add_tail(&page->lru, &tmplist);
3565 } 3571 }
3572 /* Fallback to the readpage in error/reconnect cases */
3566 kref_put(&rdata->refcount, cifs_readdata_release); 3573 kref_put(&rdata->refcount, cifs_readdata_release);
3567 if (rc == -EAGAIN) {
3568 /* Re-add pages to the page_list and retry */
3569 list_splice(&tmplist, page_list);
3570 continue;
3571 }
3572 break; 3574 break;
3573 } 3575 }
3574 3576
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 426d6c6ad8bf..7899a40465b3 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1720,13 +1720,22 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1720unlink_target: 1720unlink_target:
1721 /* Try unlinking the target dentry if it's not negative */ 1721 /* Try unlinking the target dentry if it's not negative */
1722 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { 1722 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
1723 tmprc = cifs_unlink(target_dir, target_dentry); 1723 if (d_is_dir(target_dentry))
1724 tmprc = cifs_rmdir(target_dir, target_dentry);
1725 else
1726 tmprc = cifs_unlink(target_dir, target_dentry);
1724 if (tmprc) 1727 if (tmprc)
1725 goto cifs_rename_exit; 1728 goto cifs_rename_exit;
1726 rc = cifs_do_rename(xid, source_dentry, from_name, 1729 rc = cifs_do_rename(xid, source_dentry, from_name,
1727 target_dentry, to_name); 1730 target_dentry, to_name);
1728 } 1731 }
1729 1732
1733 /* force revalidate to go get info when needed */
1734 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1735
1736 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
1737 target_dir->i_mtime = current_fs_time(source_dir->i_sb);
1738
1730cifs_rename_exit: 1739cifs_rename_exit:
1731 kfree(info_buf_source); 1740 kfree(info_buf_source);
1732 kfree(from_name); 1741 kfree(from_name);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 68559fd557fb..5657416d3483 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -213,8 +213,12 @@ create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
213 if (rc) 213 if (rc)
214 goto out; 214 goto out;
215 215
216 rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb, 216 if (tcon->ses->server->ops->create_mf_symlink)
217 fromName, buf, &bytes_written); 217 rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon,
218 cifs_sb, fromName, buf, &bytes_written);
219 else
220 rc = -EOPNOTSUPP;
221
218 if (rc) 222 if (rc)
219 goto out; 223 goto out;
220 224
@@ -339,9 +343,11 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
339 if (rc) 343 if (rc)
340 return rc; 344 return rc;
341 345
342 if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) 346 if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
347 rc = -ENOENT;
343 /* it's not a symlink */ 348 /* it's not a symlink */
344 goto out; 349 goto out;
350 }
345 351
346 io_parms.netfid = fid.netfid; 352 io_parms.netfid = fid.netfid;
347 io_parms.pid = current->tgid; 353 io_parms.pid = current->tgid;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 81340c6253eb..b7415d596dbd 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -574,13 +574,6 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
574 cinode->oplock = 0; 574 cinode->oplock = 0;
575} 575}
576 576
577static int
578cifs_oplock_break_wait(void *unused)
579{
580 schedule();
581 return signal_pending(current) ? -ERESTARTSYS : 0;
582}
583
584/* 577/*
585 * We wait for oplock breaks to be processed before we attempt to perform 578 * We wait for oplock breaks to be processed before we attempt to perform
586 * writes. 579 * writes.
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 6834b9c3bec1..b333ff60781d 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -925,11 +925,23 @@ cifs_NTtimeToUnix(__le64 ntutc)
925 /* BB what about the timezone? BB */ 925 /* BB what about the timezone? BB */
926 926
927 /* Subtract the NTFS time offset, then convert to 1s intervals. */ 927 /* Subtract the NTFS time offset, then convert to 1s intervals. */
928 u64 t; 928 s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
929
930 /*
931 * Unfortunately can not use normal 64 bit division on 32 bit arch, but
932 * the alternative, do_div, does not work with negative numbers so have
933 * to special case them
934 */
935 if (t < 0) {
936 t = -t;
937 ts.tv_nsec = (long)(do_div(t, 10000000) * 100);
938 ts.tv_nsec = -ts.tv_nsec;
939 ts.tv_sec = -t;
940 } else {
941 ts.tv_nsec = (long)do_div(t, 10000000) * 100;
942 ts.tv_sec = t;
943 }
929 944
930 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
931 ts.tv_nsec = do_div(t, 10000000) * 100;
932 ts.tv_sec = t;
933 return ts; 945 return ts;
934} 946}
935 947
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b15862e0f68c..b334a89d6a66 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -593,11 +593,11 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
593 /* close and restart search */ 593 /* close and restart search */
594 cifs_dbg(FYI, "search backing up - close and restart search\n"); 594 cifs_dbg(FYI, "search backing up - close and restart search\n");
595 spin_lock(&cifs_file_list_lock); 595 spin_lock(&cifs_file_list_lock);
596 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { 596 if (server->ops->dir_needs_close(cfile)) {
597 cfile->invalidHandle = true; 597 cfile->invalidHandle = true;
598 spin_unlock(&cifs_file_list_lock); 598 spin_unlock(&cifs_file_list_lock);
599 if (server->ops->close) 599 if (server->ops->close_dir)
600 server->ops->close(xid, tcon, &cfile->fid); 600 server->ops->close_dir(xid, tcon, &cfile->fid);
601 } else 601 } else
602 spin_unlock(&cifs_file_list_lock); 602 spin_unlock(&cifs_file_list_lock);
603 if (cfile->srch_inf.ntwrk_buf_start) { 603 if (cfile->srch_inf.ntwrk_buf_start) {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 39ee32688eac..57db63ff88da 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -243,10 +243,11 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
243 kfree(ses->serverOS); 243 kfree(ses->serverOS);
244 244
245 ses->serverOS = kzalloc(len + 1, GFP_KERNEL); 245 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
246 if (ses->serverOS) 246 if (ses->serverOS) {
247 strncpy(ses->serverOS, bcc_ptr, len); 247 strncpy(ses->serverOS, bcc_ptr, len);
248 if (strncmp(ses->serverOS, "OS/2", 4) == 0) 248 if (strncmp(ses->serverOS, "OS/2", 4) == 0)
249 cifs_dbg(FYI, "OS/2 server\n"); 249 cifs_dbg(FYI, "OS/2 server\n");
250 }
250 251
251 bcc_ptr += len + 1; 252 bcc_ptr += len + 1;
252 bleft -= len + 1; 253 bleft -= len + 1;
@@ -744,14 +745,6 @@ out:
744 sess_free_buffer(sess_data); 745 sess_free_buffer(sess_data);
745} 746}
746 747
747#else
748
749static void
750sess_auth_lanman(struct sess_data *sess_data)
751{
752 sess_data->result = -EOPNOTSUPP;
753 sess_data->func = NULL;
754}
755#endif 748#endif
756 749
757static void 750static void
@@ -1102,15 +1095,6 @@ out:
1102 ses->auth_key.response = NULL; 1095 ses->auth_key.response = NULL;
1103} 1096}
1104 1097
1105#else
1106
1107static void
1108sess_auth_kerberos(struct sess_data *sess_data)
1109{
1110 cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
1111 sess_data->result = -ENOSYS;
1112 sess_data->func = NULL;
1113}
1114#endif /* ! CONFIG_CIFS_UPCALL */ 1098#endif /* ! CONFIG_CIFS_UPCALL */
1115 1099
1116/* 1100/*
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 5e8c22d6c7b9..52131d8cb4d5 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -586,7 +586,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
586 tmprc = CIFS_open(xid, &oparms, &oplock, NULL); 586 tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
587 if (tmprc == -EOPNOTSUPP) 587 if (tmprc == -EOPNOTSUPP)
588 *symlink = true; 588 *symlink = true;
589 else 589 else if (tmprc == 0)
590 CIFSSMBClose(xid, tcon, fid.netfid); 590 CIFSSMBClose(xid, tcon, fid.netfid);
591 } 591 }
592 592
@@ -1015,6 +1015,12 @@ cifs_wp_retry_size(struct inode *inode)
1015 return CIFS_SB(inode->i_sb)->wsize; 1015 return CIFS_SB(inode->i_sb)->wsize;
1016} 1016}
1017 1017
1018static bool
1019cifs_dir_needs_close(struct cifsFileInfo *cfile)
1020{
1021 return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
1022}
1023
1018struct smb_version_operations smb1_operations = { 1024struct smb_version_operations smb1_operations = {
1019 .send_cancel = send_nt_cancel, 1025 .send_cancel = send_nt_cancel,
1020 .compare_fids = cifs_compare_fids, 1026 .compare_fids = cifs_compare_fids,
@@ -1086,6 +1092,7 @@ struct smb_version_operations smb1_operations = {
1086 .create_mf_symlink = cifs_create_mf_symlink, 1092 .create_mf_symlink = cifs_create_mf_symlink,
1087 .is_read_op = cifs_is_read_op, 1093 .is_read_op = cifs_is_read_op,
1088 .wp_retry_size = cifs_wp_retry_size, 1094 .wp_retry_size = cifs_wp_retry_size,
1095 .dir_needs_close = cifs_dir_needs_close,
1089#ifdef CONFIG_CIFS_XATTR 1096#ifdef CONFIG_CIFS_XATTR
1090 .query_all_EAs = CIFSSMBQAllEAs, 1097 .query_all_EAs = CIFSSMBQAllEAs,
1091 .set_EA = CIFSSMBSetEA, 1098 .set_EA = CIFSSMBSetEA,
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index 3f17b4550831..45992944e238 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -50,7 +50,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
50 goto out; 50 goto out;
51 } 51 }
52 52
53 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, 53 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
54 GFP_KERNEL); 54 GFP_KERNEL);
55 if (smb2_data == NULL) { 55 if (smb2_data == NULL) {
56 rc = -ENOMEM; 56 rc = -ENOMEM;
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 0150182a4494..899bbc86f73e 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -131,7 +131,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
131 *adjust_tz = false; 131 *adjust_tz = false;
132 *symlink = false; 132 *symlink = false;
133 133
134 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, 134 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
135 GFP_KERNEL); 135 GFP_KERNEL);
136 if (smb2_data == NULL) 136 if (smb2_data == NULL)
137 return -ENOMEM; 137 return -ENOMEM;
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
index e31a9dfdcd39..8257a5a97cc0 100644
--- a/fs/cifs/smb2maperror.c
+++ b/fs/cifs/smb2maperror.c
@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
214 {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, 214 {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
215 {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, 215 {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
216 {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, 216 {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"},
217 {STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"}, 217 {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
218 {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, 218 {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
219 {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, 219 {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
220 {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"}, 220 {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
@@ -256,6 +256,8 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
256 {STATUS_DLL_MIGHT_BE_INCOMPATIBLE, -EIO, 256 {STATUS_DLL_MIGHT_BE_INCOMPATIBLE, -EIO,
257 "STATUS_DLL_MIGHT_BE_INCOMPATIBLE"}, 257 "STATUS_DLL_MIGHT_BE_INCOMPATIBLE"},
258 {STATUS_STOPPED_ON_SYMLINK, -EOPNOTSUPP, "STATUS_STOPPED_ON_SYMLINK"}, 258 {STATUS_STOPPED_ON_SYMLINK, -EOPNOTSUPP, "STATUS_STOPPED_ON_SYMLINK"},
259 {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EOPNOTSUPP,
260 "STATUS_REPARSE_NOT_HANDLED"},
259 {STATUS_DEVICE_REQUIRES_CLEANING, -EIO, 261 {STATUS_DEVICE_REQUIRES_CLEANING, -EIO,
260 "STATUS_DEVICE_REQUIRES_CLEANING"}, 262 "STATUS_DEVICE_REQUIRES_CLEANING"},
261 {STATUS_DEVICE_DOOR_OPEN, -EIO, "STATUS_DEVICE_DOOR_OPEN"}, 263 {STATUS_DEVICE_DOOR_OPEN, -EIO, "STATUS_DEVICE_DOOR_OPEN"},
@@ -298,7 +300,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
298 {STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"}, 300 {STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"},
299 {STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"}, 301 {STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"},
300 {STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"}, 302 {STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"},
301 {STATUS_INVALID_DEVICE_REQUEST, -EIO, "STATUS_INVALID_DEVICE_REQUEST"}, 303 {STATUS_INVALID_DEVICE_REQUEST, -EOPNOTSUPP, "STATUS_INVALID_DEVICE_REQUEST"},
302 {STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"}, 304 {STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"},
303 {STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"}, 305 {STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"},
304 {STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"}, 306 {STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"},
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index f2e6ac29a8d6..4aa7a0f07d6e 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -178,9 +178,24 @@ smb2_check_message(char *buf, unsigned int length)
178 /* Windows 7 server returns 24 bytes more */ 178 /* Windows 7 server returns 24 bytes more */
179 if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE) 179 if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
180 return 0; 180 return 0;
181 /* server can return one byte more */ 181 /* server can return one byte more due to implied bcc[0] */
182 if (clc_len == 4 + len + 1) 182 if (clc_len == 4 + len + 1)
183 return 0; 183 return 0;
184
185 /*
186 * MacOS server pads after SMB2.1 write response with 3 bytes
187 * of junk. Other servers match RFC1001 len to actual
188 * SMB2/SMB3 frame length (header + smb2 response specific data)
189 * Log the server error (once), but allow it and continue
190 * since the frame is parseable.
191 */
192 if (clc_len < 4 /* RFC1001 header size */ + len) {
193 printk_once(KERN_WARNING
194 "SMB2 server sent bad RFC1001 len %d not %d\n",
195 len, clc_len - 4);
196 return 0;
197 }
198
184 return 1; 199 return 1;
185 } 200 }
186 return 0; 201 return 0;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 77f8aeb9c2fc..f522193b7184 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -389,7 +389,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
389 int rc; 389 int rc;
390 struct smb2_file_all_info *smb2_data; 390 struct smb2_file_all_info *smb2_data;
391 391
392 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, 392 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
393 GFP_KERNEL); 393 GFP_KERNEL);
394 if (smb2_data == NULL) 394 if (smb2_data == NULL)
395 return -ENOMEM; 395 return -ENOMEM;
@@ -731,11 +731,72 @@ smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile,
731 return SMB2_write(xid, parms, written, iov, nr_segs); 731 return SMB2_write(xid, parms, written, iov, nr_segs);
732} 732}
733 733
734/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
735static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
736 struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
737{
738 struct cifsInodeInfo *cifsi;
739 int rc;
740
741 cifsi = CIFS_I(inode);
742
743 /* if file already sparse don't bother setting sparse again */
744 if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
745 return true; /* already sparse */
746
747 if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
748 return true; /* already not sparse */
749
750 /*
751 * Can't check for sparse support on share the usual way via the
752 * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
753 * since Samba server doesn't set the flag on the share, yet
754 * supports the set sparse FSCTL and returns sparse correctly
755 * in the file attributes. If we fail setting sparse though we
756 * mark that server does not support sparse files for this share
757 * to avoid repeatedly sending the unsupported fsctl to server
758 * if the file is repeatedly extended.
759 */
760 if (tcon->broken_sparse_sup)
761 return false;
762
763 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
764 cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
765 true /* is_fctl */, &setsparse, 1, NULL, NULL);
766 if (rc) {
767 tcon->broken_sparse_sup = true;
768 cifs_dbg(FYI, "set sparse rc = %d\n", rc);
769 return false;
770 }
771
772 if (setsparse)
773 cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
774 else
775 cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
776
777 return true;
778}
779
734static int 780static int
735smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon, 781smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
736 struct cifsFileInfo *cfile, __u64 size, bool set_alloc) 782 struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
737{ 783{
738 __le64 eof = cpu_to_le64(size); 784 __le64 eof = cpu_to_le64(size);
785 struct inode *inode;
786
787 /*
788 * If extending file more than one page make sparse. Many Linux fs
789 * make files sparse by default when extending via ftruncate
790 */
791 inode = cfile->dentry->d_inode;
792
793 if (!set_alloc && (size > inode->i_size + 8192)) {
794 __u8 set_sparse = 1;
795
796 /* whether set sparse succeeds or not, extend the file */
797 smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
798 }
799
739 return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, 800 return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
740 cfile->fid.volatile_fid, cfile->pid, &eof, false); 801 cfile->fid.volatile_fid, cfile->pid, &eof, false);
741} 802}
@@ -954,6 +1015,105 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
954 return rc; 1015 return rc;
955} 1016}
956 1017
1018static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
1019 loff_t offset, loff_t len, bool keep_size)
1020{
1021 struct inode *inode;
1022 struct cifsInodeInfo *cifsi;
1023 struct cifsFileInfo *cfile = file->private_data;
1024 struct file_zero_data_information fsctl_buf;
1025 long rc;
1026 unsigned int xid;
1027
1028 xid = get_xid();
1029
1030 inode = cfile->dentry->d_inode;
1031 cifsi = CIFS_I(inode);
1032
1033 /* if file not oplocked can't be sure whether asking to extend size */
1034 if (!CIFS_CACHE_READ(cifsi))
1035 if (keep_size == false)
1036 return -EOPNOTSUPP;
1037
1038 /*
1039 * Must check if file sparse since fallocate -z (zero range) assumes
1040 * non-sparse allocation
1041 */
1042 if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE))
1043 return -EOPNOTSUPP;
1044
1045 /*
1046 * need to make sure we are not asked to extend the file since the SMB3
1047 * fsctl does not change the file size. In the future we could change
1048 * this to zero the first part of the range then set the file size
1049 * which for a non sparse file would zero the newly extended range
1050 */
1051 if (keep_size == false)
1052 if (i_size_read(inode) < offset + len)
1053 return -EOPNOTSUPP;
1054
1055 cifs_dbg(FYI, "offset %lld len %lld", offset, len);
1056
1057 fsctl_buf.FileOffset = cpu_to_le64(offset);
1058 fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
1059
1060 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1061 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
1062 true /* is_fctl */, (char *)&fsctl_buf,
1063 sizeof(struct file_zero_data_information), NULL, NULL);
1064 free_xid(xid);
1065 return rc;
1066}
1067
1068static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
1069 loff_t offset, loff_t len)
1070{
1071 struct inode *inode;
1072 struct cifsInodeInfo *cifsi;
1073 struct cifsFileInfo *cfile = file->private_data;
1074 struct file_zero_data_information fsctl_buf;
1075 long rc;
1076 unsigned int xid;
1077 __u8 set_sparse = 1;
1078
1079 xid = get_xid();
1080
1081 inode = cfile->dentry->d_inode;
1082 cifsi = CIFS_I(inode);
1083
1084 /* Need to make file sparse, if not already, before freeing range. */
1085 /* Consider adding equivalent for compressed since it could also work */
1086 if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse))
1087 return -EOPNOTSUPP;
1088
1089 cifs_dbg(FYI, "offset %lld len %lld", offset, len);
1090
1091 fsctl_buf.FileOffset = cpu_to_le64(offset);
1092 fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
1093
1094 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1095 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
1096 true /* is_fctl */, (char *)&fsctl_buf,
1097 sizeof(struct file_zero_data_information), NULL, NULL);
1098 free_xid(xid);
1099 return rc;
1100}
1101
1102static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
1103 loff_t off, loff_t len)
1104{
1105 /* KEEP_SIZE already checked for by do_fallocate */
1106 if (mode & FALLOC_FL_PUNCH_HOLE)
1107 return smb3_punch_hole(file, tcon, off, len);
1108 else if (mode & FALLOC_FL_ZERO_RANGE) {
1109 if (mode & FALLOC_FL_KEEP_SIZE)
1110 return smb3_zero_range(file, tcon, off, len, true);
1111 return smb3_zero_range(file, tcon, off, len, false);
1112 }
1113
1114 return -EOPNOTSUPP;
1115}
1116
957static void 1117static void
958smb2_downgrade_oplock(struct TCP_Server_Info *server, 1118smb2_downgrade_oplock(struct TCP_Server_Info *server,
959 struct cifsInodeInfo *cinode, bool set_level2) 1119 struct cifsInodeInfo *cinode, bool set_level2)
@@ -1161,6 +1321,12 @@ smb2_wp_retry_size(struct inode *inode)
1161 SMB2_MAX_BUFFER_SIZE); 1321 SMB2_MAX_BUFFER_SIZE);
1162} 1322}
1163 1323
1324static bool
1325smb2_dir_needs_close(struct cifsFileInfo *cfile)
1326{
1327 return !cfile->invalidHandle;
1328}
1329
1164struct smb_version_operations smb20_operations = { 1330struct smb_version_operations smb20_operations = {
1165 .compare_fids = smb2_compare_fids, 1331 .compare_fids = smb2_compare_fids,
1166 .setup_request = smb2_setup_request, 1332 .setup_request = smb2_setup_request,
@@ -1236,6 +1402,7 @@ struct smb_version_operations smb20_operations = {
1236 .parse_lease_buf = smb2_parse_lease_buf, 1402 .parse_lease_buf = smb2_parse_lease_buf,
1237 .clone_range = smb2_clone_range, 1403 .clone_range = smb2_clone_range,
1238 .wp_retry_size = smb2_wp_retry_size, 1404 .wp_retry_size = smb2_wp_retry_size,
1405 .dir_needs_close = smb2_dir_needs_close,
1239}; 1406};
1240 1407
1241struct smb_version_operations smb21_operations = { 1408struct smb_version_operations smb21_operations = {
@@ -1313,6 +1480,7 @@ struct smb_version_operations smb21_operations = {
1313 .parse_lease_buf = smb2_parse_lease_buf, 1480 .parse_lease_buf = smb2_parse_lease_buf,
1314 .clone_range = smb2_clone_range, 1481 .clone_range = smb2_clone_range,
1315 .wp_retry_size = smb2_wp_retry_size, 1482 .wp_retry_size = smb2_wp_retry_size,
1483 .dir_needs_close = smb2_dir_needs_close,
1316}; 1484};
1317 1485
1318struct smb_version_operations smb30_operations = { 1486struct smb_version_operations smb30_operations = {
@@ -1393,6 +1561,8 @@ struct smb_version_operations smb30_operations = {
1393 .clone_range = smb2_clone_range, 1561 .clone_range = smb2_clone_range,
1394 .validate_negotiate = smb3_validate_negotiate, 1562 .validate_negotiate = smb3_validate_negotiate,
1395 .wp_retry_size = smb2_wp_retry_size, 1563 .wp_retry_size = smb2_wp_retry_size,
1564 .dir_needs_close = smb2_dir_needs_close,
1565 .fallocate = smb3_fallocate,
1396}; 1566};
1397 1567
1398struct smb_version_values smb20_values = { 1568struct smb_version_values smb20_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 42ebc1a8be6c..74b3a6684383 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -530,7 +530,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
530 struct smb2_sess_setup_rsp *rsp = NULL; 530 struct smb2_sess_setup_rsp *rsp = NULL;
531 struct kvec iov[2]; 531 struct kvec iov[2];
532 int rc = 0; 532 int rc = 0;
533 int resp_buftype; 533 int resp_buftype = CIFS_NO_BUFFER;
534 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ 534 __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
535 struct TCP_Server_Info *server = ses->server; 535 struct TCP_Server_Info *server = ses->server;
536 u16 blob_length = 0; 536 u16 blob_length = 0;
@@ -907,7 +907,8 @@ tcon_exit:
907tcon_error_exit: 907tcon_error_exit:
908 if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { 908 if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
909 cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); 909 cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
910 tcon->bad_network_name = true; 910 if (tcon)
911 tcon->bad_network_name = true;
911 } 912 }
912 goto tcon_exit; 913 goto tcon_exit;
913} 914}
@@ -1224,7 +1225,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
1224 1225
1225 cifs_dbg(FYI, "SMB2 IOCTL\n"); 1226 cifs_dbg(FYI, "SMB2 IOCTL\n");
1226 1227
1227 *out_data = NULL; 1228 if (out_data != NULL)
1229 *out_data = NULL;
1230
1228 /* zero out returned data len, in case of error */ 1231 /* zero out returned data len, in case of error */
1229 if (plen) 1232 if (plen)
1230 *plen = 0; 1233 *plen = 0;
@@ -1400,8 +1403,7 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
1400 rsp = (struct smb2_close_rsp *)iov[0].iov_base; 1403 rsp = (struct smb2_close_rsp *)iov[0].iov_base;
1401 1404
1402 if (rc != 0) { 1405 if (rc != 0) {
1403 if (tcon) 1406 cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
1404 cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
1405 goto close_exit; 1407 goto close_exit;
1406 } 1408 }
1407 1409
@@ -1530,7 +1532,7 @@ SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
1530{ 1532{
1531 return query_info(xid, tcon, persistent_fid, volatile_fid, 1533 return query_info(xid, tcon, persistent_fid, volatile_fid,
1532 FILE_ALL_INFORMATION, 1534 FILE_ALL_INFORMATION,
1533 sizeof(struct smb2_file_all_info) + MAX_NAME * 2, 1535 sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
1534 sizeof(struct smb2_file_all_info), data); 1536 sizeof(struct smb2_file_all_info), data);
1535} 1537}
1536 1538
@@ -2177,6 +2179,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
2177 rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; 2179 rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base;
2178 2180
2179 if (rc) { 2181 if (rc) {
2182 if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) {
2183 srch_inf->endOfSearch = true;
2184 rc = 0;
2185 }
2180 cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); 2186 cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
2181 goto qdir_exit; 2187 goto qdir_exit;
2182 } 2188 }
@@ -2214,11 +2220,6 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
2214 else 2220 else
2215 cifs_dbg(VFS, "illegal search buffer type\n"); 2221 cifs_dbg(VFS, "illegal search buffer type\n");
2216 2222
2217 if (rsp->hdr.Status == STATUS_NO_MORE_FILES)
2218 srch_inf->endOfSearch = 1;
2219 else
2220 srch_inf->endOfSearch = 0;
2221
2222 return rc; 2223 return rc;
2223 2224
2224qdir_exit: 2225qdir_exit:
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 69f3595d3952..fbe486c285a9 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -573,6 +573,12 @@ struct copychunk_ioctl {
573 __u32 Reserved2; 573 __u32 Reserved2;
574} __packed; 574} __packed;
575 575
576/* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */
577struct file_zero_data_information {
578 __le64 FileOffset;
579 __le64 BeyondFinalZero;
580} __packed;
581
576struct copychunk_ioctl_rsp { 582struct copychunk_ioctl_rsp {
577 __le32 ChunksWritten; 583 __le32 ChunksWritten;
578 __le32 ChunkBytesWritten; 584 __le32 ChunkBytesWritten;
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
index 0e538b5c9622..83efa59535be 100644
--- a/fs/cifs/smbfsctl.h
+++ b/fs/cifs/smbfsctl.h
@@ -63,7 +63,7 @@
63#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */ 63#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
64#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */ 64#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
65#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */ 65#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */
66#define FSCTL_SET_ZERO_DATA 0x000900C8 /* BB add struct */ 66#define FSCTL_SET_ZERO_DATA 0x000980C8
67#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */ 67#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */
68#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */ 68#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */
69#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */ 69#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */