2012/7/24 Jeff Layton <[email protected]>:
> On Wed, 18 Jul 2012 19:48:17 +0400
> Pavel Shilovsky <[email protected]> wrote:
>
>> Since both CIFS and SMB2 use ses->capabilities (server->capabilities)
>> field but flags are different we should make such checks protocol
>> independent.
>>
>> Signed-off-by: Pavel Shilovsky <[email protected]>
>> ---
>> fs/cifs/cifsglob.h | 10 ++++++++++
>> fs/cifs/connect.c | 6 +++---
>> fs/cifs/dir.c | 3 +--
>> fs/cifs/file.c | 33 ++++++++++++++++-----------------
>> fs/cifs/inode.c | 26 ++++++++++++--------------
>> fs/cifs/link.c | 6 +++---
>> fs/cifs/readdir.c | 16 ++++++++--------
>> fs/cifs/smb1ops.c | 3 +++
>> fs/cifs/smb2ops.c | 3 +++
>> fs/cifs/smb2pdu.c | 2 ++
>> fs/cifs/smb2pdu.h | 3 +++
>> 11 files changed, 64 insertions(+), 47 deletions(-)
>>
>> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
>> index 12b1176..5695693 100644
>> --- a/fs/cifs/cifsglob.h
>> +++ b/fs/cifs/cifsglob.h
>> @@ -258,6 +258,9 @@ struct smb_version_values {
>> size_t max_header_size;
>> size_t read_rsp_size;
>> __le16 lock_cmd;
>> + int cap_unix;
>> + int cap_nt_find;
>> + int cap_large_files;
>
> These should probably be unsigned values, and the ses->capabilities and
> server->capabilities flags should be turned into unsigned values as
> well.
>
> For that matter, it's not clear to me why we have capabilities fields
> for both ses and server. I see in one case where they can be different
> (if linuxExtEnabled == 0). Probably they should be converted to always
> use the server one and we get rid of the ses one.
>
>> };
>>
>> #define HEADER_SIZE(server) (server->vals->header_size)
>> @@ -554,6 +557,13 @@ struct cifs_ses {
>> which do not negotiate NTLM or POSIX dialects, but instead
>> negotiate one of the older LANMAN dialects */
>> #define CIFS_SES_LANMAN 8
>> +
>> +static inline bool
>> +cap_unix(struct cifs_ses *ses)
>> +{
>> + return ses->server->vals->cap_unix & ses->capabilities;
>> +}
>> +
>> /*
>> * there is one of these for each connection to a resource on a particular
>> * session
>> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
>> index b1ab89a..99d50bf 100644
>> --- a/fs/cifs/connect.c
>> +++ b/fs/cifs/connect.c
>> @@ -3633,7 +3633,7 @@ try_mount_again:
>> }
>>
>> /* tell server which Unix caps we support */
>> - if (tcon->ses->capabilities & CAP_UNIX) {
>> + if (cap_unix(tcon->ses)) {
>> /* reset of caps checks mount to see if unix extensions
>> disabled for just this mount */
>> reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
>> @@ -3992,7 +3992,7 @@ cifs_setup_session(const unsigned int xid, struct
>> cifs_ses *ses,
>> ses->flags = 0;
>> ses->capabilities = server->capabilities;
>> if (linuxExtEnabled == 0)
>> - ses->capabilities &= (~CAP_UNIX);
>> + ses->capabilities &= (~server->vals->cap_unix);
>>
>> cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
>> server->sec_mode, server->capabilities, server->timeAdj);
>> @@ -4099,7 +4099,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb,
>> uid_t fsuid)
>> goto out;
>> }
>>
>> - if (ses->capabilities & CAP_UNIX)
>> + if (cap_unix(ses))
>> reset_cifs_unix_caps(0, tcon, NULL, vol_info);
>> out:
>> kfree(vol_info->username);
>> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
>> index 2caba0b..cbe709a 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,
>> goto out;
>> }
>>
>> - if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
>> - !tcon->broken_posix_open &&
>> + if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open
>> &&
>> (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> rc = cifs_posix_open(full_path, &newinode,
>> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> index ea1bb66..1712794 100644
>> --- a/fs/cifs/file.c
>> +++ b/fs/cifs/file.c
>> @@ -385,9 +385,8 @@ int cifs_open(struct inode *inode, struct file *file)
>> oplock = 0;
>>
>> if (!tcon->broken_posix_open && tcon->unix_ext &&
>> - (tcon->ses->capabilities & CAP_UNIX) &&
>> - (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> - le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> + cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> + le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> /* can not refresh inode info since size could be stale */
>> rc = cifs_posix_open(full_path, &inode, inode->i_sb,
>> cifs_sb->mnt_file_mode /* ignored */,
>> @@ -509,10 +508,9 @@ static int cifs_reopen_file(struct cifsFileInfo
>> *pCifsFile, bool can_flush)
>> else
>> oplock = 0;
>>
>> - if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
>> + if (tcon->unix_ext && cap_unix(tcon->ses) &&
>> (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> - le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> -
>> + le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> /*
>> * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
>> * original open. Must mask them off for a reopen.
>> @@ -1073,7 +1071,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
>> struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
>> struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
>>
>> - if ((tcon->ses->capabilities & CAP_UNIX) &&
>> + if (cap_unix(tcon->ses) &&
>> (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
>> ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
>> return cifs_push_posix_locks(cfile);
>> @@ -1421,7 +1419,7 @@ int cifs_lock(struct file *file, int cmd, struct
>> file_lock *flock)
>> netfid = cfile->netfid;
>> cinode = CIFS_I(file->f_path.dentry->d_inode);
>>
>> - if ((tcon->ses->capabilities & CAP_UNIX) &&
>> + if (cap_unix(tcon->ses) &&
>> (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
>> ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
>> posix_lck = true;
>> @@ -2747,7 +2745,7 @@ static ssize_t cifs_read(struct file *file, char
>> *read_data, size_t read_size,
>> unsigned int current_read_size;
>> unsigned int rsize;
>> struct cifs_sb_info *cifs_sb;
>> - struct cifs_tcon *pTcon;
>> + struct cifs_tcon *tcon;
>> unsigned int xid;
>> char *current_offset;
>> struct cifsFileInfo *open_file;
>> @@ -2767,7 +2765,7 @@ static ssize_t cifs_read(struct file *file, char
>> *read_data, size_t read_size,
>> return rc;
>> }
>> open_file = file->private_data;
>> - pTcon = tlink_tcon(open_file->tlink);
>> + tcon = tlink_tcon(open_file->tlink);
>>
>> if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
>> pid = open_file->pid;
>> @@ -2781,11 +2779,12 @@ static ssize_t cifs_read(struct file *file, char
>> *read_data, size_t read_size,
>> read_size > total_read;
>> total_read += bytes_read, current_offset += bytes_read) {
>> current_read_size = min_t(uint, read_size - total_read, rsize);
>> -
>> - /* For windows me and 9x we do not want to request more
>> - than it negotiated since it will refuse the read then */
>> - if ((pTcon->ses) &&
>> - !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
>> + /*
>> + * For windows me and 9x we do not want to request more than it
>> + * negotiated since it will refuse the read then.
>> + */
>> + if ((tcon->ses) && !(tcon->ses->capabilities |
>> + tcon->ses->server->vals->cap_large_files)) {
>
> ^^^^
> Bug? Shouldn't that be & cap_large_files ?
Oh, thanks! It is definitly a bug - will fix.
>
>> current_read_size = min_t(uint, current_read_size,
>> CIFSMaxBufSize);
>> }
>> @@ -2798,7 +2797,7 @@ static ssize_t cifs_read(struct file *file, char
>> *read_data, size_t read_size,
>> }
>> io_parms.netfid = open_file->netfid;
>> io_parms.pid = pid;
>> - io_parms.tcon = pTcon;
>> + io_parms.tcon = tcon;
>> io_parms.offset = *poffset;
>> io_parms.length = current_read_size;
>> rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
>> @@ -2812,7 +2811,7 @@ static ssize_t cifs_read(struct file *file, char
>> *read_data, size_t read_size,
>> return rc;
>> }
>> } else {
>> - cifs_stats_bytes_read(pTcon, total_read);
>> + cifs_stats_bytes_read(tcon, total_read);
>> *poffset += bytes_read;
>> }
>> }
>> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
>> index def1006..35cb6a3 100644
>> --- a/fs/cifs/inode.c
>> +++ b/fs/cifs/inode.c
>> @@ -1149,9 +1149,8 @@ int cifs_unlink(struct inode *dir, struct dentry
>> *dentry)
>> goto unlink_out;
>> }
>>
>> - if ((tcon->ses->capabilities & CAP_UNIX) &&
>> - (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> - le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> + if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> + le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> rc = CIFSPOSIXDelFile(xid, tcon, full_path,
>> SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
>> 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)
>> unsigned int xid;
>> struct cifs_sb_info *cifs_sb;
>> struct tcon_link *tlink;
>> - struct cifs_tcon *pTcon;
>> + struct cifs_tcon *tcon;
>> char *full_path = NULL;
>> struct inode *newinode = NULL;
>> struct cifs_fattr fattr;
>> @@ -1237,7 +1236,7 @@ int cifs_mkdir(struct inode *inode, struct dentry
>> *direntry, umode_t mode)
>> tlink = cifs_sb_tlink(cifs_sb);
>> if (IS_ERR(tlink))
>> return PTR_ERR(tlink);
>> - pTcon = tlink_tcon(tlink);
>> + tcon = tlink_tcon(tlink);
>>
>> xid = get_xid();
>>
>> @@ -1247,9 +1246,8 @@ int cifs_mkdir(struct inode *inode, struct dentry
>> *direntry, umode_t mode)
>> goto mkdir_out;
>> }
>>
>> - if ((pTcon->ses->capabilities & CAP_UNIX) &&
>> - (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> - le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
>> + if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
>> + le64_to_cpu(tcon->fsUnixInfo.Capability))) {
>> u32 oplock = 0;
>> FILE_UNIX_BASIC_INFO *pInfo =
>> kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
>> @@ -1259,7 +1257,7 @@ int cifs_mkdir(struct inode *inode, struct dentry
>> *direntry, umode_t mode)
>> }
>>
>> mode &= ~current_umask();
>> - rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
>> + rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT,
>> mode, NULL /* netfid */, pInfo, &oplock,
>> full_path, cifs_sb->local_nls,
>> cifs_sb->mnt_cifs_flags &
>> @@ -1303,14 +1301,14 @@ int cifs_mkdir(struct inode *inode, struct dentry
>> *direntry, umode_t mode)
>> }
>> mkdir_retry_old:
>> /* BB add setting the equivalent of mode via CreateX w/ACLs */
>> - rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
>> + rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
>> cifs_sb->mnt_cifs_flags &
>> CIFS_MOUNT_MAP_SPECIAL_CHR);
>> if (rc) {
>> cFYI(1, "cifs_mkdir returned 0x%x", rc);
>> d_drop(direntry);
>> } else {
>> mkdir_get_info:
>> - if (pTcon->unix_ext)
>> + if (tcon->unix_ext)
>> rc = cifs_get_inode_info_unix(&newinode, full_path,
>> inode->i_sb, xid);
>> else
>> @@ -1328,7 +1326,7 @@ mkdir_get_info:
>> if (inode->i_mode & S_ISGID)
>> mode |= S_ISGID;
>>
>> - if (pTcon->unix_ext) {
>> + if (tcon->unix_ext) {
>> struct cifs_unix_set_info_args args = {
>> .mode = mode,
>> .ctime = NO_CHANGE_64,
>> @@ -1346,7 +1344,7 @@ mkdir_get_info:
>> args.uid = NO_CHANGE_64;
>> args.gid = NO_CHANGE_64;
>> }
>> - CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
>> + CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
>> cifs_sb->local_nls,
>> cifs_sb->mnt_cifs_flags &
>> CIFS_MOUNT_MAP_SPECIAL_CHR);
>> @@ -1361,7 +1359,7 @@ mkdir_get_info:
>> cifsInode = CIFS_I(newinode);
>> dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
>> pInfo.Attributes = cpu_to_le32(dosattrs);
>> - tmprc = CIFSSMBSetPathInfo(xid, pTcon,
>> + tmprc = CIFSSMBSetPathInfo(xid, tcon,
>> full_path, &pInfo,
>> cifs_sb->local_nls,
>> cifs_sb->mnt_cifs_flags &
>> diff --git a/fs/cifs/link.c b/fs/cifs/link.c
>> index 77d781a..d08b76c 100644
>> --- a/fs/cifs/link.c
>> +++ b/fs/cifs/link.c
>> @@ -495,8 +495,8 @@ cifs_follow_link(struct dentry *direntry, struct
>> nameidata *nd)
>> * but there doesn't seem to be any harm in allowing the client to
>> * read them.
>> */
>> - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
>> - && !(tcon->ses->capabilities & CAP_UNIX)) {
>> + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
>> + !cap_unix(tcon->ses)) {
>> rc = -EACCES;
>> goto out;
>> }
>> @@ -518,7 +518,7 @@ cifs_follow_link(struct dentry *direntry, struct
>> nameidata *nd)
>> cifs_sb->mnt_cifs_flags &
>> CIFS_MOUNT_MAP_SPECIAL_CHR);
>>
>> - if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX))
>> + if ((rc != 0) && cap_unix(tcon->ses))
>> rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path,
>> &target_path,
>> cifs_sb->local_nls);
>>
>> diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
>> index da30d96..d87f826 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)
>> struct cifsFileInfo *cifsFile;
>> struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
>> struct tcon_link *tlink = NULL;
>> - struct cifs_tcon *pTcon;
>> + struct cifs_tcon *tcon;
>>
>> if (file->private_data == NULL) {
>> tlink = cifs_sb_tlink(cifs_sb);
>> @@ -242,10 +242,10 @@ static int initiate_cifs_search(const unsigned int
>> xid, struct file *file)
>> }
>> file->private_data = cifsFile;
>> cifsFile->tlink = cifs_get_tlink(tlink);
>> - pTcon = tlink_tcon(tlink);
>> + tcon = tlink_tcon(tlink);
>> } else {
>> cifsFile = file->private_data;
>> - pTcon = tlink_tcon(cifsFile->tlink);
>> + tcon = tlink_tcon(cifsFile->tlink);
>> }
>>
>> cifsFile->invalidHandle = true;
>> @@ -262,11 +262,11 @@ static int initiate_cifs_search(const unsigned int
>> xid, struct file *file)
>> ffirst_retry:
>> /* test for Unix extensions */
>> /* but now check for them on the share/mount not on the SMB session */
>> -/* if (pTcon->ses->capabilities & CAP_UNIX) { */
>> - if (pTcon->unix_ext)
>> + /* if (cap_unix(tcon->ses) { */
>> + if (tcon->unix_ext)
>> cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
>> - else if ((pTcon->ses->capabilities &
>> - (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
>> + else if ((tcon->ses->capabilities &
>> + tcon->ses->server->vals->cap_nt_find) == 0) {
>> cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
>> } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
>> cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
>> @@ -278,7 +278,7 @@ ffirst_retry:
>> if (backup_cred(cifs_sb))
>> search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
>>
>> - rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
>> + rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb->local_nls,
>> &cifsFile->netfid, search_flags, &cifsFile->srch_inf,
>> cifs_sb->mnt_cifs_flags &
>> CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
>> diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
>> index 5817409..c40356d 100644
>> --- a/fs/cifs/smb1ops.c
>> +++ b/fs/cifs/smb1ops.c
>> @@ -632,4 +632,7 @@ struct smb_version_values smb1_values = {
>> .max_header_size = MAX_CIFS_HDR_SIZE,
>> .read_rsp_size = sizeof(READ_RSP),
>> .lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
>> + .cap_unix = CAP_UNIX,
>> + .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
>> + .cap_large_files = CAP_LARGE_FILES,
>> };
>> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
>> index 1018c5c..410cf92 100644
>> --- a/fs/cifs/smb2ops.c
>> +++ b/fs/cifs/smb2ops.c
>> @@ -325,4 +325,7 @@ struct smb_version_values smb21_values = {
>> .header_size = sizeof(struct smb2_hdr),
>> .max_header_size = MAX_SMB2_HDR_SIZE,
>> .lock_cmd = SMB2_LOCK,
>> + .cap_unix = 0,
>> + .cap_nt_find = SMB2_NT_FIND,
>> + .cap_large_files = SMB2_LARGE_FILES,
>> };
>> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
>> index e4eb1d3..62b3f17 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)
>> /* BB Do we need to validate the SecurityMode? */
>> server->sec_mode = le16_to_cpu(rsp->SecurityMode);
>> server->capabilities = le32_to_cpu(rsp->Capabilities);
>> + /* Internal types */
>> + server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
>>
>> security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
>> &rsp->hdr);
>> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
>> index 59aae60..f37a1b4 100644
>> --- a/fs/cifs/smb2pdu.h
>> +++ b/fs/cifs/smb2pdu.h
>> @@ -167,6 +167,9 @@ struct smb2_negotiate_req {
>> #define SMB2_GLOBAL_CAP_DFS 0x00000001
>> #define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to
>> SMB2.1 */
>> #define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1
>> */
>> +/* Internal types */
>> +#define SMB2_NT_FIND 0x00100000
>> +#define SMB2_LARGE_FILES 0x00200000
>>
>> struct smb2_negotiate_rsp {
>> struct smb2_hdr hdr;
>
>
> --
> Jeff Layton <[email protected]>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html