aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsglob.h14
-rw-r--r--fs/cifs/connect.c6
-rw-r--r--fs/cifs/dir.c3
-rw-r--r--fs/cifs/file.c33
-rw-r--r--fs/cifs/inode.c26
-rw-r--r--fs/cifs/link.c6
-rw-r--r--fs/cifs/readdir.c16
-rw-r--r--fs/cifs/smb1ops.c3
-rw-r--r--fs/cifs/smb2ops.c3
-rw-r--r--fs/cifs/smb2pdu.c2
-rw-r--r--fs/cifs/smb2pdu.h3
11 files changed, 66 insertions, 49 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 12b1176b87b0..bcdf4d4420f1 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -258,6 +258,9 @@ struct smb_version_values {
258 size_t max_header_size; 258 size_t max_header_size;
259 size_t read_rsp_size; 259 size_t read_rsp_size;
260 __le16 lock_cmd; 260 __le16 lock_cmd;
261 unsigned int cap_unix;
262 unsigned int cap_nt_find;
263 unsigned int cap_large_files;
261}; 264};
262 265
263#define HEADER_SIZE(server) (server->vals->header_size) 266#define HEADER_SIZE(server) (server->vals->header_size)
@@ -408,7 +411,7 @@ struct TCP_Server_Info {
408 unsigned int max_vcs; /* maximum number of smb sessions, at least 411 unsigned int max_vcs; /* maximum number of smb sessions, at least
409 those that can be specified uniquely with 412 those that can be specified uniquely with
410 vcnumbers */ 413 vcnumbers */
411 int capabilities; /* allow selective disabling of caps by smb sess */ 414 unsigned int capabilities; /* selective disabling of caps by smb sess */
412 int timeAdj; /* Adjust for difference in server time zone in sec */ 415 int timeAdj; /* Adjust for difference in server time zone in sec */
413 __u64 CurrentMid; /* multiplex id - rotating counter */ 416 __u64 CurrentMid; /* multiplex id - rotating counter */
414 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ 417 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
@@ -532,7 +535,7 @@ struct cifs_ses {
532 __u64 Suid; /* remote smb uid */ 535 __u64 Suid; /* remote smb uid */
533 uid_t linux_uid; /* overriding owner of files on the mount */ 536 uid_t linux_uid; /* overriding owner of files on the mount */
534 uid_t cred_uid; /* owner of credentials */ 537 uid_t cred_uid; /* owner of credentials */
535 int capabilities; 538 unsigned int capabilities;
536 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for 539 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
537 TCP names - will ipv6 and sctp addresses fit? */ 540 TCP names - will ipv6 and sctp addresses fit? */
538 char *user_name; /* must not be null except during init of sess 541 char *user_name; /* must not be null except during init of sess
@@ -554,6 +557,13 @@ struct cifs_ses {
554 which do not negotiate NTLM or POSIX dialects, but instead 557 which do not negotiate NTLM or POSIX dialects, but instead
555 negotiate one of the older LANMAN dialects */ 558 negotiate one of the older LANMAN dialects */
556#define CIFS_SES_LANMAN 8 559#define CIFS_SES_LANMAN 8
560
561static inline bool
562cap_unix(struct cifs_ses *ses)
563{
564 return ses->server->vals->cap_unix & ses->capabilities;
565}
566
557/* 567/*
558 * there is one of these for each connection to a resource on a particular 568 * there is one of these for each connection to a resource on a particular
559 * session 569 * session
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5ab173fd6339..6df6fa14cba8 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3634,7 +3634,7 @@ try_mount_again:
3634 } 3634 }
3635 3635
3636 /* tell server which Unix caps we support */ 3636 /* tell server which Unix caps we support */
3637 if (tcon->ses->capabilities & CAP_UNIX) { 3637 if (cap_unix(tcon->ses)) {
3638 /* reset of caps checks mount to see if unix extensions 3638 /* reset of caps checks mount to see if unix extensions
3639 disabled for just this mount */ 3639 disabled for just this mount */
3640 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info); 3640 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
@@ -3993,7 +3993,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
3993 ses->flags = 0; 3993 ses->flags = 0;
3994 ses->capabilities = server->capabilities; 3994 ses->capabilities = server->capabilities;
3995 if (linuxExtEnabled == 0) 3995 if (linuxExtEnabled == 0)
3996 ses->capabilities &= (~CAP_UNIX); 3996 ses->capabilities &= (~server->vals->cap_unix);
3997 3997
3998 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", 3998 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3999 server->sec_mode, server->capabilities, server->timeAdj); 3999 server->sec_mode, server->capabilities, server->timeAdj);
@@ -4100,7 +4100,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
4100 goto out; 4100 goto out;
4101 } 4101 }
4102 4102
4103 if (ses->capabilities & CAP_UNIX) 4103 if (cap_unix(ses))
4104 reset_cifs_unix_caps(0, tcon, NULL, vol_info); 4104 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4105out: 4105out:
4106 kfree(vol_info->username); 4106 kfree(vol_info->username);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 2caba0b54acb..cbe709ad6663 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -182,8 +182,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
182 goto out; 182 goto out;
183 } 183 }
184 184
185 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && 185 if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
186 !tcon->broken_posix_open &&
187 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 186 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
188 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 187 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
189 rc = cifs_posix_open(full_path, &newinode, 188 rc = cifs_posix_open(full_path, &newinode,
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 93b3b1358409..07e9d41cade7 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -385,9 +385,8 @@ int cifs_open(struct inode *inode, struct file *file)
385 oplock = 0; 385 oplock = 0;
386 386
387 if (!tcon->broken_posix_open && tcon->unix_ext && 387 if (!tcon->broken_posix_open && tcon->unix_ext &&
388 (tcon->ses->capabilities & CAP_UNIX) && 388 cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
389 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 389 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
390 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
391 /* can not refresh inode info since size could be stale */ 390 /* can not refresh inode info since size could be stale */
392 rc = cifs_posix_open(full_path, &inode, inode->i_sb, 391 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
393 cifs_sb->mnt_file_mode /* ignored */, 392 cifs_sb->mnt_file_mode /* ignored */,
@@ -509,10 +508,9 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
509 else 508 else
510 oplock = 0; 509 oplock = 0;
511 510
512 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && 511 if (tcon->unix_ext && cap_unix(tcon->ses) &&
513 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 512 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
514 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 513 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
515
516 /* 514 /*
517 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the 515 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
518 * original open. Must mask them off for a reopen. 516 * original open. Must mask them off for a reopen.
@@ -1071,7 +1069,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
1071 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); 1069 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1072 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 1070 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1073 1071
1074 if ((tcon->ses->capabilities & CAP_UNIX) && 1072 if (cap_unix(tcon->ses) &&
1075 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && 1073 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1076 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) 1074 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1077 return cifs_push_posix_locks(cfile); 1075 return cifs_push_posix_locks(cfile);
@@ -1419,7 +1417,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1419 netfid = cfile->netfid; 1417 netfid = cfile->netfid;
1420 cinode = CIFS_I(file->f_path.dentry->d_inode); 1418 cinode = CIFS_I(file->f_path.dentry->d_inode);
1421 1419
1422 if ((tcon->ses->capabilities & CAP_UNIX) && 1420 if (cap_unix(tcon->ses) &&
1423 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && 1421 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1424 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) 1422 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1425 posix_lck = true; 1423 posix_lck = true;
@@ -2745,7 +2743,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
2745 unsigned int current_read_size; 2743 unsigned int current_read_size;
2746 unsigned int rsize; 2744 unsigned int rsize;
2747 struct cifs_sb_info *cifs_sb; 2745 struct cifs_sb_info *cifs_sb;
2748 struct cifs_tcon *pTcon; 2746 struct cifs_tcon *tcon;
2749 unsigned int xid; 2747 unsigned int xid;
2750 char *current_offset; 2748 char *current_offset;
2751 struct cifsFileInfo *open_file; 2749 struct cifsFileInfo *open_file;
@@ -2765,7 +2763,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
2765 return rc; 2763 return rc;
2766 } 2764 }
2767 open_file = file->private_data; 2765 open_file = file->private_data;
2768 pTcon = tlink_tcon(open_file->tlink); 2766 tcon = tlink_tcon(open_file->tlink);
2769 2767
2770 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 2768 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2771 pid = open_file->pid; 2769 pid = open_file->pid;
@@ -2779,11 +2777,12 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
2779 read_size > total_read; 2777 read_size > total_read;
2780 total_read += bytes_read, current_offset += bytes_read) { 2778 total_read += bytes_read, current_offset += bytes_read) {
2781 current_read_size = min_t(uint, read_size - total_read, rsize); 2779 current_read_size = min_t(uint, read_size - total_read, rsize);
2782 2780 /*
2783 /* For windows me and 9x we do not want to request more 2781 * For windows me and 9x we do not want to request more than it
2784 than it negotiated since it will refuse the read then */ 2782 * negotiated since it will refuse the read then.
2785 if ((pTcon->ses) && 2783 */
2786 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) { 2784 if ((tcon->ses) && !(tcon->ses->capabilities &
2785 tcon->ses->server->vals->cap_large_files)) {
2787 current_read_size = min_t(uint, current_read_size, 2786 current_read_size = min_t(uint, current_read_size,
2788 CIFSMaxBufSize); 2787 CIFSMaxBufSize);
2789 } 2788 }
@@ -2796,7 +2795,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
2796 } 2795 }
2797 io_parms.netfid = open_file->netfid; 2796 io_parms.netfid = open_file->netfid;
2798 io_parms.pid = pid; 2797 io_parms.pid = pid;
2799 io_parms.tcon = pTcon; 2798 io_parms.tcon = tcon;
2800 io_parms.offset = *poffset; 2799 io_parms.offset = *poffset;
2801 io_parms.length = current_read_size; 2800 io_parms.length = current_read_size;
2802 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, 2801 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
@@ -2810,7 +2809,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
2810 return rc; 2809 return rc;
2811 } 2810 }
2812 } else { 2811 } else {
2813 cifs_stats_bytes_read(pTcon, total_read); 2812 cifs_stats_bytes_read(tcon, total_read);
2814 *poffset += bytes_read; 2813 *poffset += bytes_read;
2815 } 2814 }
2816 } 2815 }
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index def10064fe9d..35cb6a374a45 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1149,9 +1149,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
1149 goto unlink_out; 1149 goto unlink_out;
1150 } 1150 }
1151 1151
1152 if ((tcon->ses->capabilities & CAP_UNIX) && 1152 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1153 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 1153 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1154 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1155 rc = CIFSPOSIXDelFile(xid, tcon, full_path, 1154 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
1156 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, 1155 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1157 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 1156 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -1226,7 +1225,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1226 unsigned int xid; 1225 unsigned int xid;
1227 struct cifs_sb_info *cifs_sb; 1226 struct cifs_sb_info *cifs_sb;
1228 struct tcon_link *tlink; 1227 struct tcon_link *tlink;
1229 struct cifs_tcon *pTcon; 1228 struct cifs_tcon *tcon;
1230 char *full_path = NULL; 1229 char *full_path = NULL;
1231 struct inode *newinode = NULL; 1230 struct inode *newinode = NULL;
1232 struct cifs_fattr fattr; 1231 struct cifs_fattr fattr;
@@ -1237,7 +1236,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1237 tlink = cifs_sb_tlink(cifs_sb); 1236 tlink = cifs_sb_tlink(cifs_sb);
1238 if (IS_ERR(tlink)) 1237 if (IS_ERR(tlink))
1239 return PTR_ERR(tlink); 1238 return PTR_ERR(tlink);
1240 pTcon = tlink_tcon(tlink); 1239 tcon = tlink_tcon(tlink);
1241 1240
1242 xid = get_xid(); 1241 xid = get_xid();
1243 1242
@@ -1247,9 +1246,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1247 goto mkdir_out; 1246 goto mkdir_out;
1248 } 1247 }
1249 1248
1250 if ((pTcon->ses->capabilities & CAP_UNIX) && 1249 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1251 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 1250 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1252 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
1253 u32 oplock = 0; 1251 u32 oplock = 0;
1254 FILE_UNIX_BASIC_INFO *pInfo = 1252 FILE_UNIX_BASIC_INFO *pInfo =
1255 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); 1253 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
@@ -1259,7 +1257,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1259 } 1257 }
1260 1258
1261 mode &= ~current_umask(); 1259 mode &= ~current_umask();
1262 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, 1260 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT,
1263 mode, NULL /* netfid */, pInfo, &oplock, 1261 mode, NULL /* netfid */, pInfo, &oplock,
1264 full_path, cifs_sb->local_nls, 1262 full_path, cifs_sb->local_nls,
1265 cifs_sb->mnt_cifs_flags & 1263 cifs_sb->mnt_cifs_flags &
@@ -1303,14 +1301,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
1303 } 1301 }
1304mkdir_retry_old: 1302mkdir_retry_old:
1305 /* BB add setting the equivalent of mode via CreateX w/ACLs */ 1303 /* BB add setting the equivalent of mode via CreateX w/ACLs */
1306 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, 1304 rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
1307 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 1305 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1308 if (rc) { 1306 if (rc) {
1309 cFYI(1, "cifs_mkdir returned 0x%x", rc); 1307 cFYI(1, "cifs_mkdir returned 0x%x", rc);
1310 d_drop(direntry); 1308 d_drop(direntry);
1311 } else { 1309 } else {
1312mkdir_get_info: 1310mkdir_get_info:
1313 if (pTcon->unix_ext) 1311 if (tcon->unix_ext)
1314 rc = cifs_get_inode_info_unix(&newinode, full_path, 1312 rc = cifs_get_inode_info_unix(&newinode, full_path,
1315 inode->i_sb, xid); 1313 inode->i_sb, xid);
1316 else 1314 else
@@ -1328,7 +1326,7 @@ mkdir_get_info:
1328 if (inode->i_mode & S_ISGID) 1326 if (inode->i_mode & S_ISGID)
1329 mode |= S_ISGID; 1327 mode |= S_ISGID;
1330 1328
1331 if (pTcon->unix_ext) { 1329 if (tcon->unix_ext) {
1332 struct cifs_unix_set_info_args args = { 1330 struct cifs_unix_set_info_args args = {
1333 .mode = mode, 1331 .mode = mode,
1334 .ctime = NO_CHANGE_64, 1332 .ctime = NO_CHANGE_64,
@@ -1346,7 +1344,7 @@ mkdir_get_info:
1346 args.uid = NO_CHANGE_64; 1344 args.uid = NO_CHANGE_64;
1347 args.gid = NO_CHANGE_64; 1345 args.gid = NO_CHANGE_64;
1348 } 1346 }
1349 CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, 1347 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1350 cifs_sb->local_nls, 1348 cifs_sb->local_nls,
1351 cifs_sb->mnt_cifs_flags & 1349 cifs_sb->mnt_cifs_flags &
1352 CIFS_MOUNT_MAP_SPECIAL_CHR); 1350 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -1361,7 +1359,7 @@ mkdir_get_info:
1361 cifsInode = CIFS_I(newinode); 1359 cifsInode = CIFS_I(newinode);
1362 dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; 1360 dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
1363 pInfo.Attributes = cpu_to_le32(dosattrs); 1361 pInfo.Attributes = cpu_to_le32(dosattrs);
1364 tmprc = CIFSSMBSetPathInfo(xid, pTcon, 1362 tmprc = CIFSSMBSetPathInfo(xid, tcon,
1365 full_path, &pInfo, 1363 full_path, &pInfo,
1366 cifs_sb->local_nls, 1364 cifs_sb->local_nls,
1367 cifs_sb->mnt_cifs_flags & 1365 cifs_sb->mnt_cifs_flags &
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index f78971511f57..09e4b3ae4564 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -495,8 +495,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
495 * but there doesn't seem to be any harm in allowing the client to 495 * but there doesn't seem to be any harm in allowing the client to
496 * read them. 496 * read them.
497 */ 497 */
498 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 498 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
499 && !(tcon->ses->capabilities & CAP_UNIX)) { 499 !cap_unix(tcon->ses)) {
500 rc = -EACCES; 500 rc = -EACCES;
501 goto out; 501 goto out;
502 } 502 }
@@ -518,7 +518,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
518 cifs_sb->mnt_cifs_flags & 518 cifs_sb->mnt_cifs_flags &
519 CIFS_MOUNT_MAP_SPECIAL_CHR); 519 CIFS_MOUNT_MAP_SPECIAL_CHR);
520 520
521 if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX)) 521 if ((rc != 0) && cap_unix(tcon->ses))
522 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, 522 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
523 cifs_sb->local_nls); 523 cifs_sb->local_nls);
524 524
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index da30d96a7495..d87f82678bc7 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -228,7 +228,7 @@ static int initiate_cifs_search(const unsigned int xid, struct file *file)
228 struct cifsFileInfo *cifsFile; 228 struct cifsFileInfo *cifsFile;
229 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 229 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
230 struct tcon_link *tlink = NULL; 230 struct tcon_link *tlink = NULL;
231 struct cifs_tcon *pTcon; 231 struct cifs_tcon *tcon;
232 232
233 if (file->private_data == NULL) { 233 if (file->private_data == NULL) {
234 tlink = cifs_sb_tlink(cifs_sb); 234 tlink = cifs_sb_tlink(cifs_sb);
@@ -242,10 +242,10 @@ static int initiate_cifs_search(const unsigned int xid, struct file *file)
242 } 242 }
243 file->private_data = cifsFile; 243 file->private_data = cifsFile;
244 cifsFile->tlink = cifs_get_tlink(tlink); 244 cifsFile->tlink = cifs_get_tlink(tlink);
245 pTcon = tlink_tcon(tlink); 245 tcon = tlink_tcon(tlink);
246 } else { 246 } else {
247 cifsFile = file->private_data; 247 cifsFile = file->private_data;
248 pTcon = tlink_tcon(cifsFile->tlink); 248 tcon = tlink_tcon(cifsFile->tlink);
249 } 249 }
250 250
251 cifsFile->invalidHandle = true; 251 cifsFile->invalidHandle = true;
@@ -262,11 +262,11 @@ static int initiate_cifs_search(const unsigned int xid, struct file *file)
262ffirst_retry: 262ffirst_retry:
263 /* test for Unix extensions */ 263 /* test for Unix extensions */
264 /* but now check for them on the share/mount not on the SMB session */ 264 /* but now check for them on the share/mount not on the SMB session */
265/* if (pTcon->ses->capabilities & CAP_UNIX) { */ 265 /* if (cap_unix(tcon->ses) { */
266 if (pTcon->unix_ext) 266 if (tcon->unix_ext)
267 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 267 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
268 else if ((pTcon->ses->capabilities & 268 else if ((tcon->ses->capabilities &
269 (CAP_NT_SMBS | CAP_NT_FIND)) == 0) { 269 tcon->ses->server->vals->cap_nt_find) == 0) {
270 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD; 270 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
271 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 271 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
272 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; 272 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
@@ -278,7 +278,7 @@ ffirst_retry:
278 if (backup_cred(cifs_sb)) 278 if (backup_cred(cifs_sb))
279 search_flags |= CIFS_SEARCH_BACKUP_SEARCH; 279 search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
280 280
281 rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, 281 rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb->local_nls,
282 &cifsFile->netfid, search_flags, &cifsFile->srch_inf, 282 &cifsFile->netfid, search_flags, &cifsFile->srch_inf,
283 cifs_sb->mnt_cifs_flags & 283 cifs_sb->mnt_cifs_flags &
284 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); 284 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 581740998735..c40356d24c5c 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -632,4 +632,7 @@ struct smb_version_values smb1_values = {
632 .max_header_size = MAX_CIFS_HDR_SIZE, 632 .max_header_size = MAX_CIFS_HDR_SIZE,
633 .read_rsp_size = sizeof(READ_RSP), 633 .read_rsp_size = sizeof(READ_RSP),
634 .lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX), 634 .lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
635 .cap_unix = CAP_UNIX,
636 .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
637 .cap_large_files = CAP_LARGE_FILES,
635}; 638};
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 1018c5c6b5be..410cf925ea26 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -325,4 +325,7 @@ struct smb_version_values smb21_values = {
325 .header_size = sizeof(struct smb2_hdr), 325 .header_size = sizeof(struct smb2_hdr),
326 .max_header_size = MAX_SMB2_HDR_SIZE, 326 .max_header_size = MAX_SMB2_HDR_SIZE,
327 .lock_cmd = SMB2_LOCK, 327 .lock_cmd = SMB2_LOCK,
328 .cap_unix = 0,
329 .cap_nt_find = SMB2_NT_FIND,
330 .cap_large_files = SMB2_LARGE_FILES,
328}; 331};
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index e4eb1d3fb7d9..62b3f17d0613 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -428,6 +428,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
428 /* BB Do we need to validate the SecurityMode? */ 428 /* BB Do we need to validate the SecurityMode? */
429 server->sec_mode = le16_to_cpu(rsp->SecurityMode); 429 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
430 server->capabilities = le32_to_cpu(rsp->Capabilities); 430 server->capabilities = le32_to_cpu(rsp->Capabilities);
431 /* Internal types */
432 server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
431 433
432 security_blob = smb2_get_data_area_len(&blob_offset, &blob_length, 434 security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
433 &rsp->hdr); 435 &rsp->hdr);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 59aae608d366..f37a1b41b402 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -167,6 +167,9 @@ struct smb2_negotiate_req {
167#define SMB2_GLOBAL_CAP_DFS 0x00000001 167#define SMB2_GLOBAL_CAP_DFS 0x00000001
168#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */ 168#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
169#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */ 169#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */
170/* Internal types */
171#define SMB2_NT_FIND 0x00100000
172#define SMB2_LARGE_FILES 0x00200000
170 173
171struct smb2_negotiate_rsp { 174struct smb2_negotiate_rsp {
172 struct smb2_hdr hdr; 175 struct smb2_hdr hdr;