1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * Dispatch function for SMB2_CANCEL
18 */
19
20 #include <smbsrv/smb2_kproto.h>
21
22 static void smb2sr_cancel_async(smb_request_t *);
23 static void smb2sr_cancel_sync(smb_request_t *);
24
25 /*
26 * This handles an SMB2_CANCEL request when seen in the reader.
27 * (See smb2sr_newrq) Handle this immediately, rather than
28 * going through the normal taskq dispatch mechanism.
29 * Note that Cancel does NOT get a response.
30 */
31 int
smb2sr_newrq_cancel(smb_request_t * sr)32 smb2sr_newrq_cancel(smb_request_t *sr)
33 {
34 int rc;
35
36 /*
37 * Decode the header
38 */
39 if ((rc = smb2_decode_header(sr)) != 0)
40 return (rc);
41
42 if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND)
43 smb2sr_cancel_async(sr);
44 else
45 smb2sr_cancel_sync(sr);
46
47 return (0);
48 }
49
50 static void
smb2sr_cancel_sync(smb_request_t * sr)51 smb2sr_cancel_sync(smb_request_t *sr)
52 {
53 struct smb_request *req;
54 struct smb_session *session = sr->session;
55 int cnt = 0;
56
57 smb_slist_enter(&session->s_req_list);
58 req = smb_slist_head(&session->s_req_list);
59 while (req) {
60 ASSERT(req->sr_magic == SMB_REQ_MAGIC);
61 if ((req != sr) &&
62 (req->smb2_messageid == sr->smb2_messageid)) {
63 smb_request_cancel(req);
64 cnt++;
65 }
66 req = smb_slist_next(&session->s_req_list, req);
67 }
68 if (cnt != 1) {
69 DTRACE_PROBE2(smb2__cancel__error,
70 uint64_t, sr->smb2_messageid, int, cnt);
71 }
72 smb_slist_exit(&session->s_req_list);
73 }
74
75 static void
smb2sr_cancel_async(smb_request_t * sr)76 smb2sr_cancel_async(smb_request_t *sr)
77 {
78 struct smb_request *req;
79 struct smb_session *session = sr->session;
80 int cnt = 0;
81
82 smb_slist_enter(&session->s_req_list);
83 req = smb_slist_head(&session->s_req_list);
84 while (req) {
85 ASSERT(req->sr_magic == SMB_REQ_MAGIC);
86 if ((req != sr) &&
87 (req->smb2_async_id == sr->smb2_async_id)) {
88 smb_request_cancel(req);
89 cnt++;
90 }
91 req = smb_slist_next(&session->s_req_list, req);
92 }
93 if (cnt != 1) {
94 DTRACE_PROBE2(smb2__cancel__error,
95 uint64_t, sr->smb2_async_id, int, cnt);
96 }
97 smb_slist_exit(&session->s_req_list);
98 }
99