/*
 *	Filesystem stub for filesystems implemented with user-level
 *	programs.
 *
 *	This file forms the definition of the protocol between the
 *	kernel and the user process through the file descriptors.
 *
 *	There are two file descriptors passed to the kernel as part
 *	of the args to mount().  One is for data from the kernel
 *	to the filesystem, the other from the filesystem to the
 *	kernel.  Control and data information are encoded along
 *	the same path.
 *
 *	The filesystem process never initiates any transaction - they
 *	are all generated by the kernel on the behalf of the other
 *	user processes using the filesystem.
 *
 *	The connction between the user process and the kernel is
 *	stateful, so if the connection breaks, Something Bad happens -
 *	I suppose it should be considered a umount - but what about
 *	outstanding writes?
 *
 *	For much the same reasons as nfs and dosfs, there can be no
 *	direct mapping from files, making exec() less memory and time
 *	efficient.  I don't see this as a big problem.
 *
 *	Jeremy Fitzhardinge 1993
 */

#ifndef _LINUX_USERFS_FS
#define _LINUX_USERFS_FS

/*
 * These operations map closely with the elements in the various
 * operations structures.
 *
 * Things are missing here, or overloaded.  Open does create, mknod and
 * mkdir.  Unlink can also do a rmdir.
 */
typedef enum
{
	up_create,	/*  0 create files, devices, dirs */
	up_lookup,	/*  1 path->file handle */
	up_close,	/*  2 close on fh */
	up_read,	/*  3 read from file */
	up_write,	/*  4 write to file */
	up_truncate,	/*  5 set file length */
	up_fsync,	/*  6 sync file */
	up_readdir,	/*  7 read dir entries */
	up_link,	/*  8 link files */
	up_unlink,	/*  9 unlink file */
	up_symlink,	/* 10 create symlink */
	up_readlink,	/* 11 read link contents */
	up_followlink,	/* 12 resolve path through link */
	up_mount,	/* 13 mount request */
	up_umount,	/* 14 unmount request */
	up_iread,	/* 15 get contents of inode for file */
	up_iwrite,	/* 16 set inode contents */
	up_statfs,	/* 17 stat filesystem wide things */
	up_iput,	/* 18 put an inode after finished */
	up_open,	/* 19 open of a file */
	up_permission,	/* 20 check file permissions */
	up_rename,	/* 21 rename file */
	up_multireaddir,	/* 22 read multiple dir entries */
	up_notify_change,	/* 23 notify inode changes */
} up_ops;

/* increment this when the structure shapes change */
#define UP_VERSION	17

/*
 * Max transfer size currently limited to largest allocatable
 * block.  There's also not much need to make it bigger.
 */
#define USERFS_MAX_XFER	(4080)

#ifdef __KERNEL__
#include <linux/param.h>	/* For NGROUPS */
#include <linux/userfs_types.h>

typedef unsigned char *(*encode_func)(const void *, unsigned char *);
typedef unsigned char *(*decode_func)(void *, unsigned char *);
typedef unsigned int (*sizeof_func)(const void *);

#define GEN_ENC(var)	(encode_func)(var)
#define GEN_DEC(var)	(decode_func)(var)
#define GEN_SIZ(var)	(sizeof_func)(var)

void userfs_genpkt(struct super_block *, up_preamble *, up_ops);

/* Encode and send request, receive and decode reply */
#define userfs_doop(sb, pre, repl, st, ss, rt, rs)\
	__userfs_doop(sb, pre, repl, \
		      GEN_ENC(encode_##st), (void *)ss, \
		      GEN_DEC(decode_##rt), (void *)rs, \
		      GEN_SIZ(sizeof_##st), GEN_SIZ(sizeof_##rt))

int __userfs_doop(struct super_block *, up_preamble *pre, upp_repl *repl, encode_func, void *, decode_func, void *, sizeof_func, sizeof_func);
#endif /* __KERNEL__ */

#endif /* _LINUX_USERFS_FS */
