xref: /linux/fs/smb/server/server.c (revision 50a400cff59f534254ace2828f2eb9d844517fbb)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
4  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
5  */
6 
7 #include "glob.h"
8 #include "oplock.h"
9 #include "misc.h"
10 #include <linux/sched/signal.h>
11 #include <linux/workqueue.h>
12 #include <linux/sysfs.h>
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 
16 #include "server.h"
17 #include "smb_common.h"
18 #include "smb2pdu.h"
19 #include "../common/smb2status.h"
20 #include "connection.h"
21 #include "transport_ipc.h"
22 #include "mgmt/user_session.h"
23 #include "crypto_ctx.h"
24 #include "auth.h"
25 #include "stats.h"
26 #include "compress.h"
27 #include "mgmt/share_config.h"
28 #include "mgmt/tree_connect.h"
29 
30 int ksmbd_debug_types;
31 
32 struct ksmbd_server_config server_conf;
33 
34 enum SERVER_CTRL_TYPE {
35 	SERVER_CTRL_TYPE_INIT,
36 	SERVER_CTRL_TYPE_RESET,
37 };
38 
39 struct server_ctrl_struct {
40 	int			type;
41 	struct work_struct	ctrl_work;
42 };
43 
44 static DEFINE_MUTEX(ctrl_lock);
45 
46 static int ___server_conf_set(int idx, char *val)
47 {
48 	if (idx >= ARRAY_SIZE(server_conf.conf))
49 		return -EINVAL;
50 
51 	if (!val || val[0] == 0x00)
52 		return -EINVAL;
53 
54 	kfree(server_conf.conf[idx]);
55 	server_conf.conf[idx] = kstrdup(val, KSMBD_DEFAULT_GFP);
56 	if (!server_conf.conf[idx])
57 		return -ENOMEM;
58 	return 0;
59 }
60 
61 int ksmbd_set_netbios_name(char *v)
62 {
63 	return ___server_conf_set(SERVER_CONF_NETBIOS_NAME, v);
64 }
65 
66 int ksmbd_set_server_string(char *v)
67 {
68 	return ___server_conf_set(SERVER_CONF_SERVER_STRING, v);
69 }
70 
71 int ksmbd_set_work_group(char *v)
72 {
73 	return ___server_conf_set(SERVER_CONF_WORK_GROUP, v);
74 }
75 
76 char *ksmbd_netbios_name(void)
77 {
78 	return server_conf.conf[SERVER_CONF_NETBIOS_NAME];
79 }
80 
81 char *ksmbd_server_string(void)
82 {
83 	return server_conf.conf[SERVER_CONF_SERVER_STRING];
84 }
85 
86 char *ksmbd_work_group(void)
87 {
88 	return server_conf.conf[SERVER_CONF_WORK_GROUP];
89 }
90 
91 /**
92  * check_conn_state() - check state of server thread connection
93  * @work:     smb work containing server thread information
94  *
95  * Return:	0 on valid connection, otherwise 1 to reconnect
96  */
97 static inline int check_conn_state(struct ksmbd_work *work)
98 {
99 	struct smb_hdr *rsp_hdr;
100 
101 	if (ksmbd_conn_exiting(work->conn) ||
102 	    ksmbd_conn_need_reconnect(work->conn)) {
103 		rsp_hdr = smb_get_msg(work->response_buf);
104 		rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
105 		return 1;
106 	}
107 	return 0;
108 }
109 
110 #define SERVER_HANDLER_CONTINUE		0
111 #define SERVER_HANDLER_ABORT		1
112 
113 static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
114 			     u16 *cmd)
115 {
116 	struct smb_version_cmds *cmds;
117 	u16 command;
118 	bool signed_req;
119 	int ret;
120 
121 	if (check_conn_state(work))
122 		return SERVER_HANDLER_CONTINUE;
123 
124 	if (ksmbd_verify_smb_message(work)) {
125 		conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
126 		return SERVER_HANDLER_ABORT;
127 	}
128 
129 	command = conn->ops->get_cmd_val(work);
130 	*cmd = command;
131 
132 andx_again:
133 	if (command >= conn->max_cmds) {
134 		conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
135 		return SERVER_HANDLER_ABORT;
136 	}
137 
138 	cmds = &conn->cmds[command];
139 	if (!cmds->proc) {
140 		ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
141 		conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
142 		return SERVER_HANDLER_ABORT;
143 	}
144 
145 	signed_req = conn->ops->is_sign_req && conn->ops->is_sign_req(work, command);
146 	if (work->sess && work->sess->sign && !work->encrypted &&
147 	    !signed_req) {
148 		conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
149 		return SERVER_HANDLER_ABORT;
150 	}
151 
152 	if (work->sess && signed_req) {
153 		ret = conn->ops->check_sign_req(work);
154 		if (!ret) {
155 			conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
156 			return SERVER_HANDLER_ABORT;
157 		}
158 	}
159 
160 	ret = cmds->proc(work);
161 	if (conn->ops->inc_reqs) {
162 		struct smb2_hdr *rsp = ksmbd_resp_buf_curr(work);
163 
164 		conn->ops->inc_reqs(command, rsp->Status);
165 	}
166 
167 	if (ret < 0)
168 		ksmbd_debug(CONN, "Failed to process %u [%d]\n", command, ret);
169 	/* AndX commands - chained request can return positive values */
170 	else if (ret > 0) {
171 		command = ret;
172 		*cmd = command;
173 		goto andx_again;
174 	}
175 
176 	if (work->send_no_response)
177 		return SERVER_HANDLER_ABORT;
178 	return SERVER_HANDLER_CONTINUE;
179 }
180 
181 static void __handle_ksmbd_work(struct ksmbd_work *work,
182 				struct ksmbd_conn *conn)
183 {
184 	u16 command = 0;
185 	int rc;
186 	bool is_chained = false;
187 
188 	if (conn->ops->is_transform_hdr &&
189 	    conn->ops->is_transform_hdr(work->request_buf)) {
190 		rc = conn->ops->decrypt_req(work);
191 		if (rc < 0)
192 			return;
193 		work->encrypted = true;
194 	}
195 
196 	if (conn->ops->allocate_rsp_buf(work))
197 		return;
198 
199 	rc = conn->ops->init_rsp_hdr(work);
200 	if (rc) {
201 		/* either uid or tid is not correct */
202 		conn->ops->set_rsp_status(work, STATUS_INVALID_HANDLE);
203 		goto send;
204 	}
205 
206 	do {
207 		if (conn->ops->check_user_session) {
208 			rc = conn->ops->check_user_session(work);
209 			if (rc < 0) {
210 				if (rc == -EINVAL)
211 					conn->ops->set_rsp_status(work,
212 						STATUS_INVALID_PARAMETER);
213 				else if (rc == -EKEYEXPIRED)
214 					conn->ops->set_rsp_status(work,
215 						STATUS_NETWORK_SESSION_EXPIRED);
216 				else
217 					conn->ops->set_rsp_status(work,
218 						STATUS_USER_SESSION_DELETED);
219 				if (conn->ops->is_sign_req(work, conn->ops->get_cmd_val(work))) {
220 					struct smb2_hdr *rsp_hdr;
221 
222 					rsp_hdr = ksmbd_resp_buf_curr(work);
223 					if (rc == -EKEYEXPIRED && work->sess &&
224 					    conn->ops->set_sign_rsp)
225 						conn->ops->set_sign_rsp(work);
226 					else
227 						rsp_hdr->Flags |= SMB2_FLAGS_SIGNED;
228 				}
229 				goto send;
230 			} else if (rc > 0) {
231 				rc = conn->ops->get_ksmbd_tcon(work);
232 				if (rc < 0) {
233 					if (rc == -EINVAL)
234 						conn->ops->set_rsp_status(work,
235 							STATUS_INVALID_PARAMETER);
236 					else
237 						conn->ops->set_rsp_status(work,
238 							STATUS_NETWORK_NAME_DELETED);
239 					goto send;
240 				}
241 
242 				if (work->tcon &&
243 				    test_share_config_flag(work->tcon->share_conf,
244 							   KSMBD_SHARE_FLAG_ENCRYPT_DATA) &&
245 				    !work->encrypted) {
246 					conn->ops->set_rsp_status(work,
247 								  STATUS_ACCESS_DENIED);
248 					goto send;
249 				}
250 			}
251 		}
252 
253 		rc = __process_request(work, conn, &command);
254 		if (rc == SERVER_HANDLER_ABORT) {
255 			smb2_complete_request_open(work);
256 			break;
257 		}
258 
259 		/*
260 		 * Call smb2_set_rsp_credits() function to set number of credits
261 		 * granted in hdr of smb2 response.
262 		 */
263 		if (conn->ops->set_rsp_credits) {
264 			spin_lock(&conn->credits_lock);
265 			rc = conn->ops->set_rsp_credits(work);
266 			spin_unlock(&conn->credits_lock);
267 			if (rc < 0) {
268 				conn->ops->set_rsp_status(work,
269 					STATUS_INVALID_PARAMETER);
270 				smb2_complete_request_open(work);
271 				goto send;
272 			}
273 		}
274 
275 		smb2_complete_request_open(work);
276 
277 		is_chained = is_chained_smb2_message(work);
278 
279 		if (work->sess &&
280 		    (work->sess->sign || smb3_11_final_sess_setup_resp(work) ||
281 		     conn->ops->is_sign_req(work, command))) {
282 			if (command == SMB2_SESSION_SETUP_HE &&
283 			    work->sess->dialect >= SMB30_PROT_ID &&
284 			    conn->dialect < SMB30_PROT_ID)
285 				smb3_set_sign_rsp(work);
286 			else
287 				conn->ops->set_sign_rsp(work);
288 		}
289 	} while (is_chained == true);
290 
291 send:
292 	smb2_complete_request_open(work);
293 	/*
294 	 * Release any credit charge still outstanding for this request.  On
295 	 * the normal path smb2_set_rsp_credits() already returned it, but the
296 	 * abort, error and send-no-response paths skip that call, so the
297 	 * charge would otherwise leak and eventually exhaust the connection's
298 	 * outstanding credit window.
299 	 */
300 	if (work->credit_charge) {
301 		spin_lock(&conn->credits_lock);
302 		conn->outstanding_credits -= work->credit_charge;
303 		work->credit_charge = 0;
304 		spin_unlock(&conn->credits_lock);
305 	}
306 
307 	if (work->tcon)
308 		ksmbd_tree_connect_put(work->tcon);
309 	smb3_preauth_hash_rsp(work);
310 	/*
311 	 * Preauthentication hashes cover the original SMB2 response. Apply the
312 	 * transport compression wrapper only after updating the hash.
313 	 */
314 	if (work->compress_response) {
315 		rc = ksmbd_compress_response(work);
316 		if (rc < 0)
317 			ksmbd_debug(CONN, "Failed to compress response: %d\n", rc);
318 	}
319 	if (work->sess && work->sess->enc && work->encrypted &&
320 	    conn->ops->encrypt_resp) {
321 		rc = conn->ops->encrypt_resp(work);
322 		if (rc < 0)
323 			conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
324 	}
325 	if (work->sess)
326 		ksmbd_user_session_put(work->sess);
327 
328 	ksmbd_conn_write(work);
329 }
330 
331 /**
332  * handle_ksmbd_work() - process pending smb work requests
333  * @wk:	smb work containing request command buffer
334  *
335  * called by kworker threads to processing remaining smb work requests
336  */
337 static void handle_ksmbd_work(struct work_struct *wk)
338 {
339 	struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
340 	struct ksmbd_conn *conn = work->conn;
341 
342 	atomic64_inc(&conn->stats.request_served);
343 
344 	__handle_ksmbd_work(work, conn);
345 
346 	ksmbd_conn_try_dequeue_request(work);
347 	ksmbd_free_work_struct(work);
348 	ksmbd_conn_r_count_dec(conn);
349 }
350 
351 /**
352  * queue_ksmbd_work() - queue a smb request to worker thread queue
353  *		for processing smb command and sending response
354  * @conn:	connection instance
355  *
356  * read remaining data from socket create and submit work.
357  */
358 static int queue_ksmbd_work(struct ksmbd_conn *conn)
359 {
360 	struct ksmbd_work *work;
361 	int err;
362 
363 	err = ksmbd_init_smb_server(conn);
364 	if (err)
365 		return 0;
366 
367 	work = ksmbd_alloc_work_struct();
368 	if (!work) {
369 		pr_err("allocation for work failed\n");
370 		return -ENOMEM;
371 	}
372 
373 	work->conn = conn;
374 	work->request_buf = conn->request_buf;
375 	conn->request_buf = NULL;
376 
377 	ksmbd_conn_enqueue_request(work);
378 	ksmbd_conn_r_count_inc(conn);
379 	/* update activity on connection */
380 	conn->last_active = jiffies;
381 	INIT_WORK(&work->work, handle_ksmbd_work);
382 	ksmbd_queue_work(work);
383 	return 0;
384 }
385 
386 static int ksmbd_server_process_request(struct ksmbd_conn *conn)
387 {
388 	return queue_ksmbd_work(conn);
389 }
390 
391 static int ksmbd_server_terminate_conn(struct ksmbd_conn *conn)
392 {
393 	ksmbd_sessions_deregister(conn);
394 	destroy_lease_table(conn);
395 	return 0;
396 }
397 
398 static void ksmbd_server_tcp_callbacks_init(void)
399 {
400 	struct ksmbd_conn_ops ops;
401 
402 	ops.process_fn = ksmbd_server_process_request;
403 	ops.terminate_fn = ksmbd_server_terminate_conn;
404 
405 	ksmbd_conn_init_server_callbacks(&ops);
406 }
407 
408 static void server_conf_free(void)
409 {
410 	int i;
411 
412 	for (i = 0; i < ARRAY_SIZE(server_conf.conf); i++) {
413 		kfree(server_conf.conf[i]);
414 		server_conf.conf[i] = NULL;
415 	}
416 }
417 
418 static int server_conf_init(void)
419 {
420 	WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
421 	server_conf.enforced_signing = 0;
422 	server_conf.min_protocol = ksmbd_min_protocol();
423 	server_conf.max_protocol = ksmbd_max_protocol();
424 	server_conf.auth_mechs = KSMBD_AUTH_NTLMSSP;
425 #ifdef CONFIG_SMB_SERVER_KERBEROS5
426 	server_conf.auth_mechs |= KSMBD_AUTH_KRB5 |
427 				KSMBD_AUTH_MSKRB5;
428 #endif
429 	server_conf.max_inflight_req = SMB2_MAX_CREDITS;
430 	return 0;
431 }
432 
433 static void server_ctrl_handle_init(struct server_ctrl_struct *ctrl)
434 {
435 	int ret;
436 
437 	ksmbd_proc_reset();
438 	ret = ksmbd_conn_transport_init();
439 	if (ret) {
440 		server_queue_ctrl_reset_work();
441 		return;
442 	}
443 
444 	pr_info("running\n");
445 	WRITE_ONCE(server_conf.state, SERVER_STATE_RUNNING);
446 }
447 
448 static void server_ctrl_handle_reset(struct server_ctrl_struct *ctrl)
449 {
450 	ksmbd_ipc_soft_reset();
451 	ksmbd_conn_transport_destroy();
452 	ksmbd_stop_durable_scavenger();
453 	server_conf_free();
454 	server_conf_init();
455 	WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
456 }
457 
458 static void server_ctrl_handle_work(struct work_struct *work)
459 {
460 	struct server_ctrl_struct *ctrl;
461 
462 	ctrl = container_of(work, struct server_ctrl_struct, ctrl_work);
463 
464 	mutex_lock(&ctrl_lock);
465 	switch (ctrl->type) {
466 	case SERVER_CTRL_TYPE_INIT:
467 		server_ctrl_handle_init(ctrl);
468 		break;
469 	case SERVER_CTRL_TYPE_RESET:
470 		server_ctrl_handle_reset(ctrl);
471 		break;
472 	default:
473 		pr_err("Unknown server work type: %d\n", ctrl->type);
474 	}
475 	mutex_unlock(&ctrl_lock);
476 	kfree(ctrl);
477 	module_put(THIS_MODULE);
478 }
479 
480 static int __queue_ctrl_work(int type)
481 {
482 	struct server_ctrl_struct *ctrl;
483 
484 	ctrl = kmalloc_obj(struct server_ctrl_struct, KSMBD_DEFAULT_GFP);
485 	if (!ctrl)
486 		return -ENOMEM;
487 
488 	__module_get(THIS_MODULE);
489 	ctrl->type = type;
490 	INIT_WORK(&ctrl->ctrl_work, server_ctrl_handle_work);
491 	queue_work(system_long_wq, &ctrl->ctrl_work);
492 	return 0;
493 }
494 
495 int server_queue_ctrl_init_work(void)
496 {
497 	return __queue_ctrl_work(SERVER_CTRL_TYPE_INIT);
498 }
499 
500 int server_queue_ctrl_reset_work(void)
501 {
502 	return __queue_ctrl_work(SERVER_CTRL_TYPE_RESET);
503 }
504 
505 static ssize_t stats_show(const struct class *class, const struct class_attribute *attr,
506 			  char *buf)
507 {
508 	/*
509 	 * Inc this each time you change stats output format,
510 	 * so user space will know what to do.
511 	 */
512 	static int stats_version = 2;
513 	static const char * const state[] = {
514 		"startup",
515 		"running",
516 		"reset",
517 		"shutdown"
518 	};
519 	return sysfs_emit(buf, "%d %s %d %lu\n", stats_version,
520 			  state[server_conf.state], server_conf.tcp_port,
521 			  server_conf.ipc_last_active / HZ);
522 }
523 
524 static ssize_t kill_server_store(const struct class *class,
525 				 const struct class_attribute *attr, const char *buf,
526 				 size_t len)
527 {
528 	if (!sysfs_streq(buf, "hard"))
529 		return len;
530 
531 	pr_info("kill command received\n");
532 	mutex_lock(&ctrl_lock);
533 	WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
534 	__module_get(THIS_MODULE);
535 	server_ctrl_handle_reset(NULL);
536 	module_put(THIS_MODULE);
537 	mutex_unlock(&ctrl_lock);
538 	return len;
539 }
540 
541 static const char * const debug_type_strings[] = {"smb", "auth", "vfs",
542 						  "oplock", "ipc", "conn",
543 						  "rdma"};
544 
545 static ssize_t debug_show(const struct class *class, const struct class_attribute *attr,
546 			  char *buf)
547 {
548 	ssize_t sz = 0;
549 	int i, pos = 0;
550 
551 	for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
552 		if ((ksmbd_debug_types >> i) & 1) {
553 			pos = sysfs_emit_at(buf, sz, "[%s] ", debug_type_strings[i]);
554 		} else {
555 			pos = sysfs_emit_at(buf, sz, "%s ", debug_type_strings[i]);
556 		}
557 		sz += pos;
558 	}
559 	sz += sysfs_emit_at(buf, sz, "\n");
560 	return sz;
561 }
562 
563 static ssize_t debug_store(const struct class *class, const struct class_attribute *attr,
564 			   const char *buf, size_t len)
565 {
566 	int i;
567 
568 	for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
569 		if (sysfs_streq(buf, "all")) {
570 			if (ksmbd_debug_types == KSMBD_DEBUG_ALL)
571 				ksmbd_debug_types = 0;
572 			else
573 				ksmbd_debug_types = KSMBD_DEBUG_ALL;
574 			break;
575 		}
576 
577 		if (sysfs_streq(buf, debug_type_strings[i])) {
578 			if (ksmbd_debug_types & (1 << i))
579 				ksmbd_debug_types &= ~(1 << i);
580 			else
581 				ksmbd_debug_types |= (1 << i);
582 			break;
583 		}
584 	}
585 
586 	return len;
587 }
588 
589 static CLASS_ATTR_RO(stats);
590 static CLASS_ATTR_WO(kill_server);
591 static CLASS_ATTR_RW(debug);
592 
593 static struct attribute *ksmbd_control_class_attrs[] = {
594 	&class_attr_stats.attr,
595 	&class_attr_kill_server.attr,
596 	&class_attr_debug.attr,
597 	NULL,
598 };
599 ATTRIBUTE_GROUPS(ksmbd_control_class);
600 
601 static struct class ksmbd_control_class = {
602 	.name		= "ksmbd-control",
603 	.class_groups	= ksmbd_control_class_groups,
604 };
605 
606 static int ksmbd_server_shutdown(void)
607 {
608 	WRITE_ONCE(server_conf.state, SERVER_STATE_SHUTTING_DOWN);
609 
610 	class_unregister(&ksmbd_control_class);
611 	ksmbd_workqueue_destroy();
612 	ksmbd_ipc_release();
613 	ksmbd_conn_transport_destroy();
614 	/*
615 	 * ksmbd_conn_transport_destroy() calls delete_proc_clients() and destroys
616 	 * sessions. ksmbd_session_destroy() removes each session's proc entry.
617 	 * Keep the procfs tree alive until these entries have been removed.
618 	 */
619 	ksmbd_proc_cleanup();
620 	ksmbd_crypto_destroy();
621 	ksmbd_free_global_file_table();
622 	destroy_lease_table(NULL);
623 	ksmbd_work_pool_destroy();
624 	ksmbd_exit_file_cache();
625 	server_conf_free();
626 	return 0;
627 }
628 
629 static int __init ksmbd_server_init(void)
630 {
631 	int ret;
632 
633 	ret = class_register(&ksmbd_control_class);
634 	if (ret) {
635 		pr_err("Unable to register ksmbd-control class\n");
636 		return ret;
637 	}
638 
639 	ret = ksmbd_proc_init();
640 	if (ret)
641 		goto err_unregister;
642 	create_proc_sessions();
643 	create_proc_shares();
644 
645 	ksmbd_server_tcp_callbacks_init();
646 
647 	ret = server_conf_init();
648 	if (ret)
649 		goto err_proc_cleanup;
650 
651 	ret = ksmbd_work_pool_init();
652 	if (ret)
653 		goto err_proc_cleanup;
654 
655 	ret = ksmbd_init_file_cache();
656 	if (ret)
657 		goto err_destroy_work_pools;
658 
659 	ret = ksmbd_ipc_init();
660 	if (ret)
661 		goto err_exit_file_cache;
662 
663 	ret = ksmbd_init_global_file_table();
664 	if (ret)
665 		goto err_ipc_release;
666 
667 	ret = ksmbd_inode_hash_init();
668 	if (ret)
669 		goto err_destroy_file_table;
670 
671 	ret = ksmbd_crypto_create();
672 	if (ret)
673 		goto err_release_inode_hash;
674 
675 	ret = ksmbd_workqueue_init();
676 	if (ret)
677 		goto err_crypto_destroy;
678 
679 	ret = ksmbd_conn_wq_init();
680 	if (ret)
681 		goto err_workqueue_destroy;
682 
683 	return 0;
684 
685 err_workqueue_destroy:
686 	ksmbd_workqueue_destroy();
687 err_crypto_destroy:
688 	ksmbd_crypto_destroy();
689 err_release_inode_hash:
690 	ksmbd_release_inode_hash();
691 err_destroy_file_table:
692 	ksmbd_free_global_file_table();
693 err_ipc_release:
694 	ksmbd_ipc_release();
695 err_exit_file_cache:
696 	ksmbd_exit_file_cache();
697 err_destroy_work_pools:
698 	ksmbd_work_pool_destroy();
699 err_proc_cleanup:
700 	ksmbd_proc_cleanup();
701 err_unregister:
702 	class_unregister(&ksmbd_control_class);
703 
704 	return ret;
705 }
706 
707 /**
708  * ksmbd_server_exit() - shutdown forker thread and free memory at module exit
709  */
710 static void __exit ksmbd_server_exit(void)
711 {
712 	ksmbd_server_shutdown();
713 	rcu_barrier();
714 	/*
715 	 * ksmbd_conn_put() defers the final release onto ksmbd_conn_wq,
716 	 * so drain it after rcu_barrier() has fired any pending RCU
717 	 * callbacks that may have queued a release.
718 	 */
719 	ksmbd_conn_wq_destroy();
720 	ksmbd_release_inode_hash();
721 }
722 
723 MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>");
724 MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
725 MODULE_LICENSE("GPL");
726 MODULE_SOFTDEP("pre: nls");
727 MODULE_SOFTDEP("pre: aes");
728 MODULE_SOFTDEP("pre: aead2");
729 MODULE_SOFTDEP("pre: ccm");
730 MODULE_SOFTDEP("pre: gcm");
731 module_init(ksmbd_server_init)
732 module_exit(ksmbd_server_exit)
733