/*
 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/module.h>
#include <linux/backing-dev.h>
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/slab.h>
#include <linux/mempool.h>

#include "netfs.h"

static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi,
		u64 id, u64 start, u32 size, int type)
{
	struct inode *inode = &pi->vfs_inode;
	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
	struct netfs_trans *t;
	struct netfs_cmd *cmd;
	int path_len, err;
	void *data;
	struct netfs_lock *l;
	int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info);

	err = pohmelfs_path_length(pi);
	if (err < 0)
		goto err_out_exit;

	path_len = err;

	err = -ENOMEM;
	t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize,
			NETFS_TRANS_SINGLE_DST, 0);
	if (!t)
		goto err_out_exit;

	cmd = netfs_trans_current(t);
	data = cmd + 1;

	err = pohmelfs_construct_path_string(pi, data, path_len);
	if (err < 0)
		goto err_out_free;
	path_len = err;

	l = data + path_len;

	l->start = start;
	l->size = size;
	l->type = type;
	l->ino = pi->ino;

	cmd->cmd = NETFS_LOCK;
	cmd->start = 0;
	cmd->id = id;
	cmd->size = sizeof(struct netfs_lock) + path_len + isize;
	cmd->ext = path_len;
	cmd->csize = 0;

	netfs_convert_cmd(cmd);
	netfs_convert_lock(l);

	if (isize) {
		struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1);

		info->mode = inode->i_mode;
		info->nlink = inode->i_nlink;
		info->uid = inode->i_uid;
		info->gid = inode->i_gid;
		info->blocks = inode->i_blocks;
		info->rdev = inode->i_rdev;
		info->size = inode->i_size;
		info->version = inode->i_version;

		netfs_convert_inode_info(info);
	}

	netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize);

	return netfs_trans_finish(t, psb);

err_out_free:
	netfs_trans_free(t);
err_out_exit:
	printk("%s: err: %d.\n", __func__, err);
	return err;
}

int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
{
	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
	struct pohmelfs_mcache *m;
	int err = -ENOMEM;
	struct iattr iattr;
	struct inode *inode = &pi->vfs_inode;

	dprintk("%s: %p: ino: %llu, start: %llu, size: %u, "
			"type: %d, locked as: %d, owned: %d.\n",
			__func__, &pi->vfs_inode, pi->ino,
			start, size, type, pi->lock_type,
			!!test_bit(NETFS_INODE_OWNED, &pi->state));

	if (!pohmelfs_need_lock(pi, type))
		return 0;

	m = pohmelfs_mcache_alloc(psb, start, size, NULL);
	if (IS_ERR(m))
		return PTR_ERR(m);

	err = pohmelfs_send_lock_trans(pi, m->gen, start, size,
			type | POHMELFS_LOCK_GRAB);
	if (err)
		goto err_out_put;

	err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout);
	if (err)
		err = m->err;
	else
		err = -ETIMEDOUT;

	if (err) {
		printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n",
			__func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err);
	}

	if (err && (err != -ENOENT))
		goto err_out_put;

	if (!err) {
		netfs_convert_inode_info(&m->info);

		iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME;
		iattr.ia_mode = m->info.mode;
		iattr.ia_uid = m->info.uid;
		iattr.ia_gid = m->info.gid;
		iattr.ia_size = m->info.size;
		iattr.ia_atime = CURRENT_TIME;

		dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n",
			__func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size);

		err = pohmelfs_setattr_raw(inode, &iattr);
		if (!err) {
			struct dentry *dentry = d_find_alias(inode);
			if (dentry) {
				fsnotify_change(dentry, iattr.ia_valid);
				dput(dentry);
			}
		}
	}

	pi->lock_type = type;
	set_bit(NETFS_INODE_OWNED, &pi->state);

	pohmelfs_mcache_put(psb, m);

	return 0;

err_out_put:
	pohmelfs_mcache_put(psb, m);
	return err;
}

int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
{
	dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n",
			__func__, &pi->vfs_inode, pi->ino, start, size, type);
	pi->lock_type = 0;
	clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state);
	clear_bit(NETFS_INODE_OWNED, &pi->state);
	return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type);
}
