From dc528770edb138e26a533f8a77de5c4db18ea7f3 Mon Sep 17 00:00:00 2001 From: Bharath SM Date: Tue, 12 Mar 2024 21:21:41 -0500 Subject: cifs: defer close file handles having RH lease Previously we only deferred closing file handles with RHW lease. To enhance performance benefits from deferred closes, we now include handles with RH leases as well. Signed-off-by: Bharath SM Signed-off-by: Steve French --- fs/smb/client/file.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index ec25d3c3e1ee..e7d5e8f972a0 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -1073,6 +1073,19 @@ void smb2_deferred_work_close(struct work_struct *work) _cifsFileInfo_put(cfile, true, false); } +static bool +smb2_can_defer_close(struct inode *inode, struct cifs_deferred_close *dclose) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifsInodeInfo *cinode = CIFS_I(inode); + + return (cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose && + (cinode->oplock == CIFS_CACHE_RHW_FLG || + cinode->oplock == CIFS_CACHE_RH_FLG) && + !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags)); + +} + int cifs_close(struct inode *inode, struct file *file) { struct cifsFileInfo *cfile; @@ -1086,10 +1099,8 @@ int cifs_close(struct inode *inode, struct file *file) cfile = file->private_data; file->private_data = NULL; dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); - if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG) - && cinode->lease_granted && - !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && - dclose && !(cfile->status_file_deleted)) { + if ((cfile->status_file_deleted == false) && + (smb2_can_defer_close(inode, dclose))) { if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); -- cgit v1.2.3 From 13c0a74747cb7fdadf58c5d3a7d52cfca2d51736 Mon Sep 17 00:00:00 2001 From: Shyam Prasad N Date: Wed, 13 Mar 2024 10:40:41 +0000 Subject: cifs: make sure server interfaces are requested only for SMB3+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some code paths for querying server interfaces make a false assumption that it will only get called for SMB3+. Since this function now can get called from a generic code paths, the correct thing to do is to have specific handler for this functionality per SMB dialect, and call this handler. This change adds such a handler and implements this handler only for SMB 3.0 and 3.1.1. Cc: stable@vger.kernel.org Cc: Jan Čermák Reported-by: Paulo Alcantara Signed-off-by: Shyam Prasad N Signed-off-by: Steve French --- fs/smb/client/cifsglob.h | 3 +++ fs/smb/client/connect.c | 6 +++++- fs/smb/client/smb2ops.c | 2 ++ fs/smb/client/smb2pdu.c | 5 +++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 8be62ed053a2..3da625d53235 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -355,6 +355,9 @@ struct smb_version_operations { /* informational QFS call */ void (*qfs_tcon)(const unsigned int, struct cifs_tcon *, struct cifs_sb_info *); + /* query for server interfaces */ + int (*query_server_interfaces)(const unsigned int, struct cifs_tcon *, + bool); /* check if a path is accessible or not */ int (*is_path_accessible)(const unsigned int, struct cifs_tcon *, struct cifs_sb_info *, const char *); diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 86ae578904a2..4cbb79418e50 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -123,12 +123,16 @@ static void smb2_query_server_interfaces(struct work_struct *work) struct cifs_tcon *tcon = container_of(work, struct cifs_tcon, query_interfaces.work); + struct TCP_Server_Info *server = tcon->ses->server; /* * query server network interfaces, in case they change */ + if (!server->ops->query_server_interfaces) + return; + xid = get_xid(); - rc = SMB3_request_interfaces(xid, tcon, false); + rc = server->ops->query_server_interfaces(xid, tcon, false); free_xid(xid); if (rc) { diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 6ee22d0dbc00..2ed456948f34 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -5290,6 +5290,7 @@ struct smb_version_operations smb30_operations = { .tree_connect = SMB2_tcon, .tree_disconnect = SMB2_tdis, .qfs_tcon = smb3_qfs_tcon, + .query_server_interfaces = SMB3_request_interfaces, .is_path_accessible = smb2_is_path_accessible, .can_echo = smb2_can_echo, .echo = SMB2_echo, @@ -5405,6 +5406,7 @@ struct smb_version_operations smb311_operations = { .tree_connect = SMB2_tcon, .tree_disconnect = SMB2_tdis, .qfs_tcon = smb3_qfs_tcon, + .query_server_interfaces = SMB3_request_interfaces, .is_path_accessible = smb2_is_path_accessible, .can_echo = smb2_can_echo, .echo = SMB2_echo, diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index e5e6b14f8cae..3ea688558e6c 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -409,14 +409,15 @@ skip_sess_setup: spin_unlock(&ses->ses_lock); if (!rc && - (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { + (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) && + server->ops->query_server_interfaces) { mutex_unlock(&ses->session_mutex); /* * query server network interfaces, in case they change */ xid = get_xid(); - rc = SMB3_request_interfaces(xid, tcon, false); + rc = server->ops->query_server_interfaces(xid, tcon, false); free_xid(xid); if (rc == -EOPNOTSUPP && ses->chan_count > 1) { -- cgit v1.2.3 From 16a57d7681110b25708c7042688412238e6f73a9 Mon Sep 17 00:00:00 2001 From: Shyam Prasad N Date: Wed, 13 Mar 2024 10:40:40 +0000 Subject: cifs: reduce warning log level for server not advertising interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several users have reported this log getting dumped too regularly to kernel log. The likely root cause has been identified, and it suggests that this situation is expected for some configurations (for example SMB2.1). Since the function returns appropriately even for such cases, it is fairly harmless to make this a debug log. When needed, the verbosity can be increased to capture this log. Cc: stable@vger.kernel.org Reported-by: Jan Čermák Signed-off-by: Shyam Prasad N Signed-off-by: Steve French --- fs/smb/client/sess.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c index 8f37373fd333..3216f786908f 100644 --- a/fs/smb/client/sess.c +++ b/fs/smb/client/sess.c @@ -230,7 +230,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses) spin_lock(&ses->iface_lock); if (!ses->iface_count) { spin_unlock(&ses->iface_lock); - cifs_dbg(VFS, "server %s does not advertise interfaces\n", + cifs_dbg(ONCE, "server %s does not advertise interfaces\n", ses->server->hostname); break; } @@ -396,7 +396,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) spin_lock(&ses->iface_lock); if (!ses->iface_count) { spin_unlock(&ses->iface_lock); - cifs_dbg(VFS, "server %s does not advertise interfaces\n", ses->server->hostname); + cifs_dbg(ONCE, "server %s does not advertise interfaces\n", ses->server->hostname); return; } -- cgit v1.2.3 From f1b8224b4e6ed59e7e6f5c548673c67410098d8d Mon Sep 17 00:00:00 2001 From: Eugene Korenevsky Date: Fri, 1 Mar 2024 17:53:44 +0300 Subject: cifs: open_cached_dir(): add FILE_READ_EA to desired access Since smb2_query_eas() reads EA and uses cached directory, open_cached_dir() should request FILE_READ_EA access. Otherwise listxattr() and getxattr() will fail with EACCES (0xc0000022 STATUS_ACCESS_DENIED SMB status). Link: https://bugzilla.kernel.org/show_bug.cgi?id=218543 Cc: stable@vger.kernel.org Signed-off-by: Eugene Korenevsky Signed-off-by: Steve French --- fs/smb/client/cached_dir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index 3de5047a7ff9..a0017724d523 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -239,7 +239,8 @@ replay_again: .tcon = tcon, .path = path, .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE), - .desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES, + .desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES | + FILE_READ_EA, .disposition = FILE_OPEN, .fid = pfid, .replay = !!(retries), -- cgit v1.2.3 From fc20c523211a38b87fc850a959cb2149e4fd64b0 Mon Sep 17 00:00:00 2001 From: Meetakshi Setiya Date: Thu, 14 Mar 2024 08:05:49 -0400 Subject: cifs: fixes for get_inode_info Fix potential memory leaks, add error checking, remove unnecessary initialisation of status_file_deleted and do not use cifs_iget() to get inode in reparse_info_to_fattr since fattrs may not be fully set. Fixes: ffceb7640cbf ("smb: client: do not defer close open handles to deleted files") Reported-by: Paulo Alcantara Signed-off-by: Meetakshi Setiya Signed-off-by: Steve French --- fs/smb/client/file.c | 1 - fs/smb/client/inode.c | 24 +++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index e7d5e8f972a0..16aadce492b2 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -486,7 +486,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, cfile->uid = current_fsuid(); cfile->dentry = dget(dentry); cfile->f_flags = file->f_flags; - cfile->status_file_deleted = false; cfile->invalidHandle = false; cfile->deferred_close_scheduled = false; cfile->tlink = cifs_get_tlink(tlink); diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 8177ec59afee..6092729bf7f6 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -820,8 +820,10 @@ cifs_get_file_info(struct file *filp) void *page = alloc_dentry_path(); const unsigned char *path; - if (!server->ops->query_file_info) + if (!server->ops->query_file_info) { + free_dentry_path(page); return -ENOSYS; + } xid = get_xid(); rc = server->ops->query_file_info(xid, tcon, cfile, &data); @@ -835,8 +837,8 @@ cifs_get_file_info(struct file *filp) } path = build_path_from_dentry(dentry, page); if (IS_ERR(path)) { - free_dentry_path(page); - return PTR_ERR(path); + rc = PTR_ERR(path); + goto cgfi_exit; } cifs_open_info_to_fattr(&fattr, &data, inode->i_sb); if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) @@ -1009,7 +1011,6 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, struct kvec rsp_iov, *iov = NULL; int rsp_buftype = CIFS_NO_BUFFER; u32 tag = data->reparse.tag; - struct inode *inode = NULL; int rc = 0; if (!tag && server->ops->query_reparse_point) { @@ -1049,12 +1050,8 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, if (tcon->posix_extensions) smb311_posix_info_to_fattr(fattr, data, sb); - else { + else cifs_open_info_to_fattr(fattr, data, sb); - inode = cifs_iget(sb, fattr); - if (inode && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING) - cifs_mark_open_handles_for_deleted_file(inode, full_path); - } out: fattr->cf_cifstag = data->reparse.tag; free_rsp_buf(rsp_buftype, rsp_iov.iov_base); @@ -1109,9 +1106,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data, full_path, fattr); } else { cifs_open_info_to_fattr(fattr, data, sb); - if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING) - cifs_mark_open_handles_for_deleted_file(*inode, full_path); } + if (!rc && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING) + cifs_mark_open_handles_for_deleted_file(*inode, full_path); break; case -EREMOTE: /* DFS link, no metadata available on this server */ @@ -1340,6 +1337,8 @@ int smb311_posix_get_inode_info(struct inode **inode, goto out; rc = update_inode_info(sb, &fattr, inode); + if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) + cifs_mark_open_handles_for_deleted_file(*inode, full_path); out: kfree(fattr.cf_symlink_target); return rc; @@ -1501,6 +1500,9 @@ iget_root: goto out; } + if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) + cifs_mark_open_handles_for_deleted_file(inode, path); + if (rc && tcon->pipe) { cifs_dbg(FYI, "ipc connection - fake read inode\n"); spin_lock(&inode->i_lock); -- cgit v1.2.3 From 2760161d149f8d60c3f767fc62a823a1ead9d367 Mon Sep 17 00:00:00 2001 From: Bharath SM Date: Thu, 14 Mar 2024 23:36:36 +0530 Subject: cifs: remove redundant variable assignment This removes an unnecessary variable assignment. The assigned value will be overwritten by cifs_fattr_to_inode before it is accessed, making the line redundant. Signed-off-by: Bharath SM Signed-off-by: Steve French --- fs/smb/client/inode.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 6092729bf7f6..d28ab0af6049 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -401,7 +401,6 @@ cifs_get_file_info_unix(struct file *filp) cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); } else if (rc == -EREMOTE) { cifs_create_junction_fattr(&fattr, inode->i_sb); - rc = 0; } else goto cifs_gfiunix_out; @@ -846,7 +845,6 @@ cifs_get_file_info(struct file *filp) break; case -EREMOTE: cifs_create_junction_fattr(&fattr, inode->i_sb); - rc = 0; break; case -EOPNOTSUPP: case -EINVAL: -- cgit v1.2.3 From 5b142b37c70b1fa6936fa2d0babb0b8c16767d3a Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 15 Mar 2024 17:46:56 +0000 Subject: cifs: Move some extern decls from .c files to .h Move the following: extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_mid_poolp; extern bool disable_legacy_dialects; from various .c files to cifsglob.h. Signed-off-by: David Howells cc: linux-cifs@vger.kernel.org Signed-off-by: Steve French --- fs/smb/client/cifsfs.c | 4 ---- fs/smb/client/cifsglob.h | 2 ++ fs/smb/client/connect.c | 3 --- fs/smb/client/misc.c | 3 --- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 81d9aafd2210..aa6f1ecb7c0e 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -151,10 +151,6 @@ MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be " "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker" " and less secure. Default: n/N/0"); -extern mempool_t *cifs_sm_req_poolp; -extern mempool_t *cifs_req_poolp; -extern mempool_t *cifs_mid_poolp; - struct workqueue_struct *cifsiod_wq; struct workqueue_struct *decrypt_wq; struct workqueue_struct *fileinfo_put_wq; diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 3da625d53235..7ed9d05f6890 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -2107,6 +2107,8 @@ extern struct workqueue_struct *cifsoplockd_wq; extern struct workqueue_struct *deferredclose_wq; extern __u32 cifs_lock_secret; +extern mempool_t *cifs_sm_req_poolp; +extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_mid_poolp; /* Operations for different SMB versions */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 4cbb79418e50..9b85b5341822 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -52,9 +52,6 @@ #include "fs_context.h" #include "cifs_swn.h" -extern mempool_t *cifs_req_poolp; -extern bool disable_legacy_dialects; - /* FIXME: should these be tunable? */ #define TLINK_ERROR_EXPIRE (1 * HZ) #define TLINK_IDLE_EXPIRE (600 * HZ) diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 9428a0db7718..c3771fc81328 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -27,9 +27,6 @@ #include "fs_context.h" #include "cached_dir.h" -extern mempool_t *cifs_sm_req_poolp; -extern mempool_t *cifs_req_poolp; - /* The xid serves as a useful identifier for each incoming vfs request, in a similar way to the mid which is useful to track each sent smb, and CurrentXid can also provide a running counter (although it -- cgit v1.2.3 From 68c5818a27afcb5cdddab041b82e9d47c996cb6a Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 19 Mar 2024 15:59:38 -0500 Subject: smb311: correct incorrect offset field in compression header The offset field in the compression header is 32 bits not 16. Reviewed-by: Bharath SM Reported-by: Enzo Matsumiya Signed-off-by: Steve French --- fs/smb/common/smb2pdu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index 20784f76a604..a23b56f93c36 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -227,7 +227,7 @@ struct smb2_compression_hdr { __le32 OriginalCompressedSegmentSize; __le16 CompressionAlgorithm; __le16 Flags; - __le16 Offset; /* this is the size of the uncompressed SMB2 header below */ + __le32 Offset; /* this is the size of the uncompressed SMB2 header below */ /* uncompressed SMB2 header (READ or WRITE) goes here */ /* compressed data goes here */ } __packed; -- cgit v1.2.3 From e56bc745fa1de77abc2ad8debc4b1b83e0426c49 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 19 Mar 2024 17:00:01 -0500 Subject: smb311: additional compression flag defined in updated protocol spec Added new compression flag that was recently documented, in addition fix some typos and clarify the sid_attr_data struct definition. Reviewed-by: Bharath SM Signed-off-by: Steve French --- fs/smb/common/smb2pdu.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index a23b56f93c36..1b594307c9d5 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -280,15 +280,16 @@ struct smb3_blob_data { #define SE_GROUP_RESOURCE 0x20000000 #define SE_GROUP_LOGON_ID 0xC0000000 -/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */ - struct sid_array_data { __le16 SidAttrCount; /* SidAttrList - array of sid_attr_data structs */ } __packed; -struct luid_attr_data { - +/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */ +struct sid_attr_data { + __le16 BlobSize; + __u8 BlobData[]; + /* __le32 Attr */ } __packed; /* @@ -502,6 +503,7 @@ struct smb2_encryption_neg_context { #define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003) /* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */ #define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) /* Pattern_V1 */ +#define SMB3_COMPRESS_LZ4 cpu_to_le16(0x0005) /* Compression Flags */ #define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000) -- cgit v1.2.3