diff options
author | Enzo Matsumiya <ematsumiya@suse.de> | 2024-11-14 15:46:54 -0300 |
---|---|---|
committer | Enzo Matsumiya <ematsumiya@suse.de> | 2024-11-14 15:54:45 -0300 |
commit | 7761b7e5370826850a1421d7ffc17b85f6c59a99 (patch) | |
tree | d692c8a93c10dd1e5ebe4fa738e69ca07bdf0949 | |
parent | 60eed99db98cb0138209a943d5b8c79af7f7481f (diff) | |
download | linux-hw24.tar.gz linux-hw24.tar.bz2 linux-hw24.zip |
smb: client: leave only string and id in smb_version_valueshw24
Remove all other values as they're the same for SMB 3.0+.
For SMB 2.1 handle the only 2 different values (.req_capabilities and
.create_lease_size) in-place.
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
-rw-r--r-- | fs/smb/client/cifsfs.c | 5 | ||||
-rw-r--r-- | fs/smb/client/cifsglob.h | 29 | ||||
-rw-r--r-- | fs/smb/client/connect.c | 17 | ||||
-rw-r--r-- | fs/smb/client/file.c | 99 | ||||
-rw-r--r-- | fs/smb/client/readdir.c | 3 | ||||
-rw-r--r-- | fs/smb/client/smb2ops.c | 141 | ||||
-rw-r--r-- | fs/smb/client/smb2pdu.c | 24 | ||||
-rw-r--r-- | fs/smb/client/smb2transport.c | 2 | ||||
-rw-r--r-- | fs/smb/client/transport.c | 43 |
9 files changed, 101 insertions, 262 deletions
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 96c21b1661c6..c585b5e80f01 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -198,10 +198,9 @@ cifs_read_super(struct super_block *sb) if (tcon->snapshot_time) sb->s_flags |= SB_RDONLY; - if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files) + sb->s_maxbytes = MAX_NON_LFS; + if (tcon->ses->capabilities & SMB2_LARGE_FILES) sb->s_maxbytes = MAX_LFS_FILESIZE; - else - sb->s_maxbytes = MAX_NON_LFS; /* * Almost every server, including all SMB2+, uses DCE TIME diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index ca1b3739717c..303c1a7759e6 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -303,28 +303,11 @@ struct smb_version_operations { struct smb_version_values { char *version_string; __u16 protocol_id; - __u32 req_capabilities; - __u32 large_lock_type; - __u32 exclusive_lock_type; - __u32 shared_lock_type; - __u32 unlock_lock_type; - size_t header_preamble_size; - size_t header_size; - size_t max_header_size; - size_t read_rsp_size; - __le16 lock_cmd; - unsigned int cap_unix; - unsigned int cap_nt_find; - unsigned int cap_large_files; - __u16 signing_enabled; - __u16 signing_required; - size_t create_lease_size; }; -#define HEADER_SIZE(server) (server->vals->header_size) -#define MAX_HEADER_SIZE(server) (server->vals->max_header_size) -#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size) -#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server)) +#define HEADER_SIZE(server) (sizeof(struct smb2_hdr)) +#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1) +#define READ_RSP_SIZE (sizeof(struct smb2_read_rsp)) /** * CIFS superblock mount flags (mnt_cifs_flags) to consider when @@ -826,12 +809,6 @@ struct cifs_ses { struct nls_table *local_nls; }; -static inline bool -cap_unix(struct cifs_ses *ses) -{ - return ses->server->vals->cap_unix & ses->capabilities; -} - /* * common struct for holding inode info when searching for or updating an * inode with new info diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 065dde89febf..4c269eaf6013 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -909,10 +909,13 @@ handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, int cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) { - bool srv_sign_required = server->sec_mode & server->vals->signing_required; - bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled; + bool srv_sign_required; + bool srv_sign_enabled; bool mnt_sign_enabled; + srv_sign_required = (server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED); + srv_sign_enabled = srv_sign_required || (server->sec_mode & SMB2_NEGOTIATE_SIGNING_ENABLED); + /* * Is signing required by mnt options? If not then check * global_secflags to see if it is there. @@ -1053,8 +1056,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) unsigned int pdu_length = server->pdu_size; /* make sure this will fit in a large buffer */ - if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - - HEADER_PREAMBLE_SIZE(server)) { + if (pdu_length > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) { cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); cifs_reconnect(server, true); return -ECONNABORTED; @@ -1215,9 +1217,7 @@ next_pdu: } /* read down to the MID */ - length = cifs_read_from_socket(server, - buf + HEADER_PREAMBLE_SIZE(server), - MID_HEADER_SIZE(server)); + length = cifs_read_from_socket(server, buf, MID_HEADER_SIZE(server)); if (length < 0) continue; server->total_read += length; @@ -3662,7 +3662,8 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, if (!is_binding) { ses->capabilities = server->capabilities; if (!linuxExtEnabled) - ses->capabilities &= (~server->vals->cap_unix); + /* XXX: remove this? (was ~cap_unix) */ + ses->capabilities &= (~0); if (ses->auth_key.response) { cifs_dbg(FYI, "Free previous auth_key.response = %p\n", diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index 23e75de833bc..0e50634d77e6 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -1352,25 +1352,21 @@ cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset, { struct cifsLockInfo *li; struct cifsFileInfo *cur_cfile = fdlocks->cfile; - struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; list_for_each_entry(li, &fdlocks->locks, llist) { - if (offset + length <= li->offset || - offset >= li->offset + li->length) + if (offset + length <= li->offset || offset >= li->offset + li->length) continue; if (rw_check != CIFS_LOCK_OP && current->tgid == li->pid && smb2_compare_fids(cfile, cur_cfile)) { /* shared lock prevents write op through the same fid */ - if (!(li->type & server->vals->shared_lock_type) || - rw_check != CIFS_WRITE_OP) + if (!(li->type & SMB2_LOCKFLAG_SHARED) || rw_check != CIFS_WRITE_OP) continue; } - if ((type & server->vals->shared_lock_type) && - ((smb2_compare_fids(cfile, cur_cfile) && + if ((type & SMB2_LOCKFLAG_SHARED) && ((smb2_compare_fids(cfile, cur_cfile) && current->tgid == li->pid) || type == li->type)) continue; - if (rw_check == CIFS_LOCK_OP && - (flags & FL_OFDLCK) && (li->flags & FL_OFDLCK) && + + if (rw_check == CIFS_LOCK_OP && (flags & FL_OFDLCK) && (li->flags & FL_OFDLCK) && smb2_compare_fids(cfile, cur_cfile)) continue; if (conf_lock) @@ -1414,7 +1410,6 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, int rc = 0; struct cifsLockInfo *conf_lock; struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); - struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; bool exist; down_read(&cinode->lock_sem); @@ -1426,7 +1421,7 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, flock->fl_start = conf_lock->offset; flock->fl_end = conf_lock->offset + conf_lock->length - 1; flock->c.flc_pid = conf_lock->pid; - if (conf_lock->type & server->vals->shared_lock_type) + if (conf_lock->type & SMB2_LOCKFLAG_SHARED) flock->c.flc_type = F_RDLCK; else flock->c.flc_type = F_WRLCK; @@ -1549,27 +1544,27 @@ cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock, cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->c.flc_flags); - *type = server->vals->large_lock_type; + *type = 0; if (lock_is_write(flock)) { cifs_dbg(FYI, "F_WRLCK\n"); - *type |= server->vals->exclusive_lock_type; + *type |= SMB2_LOCKFLAG_EXCLUSIVE; *lock = 1; } else if (lock_is_unlock(flock)) { cifs_dbg(FYI, "F_UNLCK\n"); - *type |= server->vals->unlock_lock_type; + *type |= SMB2_LOCKFLAG_UNLOCK; *unlock = 1; /* Check if unlock includes more than one lock range */ } else if (lock_is_read(flock)) { cifs_dbg(FYI, "F_RDLCK\n"); - *type |= server->vals->shared_lock_type; + *type |= SMB2_LOCKFLAG_SHARED; *lock = 1; } else if (flock->c.flc_type == F_EXLCK) { cifs_dbg(FYI, "F_EXLCK\n"); - *type |= server->vals->exclusive_lock_type; + *type |= SMB2_LOCKFLAG_EXCLUSIVE; *lock = 1; } else if (flock->c.flc_type == F_SHLCK) { cifs_dbg(FYI, "F_SHLCK\n"); - *type |= server->vals->shared_lock_type; + *type |= SMB2_LOCKFLAG_SHARED; *lock = 1; } else cifs_dbg(FYI, "Unknown type of lock\n"); @@ -1582,8 +1577,6 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, int rc = 0; __u64 length = cifs_flock_len(flock); struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct TCP_Server_Info *server = tcon->ses->server; rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock); if (!rc) @@ -1602,19 +1595,18 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, return 0; } - if (type & server->vals->shared_lock_type) { + if (type & SMB2_LOCKFLAG_SHARED) { flock->c.flc_type = F_WRLCK; return 0; } - type &= ~server->vals->exclusive_lock_type; + type &= ~SMB2_LOCKFLAG_EXCLUSIVE; - rc = smb2_mand_lock(xid, cfile, flock->fl_start, length, - type | server->vals->shared_lock_type, - 1, 0, false); + rc = smb2_mand_lock(xid, cfile, flock->fl_start, length, type | SMB2_LOCKFLAG_SHARED, + 1, 0, false); if (rc == 0) { rc = smb2_mand_lock(xid, cfile, flock->fl_start, length, - type | server->vals->shared_lock_type, 0, 1, false); + type | SMB2_LOCKFLAG_SHARED, 0, 1, false); flock->c.flc_type = F_RDLCK; if (rc != 0) cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n", @@ -1720,7 +1712,6 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl) int rc, xid; int lock = 0, unlock = 0; bool wait_flag = false; - bool posix_lck = false; struct cifs_sb_info *cifs_sb; struct cifs_tcon *tcon; struct cifsFileInfo *cfile; @@ -1741,11 +1732,6 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl) tcon->ses->server); cifs_sb = CIFS_FILE_SB(file); - 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; - if (!lock && !unlock) { /* * if no lock or unlock then nothing to do since we do not @@ -1756,8 +1742,8 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl) return rc; } - rc = cifs_setlk(file, fl, type, wait_flag, posix_lck, lock, unlock, - xid); + rc = cifs_setlk(file, fl, type, wait_flag, false /* XXX: remove this? (was posix_lck) */, + lock, unlock, xid); free_xid(xid); return rc; @@ -1769,7 +1755,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) int rc, xid; int lock = 0, unlock = 0; bool wait_flag = false; - bool posix_lck = false; struct cifs_sb_info *cifs_sb; struct cifs_tcon *tcon; struct cifsFileInfo *cfile; @@ -1790,17 +1775,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) tcon->ses->server); cifs_sb = CIFS_FILE_SB(file); set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags); - - 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; /* * BB add code here to normalize offset and length to account for * negative length which we can not accept over the wire. */ if (IS_GETLK(cmd)) { - rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid); + rc = cifs_getlk(file, flock, type, wait_flag, + false /* XXX: remove this? (was posix_lck) */, + xid); free_xid(xid); return rc; } @@ -1814,8 +1796,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) return -EOPNOTSUPP; } - rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock, - xid); + rc = cifs_setlk(file, flock, type, wait_flag, + false /* XXX: remove this? (was posix_lck) */, + lock, unlock, xid); free_xid(xid); return rc; } @@ -2168,7 +2151,6 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; struct inode *inode = file->f_mapping->host; struct cifsInodeInfo *cinode = CIFS_I(inode); - struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); ssize_t rc; @@ -2188,8 +2170,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) && (cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), - server->vals->exclusive_lock_type, 0, - NULL, CIFS_WRITE_OP))) { + SMB2_LOCKFLAG_EXCLUSIVE, 0, NULL, CIFS_WRITE_OP))) { rc = -EACCES; goto out; } @@ -2209,10 +2190,6 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) { struct inode *inode = file_inode(iocb->ki_filp); struct cifsInodeInfo *cinode = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsFileInfo *cfile = (struct cifsFileInfo *) - iocb->ki_filp->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); ssize_t written; written = cifs_get_writer(cinode); @@ -2220,12 +2197,6 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) return written; if (CIFS_CACHE_WRITE(cinode)) { - if (cap_unix(tcon->ses) && - (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && - ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { - written = netfs_file_write_iter(iocb, from); - goto out; - } written = cifs_writev(iocb, from); goto out; } @@ -2311,9 +2282,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) struct inode *inode = file_inode(iocb->ki_filp); struct cifsInodeInfo *cinode = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsFileInfo *cfile = (struct cifsFileInfo *) - iocb->ki_filp->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); + struct cifsFileInfo *cfile = (struct cifsFileInfo *)iocb->ki_filp->private_data; int rc = -EACCES; /* @@ -2343,11 +2312,10 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) goto out; rc = -EACCES; down_read(&cinode->lock_sem); - if (!cifs_find_lock_conflict( - cfile, iocb->ki_pos, iov_iter_count(to), - tcon->ses->server->vals->shared_lock_type, - 0, NULL, CIFS_READ_OP)) + if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to), + SMB2_LOCKFLAG_SHARED, 0, NULL, CIFS_READ_OP)) rc = netfs_unbuffered_read_iter_locked(iocb, to); + up_read(&cinode->lock_sem); netfs_end_io_direct(inode); } else { @@ -2356,11 +2324,10 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) goto out; rc = -EACCES; down_read(&cinode->lock_sem); - if (!cifs_find_lock_conflict( - cfile, iocb->ki_pos, iov_iter_count(to), - tcon->ses->server->vals->shared_lock_type, - 0, NULL, CIFS_READ_OP)) + if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to), + SMB2_LOCKFLAG_SHARED, 0, NULL, CIFS_READ_OP)) rc = filemap_read(iocb, to, 0); + up_read(&cinode->lock_sem); netfs_end_io_read(inode); } diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c index 5c0d002fe8cb..3f705e3aea1b 100644 --- a/fs/smb/client/readdir.c +++ b/fs/smb/client/readdir.c @@ -367,12 +367,11 @@ _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 (cap_unix(tcon->ses) { */ if (tcon->unix_ext) cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; else if (tcon->posix_extensions) cifsFile->srch_inf.info_level = SMB_FIND_FILE_POSIX_INFO; - else if ((tcon->ses->capabilities & server->vals->cap_nt_find) == 0) + else if ((tcon->ses->capabilities & SMB2_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; diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 7837b95597f2..4afe7f354631 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4433,14 +4433,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, /* set up first two iov to get credits */ rdata->iov[0].iov_base = buf; - rdata->iov[0].iov_len = 0; - rdata->iov[1].iov_base = buf; - rdata->iov[1].iov_len = - min_t(unsigned int, buf_len, server->vals->read_rsp_size); + rdata->iov[0].iov_len = min_t(unsigned int, buf_len, READ_RSP_SIZE); + cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", rdata->iov[0].iov_base, rdata->iov[0].iov_len); - cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n", - rdata->iov[1].iov_base, rdata->iov[1].iov_len); rdata->result = map_smb2_to_linux_error(buf, true); if (rdata->result != 0) { @@ -4460,7 +4456,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, #endif data_len = smb2_read_data_length(buf, use_rdma_mr); - if (data_offset < server->vals->read_rsp_size) { + if (data_offset < READ_RSP_SIZE) { /* * win2k8 sometimes sends an offset of 0 when the read * is beyond the EOF. Treat it as if the data starts just after @@ -4468,7 +4464,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, */ cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n", __func__, data_offset); - data_offset = server->vals->read_rsp_size; + data_offset = READ_RSP_SIZE; } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) { /* data_offset is beyond the end of smallbuf */ cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", @@ -4481,7 +4477,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, return 0; } - pad_len = data_offset - server->vals->read_rsp_size; + pad_len = data_offset - READ_RSP_SIZE; if (buf_len <= data_offset) { /* read response payload is in pages */ @@ -4566,8 +4562,7 @@ static void smb2_decrypt_offload(struct work_struct *work) struct iov_iter iter; iov_iter_xarray(&iter, ITER_DEST, &dw->buffer, 0, dw->len); - rc = decrypt_raw_data(dw->server, dw->buf, dw->server->vals->read_rsp_size, - &iter, true); + rc = decrypt_raw_data(dw->server, dw->buf, READ_RSP_SIZE, &iter, true); if (rc) { cifs_dbg(VFS, "error decrypting rc=%d\n", rc); goto free_pages; @@ -4579,10 +4574,8 @@ static void smb2_decrypt_offload(struct work_struct *work) cifs_dbg(FYI, "mid not found\n"); else { mid->decrypted = true; - rc = handle_read_data(dw->server, mid, dw->buf, - dw->server->vals->read_rsp_size, - &dw->buffer, dw->len, - true); + rc = handle_read_data(dw->server, mid, dw->buf, READ_RSP_SIZE, &dw->buffer, + dw->len, true); if (rc >= 0) { #ifdef CONFIG_CIFS_STATS2 mid->when_received = jiffies; @@ -4639,16 +4632,15 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, dw->server = server; *num_mids = 1; - len = min_t(unsigned int, buflen, server->vals->read_rsp_size + - sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; + len = min_t(unsigned int, buflen, + READ_RSP_SIZE + sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len); if (rc < 0) goto free_dw; server->total_read += rc; - len = le32_to_cpu(tr_hdr->OriginalMessageSize) - - server->vals->read_rsp_size; + len = le32_to_cpu(tr_hdr->OriginalMessageSize) - READ_RSP_SIZE; dw->len = len; npages = DIV_ROUND_UP(len, PAGE_SIZE); @@ -4701,8 +4693,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, return -1; } - rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size, - &iter, false); + rc = decrypt_raw_data(server, buf, READ_RSP_SIZE, &iter, false); if (rc) goto free_pages; @@ -4712,9 +4703,8 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, } else { cifs_dbg(FYI, "mid found\n"); (*mid)->decrypted = true; - rc = handle_read_data(server, *mid, buf, - server->vals->read_rsp_size, - &dw->buffer, dw->len, false); + rc = handle_read_data(server, *mid, buf, READ_RSP_SIZE, &dw->buffer, dw->len, + false); if (rc >= 0) smb2_is_network_name_deleted(buf, server); } @@ -4847,9 +4837,8 @@ int smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry ** } /* TODO: add support for compounds containing READ. */ - if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) { + if (pdu_length > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) return receive_encrypted_read(server, &mids[0], num_mids); - } return receive_encrypted_standard(server, mids, bufs, num_mids); } @@ -5021,125 +5010,29 @@ struct smb_version_operations smb311_operations = { struct smb_version_values smb21_values = { .version_string = SMB21_VERSION_STRING, .protocol_id = SMB21_PROT_ID, - .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */ - .large_lock_type = 0, - .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, - .shared_lock_type = SMB2_LOCKFLAG_SHARED, - .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, - .header_size = sizeof(struct smb2_hdr), - .header_preamble_size = 0, - .max_header_size = MAX_SMB2_HDR_SIZE, - .read_rsp_size = sizeof(struct smb2_read_rsp), - .lock_cmd = SMB2_LOCK, - .cap_unix = 0, - .cap_nt_find = SMB2_NT_FIND, - .cap_large_files = SMB2_LARGE_FILES, - .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, - .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, - .create_lease_size = sizeof(struct create_lease), }; struct smb_version_values smb3any_values = { .version_string = SMB3ANY_VERSION_STRING, - .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */ - .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING, - .large_lock_type = 0, - .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, - .shared_lock_type = SMB2_LOCKFLAG_SHARED, - .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, - .header_size = sizeof(struct smb2_hdr), - .header_preamble_size = 0, - .max_header_size = MAX_SMB2_HDR_SIZE, - .read_rsp_size = sizeof(struct smb2_read_rsp), - .lock_cmd = SMB2_LOCK, - .cap_unix = 0, - .cap_nt_find = SMB2_NT_FIND, - .cap_large_files = SMB2_LARGE_FILES, - .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, - .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, - .create_lease_size = sizeof(struct create_lease_v2), + .protocol_id = SMB30_PROT_ID, /* doesn't matter, send protocol array */ }; struct smb_version_values smbdefault_values = { .version_string = SMBDEFAULT_VERSION_STRING, - .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */ - .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING, - .large_lock_type = 0, - .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, - .shared_lock_type = SMB2_LOCKFLAG_SHARED, - .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, - .header_size = sizeof(struct smb2_hdr), - .header_preamble_size = 0, - .max_header_size = MAX_SMB2_HDR_SIZE, - .read_rsp_size = sizeof(struct smb2_read_rsp), - .lock_cmd = SMB2_LOCK, - .cap_unix = 0, - .cap_nt_find = SMB2_NT_FIND, - .cap_large_files = SMB2_LARGE_FILES, - .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, - .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, - .create_lease_size = sizeof(struct create_lease_v2), + .protocol_id = SMB30_PROT_ID, /* doesn't matter, send protocol array */ }; struct smb_version_values smb30_values = { .version_string = SMB30_VERSION_STRING, .protocol_id = SMB30_PROT_ID, - .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING, - .large_lock_type = 0, - .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, - .shared_lock_type = SMB2_LOCKFLAG_SHARED, - .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, - .header_size = sizeof(struct smb2_hdr), - .header_preamble_size = 0, - .max_header_size = MAX_SMB2_HDR_SIZE, - .read_rsp_size = sizeof(struct smb2_read_rsp), - .lock_cmd = SMB2_LOCK, - .cap_unix = 0, - .cap_nt_find = SMB2_NT_FIND, - .cap_large_files = SMB2_LARGE_FILES, - .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, - .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, - .create_lease_size = sizeof(struct create_lease_v2), }; struct smb_version_values smb302_values = { .version_string = SMB302_VERSION_STRING, .protocol_id = SMB302_PROT_ID, - .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING, - .large_lock_type = 0, - .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, - .shared_lock_type = SMB2_LOCKFLAG_SHARED, - .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, - .header_size = sizeof(struct smb2_hdr), - .header_preamble_size = 0, - .max_header_size = MAX_SMB2_HDR_SIZE, - .read_rsp_size = sizeof(struct smb2_read_rsp), - .lock_cmd = SMB2_LOCK, - .cap_unix = 0, - .cap_nt_find = SMB2_NT_FIND, - .cap_large_files = SMB2_LARGE_FILES, - .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, - .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, - .create_lease_size = sizeof(struct create_lease_v2), }; struct smb_version_values smb311_values = { .version_string = SMB311_VERSION_STRING, .protocol_id = SMB311_PROT_ID, - .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING, - .large_lock_type = 0, - .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, - .shared_lock_type = SMB2_LOCKFLAG_SHARED, - .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, - .header_size = sizeof(struct smb2_hdr), - .header_preamble_size = 0, - .max_header_size = MAX_SMB2_HDR_SIZE, - .read_rsp_size = sizeof(struct smb2_read_rsp), - .lock_cmd = SMB2_LOCK, - .cap_unix = 0, - .cap_nt_find = SMB2_NT_FIND, - .cap_large_files = SMB2_LARGE_FILES, - .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, - .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, - .create_lease_size = sizeof(struct create_lease_v2), }; diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 6af0e0dc45ce..e09a24d64f85 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -1100,7 +1100,14 @@ SMB2_negotiate(const unsigned int xid, else req->SecurityMode = 0; - req->Capabilities = cpu_to_le32(server->vals->req_capabilities); + req->Capabilities = 0; + if (server->vals->protocol_id >= SMB30_PROT_ID) + req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | + SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | + SMB2_GLOBAL_CAP_LARGE_MTU | + SMB2_GLOBAL_CAP_ENCRYPTION | + SMB2_GLOBAL_CAP_DIRECTORY_LEASING); + if (ses->chan_max > 1) req->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL); @@ -1296,8 +1303,12 @@ static int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tco if (!pneg_inbuf) return -ENOMEM; - pneg_inbuf->Capabilities = - cpu_to_le32(server->vals->req_capabilities); + pneg_inbuf->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | + SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | + SMB2_GLOBAL_CAP_LARGE_MTU | + SMB2_GLOBAL_CAP_ENCRYPTION | + SMB2_GLOBAL_CAP_DIRECTORY_LEASING); + if (tcon->ses->chan_max > 1) pneg_inbuf->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL); @@ -2460,7 +2471,12 @@ add_lease_context(struct TCP_Server_Info *server, iov[num].iov_base = create_lease_buf(lease_key, *oplock, server->vals->protocol_id); if (iov[num].iov_base == NULL) return -ENOMEM; - iov[num].iov_len = server->vals->create_lease_size; + iov[num].iov_len = sizeof(struct create_lease_v2); + + /* Remove 4 bytes from the padding in create_lease_v2 if SMB 2.1 */ + if (server->vals->protocol_id == SMB21_PROT_ID) + iov[num].iov_len -= 4; + req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE; *num_iovec = num + 1; return 0; diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 803474b42f18..e5c68d9b542d 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -651,7 +651,7 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) ssr = (struct smb2_sess_setup_req *)shdr; is_binding = shdr->Command == SMB2_SESSION_SETUP && - (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING); + (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING); is_signed = shdr->Flags & SMB2_FLAGS_SIGNED; if (!is_signed) diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 949a65b61963..77073b4c0767 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -45,7 +45,7 @@ void __release_mid(struct kref *refcount) struct mid_q_entry *midEntry = container_of(refcount, struct mid_q_entry, refcount); #ifdef CONFIG_CIFS_STATS2 - __le16 command = midEntry->server->vals->lock_cmd; + __le16 command = SMB2_LOCK; __u16 smb_cmd = le16_to_cpu(midEntry->command); unsigned long now; unsigned long roundtrip_time; @@ -1051,8 +1051,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, goto out; } - if (!midQ[i]->resp_buf || - midQ[i]->mid_state != MID_RESPONSE_READY) { + if (!midQ[i]->resp_buf || midQ[i]->mid_state != MID_RESPONSE_READY) { rc = -EIO; cifs_dbg(FYI, "Bad MID state?\n"); goto out; @@ -1060,16 +1059,14 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, buf = (char *)midQ[i]->resp_buf; resp_iov[i].iov_base = buf; - resp_iov[i].iov_len = midQ[i]->resp_buf_size + - HEADER_PREAMBLE_SIZE(server); + resp_iov[i].iov_len = midQ[i]->resp_buf_size; if (midQ[i]->large_buf) resp_buf_type[i] = CIFS_LARGE_BUFFER; else resp_buf_type[i] = CIFS_SMALL_BUFFER; - rc = smb2_check_receive(midQ[i], server, - flags & CIFS_LOG_ERROR); + rc = smb2_check_receive(midQ[i], server, flags & CIFS_LOG_ERROR); /* mark it so buf will not be freed by delete_mid */ if ((flags & CIFS_NO_RSP_BUF) == 0) @@ -1127,15 +1124,13 @@ int cifs_discard_remaining_data(struct TCP_Server_Info *server) { unsigned int rfclen = server->pdu_size; - size_t remaining = rfclen + HEADER_PREAMBLE_SIZE(server) - - server->total_read; + size_t remaining = rfclen - server->total_read; while (remaining > 0) { ssize_t length; - length = cifs_discard_from_socket(server, - min_t(size_t, remaining, - CIFSMaxBufSize + MAX_HEADER_SIZE(server))); + length = cifs_discard_from_socket(server, min_t(size_t, remaining, + CIFSMaxBufSize + MAX_SMB2_HDR_SIZE)); if (length < 0) return length; server->total_read += length; @@ -1173,7 +1168,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) unsigned int data_offset, data_len; struct cifs_io_subrequest *rdata = mid->callback_data; char *buf = server->smallbuf; - unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server); + unsigned int buflen = server->pdu_size; bool use_rdma_mr = false; cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%zu\n", @@ -1184,11 +1179,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) * can if there's not enough data. At this point, we've read down to * the Mid. */ - len = min_t(unsigned int, buflen, server->vals->read_rsp_size) - - HEADER_SIZE(server) + 1; + len = min_t(unsigned int, buflen, READ_RSP_SIZE) - HEADER_SIZE(server) + 1; - length = cifs_read_from_socket(server, - buf + HEADER_SIZE(server) - 1, len); + length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len); if (length < 0) return length; server->total_read += length; @@ -1205,14 +1198,10 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) /* set up first two iov for signature check and to get credits */ rdata->iov[0].iov_base = buf; - rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server); - rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server); - rdata->iov[1].iov_len = - server->total_read - HEADER_PREAMBLE_SIZE(server); + rdata->iov[0].iov_len = server->total_read; + cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", rdata->iov[0].iov_base, rdata->iov[0].iov_len); - cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n", - rdata->iov[1].iov_base, rdata->iov[1].iov_len); /* Was the SMB read successful? */ rdata->result = map_smb2_to_linux_error(buf, false); @@ -1224,16 +1213,14 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) } /* Is there enough to get to the rest of the READ_RSP header? */ - if (server->total_read < server->vals->read_rsp_size) { + if (server->total_read < READ_RSP_SIZE) { cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n", - __func__, server->total_read, - server->vals->read_rsp_size); + __func__, server->total_read, READ_RSP_SIZE); rdata->result = -EIO; return cifs_readv_discard(server, mid); } - data_offset = smb2_read_data_offset(buf) + - HEADER_PREAMBLE_SIZE(server); + data_offset = smb2_read_data_offset(buf); if (data_offset < server->total_read) { /* * win2k8 sometimes sends an offset of 0 when the read |