Beispiel #1
0
static 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 = 0;

	if (acl == NULL && (!S_ISDIR(inode->i_mode) || dfacl == NULL))
		goto out;

	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);
	}
Beispiel #2
0
/* GETACL */
static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
		struct nfsd3_getaclres *resp)
{
	struct dentry *dentry = resp->fh.fh_dentry;
	struct inode *inode;
	struct kvec *head = rqstp->rq_res.head;
	unsigned int base;
	int n;
	int w;

	/*
	 * Since this is version 2, the check for nfserr in
	 * nfsd_dispatch actually ensures the following cannot happen.
	 * However, it seems fragile to depend on that.
	 */
	if (dentry == NULL || dentry->d_inode == NULL)
		return 0;
	inode = dentry->d_inode;

	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
	*p++ = htonl(resp->mask);
	if (!xdr_ressize_check(rqstp, p))
		return 0;
	base = (char *)p - (char *)head->iov_base;

	rqstp->rq_res.page_len = w = nfsacl_size(
		(resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
		(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
	while (w > 0) {
		if (!rqstp->rq_respages[rqstp->rq_resused++])
			return 0;
		w -= PAGE_SIZE;
	}

	n = nfsacl_encode(&rqstp->rq_res, base, inode,
			  resp->acl_access,
			  resp->mask & NFS_ACL, 0);
	if (n > 0)
		n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
				  resp->acl_default,
				  resp->mask & NFS_DFACL,
				  NFS_ACL_DEFAULT);
	if (n <= 0)
		return 0;
	return 1;
}
Beispiel #3
0
/* GETACL */
static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
		struct nfsd3_getaclres *resp)
{
	struct dentry *dentry = resp->fh.fh_dentry;

	p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
	if (resp->status == 0 && dentry && dentry->d_inode) {
		struct inode *inode = dentry->d_inode;
		struct kvec *head = rqstp->rq_res.head;
		unsigned int base;
		int n;
		int w;

		*p++ = htonl(resp->mask);
		if (!xdr_ressize_check(rqstp, p))
			return 0;
		base = (char *)p - (char *)head->iov_base;

		rqstp->rq_res.page_len = w = nfsacl_size(
			(resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
			(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
		while (w > 0) {
			if (!rqstp->rq_respages[rqstp->rq_resused++])
				return 0;
			w -= PAGE_SIZE;
		}

		n = nfsacl_encode(&rqstp->rq_res, base, inode,
				  resp->acl_access,
				  resp->mask & NFS_ACL, 0);
		if (n > 0)
			n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
					  resp->acl_default,
					  resp->mask & NFS_DFACL,
					  NFS_ACL_DEFAULT);
		if (n <= 0)
			return 0;
	} else
		if (!xdr_ressize_check(rqstp, p))
			return 0;

	return 1;
}