Skip to content

Commit dac6acd

Browse files
committed
ksmbd: convert tree_conns_lock to rw_semaphore
Converts tree_conns_lock to an rw_semaphore to allow sleeping while the lock is held. Additionally, it simplifies the locking logic in ksmbd_tree_conn_session_logoff() and introduces __ksmbd_tree_conn_disconnect() to avoid redundant locking. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent b784e1b commit dac6acd

File tree

4 files changed

+30
-19
lines changed

4 files changed

+30
-19
lines changed

mgmt/tree_connect.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
8080
status.tree_conn = tree_conn;
8181
atomic_set(&tree_conn->refcount, 1);
8282

83+
down_write(&sess->tree_conns_lock);
8384
ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
8485
KSMBD_DEFAULT_GFP));
86+
up_write(&sess->tree_conns_lock);
8587
if (ret) {
8688
status.ret = -ENOMEM;
8789
goto out_error;
@@ -105,15 +107,11 @@ void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon)
105107
kfree(tcon);
106108
}
107109

108-
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
109-
struct ksmbd_tree_connect *tree_conn)
110+
static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
111+
struct ksmbd_tree_connect *tree_conn)
110112
{
111113
int ret;
112114

113-
write_lock(&sess->tree_conns_lock);
114-
xa_erase(&sess->tree_conns, tree_conn->id);
115-
write_unlock(&sess->tree_conns_lock);
116-
117115
ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
118116
ksmbd_release_tree_conn_id(sess, tree_conn->id);
119117
ksmbd_share_config_put(tree_conn->share_conf);
@@ -123,20 +121,30 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
123121
return ret;
124122
}
125123

124+
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
125+
struct ksmbd_tree_connect *tree_conn)
126+
{
127+
down_write(&sess->tree_conns_lock);
128+
xa_erase(&sess->tree_conns, tree_conn->id);
129+
up_write(&sess->tree_conns_lock);
130+
131+
return __ksmbd_tree_conn_disconnect(sess, tree_conn);
132+
}
133+
126134
struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
127135
unsigned int id)
128136
{
129137
struct ksmbd_tree_connect *tcon;
130138

131-
read_lock(&sess->tree_conns_lock);
139+
down_read(&sess->tree_conns_lock);
132140
tcon = xa_load(&sess->tree_conns, id);
133141
if (tcon) {
134142
if (tcon->t_state != TREE_CONNECTED)
135143
tcon = NULL;
136144
else if (!atomic_inc_not_zero(&tcon->refcount))
137145
tcon = NULL;
138146
}
139-
read_unlock(&sess->tree_conns_lock);
147+
up_read(&sess->tree_conns_lock);
140148

141149
return tcon;
142150
}
@@ -150,18 +158,19 @@ int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
150158
if (!sess)
151159
return -EINVAL;
152160

161+
down_write(&sess->tree_conns_lock);
153162
xa_for_each(&sess->tree_conns, id, tc) {
154-
write_lock(&sess->tree_conns_lock);
155163
if (tc->t_state == TREE_DISCONNECTED) {
156-
write_unlock(&sess->tree_conns_lock);
157164
ret = -ENOENT;
158165
continue;
159166
}
160167
tc->t_state = TREE_DISCONNECTED;
161-
write_unlock(&sess->tree_conns_lock);
162168

163-
ret |= ksmbd_tree_conn_disconnect(sess, tc);
169+
xa_erase(&sess->tree_conns, tc->id);
170+
ret |= __ksmbd_tree_conn_disconnect(sess, tc);
164171
}
165172
xa_destroy(&sess->tree_conns);
173+
up_write(&sess->tree_conns_lock);
174+
166175
return ret;
167176
}

mgmt/user_session.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static int show_proc_session(struct seq_file *m, void *v)
127127
seq_printf(m, "%-20s\t%d\n", "channels", i);
128128

129129
i = 0;
130+
down_read(&sess->tree_conns_lock);
130131
xa_for_each(&sess->tree_conns, id, tree_conn) {
131132
share_conf = tree_conn->share_conf;
132133
seq_printf(m, "%-20s\t%s\t%8d", "share",
@@ -137,6 +138,7 @@ static int show_proc_session(struct seq_file *m, void *v)
137138
seq_printf(m, " %s ", "disk");
138139
seq_putc(m, '\n');
139140
}
141+
up_read(&sess->tree_conns_lock);
140142

141143
ksmbd_user_session_put(sess);
142144
return 0;
@@ -687,8 +689,8 @@ static struct ksmbd_session *__session_create(int protocol)
687689
xa_init(&sess->ksmbd_chann_list);
688690
xa_init(&sess->rpc_handle_list);
689691
sess->sequence_number = 1;
690-
rwlock_init(&sess->tree_conns_lock);
691692
atomic_set(&sess->refcnt, 2);
693+
init_rwsem(&sess->tree_conns_lock);
692694
init_rwsem(&sess->rpc_lock);
693695
init_rwsem(&sess->chann_lock);
694696

mgmt/user_session.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct ksmbd_session {
6363

6464
struct ksmbd_file_table file_table;
6565
unsigned long last_active;
66-
rwlock_t tree_conns_lock;
66+
struct rw_semaphore tree_conns_lock;
6767

6868
#ifdef CONFIG_PROC_FS
6969
struct proc_dir_entry *proc_entry;

smb2pdu.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,9 +2055,9 @@ int smb2_tree_connect(struct ksmbd_work *work)
20552055
if (conn->posix_ext_supported)
20562056
status.tree_conn->posix_extensions = true;
20572057

2058-
write_lock(&sess->tree_conns_lock);
2058+
down_write(&sess->tree_conns_lock);
20592059
status.tree_conn->t_state = TREE_CONNECTED;
2060-
write_unlock(&sess->tree_conns_lock);
2060+
up_write(&sess->tree_conns_lock);
20612061
rsp->StructureSize = cpu_to_le16(16);
20622062
out_err1:
20632063
if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && share &&
@@ -2210,16 +2210,16 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
22102210

22112211
ksmbd_close_tree_conn_fds(work);
22122212

2213-
write_lock(&sess->tree_conns_lock);
2213+
down_write(&sess->tree_conns_lock);
22142214
if (tcon->t_state == TREE_DISCONNECTED) {
2215-
write_unlock(&sess->tree_conns_lock);
2215+
up_write(&sess->tree_conns_lock);
22162216
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
22172217
err = -ENOENT;
22182218
goto err_out;
22192219
}
22202220

22212221
tcon->t_state = TREE_DISCONNECTED;
2222-
write_unlock(&sess->tree_conns_lock);
2222+
up_write(&sess->tree_conns_lock);
22232223

22242224
err = ksmbd_tree_conn_disconnect(sess, tcon);
22252225
if (err) {

0 commit comments

Comments
 (0)