NFSv4: include bitmap in nfsv4 get acl data

The NFSv4 bitmap size is unbounded: a server can return an arbitrary
sized bitmap in an FATTR4_WORD0_ACL request.  Replace using the
nfs4_fattr_bitmap_maxsz as a guess to the maximum bitmask returned by a server
with the inclusion of the bitmap (xdr length plus bitmasks) and the acl data
xdr length to the (cached) acl page data.

This is a general solution to commit e5012d1f "NFSv4.1: update
nfs4_fattr_bitmap_maxsz" and fixes hitting a BUG_ON in xdr_shrink_bufhead
when getting ACLs.

Fix a bug in decode_getacl that returned -EINVAL on ACLs > page when getxattr
was called with a NULL buffer, preventing ACL > PAGE_SIZE from being retrieved.

Cc: stable@kernel.org
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
static int decode_getdevicelist(struct xdr_stream *xdr,
				struct pnfs_devicelist *res)
{
	__be32 *p;
	int status, i;
	struct nfs_writeverf verftemp;

	status = decode_op_hdr(xdr, OP_GETDEVICELIST);
	if (status)
		return status;

	p = xdr_inline_decode(xdr, 8 + 8 + 4);
	if (unlikely(!p))
		goto out_overflow;

	/* TODO: Skip cookie for now */
	p += 2;

	/* Read verifier */
	p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8);

	res->num_devs = be32_to_cpup(p);

	dprintk("%s: num_dev %d\n", __func__, res->num_devs);

	if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) {
		printk(KERN_ERR "%s too many result dev_num %u\n",
				__func__, res->num_devs);
		return -EIO;
	}

	p = xdr_inline_decode(xdr,
			      res->num_devs * NFS4_DEVICEID4_SIZE + 4);
	if (unlikely(!p))
		goto out_overflow;
	for (i = 0; i < res->num_devs; i++)
		p = xdr_decode_opaque_fixed(p, res->dev_id[i].data,
					    NFS4_DEVICEID4_SIZE);
	res->eof = be32_to_cpup(p);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}

static int decode_getdevicelist(struct xdr_stream *xdr,
				struct pnfs_devicelist *res)
{
	__be32 *p;
	int status, i;
	struct nfs_writeverf verftemp;

	status = decode_op_hdr(xdr, OP_GETDEVICELIST);
	if (status)
		return status;

	p = xdr_inline_decode(xdr, 8 + 8 + 4);
	if (unlikely(!p))
		goto out_overflow;

	/* TODO: Skip cookie for now */
	p += 2;

	/* Read verifier */
	p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8);

	res->num_devs = be32_to_cpup(p);

	dprintk("%s: num_dev %d\n", __func__, res->num_devs);

	if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) {
		printk(KERN_ERR "%s too many result dev_num %u\n",
				__func__, res->num_devs);
		return -EIO;
	}

	p = xdr_inline_decode(xdr,
			      res->num_devs * NFS4_DEVICEID4_SIZE + 4);
	if (unlikely(!p))
		goto out_overflow;
	for (i = 0; i < res->num_devs; i++)
		p = xdr_decode_opaque_fixed(p, res->dev_id[i].data,
					    NFS4_DEVICEID4_SIZE);
	res->eof = be32_to_cpup(p);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}
