/*
 * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
 * 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.
 */

#ifndef __COHERENCY_H
#define __COHERENCY_H

#include <linux/types.h>

#include <asm/byteorder.h>
#include <fs/pohmelfs/netfs.h>

#include "rbtree.h"
#include "list.h"

struct fserver_client;
struct fserver;
struct fserver_crypto_engine;
struct netfs_cmd;

struct coherency_user
{
	struct list_head	user_entry;

	struct fserver_client	*client;
	__u64			id, ino;
	int			intent;

	int			owner;
};

int coherency_remove_object(struct fserver_client *c, char *path, unsigned int len);
int coherency_add_object(struct fserver_client *c, char *path, unsigned int len, __u64 id, __u64 ino, int intent);
void coherency_remove_client_from_all_dirs(struct fserver_client *c);
int coherency_broadcast_hash(struct fserver *f, struct fserver_client *c, struct fserver_crypto_engine *e,
		unsigned int hash, unsigned int len, struct netfs_cmd *cmd,
		int (* callback)(struct coherency_user *u, struct netfs_cmd *cmd));

static inline int coherency_broadcast(struct fserver *f, struct fserver_client *c,
		struct fserver_crypto_engine *e, char *path,
		unsigned int len, struct netfs_cmd *cmd)
{
	return coherency_broadcast_hash(f, c, e, jhash(path, len, 0), len, cmd, NULL);
}

static inline int fserver_flush_writers_callback(struct coherency_user *u, struct netfs_cmd *cmd)
{
	int request_lock = cmd->ext & ~POHMELFS_LOCK_GRAB;

	if (request_lock == POHMELFS_WRITE_LOCK)
		goto out_send;
	if (u->intent == POHMELFS_WRITE_LOCK)
		goto out_send;

	return 1;

out_send:
	u->owner = 0;
	return 0;
}


#endif /* __COHERENCY_H */
