// SPDX-License-Identifier: GPL-2.0-or-later
/* Fileserver-directed operation handling.
 *
 * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include "internal.h"

static atomic_t afs_operation_debug_counter;

/*
 * Create an operation against a volume.
 */
struct afs_operation *afs_alloc_operation(struct key *key, struct afs_volume *volume)
{
	struct afs_operation *op;

	_enter("");

	op = kzalloc(sizeof(*op), GFP_KERNEL);
	if (!op)
		return ERR_PTR(-ENOMEM);

	if (!key) {
		key = afs_request_key(volume->cell);
		if (IS_ERR(key)) {
			kfree(op);
			return ERR_CAST(key);
		}
	} else {
		key_get(key);
	}

	op->key			= key;
	op->volume		= afs_get_volume(volume, afs_volume_trace_get_new_op);
	op->net			= volume->cell->net;
	op->cb_v_break		= atomic_read(&volume->cb_v_break);
	op->pre_volsync.creation = volume->creation_time;
	op->pre_volsync.update	= volume->update_time;
	op->debug_id		= atomic_inc_return(&afs_operation_debug_counter);
	op->nr_iterations	= -1;
	afs_op_set_error(op, -EDESTADDRREQ);

	_leave(" = [op=%08x]", op->debug_id);
	return op;
}

/*
 * Lock the vnode(s) being operated upon.
 */
static bool afs_get_io_locks(struct afs_operation *op)
{
	struct afs_vnode *vnode = op->file[0].vnode;
	struct afs_vnode *vnode2 = op->file[1].vnode;

	_enter("");

	if (op->flags & AFS_OPERATION_UNINTR) {
		mutex_lock(&vnode->io_lock);
		op->flags |= AFS_OPERATION_LOCK_0;
		_leave(" = t [1]");
		return true;
	}

	if (!vnode2 || !op->file[1].need_io_lock || vnode == vnode2)
		vnode2 = NULL;

	if (vnode2 > vnode)
		swap(vnode, vnode2);

	if (mutex_lock_interruptible(&vnode->io_lock) < 0) {
		afs_op_set_error(op, -ERESTARTSYS);
		op->flags |= AFS_OPERATION_STOP;
		_leave(" = f [I 0]");
		return false;
	}
	op->flags |= AFS_OPERATION_LOCK_0;

	if (vnode2) {
		if (mutex_lock_interruptible_nested(&vnode2->io_lock, 1) < 0) {
			afs_op_set_error(op, -ERESTARTSYS);
			op->flags |= AFS_OPERATION_STOP;
			mutex_unlock(&vnode->io_lock);
			op->flags &= ~AFS_OPERATION_LOCK_0;
			_leave(" = f [I 1]");
			return false;
		}
		op->flags |= AFS_OPERATION_LOCK_1;
	}

	_leave(" = t [2]");
	return true;
}

static void afs_drop_io_locks(struct afs_operation *op)
{
	struct afs_vnode *vnode = op->file[0].vnode;
	struct afs_vnode *vnode2 = op->file[1].vnode;

	_enter("");

	if (op->flags & AFS_OPERATION_LOCK_1)
		mutex_unlock(&vnode2->io_lock);
	if (op->flags & AFS_OPERATION_LOCK_0)
		mutex_unlock(&vnode->io_lock);
}

static void afs_prepare_vnode(struct afs_operation *op, struct afs_vnode_param *vp,
			      unsigned int index)
{
	struct afs_vnode *vnode = vp->vnode;

	if (vnode) {
		vp->fid			= vnode->fid;
		vp->dv_before		= vnode->status.data_version;
		vp->cb_break_before	= afs_calc_vnode_cb_break(vnode);
		if (vnode->lock_state != AFS_VNODE_LOCK_NONE)
			op->flags	|= AFS_OPERATION_CUR_ONLY;
		if (vp->modification)
			set_bit(AFS_VNODE_MODIFYING, &vnode->flags);
	}

	if (vp->fid.vnode)
		_debug("PREP[%u] {%llx:%llu.%u}",
		       index, vp->fid.vid, vp->fid.vnode, vp->fid.unique);
}

/*
 * Begin an operation on the fileserver.
 *
 * Fileserver operations are serialised on the server by vnode, so we serialise
 * them here also using the io_lock.
 */
bool afs_begin_vnode_operation(struct afs_operation *op)
{
	struct afs_vnode *vnode = op->file[0].vnode;

	ASSERT(vnode);

	_enter("");

	if (op->file[0].need_io_lock)
		if (!afs_get_io_locks(op))
			return false;

	afs_prepare_vnode(op, &op->file[0], 0);
	afs_prepare_vnode(op, &op->file[1], 1);
	op->cb_v_break = atomic_read(&op->volume->cb_v_break);
	_leave(" = true");
	return true;
}

/*
 * Tidy up a filesystem cursor and unlock the vnode.
 */
static void afs_end_vnode_operation(struct afs_operation *op)
{
	_enter("");

	switch (afs_op_error(op)) {
	case -EDESTADDRREQ:
	case -EADDRNOTAVAIL:
	case -ENETUNREACH:
	case -EHOSTUNREACH:
		afs_dump_edestaddrreq(op);
		break;
	}

	afs_drop_io_locks(op);
}

/*
 * Wait for an in-progress operation to complete.
 */
void afs_wait_for_operation(struct afs_operation *op)
{
	_enter("");

	while (afs_select_fileserver(op)) {
		op->call_responded = false;
		op->call_error = 0;
		op->call_abort_code = 0;
		if (test_bit(AFS_SERVER_FL_IS_YFS, &op->server->flags) &&
		    op->ops->issue_yfs_rpc)
			op->ops->issue_yfs_rpc(op);
		else if (op->ops->issue_afs_rpc)
			op->ops->issue_afs_rpc(op);
		else
			op->call_error = -ENOTSUPP;

		if (op->call) {
			afs_wait_for_call_to_complete(op->call);
			op->call_abort_code = op->call->abort_code;
			op->call_error = op->call->error;
			op->call_responded = op->call->responded;
			afs_put_call(op->call);
		}
	}

	if (op->call_responded && op->server)
		set_bit(AFS_SERVER_FL_RESPONDING, &op->server->flags);

	if (!afs_op_error(op)) {
		_debug("success");
		op->ops->success(op);
	} else if (op->cumul_error.aborted) {
		if (op->ops->aborted)
			op->ops->aborted(op);
	} else {
		if (op->ops->failed)
			op->ops->failed(op);
	}

	afs_end_vnode_operation(op);

	if (!afs_op_error(op) && op->ops->edit_dir) {
		_debug("edit_dir");
		op->ops->edit_dir(op);
	}
	_leave("");
}

/*
 * Dispose of an operation.
 */
int afs_put_operation(struct afs_operation *op)
{
	struct afs_addr_list *alist;
	int i, ret = afs_op_error(op);

	_enter("op=%08x,%d", op->debug_id, ret);

	if (op->ops && op->ops->put)
		op->ops->put(op);
	if (op->file[0].modification)
		clear_bit(AFS_VNODE_MODIFYING, &op->file[0].vnode->flags);
	if (op->file[1].modification && op->file[1].vnode != op->file[0].vnode)
		clear_bit(AFS_VNODE_MODIFYING, &op->file[1].vnode->flags);
	if (op->file[0].put_vnode)
		iput(&op->file[0].vnode->netfs.inode);
	if (op->file[1].put_vnode)
		iput(&op->file[1].vnode->netfs.inode);

	if (op->more_files) {
		for (i = 0; i < op->nr_files - 2; i++)
			if (op->more_files[i].put_vnode)
				iput(&op->more_files[i].vnode->netfs.inode);
		kfree(op->more_files);
	}

	if (op->estate) {
		alist = op->estate->addresses;
		if (alist) {
			if (op->call_responded &&
			    op->addr_index != alist->preferred &&
			    test_bit(alist->preferred, &op->addr_tried))
				WRITE_ONCE(alist->preferred, op->addr_index);
		}
	}

	afs_clear_server_states(op);
	afs_put_serverlist(op->net, op->server_list);
	afs_put_volume(op->volume, afs_volume_trace_put_put_op);
	key_put(op->key);
	kfree(op);
	return ret;
}

int afs_do_sync_operation(struct afs_operation *op)
{
	afs_begin_vnode_operation(op);
	afs_wait_for_operation(op);
	return afs_put_operation(op);
}
