]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: replace sessions list in connection with xarray
authorNamjae Jeon <linkinjeon@kernel.org>
Fri, 22 Jul 2022 01:15:10 +0000 (10:15 +0900)
committerSteve French <stfrench@microsoft.com>
Wed, 27 Jul 2022 04:38:05 +0000 (23:38 -0500)
Replace sessions list in connection with xarray.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/ksmbd/connection.c
fs/ksmbd/connection.h
fs/ksmbd/mgmt/user_session.c
fs/ksmbd/mgmt/user_session.h
fs/ksmbd/smb2pdu.c

index e8f476c5f18903b2e9816b3fdf29cc0dec320f50..ce23cc89046e7c8d8b45742b74d5de93beb6c4d8 100644 (file)
@@ -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);
index 98c1cbe45ec970b9a216e838cce7cfa207da8820..5b39f0bdeff8e8a44246f86c4341ecfdf0cf22fe 100644 (file)
@@ -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;
index 8d8ffd8c6f1929ef2b73740dcb4aca3f0d847f6b..3a44e66456fc06e1002df7002ce89d372bd75694 100644 (file)
@@ -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);
index e241f16a3851284646bdea9a347f8334a173e5b8..8b08189be3fc27f694e27d1303853d5f8f6c7c22 100644 (file)
@@ -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);
index 353f047e783cad7b843f6329eecab2c461163656..7e1620a27b8579fa07a08eac1197b370d3e2627b 100644 (file)
@@ -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 @@ out_err:
                        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)