// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 */

#include <linux/list.h>
#include <linux/slab.h>
#include <linux/xarray.h>

#include "../transport_ipc.h"
#include "../connection.h"

#include "tree_connect.h"
#include "user_config.h"
#include "share_config.h"
#include "user_session.h"

struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
			const char *share_name)
{
	struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
	struct ksmbd_tree_connect_response *resp = NULL;
	struct ksmbd_share_config *sc;
	struct ksmbd_tree_connect *tree_conn = NULL;
	struct sockaddr *peer_addr;
	int ret;

	sc = ksmbd_share_config_get(conn->um, share_name);
	if (!sc)
		return status;

	tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect), GFP_KERNEL);
	if (!tree_conn) {
		status.ret = -ENOMEM;
		goto out_error;
	}

	tree_conn->id = ksmbd_acquire_tree_conn_id(sess);
	if (tree_conn->id < 0) {
		status.ret = -EINVAL;
		goto out_error;
	}

	peer_addr = KSMBD_TCP_PEER_SOCKADDR(conn);
	resp = ksmbd_ipc_tree_connect_request(sess,
					      sc,
					      tree_conn,
					      peer_addr);
	if (!resp) {
		status.ret = -EINVAL;
		goto out_error;
	}

	status.ret = resp->status;
	if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
		goto out_error;

	tree_conn->flags = resp->connection_flags;
	if (test_tree_conn_flag(tree_conn, KSMBD_TREE_CONN_FLAG_UPDATE)) {
		struct ksmbd_share_config *new_sc;

		ksmbd_share_config_del(sc);
		new_sc = ksmbd_share_config_get(conn->um, share_name);
		if (!new_sc) {
			pr_err("Failed to update stale share config\n");
			status.ret = -ESTALE;
			goto out_error;
		}
		ksmbd_share_config_put(sc);
		sc = new_sc;
	}

	tree_conn->user = sess->user;
	tree_conn->share_conf = sc;
	tree_conn->t_state = TREE_NEW;
	status.tree_conn = tree_conn;
	atomic_set(&tree_conn->refcount, 1);
	init_waitqueue_head(&tree_conn->refcount_q);

	ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
			      GFP_KERNEL));
	if (ret) {
		status.ret = -ENOMEM;
		goto out_error;
	}
	kvfree(resp);
	return status;

out_error:
	if (tree_conn)
		ksmbd_release_tree_conn_id(sess, tree_conn->id);
	ksmbd_share_config_put(sc);
	kfree(tree_conn);
	kvfree(resp);
	return status;
}

void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon)
{
	/*
	 * Checking waitqueue to releasing tree connect on
	 * tree disconnect. waitqueue_active is safe because it
	 * uses atomic operation for condition.
	 */
	if (!atomic_dec_return(&tcon->refcount) &&
	    waitqueue_active(&tcon->refcount_q))
		wake_up(&tcon->refcount_q);
}

int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
			       struct ksmbd_tree_connect *tree_conn)
{
	int ret;

	write_lock(&sess->tree_conns_lock);
	xa_erase(&sess->tree_conns, tree_conn->id);
	write_unlock(&sess->tree_conns_lock);

	if (!atomic_dec_and_test(&tree_conn->refcount))
		wait_event(tree_conn->refcount_q,
			   atomic_read(&tree_conn->refcount) == 0);

	ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
	ksmbd_release_tree_conn_id(sess, tree_conn->id);
	ksmbd_share_config_put(tree_conn->share_conf);
	kfree(tree_conn);
	return ret;
}

struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
						  unsigned int id)
{
	struct ksmbd_tree_connect *tcon;

	read_lock(&sess->tree_conns_lock);
	tcon = xa_load(&sess->tree_conns, id);
	if (tcon) {
		if (tcon->t_state != TREE_CONNECTED)
			tcon = NULL;
		else if (!atomic_inc_not_zero(&tcon->refcount))
			tcon = NULL;
	}
	read_unlock(&sess->tree_conns_lock);

	return tcon;
}

int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
{
	int ret = 0;
	struct ksmbd_tree_connect *tc;
	unsigned long id;

	if (!sess)
		return -EINVAL;

	xa_for_each(&sess->tree_conns, id, tc) {
		write_lock(&sess->tree_conns_lock);
		if (tc->t_state == TREE_DISCONNECTED) {
			write_unlock(&sess->tree_conns_lock);
			ret = -ENOENT;
			continue;
		}
		tc->t_state = TREE_DISCONNECTED;
		write_unlock(&sess->tree_conns_lock);

		ret |= ksmbd_tree_conn_disconnect(sess, tc);
	}
	xa_destroy(&sess->tree_conns);
	return ret;
}
