From: Namjae Jeon namjae.jeon@samsung.com
mainline inclusion from mainline-5.15-rc1 commit 02b68b2065c91ce706f462fd509032a77db5d9dc category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I60T7G CVE: NA
Reference: https://git.kernel.org/torvalds/linux/c/02b68b2065c9
-------------------------------
Matthew suggest to change linked list of tree connect list to xarray. It will be tree connect lookup in O(log(n)) time instead of O(n) time.
Signed-off-by: Namjae Jeon namjae.jeon@samsung.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Jason Yan yanaijie@huawei.com Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com --- fs/cifsd/mgmt/tree_connect.c | 35 +++++++++++++++-------------------- fs/cifsd/mgmt/user_session.c | 4 +++- fs/cifsd/mgmt/user_session.h | 6 +++++- fs/cifsd/smb2pdu.c | 2 +- 4 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/fs/cifsd/mgmt/tree_connect.c b/fs/cifsd/mgmt/tree_connect.c index d5670f2596a3..0c8374e8240f 100644 --- a/fs/cifsd/mgmt/tree_connect.c +++ b/fs/cifsd/mgmt/tree_connect.c @@ -5,6 +5,8 @@
#include <linux/list.h> #include <linux/slab.h> +#include <linux/version.h> +#include <linux/xarray.h>
#include "../buffer_pool.h" #include "../transport_ipc.h" @@ -23,6 +25,7 @@ ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name) struct ksmbd_share_config *sc; struct ksmbd_tree_connect *tree_conn = NULL; struct sockaddr *peer_addr; + int ret;
sc = ksmbd_share_config_get(share_name); if (!sc) @@ -59,8 +62,12 @@ ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name) tree_conn->share_conf = sc; status.tree_conn = tree_conn;
- list_add(&tree_conn->list, &sess->tree_conn_list); - + ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn, + GFP_KERNEL)); + if (ret) { + status.ret = -ENOMEM; + goto out_error; + } ksmbd_free(resp); return status;
@@ -80,7 +87,7 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); ksmbd_release_tree_conn_id(sess, tree_conn->id); - list_del(&tree_conn->list); + xa_erase(&sess->tree_conns, tree_conn->id); ksmbd_share_config_put(tree_conn->share_conf); ksmbd_free(tree_conn); return ret; @@ -89,15 +96,7 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess, unsigned int id) { - struct ksmbd_tree_connect *tree_conn; - struct list_head *tmp; - - list_for_each(tmp, &sess->tree_conn_list) { - tree_conn = list_entry(tmp, struct ksmbd_tree_connect, list); - if (tree_conn->id == id) - return tree_conn; - } - return NULL; + return xa_load(&sess->tree_conns, id); }
struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess, @@ -114,15 +113,11 @@ struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess, int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess) { int ret = 0; + struct ksmbd_tree_connect *tc; + unsigned long id;
- while (!list_empty(&sess->tree_conn_list)) { - struct ksmbd_tree_connect *tc; - - tc = list_entry(sess->tree_conn_list.next, - struct ksmbd_tree_connect, - list); + xa_for_each(&sess->tree_conns, id, tc) ret |= ksmbd_tree_conn_disconnect(sess, tc); - } - + xa_destroy(&sess->tree_conns); return ret; } diff --git a/fs/cifsd/mgmt/user_session.c b/fs/cifsd/mgmt/user_session.c index 5a2113bf18ef..f5cc7a62d848 100644 --- a/fs/cifsd/mgmt/user_session.c +++ b/fs/cifsd/mgmt/user_session.c @@ -6,6 +6,8 @@ #include <linux/list.h> #include <linux/slab.h> #include <linux/rwsem.h> +#include <linux/version.h> +#include <linux/xarray.h>
#include "ksmbd_ida.h" #include "user_session.h" @@ -275,7 +277,7 @@ static struct ksmbd_session *__session_create(int protocol)
set_session_flag(sess, protocol); INIT_LIST_HEAD(&sess->sessions_entry); - INIT_LIST_HEAD(&sess->tree_conn_list); + xa_init(&sess->tree_conns); INIT_LIST_HEAD(&sess->ksmbd_chann_list); INIT_LIST_HEAD(&sess->rpc_handle_list); sess->sequence_number = 1; diff --git a/fs/cifsd/mgmt/user_session.h b/fs/cifsd/mgmt/user_session.h index 68018f0f5c0b..1a97c851f2fc 100644 --- a/fs/cifsd/mgmt/user_session.h +++ b/fs/cifsd/mgmt/user_session.h @@ -7,6 +7,8 @@ #define __USER_SESSION_MANAGEMENT_H__
#include <linux/hashtable.h> +#include <linux/version.h> +#include <linux/xarray.h>
#include "../smb_common.h" #include "../ntlmssp.h" @@ -50,10 +52,12 @@ struct ksmbd_session {
struct hlist_node hlist; struct list_head ksmbd_chann_list; - struct list_head tree_conn_list; + struct xarray tree_conns; struct ksmbd_ida *tree_conn_ida; struct list_head rpc_handle_list;
+ + __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; diff --git a/fs/cifsd/smb2pdu.c b/fs/cifsd/smb2pdu.c index 139041768f65..0b7199444f73 100644 --- a/fs/cifsd/smb2pdu.c +++ b/fs/cifsd/smb2pdu.c @@ -104,7 +104,7 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) return 0; }
- if (list_empty(&work->sess->tree_conn_list)) { + if (xa_empty(&work->sess->tree_conns)) { ksmbd_debug(SMB, "NO tree connected\n"); return -1; }