Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'v7.1-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

- Fix shutdown (stop sessions)

- Fix readdir unsupported info level

* tag 'v7.1-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
ksmbd: rewrite stop_sessions() with restartable iteration
smb: server: handle readdir_info_level_struct_sz() error

+47 -10
+39 -9
fs/smb/server/connection.c
··· 540 540 541 541 static void stop_sessions(void) 542 542 { 543 - struct ksmbd_conn *conn; 543 + struct ksmbd_conn *conn, *target; 544 544 struct ksmbd_transport *t; 545 + bool any; 545 546 int bkt; 546 547 548 + /* 549 + * Serialised via init_lock; no concurrent stop_sessions() can 550 + * touch conn->stop_called, so writing it under the read lock is 551 + * safe. 552 + */ 547 553 again: 554 + target = NULL; 555 + any = false; 548 556 down_read(&conn_list_lock); 549 557 hash_for_each(conn_list, bkt, conn, hlist) { 550 - t = conn->transport; 551 - ksmbd_conn_set_exiting(conn); 552 - if (t->ops->shutdown) { 553 - up_read(&conn_list_lock); 554 - t->ops->shutdown(t); 555 - down_read(&conn_list_lock); 556 - } 558 + any = true; 559 + if (conn->stop_called) 560 + continue; 561 + atomic_inc(&conn->refcnt); 562 + conn->stop_called = true; 563 + /* 564 + * Mark the connection EXITING while still holding the 565 + * read lock so the selection and the status transition 566 + * happen together. Do not regress a connection that has 567 + * already advanced to RELEASING on its own (e.g. the 568 + * handler exited its receive loop for an unrelated 569 + * reason). 570 + */ 571 + if (READ_ONCE(conn->status) != KSMBD_SESS_RELEASING) 572 + ksmbd_conn_set_exiting(conn); 573 + target = conn; 574 + break; 557 575 } 558 576 up_read(&conn_list_lock); 559 577 560 - if (!hash_empty(conn_list)) { 578 + if (target) { 579 + t = target->transport; 580 + if (t->ops->shutdown) 581 + t->ops->shutdown(t); 582 + if (atomic_dec_and_test(&target->refcnt)) { 583 + ida_destroy(&target->async_ida); 584 + t->ops->free_transport(t); 585 + kfree(target); 586 + } 587 + goto again; 588 + } 589 + 590 + if (any) { 561 591 msleep(100); 562 592 goto again; 563 593 }
+1
fs/smb/server/connection.h
··· 49 49 struct mutex srv_mutex; 50 50 int status; 51 51 unsigned int cli_cap; 52 + bool stop_called; 52 53 union { 53 54 __be32 inet_addr; 54 55 #if IS_ENABLED(CONFIG_IPV6)
+7 -1
fs/smb/server/smb2pdu.c
··· 3946 3946 goto free_conv_name; 3947 3947 } 3948 3948 3949 - struct_sz = readdir_info_level_struct_sz(info_level) + conv_len; 3949 + struct_sz = readdir_info_level_struct_sz(info_level); 3950 + if (struct_sz == -EOPNOTSUPP) { 3951 + rc = -EINVAL; 3952 + goto free_conv_name; 3953 + } 3954 + 3955 + struct_sz += conv_len; 3950 3956 next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT); 3951 3957 d_info->last_entry_off_align = next_entry_offset - struct_sz; 3952 3958