Commit e4d3e6b5 authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French
Browse files

ksmbd: replace sessions list in connection with xarray



Replace sessions list in connection with xarray.

Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Reviewed-by: default avatarHyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 8849e754
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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;
+7 −24
Original line number Diff line number Diff line
@@ -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,
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);
+2 −3
Original line number Diff line number Diff line
@@ -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,7 +83,7 @@ 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,
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,
+9 −4
Original line number Diff line number Diff line
@@ -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)