7389 smbd: hung threads when session is terminated or disconnected
[unleashed.git] / usr / src / uts / common / fs / smbsrv / smb_net.c
blob9d069f9f9e4129807520a56b692a80cd299e1949
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/time.h>
33 #include <sys/varargs.h>
34 #include <sys/modctl.h>
35 #include <sys/pathname.h>
36 #include <sys/vnode.h>
37 #include <sys/socket.h>
38 #include <sys/ksocket.h>
39 #undef mem_free /* XXX Remove this after we convert everything to kmem_alloc */
41 #include <smbsrv/smb_vops.h>
42 #include <smbsrv/smb.h>
43 #include <smbsrv/smb_kproto.h>
44 #include <smbsrv/smb_kstat.h>
47 * SMB Network Socket API
49 * smb_socreate: Creates an socket based on domain/type.
50 * smb_soshutdown: Disconnect a socket created with smb_socreate
51 * smb_sodestroy: Release resources associated with a socket
52 * smb_sosend: Send the contents of a buffer on a socket
53 * smb_sorecv: Receive data into a buffer from a socket
54 * smb_iov_sosend: Send the contents of an iovec on a socket
55 * smb_iov_sorecv: Receive data into an iovec from a socket
58 ksocket_t
59 smb_socreate(int domain, int type, int protocol)
61 ksocket_t sock;
62 int err = 0;
64 err = ksocket_socket(&sock, domain, type, protocol, KSOCKET_SLEEP,
65 CRED());
67 if (err != 0)
68 return (NULL);
69 else
70 return (sock);
74 * smb_soshutdown will disconnect the socket and prevent subsequent PDU
75 * reception and transmission. The sonode still exists but its state
76 * gets modified to indicate it is no longer connected. Calls to
77 * smb_sorecv/smb_iov_sorecv will return so smb_soshutdown can be used
78 * regain control of a thread stuck in smb_sorecv.
80 void
81 smb_soshutdown(ksocket_t so)
83 (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
87 * smb_sodestroy releases all resources associated with a socket previously
88 * created with smb_socreate. The socket must be shutdown using smb_soshutdown
89 * before the socket is destroyed with smb_sodestroy, otherwise undefined
90 * behavior will result.
92 void
93 smb_sodestroy(ksocket_t so)
95 (void) ksocket_close(so, CRED());
98 int
99 smb_sorecv(ksocket_t so, void *msg, size_t len)
101 size_t recvd;
102 int err;
104 ASSERT(so != NULL);
105 ASSERT(len != 0);
107 if ((err = ksocket_recv(so, msg, len, MSG_WAITALL, &recvd,
108 CRED())) != 0) {
109 return (err);
112 /* Successful receive */
113 return ((recvd == len) ? 0 : -1);
117 * smb_net_txl_constructor
119 * Transmit list constructor
121 void
122 smb_net_txl_constructor(smb_txlst_t *txl)
124 ASSERT(txl->tl_magic != SMB_TXLST_MAGIC);
126 mutex_init(&txl->tl_mutex, NULL, MUTEX_DEFAULT, NULL);
127 cv_init(&txl->tl_wait_cv, NULL, CV_DEFAULT, NULL);
128 txl->tl_active = B_FALSE;
129 txl->tl_magic = SMB_TXLST_MAGIC;
133 * smb_net_txl_destructor
135 * Transmit list destructor
137 void
138 smb_net_txl_destructor(smb_txlst_t *txl)
140 ASSERT(txl->tl_magic == SMB_TXLST_MAGIC);
142 txl->tl_magic = 0;
143 cv_destroy(&txl->tl_wait_cv);
144 mutex_destroy(&txl->tl_mutex);
148 * smb_net_send_uio
150 * This routine puts the transmit buffer passed in on the wire.
151 * If another thread is already sending, block on the CV.
154 smb_net_send_uio(smb_session_t *s, struct uio *uio)
156 struct msghdr msg;
157 size_t sent;
158 smb_txlst_t *txl = &s->s_txlst;
159 int rc = 0;
161 DTRACE_PROBE1(send__wait__start, struct smb_session_t *, s);
164 * Wait for our turn to send.
166 mutex_enter(&txl->tl_mutex);
167 while (txl->tl_active)
168 cv_wait(&txl->tl_wait_cv, &txl->tl_mutex);
169 txl->tl_active = B_TRUE;
170 mutex_exit(&txl->tl_mutex);
172 DTRACE_PROBE1(send__wait__done, struct smb_session_t *, s);
175 * OK, try to send.
177 * This should block until we've sent it all,
178 * or given up due to errors (socket closed).
180 bzero(&msg, sizeof (msg));
181 msg.msg_iov = uio->uio_iov;
182 msg.msg_iovlen = uio->uio_iovcnt;
183 while (uio->uio_resid > 0) {
184 rc = ksocket_sendmsg(s->sock, &msg, 0, &sent, CRED());
185 if (rc != 0)
186 break;
187 uio->uio_resid -= sent;
190 mutex_enter(&txl->tl_mutex);
191 txl->tl_active = B_FALSE;
192 cv_signal(&txl->tl_wait_cv);
193 mutex_exit(&txl->tl_mutex);
195 return (rc);