Message ID | 20220722030346.28534-1-linkinjeon@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/5] ksmbd: replace sessions list in connection with xarray | expand |
Hi Namjae, 2022년 7월 22일 (금) 오후 12:04, Namjae Jeon <linkinjeon@kernel.org>님이 작성: > > Replace sessions list in connection with xarray. > > Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Looks good to me. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> > --- > fs/ksmbd/connection.c | 3 ++- > fs/ksmbd/connection.h | 2 +- > fs/ksmbd/mgmt/user_session.c | 31 +++++++------------------------ > fs/ksmbd/mgmt/user_session.h | 5 ++--- > fs/ksmbd/smb2pdu.c | 13 +++++++++---- > 5 files changed, 21 insertions(+), 33 deletions(-) > > diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c > index e8f476c5f189..ce23cc89046e 100644 > --- a/fs/ksmbd/connection.c > +++ b/fs/ksmbd/connection.c > @@ -36,6 +36,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn) > list_del(&conn->conns_list); > write_unlock(&conn_list_lock); > > + xa_destroy(&conn->sessions); > kvfree(conn->request_buf); > kfree(conn->preauth_info); > kfree(conn); > @@ -66,12 +67,12 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) > > init_waitqueue_head(&conn->req_running_q); > INIT_LIST_HEAD(&conn->conns_list); > - INIT_LIST_HEAD(&conn->sessions); > INIT_LIST_HEAD(&conn->requests); > INIT_LIST_HEAD(&conn->async_requests); > spin_lock_init(&conn->request_lock); > spin_lock_init(&conn->credits_lock); > ida_init(&conn->async_ida); > + xa_init(&conn->sessions); > > spin_lock_init(&conn->llist_lock); > INIT_LIST_HEAD(&conn->lock_list); > diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h > index 98c1cbe45ec9..5b39f0bdeff8 100644 > --- a/fs/ksmbd/connection.h > +++ b/fs/ksmbd/connection.h > @@ -55,7 +55,7 @@ struct ksmbd_conn { > struct nls_table *local_nls; > struct list_head conns_list; > /* smb session 1 per user */ > - struct list_head sessions; > + struct xarray sessions; > unsigned long last_active; > /* How many request are running currently */ > atomic_t req_running; > diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c > index 8d8ffd8c6f19..3a44e66456fc 100644 > --- a/fs/ksmbd/mgmt/user_session.c > +++ b/fs/ksmbd/mgmt/user_session.c > @@ -152,8 +152,6 @@ void ksmbd_session_destroy(struct ksmbd_session *sess) > if (!atomic_dec_and_test(&sess->refcnt)) > return; > > - list_del(&sess->sessions_entry); > - > down_write(&sessions_table_lock); > hash_del(&sess->hlist); > up_write(&sessions_table_lock); > @@ -181,42 +179,28 @@ static struct ksmbd_session *__session_lookup(unsigned long long id) > return NULL; > } > > -void ksmbd_session_register(struct ksmbd_conn *conn, > - struct ksmbd_session *sess) > +int ksmbd_session_register(struct ksmbd_conn *conn, > + struct ksmbd_session *sess) > { > sess->conn = conn; > - list_add(&sess->sessions_entry, &conn->sessions); > + return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL)); > } > > void ksmbd_sessions_deregister(struct ksmbd_conn *conn) > { > struct ksmbd_session *sess; > + unsigned long id; > > - while (!list_empty(&conn->sessions)) { > - sess = list_entry(conn->sessions.next, > - struct ksmbd_session, > - sessions_entry); > - > + xa_for_each(&conn->sessions, id, sess) { > + xa_erase(&conn->sessions, sess->id); > ksmbd_session_destroy(sess); > } > } > > -static bool ksmbd_session_id_match(struct ksmbd_session *sess, > - unsigned long long id) > -{ > - return sess->id == id; > -} > - > struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, > unsigned long long id) > { > - struct ksmbd_session *sess = NULL; > - > - list_for_each_entry(sess, &conn->sessions, sessions_entry) { > - if (ksmbd_session_id_match(sess, id)) > - return sess; > - } > - return NULL; > + return xa_load(&conn->sessions, id); > } > > int get_session(struct ksmbd_session *sess) > @@ -314,7 +298,6 @@ static struct ksmbd_session *__session_create(int protocol) > goto error; > > set_session_flag(sess, protocol); > - INIT_LIST_HEAD(&sess->sessions_entry); > xa_init(&sess->tree_conns); > INIT_LIST_HEAD(&sess->ksmbd_chann_list); > INIT_LIST_HEAD(&sess->rpc_handle_list); > diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h > index e241f16a3851..8b08189be3fc 100644 > --- a/fs/ksmbd/mgmt/user_session.h > +++ b/fs/ksmbd/mgmt/user_session.h > @@ -57,7 +57,6 @@ struct ksmbd_session { > __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE]; > __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; > > - struct list_head sessions_entry; > struct ksmbd_file_table file_table; > atomic_t refcnt; > }; > @@ -84,8 +83,8 @@ void ksmbd_session_destroy(struct ksmbd_session *sess); > struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id); > struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, > unsigned long long id); > -void ksmbd_session_register(struct ksmbd_conn *conn, > - struct ksmbd_session *sess); > +int ksmbd_session_register(struct ksmbd_conn *conn, > + struct ksmbd_session *sess); > void ksmbd_sessions_deregister(struct ksmbd_conn *conn); > struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn, > unsigned long long id); > diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c > index 94ab1dcd80e7..04d20a2e6dee 100644 > --- a/fs/ksmbd/smb2pdu.c > +++ b/fs/ksmbd/smb2pdu.c > @@ -588,7 +588,8 @@ int smb2_check_user_session(struct ksmbd_work *work) > return -EINVAL; > } > > -static void destroy_previous_session(struct ksmbd_user *user, u64 id) > +static void destroy_previous_session(struct ksmbd_conn *conn, > + struct ksmbd_user *user, u64 id) > { > struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id); > struct ksmbd_user *prev_user; > @@ -607,6 +608,7 @@ static void destroy_previous_session(struct ksmbd_user *user, u64 id) > } > > put_session(prev_sess); > + xa_erase(&conn->sessions, prev_sess->id); > ksmbd_session_destroy(prev_sess); > } > > @@ -1439,7 +1441,7 @@ static int ntlm_authenticate(struct ksmbd_work *work) > /* Check for previous session */ > prev_id = le64_to_cpu(req->PreviousSessionId); > if (prev_id && prev_id != sess->id) > - destroy_previous_session(user, prev_id); > + destroy_previous_session(conn, user, prev_id); > > if (sess->state == SMB2_SESSION_VALID) { > /* > @@ -1561,7 +1563,7 @@ static int krb5_authenticate(struct ksmbd_work *work) > /* Check previous session */ > prev_sess_id = le64_to_cpu(req->PreviousSessionId); > if (prev_sess_id && prev_sess_id != sess->id) > - destroy_previous_session(sess->user, prev_sess_id); > + destroy_previous_session(conn, sess->user, prev_sess_id); > > if (sess->state == SMB2_SESSION_VALID) > ksmbd_free_user(sess->user); > @@ -1650,7 +1652,9 @@ int smb2_sess_setup(struct ksmbd_work *work) > goto out_err; > } > rsp->hdr.SessionId = cpu_to_le64(sess->id); > - ksmbd_session_register(conn, sess); > + rc = ksmbd_session_register(conn, sess); > + if (rc) > + goto out_err; > } else if (conn->dialect >= SMB30_PROT_ID && > (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) && > req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) { > @@ -1828,6 +1832,7 @@ int smb2_sess_setup(struct ksmbd_work *work) > if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION) > try_delay = true; > > + xa_erase(&conn->sessions, sess->id); > ksmbd_session_destroy(sess); > work->sess = NULL; > if (try_delay) > -- > 2.25.1 >
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c index e8f476c5f189..ce23cc89046e 100644 --- a/fs/ksmbd/connection.c +++ b/fs/ksmbd/connection.c @@ -36,6 +36,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn) list_del(&conn->conns_list); write_unlock(&conn_list_lock); + xa_destroy(&conn->sessions); kvfree(conn->request_buf); kfree(conn->preauth_info); kfree(conn); @@ -66,12 +67,12 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) init_waitqueue_head(&conn->req_running_q); INIT_LIST_HEAD(&conn->conns_list); - INIT_LIST_HEAD(&conn->sessions); INIT_LIST_HEAD(&conn->requests); INIT_LIST_HEAD(&conn->async_requests); spin_lock_init(&conn->request_lock); spin_lock_init(&conn->credits_lock); ida_init(&conn->async_ida); + xa_init(&conn->sessions); spin_lock_init(&conn->llist_lock); INIT_LIST_HEAD(&conn->lock_list); diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h index 98c1cbe45ec9..5b39f0bdeff8 100644 --- a/fs/ksmbd/connection.h +++ b/fs/ksmbd/connection.h @@ -55,7 +55,7 @@ struct ksmbd_conn { struct nls_table *local_nls; struct list_head conns_list; /* smb session 1 per user */ - struct list_head sessions; + struct xarray sessions; unsigned long last_active; /* How many request are running currently */ atomic_t req_running; diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c index 8d8ffd8c6f19..3a44e66456fc 100644 --- a/fs/ksmbd/mgmt/user_session.c +++ b/fs/ksmbd/mgmt/user_session.c @@ -152,8 +152,6 @@ void ksmbd_session_destroy(struct ksmbd_session *sess) if (!atomic_dec_and_test(&sess->refcnt)) return; - list_del(&sess->sessions_entry); - down_write(&sessions_table_lock); hash_del(&sess->hlist); up_write(&sessions_table_lock); @@ -181,42 +179,28 @@ static struct ksmbd_session *__session_lookup(unsigned long long id) return NULL; } -void ksmbd_session_register(struct ksmbd_conn *conn, - struct ksmbd_session *sess) +int ksmbd_session_register(struct ksmbd_conn *conn, + struct ksmbd_session *sess) { sess->conn = conn; - list_add(&sess->sessions_entry, &conn->sessions); + return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL)); } void ksmbd_sessions_deregister(struct ksmbd_conn *conn) { struct ksmbd_session *sess; + unsigned long id; - while (!list_empty(&conn->sessions)) { - sess = list_entry(conn->sessions.next, - struct ksmbd_session, - sessions_entry); - + xa_for_each(&conn->sessions, id, sess) { + xa_erase(&conn->sessions, sess->id); ksmbd_session_destroy(sess); } } -static bool ksmbd_session_id_match(struct ksmbd_session *sess, - unsigned long long id) -{ - return sess->id == id; -} - struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, unsigned long long id) { - struct ksmbd_session *sess = NULL; - - list_for_each_entry(sess, &conn->sessions, sessions_entry) { - if (ksmbd_session_id_match(sess, id)) - return sess; - } - return NULL; + return xa_load(&conn->sessions, id); } int get_session(struct ksmbd_session *sess) @@ -314,7 +298,6 @@ static struct ksmbd_session *__session_create(int protocol) goto error; set_session_flag(sess, protocol); - INIT_LIST_HEAD(&sess->sessions_entry); xa_init(&sess->tree_conns); INIT_LIST_HEAD(&sess->ksmbd_chann_list); INIT_LIST_HEAD(&sess->rpc_handle_list); diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h index e241f16a3851..8b08189be3fc 100644 --- a/fs/ksmbd/mgmt/user_session.h +++ b/fs/ksmbd/mgmt/user_session.h @@ -57,7 +57,6 @@ struct ksmbd_session { __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE]; __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; - struct list_head sessions_entry; struct ksmbd_file_table file_table; atomic_t refcnt; }; @@ -84,8 +83,8 @@ void ksmbd_session_destroy(struct ksmbd_session *sess); struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id); struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, unsigned long long id); -void ksmbd_session_register(struct ksmbd_conn *conn, - struct ksmbd_session *sess); +int ksmbd_session_register(struct ksmbd_conn *conn, + struct ksmbd_session *sess); void ksmbd_sessions_deregister(struct ksmbd_conn *conn); struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn, unsigned long long id); diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 94ab1dcd80e7..04d20a2e6dee 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -588,7 +588,8 @@ int smb2_check_user_session(struct ksmbd_work *work) return -EINVAL; } -static void destroy_previous_session(struct ksmbd_user *user, u64 id) +static void destroy_previous_session(struct ksmbd_conn *conn, + struct ksmbd_user *user, u64 id) { struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id); struct ksmbd_user *prev_user; @@ -607,6 +608,7 @@ static void destroy_previous_session(struct ksmbd_user *user, u64 id) } put_session(prev_sess); + xa_erase(&conn->sessions, prev_sess->id); ksmbd_session_destroy(prev_sess); } @@ -1439,7 +1441,7 @@ static int ntlm_authenticate(struct ksmbd_work *work) /* Check for previous session */ prev_id = le64_to_cpu(req->PreviousSessionId); if (prev_id && prev_id != sess->id) - destroy_previous_session(user, prev_id); + destroy_previous_session(conn, user, prev_id); if (sess->state == SMB2_SESSION_VALID) { /* @@ -1561,7 +1563,7 @@ static int krb5_authenticate(struct ksmbd_work *work) /* Check previous session */ prev_sess_id = le64_to_cpu(req->PreviousSessionId); if (prev_sess_id && prev_sess_id != sess->id) - destroy_previous_session(sess->user, prev_sess_id); + destroy_previous_session(conn, sess->user, prev_sess_id); if (sess->state == SMB2_SESSION_VALID) ksmbd_free_user(sess->user); @@ -1650,7 +1652,9 @@ int smb2_sess_setup(struct ksmbd_work *work) goto out_err; } rsp->hdr.SessionId = cpu_to_le64(sess->id); - ksmbd_session_register(conn, sess); + rc = ksmbd_session_register(conn, sess); + if (rc) + goto out_err; } else if (conn->dialect >= SMB30_PROT_ID && (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) && req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) { @@ -1828,6 +1832,7 @@ int smb2_sess_setup(struct ksmbd_work *work) if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION) try_delay = true; + xa_erase(&conn->sessions, sess->id); ksmbd_session_destroy(sess); work->sess = NULL; if (try_delay)
Replace sessions list in connection with xarray. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> --- fs/ksmbd/connection.c | 3 ++- fs/ksmbd/connection.h | 2 +- fs/ksmbd/mgmt/user_session.c | 31 +++++++------------------------ fs/ksmbd/mgmt/user_session.h | 5 ++--- fs/ksmbd/smb2pdu.c | 13 +++++++++---- 5 files changed, 21 insertions(+), 33 deletions(-)