summaryrefslogtreecommitdiff
path: root/fs/smb/client/smb2pdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/smb/client/smb2pdu.c')
-rw-r--r--fs/smb/client/smb2pdu.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 60793143e24c..a5efce03cb58 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -743,7 +743,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
pneg_ctxt += sizeof(struct smb2_posix_neg_context);
neg_context_count++;
- if (server->compress_algorithm) {
+ if (server->compression.requested) {
build_compression_ctxt((struct smb2_compression_capabilities_context *)
pneg_ctxt);
ctxt_len = ALIGN(sizeof(struct smb2_compression_capabilities_context), 8);
@@ -791,6 +791,9 @@ static void decode_compress_ctx(struct TCP_Server_Info *server,
struct smb2_compression_capabilities_context *ctxt)
{
unsigned int len = le16_to_cpu(ctxt->DataLength);
+ __le16 alg;
+
+ server->compression.enabled = false;
/*
* Caller checked that DataLength remains within SMB boundary. We still
@@ -801,15 +804,22 @@ static void decode_compress_ctx(struct TCP_Server_Info *server,
pr_warn_once("server sent bad compression cntxt\n");
return;
}
+
if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) {
- pr_warn_once("Invalid SMB3 compress algorithm count\n");
+ pr_warn_once("invalid SMB3 compress algorithm count\n");
return;
}
- if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) {
- pr_warn_once("unknown compression algorithm\n");
+
+ alg = ctxt->CompressionAlgorithms[0];
+
+ /* 'NONE' (0) compressor type is never negotiated */
+ if (alg == 0 || le16_to_cpu(alg) > 3) {
+ pr_warn_once("invalid compression algorithm '%u'\n", alg);
return;
}
- server->compress_algorithm = ctxt->CompressionAlgorithms[0];
+
+ server->compression.alg = alg;
+ server->compression.enabled = true;
}
static int decode_encrypt_ctx(struct TCP_Server_Info *server,
@@ -2732,6 +2742,17 @@ add_query_id_context(struct kvec *iov, unsigned int *num_iovec)
return 0;
}
+static void add_ea_context(struct cifs_open_parms *oparms,
+ struct kvec *rq_iov, unsigned int *num_iovs)
+{
+ struct kvec *iov = oparms->ea_cctx;
+
+ if (iov && iov->iov_base && iov->iov_len) {
+ rq_iov[(*num_iovs)++] = *iov;
+ memset(iov, 0, sizeof(*iov));
+ }
+}
+
static int
alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
const char *treename, const __le16 *path)
@@ -3098,6 +3119,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
}
add_query_id_context(iov, &n_iov);
+ add_ea_context(oparms, iov, &n_iov);
if (n_iov > 2) {
/*
@@ -4116,6 +4138,8 @@ void smb2_reconnect_server(struct work_struct *work)
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
if (tcon->need_reconnect || tcon->need_reopen_files) {
tcon->tc_count++;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_reconnect_server);
list_add_tail(&tcon->rlist, &tmp_list);
tcon_selected = true;
}
@@ -4154,14 +4178,14 @@ void smb2_reconnect_server(struct work_struct *work)
if (tcon->ipc)
cifs_put_smb_ses(tcon->ses);
else
- cifs_put_tcon(tcon);
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server);
}
if (!ses_exist)
goto done;
/* allocate a dummy tcon struct used for reconnect */
- tcon = tcon_info_alloc(false);
+ tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_reconnect_server);
if (!tcon) {
resched = true;
list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
@@ -4184,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work)
list_del_init(&ses->rlist);
cifs_put_smb_ses(ses);
}
- tconInfoFree(tcon);
+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_reconnect_server);
done:
cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");