#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/nfs.h>
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
#include <linux/posix_acl_xattr.h>
#include <linux/nfsacl.h>

#include "internal.h"

#define NFSDBG_FACILITY	NFSDBG_PROC

struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct page *pages[NFSACL_MAXPAGES] = { };
	struct nfs3_getaclargs args = {
		.fh = NFS_FH(inode),
		/* The xdr layer may allocate pages here. */
		.pages = pages,
	};
	struct nfs3_getaclres res = {
		NULL,
	};
	struct rpc_message msg = {
		.rpc_argp	= &args,
		.rpc_resp	= &res,
	};
	int status, count;

	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
		return ERR_PTR(-EOPNOTSUPP);

	status = nfs_revalidate_inode(server, inode);
	if (status < 0)
		return ERR_PTR(status);

	/*
	 * Only get the access acl when explicitly requested: We don't
	 * need it for access decisions, and only some applications use
	 * it. Applications which request the access acl first are not
	 * penalized from this optimization.
	 */
	if (type == ACL_TYPE_ACCESS)
		args.mask |= NFS_ACLCNT|NFS_ACL;
	if (S_ISDIR(inode->i_mode))
		args.mask |= NFS_DFACLCNT|NFS_DFACL;
	if (args.mask == 0)
		return NULL;

	dprintk("NFS call getacl\n");
	msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL];
	res.fattr = nfs_alloc_fattr();
	if (res.fattr == NULL)
		return ERR_PTR(-ENOMEM);

	status = rpc_call_sync(server->client_acl, &msg, 0);
	dprintk("NFS reply getacl: %d\n", status);

	/* pages may have been allocated at the xdr layer. */
	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
		__free_page(args.pages[count]);

	switch (status) {
		case 0:
			status = nfs_refresh_inode(inode, res.fattr);
			break;
		case -EPFNOSUPPORT:
		case -EPROTONOSUPPORT:
			dprintk("NFS_V3_ACL extension not supported; disabling\n");
			server->caps &= ~NFS_CAP_ACLS;
		case -ENOTSUPP:
			status = -EOPNOTSUPP;
		default:
			goto getout;
	}
	if ((args.mask & res.mask) != args.mask) {
		status = -EIO;
		goto getout;
	}

	if (res.acl_access != NULL) {
		if (posix_acl_equiv_mode(res.acl_access, NULL) ||
		    res.acl_access->a_count == 0) {
			posix_acl_release(res.acl_access);
			res.acl_access = NULL;
		}
	}

	if (res.mask & NFS_ACL)
		set_cached_acl(inode, ACL_TYPE_ACCESS, res.acl_access);
	else
		forget_cached_acl(inode, ACL_TYPE_ACCESS);

	if (res.mask & NFS_DFACL)
		set_cached_acl(inode, ACL_TYPE_DEFAULT, res.acl_default);
	else
		forget_cached_acl(inode, ACL_TYPE_DEFAULT);

	nfs_free_fattr(res.fattr);
	if (type == ACL_TYPE_ACCESS) {
		posix_acl_release(res.acl_default);
		return res.acl_access;
	} else {
		posix_acl_release(res.acl_access);
		return res.acl_default;
	}

getout:
	posix_acl_release(res.acl_access);
	posix_acl_release(res.acl_default);
	nfs_free_fattr(res.fattr);
	return ERR_PTR(status);
}

int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
		struct posix_acl *dfacl)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs_fattr *fattr;
	struct page *pages[NFSACL_MAXPAGES];
	struct nfs3_setaclargs args = {
		.inode = inode,
		.mask = NFS_ACL,
		.acl_access = acl,
		.pages = pages,
	};
	struct rpc_message msg = {
		.rpc_argp	= &args,
		.rpc_resp	= &fattr,
	};
	int status;

	status = -EOPNOTSUPP;
	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
		goto out;

	/* We are doing this here because XDR marshalling does not
	 * return any results, it BUGs. */
	status = -ENOSPC;
	if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
		goto out;
	if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES)
		goto out;
	if (S_ISDIR(inode->i_mode)) {
		args.mask |= NFS_DFACL;
		args.acl_default = dfacl;
		args.len = nfsacl_size(acl, dfacl);
	} else
		args.len = nfsacl_size(acl, NULL);

	if (args.len > NFS_ACL_INLINE_BUFSIZE) {
		unsigned int npages = 1 + ((args.len - 1) >> PAGE_SHIFT);

		status = -ENOMEM;
		do {
			args.pages[args.npages] = alloc_page(GFP_KERNEL);
			if (args.pages[args.npages] == NULL)
				goto out_freepages;
			args.npages++;
		} while (args.npages < npages);
	}

	dprintk("NFS call setacl\n");
	status = -ENOMEM;
	fattr = nfs_alloc_fattr();
	if (fattr == NULL)
		goto out_freepages;

	msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL];
	msg.rpc_resp = fattr;
	status = rpc_call_sync(server->client_acl, &msg, 0);
	nfs_access_zap_cache(inode);
	nfs_zap_acl_cache(inode);
	dprintk("NFS reply setacl: %d\n", status);

	switch (status) {
		case 0:
			status = nfs_refresh_inode(inode, fattr);
			set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
			set_cached_acl(inode, ACL_TYPE_DEFAULT, dfacl);
			break;
		case -EPFNOSUPPORT:
		case -EPROTONOSUPPORT:
			dprintk("NFS_V3_ACL SETACL RPC not supported"
					"(will not retry)\n");
			server->caps &= ~NFS_CAP_ACLS;
		case -ENOTSUPP:
			status = -EOPNOTSUPP;
	}
	nfs_free_fattr(fattr);
out_freepages:
	while (args.npages != 0) {
		args.npages--;
		__free_page(args.pages[args.npages]);
	}
out:
	return status;
}

int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	struct posix_acl *alloc = NULL, *dfacl = NULL;
	int status;

	if (S_ISDIR(inode->i_mode)) {
		switch(type) {
		case ACL_TYPE_ACCESS:
			alloc = dfacl = get_acl(inode, ACL_TYPE_DEFAULT);
			if (IS_ERR(alloc))
				goto fail;
			break;

		case ACL_TYPE_DEFAULT:
			dfacl = acl;
			alloc = acl = get_acl(inode, ACL_TYPE_ACCESS);
			if (IS_ERR(alloc))
				goto fail;
			break;
		}
	}

	if (acl == NULL) {
		alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
		if (IS_ERR(alloc))
			goto fail;
	}
	status = nfs3_proc_setacls(inode, acl, dfacl);
	posix_acl_release(alloc);
	return status;

fail:
	return PTR_ERR(alloc);
}

int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
		umode_t mode)
{
	struct posix_acl *default_acl, *acl;
	int error;

	error = posix_acl_create(dir, &mode, &default_acl, &acl);
	if (error)
		return (error == -EOPNOTSUPP) ? 0 : error;

	error = nfs3_proc_setacls(inode, acl, default_acl);

	if (acl)
		posix_acl_release(acl);
	if (default_acl)
		posix_acl_release(default_acl);
	return error;
}

const struct xattr_handler *nfs3_xattr_handlers[] = {
	&posix_acl_access_xattr_handler,
	&posix_acl_default_xattr_handler,
	NULL,
};
