mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 09:33:31 +02:00
nfsd: Use correct error code when decoding extents
Update error codes in decoding functions of block and scsi layout drivers to match the core nfsd code. NFS4ERR_EINVAL means that the server was able to decode the request, but the decoded values are invalid. Use NFS4ERR_BADXDR instead to indicate a decoding error. And ENOMEM is changed to nfs code NFS4ERR_DELAY. Signed-off-by: Sergey Bashirov <sergeybashirov@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
48aab1606f
commit
26d05e1c37
|
|
@ -178,11 +178,13 @@ nfsd4_block_proc_layoutcommit(struct inode *inode,
|
|||
{
|
||||
struct iomap *iomaps;
|
||||
int nr_iomaps;
|
||||
__be32 nfserr;
|
||||
|
||||
nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, i_blocksize(inode));
|
||||
if (nr_iomaps < 0)
|
||||
return nfserrno(nr_iomaps);
|
||||
nfserr = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, &nr_iomaps,
|
||||
i_blocksize(inode));
|
||||
if (nfserr != nfs_ok)
|
||||
return nfserr;
|
||||
|
||||
return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps);
|
||||
}
|
||||
|
|
@ -316,11 +318,13 @@ nfsd4_scsi_proc_layoutcommit(struct inode *inode,
|
|||
{
|
||||
struct iomap *iomaps;
|
||||
int nr_iomaps;
|
||||
__be32 nfserr;
|
||||
|
||||
nr_iomaps = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, i_blocksize(inode));
|
||||
if (nr_iomaps < 0)
|
||||
return nfserrno(nr_iomaps);
|
||||
nfserr = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, &nr_iomaps,
|
||||
i_blocksize(inode));
|
||||
if (nfserr != nfs_ok)
|
||||
return nfserr;
|
||||
|
||||
return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,34 +112,54 @@ nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
/**
|
||||
* nfsd4_block_decode_layoutupdate - decode the block layout extent array
|
||||
* @p: pointer to the xdr data
|
||||
* @len: number of bytes to decode
|
||||
* @iomapp: pointer to store the decoded extent array
|
||||
* @nr_iomapsp: pointer to store the number of extents
|
||||
* @block_size: alignment of extent offset and length
|
||||
*
|
||||
* This function decodes the opaque field of the layoutupdate4 structure
|
||||
* in a layoutcommit request for the block layout driver. The field is
|
||||
* actually an array of extents sent by the client. It also checks that
|
||||
* the file offset, storage offset and length of each extent are aligned
|
||||
* by @block_size.
|
||||
*
|
||||
* Return values:
|
||||
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
|
||||
* %nfserr_bad_xdr: The encoded array in @p is invalid
|
||||
* %nfserr_inval: An unaligned extent found
|
||||
* %nfserr_delay: Failed to allocate memory for @iomapp
|
||||
*/
|
||||
__be32
|
||||
nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size)
|
||||
int *nr_iomapsp, u32 block_size)
|
||||
{
|
||||
struct iomap *iomaps;
|
||||
u32 nr_iomaps, i;
|
||||
|
||||
if (len < sizeof(u32)) {
|
||||
dprintk("%s: extent array too small: %u\n", __func__, len);
|
||||
return -EINVAL;
|
||||
return nfserr_bad_xdr;
|
||||
}
|
||||
len -= sizeof(u32);
|
||||
if (len % PNFS_BLOCK_EXTENT_SIZE) {
|
||||
dprintk("%s: extent array invalid: %u\n", __func__, len);
|
||||
return -EINVAL;
|
||||
return nfserr_bad_xdr;
|
||||
}
|
||||
|
||||
nr_iomaps = be32_to_cpup(p++);
|
||||
if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) {
|
||||
dprintk("%s: extent array size mismatch: %u/%u\n",
|
||||
__func__, len, nr_iomaps);
|
||||
return -EINVAL;
|
||||
return nfserr_bad_xdr;
|
||||
}
|
||||
|
||||
iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL);
|
||||
if (!iomaps) {
|
||||
dprintk("%s: failed to allocate extent array\n", __func__);
|
||||
return -ENOMEM;
|
||||
return nfserr_delay;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_iomaps; i++) {
|
||||
|
|
@ -178,22 +198,42 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
|||
}
|
||||
|
||||
*iomapp = iomaps;
|
||||
return nr_iomaps;
|
||||
*nr_iomapsp = nr_iomaps;
|
||||
return nfs_ok;
|
||||
fail:
|
||||
kfree(iomaps);
|
||||
return -EINVAL;
|
||||
return nfserr_inval;
|
||||
}
|
||||
|
||||
int
|
||||
/**
|
||||
* nfsd4_scsi_decode_layoutupdate - decode the scsi layout extent array
|
||||
* @p: pointer to the xdr data
|
||||
* @len: number of bytes to decode
|
||||
* @iomapp: pointer to store the decoded extent array
|
||||
* @nr_iomapsp: pointer to store the number of extents
|
||||
* @block_size: alignment of extent offset and length
|
||||
*
|
||||
* This function decodes the opaque field of the layoutupdate4 structure
|
||||
* in a layoutcommit request for the scsi layout driver. The field is
|
||||
* actually an array of extents sent by the client. It also checks that
|
||||
* the offset and length of each extent are aligned by @block_size.
|
||||
*
|
||||
* Return values:
|
||||
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
|
||||
* %nfserr_bad_xdr: The encoded array in @p is invalid
|
||||
* %nfserr_inval: An unaligned extent found
|
||||
* %nfserr_delay: Failed to allocate memory for @iomapp
|
||||
*/
|
||||
__be32
|
||||
nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size)
|
||||
int *nr_iomapsp, u32 block_size)
|
||||
{
|
||||
struct iomap *iomaps;
|
||||
u32 nr_iomaps, expected, i;
|
||||
|
||||
if (len < sizeof(u32)) {
|
||||
dprintk("%s: extent array too small: %u\n", __func__, len);
|
||||
return -EINVAL;
|
||||
return nfserr_bad_xdr;
|
||||
}
|
||||
|
||||
nr_iomaps = be32_to_cpup(p++);
|
||||
|
|
@ -201,13 +241,13 @@ nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
|||
if (len != expected) {
|
||||
dprintk("%s: extent array size mismatch: %u/%u\n",
|
||||
__func__, len, expected);
|
||||
return -EINVAL;
|
||||
return nfserr_bad_xdr;
|
||||
}
|
||||
|
||||
iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL);
|
||||
if (!iomaps) {
|
||||
dprintk("%s: failed to allocate extent array\n", __func__);
|
||||
return -ENOMEM;
|
||||
return nfserr_delay;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_iomaps; i++) {
|
||||
|
|
@ -229,8 +269,9 @@ nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
|||
}
|
||||
|
||||
*iomapp = iomaps;
|
||||
return nr_iomaps;
|
||||
*nr_iomapsp = nr_iomaps;
|
||||
return nfs_ok;
|
||||
fail:
|
||||
kfree(iomaps);
|
||||
return -EINVAL;
|
||||
return nfserr_inval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ __be32 nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
|
|||
const struct nfsd4_getdeviceinfo *gdp);
|
||||
__be32 nfsd4_block_encode_layoutget(struct xdr_stream *xdr,
|
||||
const struct nfsd4_layoutget *lgp);
|
||||
int nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size);
|
||||
int nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size);
|
||||
__be32 nfsd4_block_decode_layoutupdate(__be32 *p, u32 len,
|
||||
struct iomap **iomapp, int *nr_iomapsp, u32 block_size);
|
||||
__be32 nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len,
|
||||
struct iomap **iomapp, int *nr_iomapsp, u32 block_size);
|
||||
|
||||
#endif /* _NFSD_BLOCKLAYOUTXDR_H */
|
||||
|
|
|
|||
|
|
@ -280,6 +280,7 @@ void nfsd_lockd_shutdown(void);
|
|||
#define nfserr_cb_path_down cpu_to_be32(NFSERR_CB_PATH_DOWN)
|
||||
#define nfserr_locked cpu_to_be32(NFSERR_LOCKED)
|
||||
#define nfserr_wrongsec cpu_to_be32(NFSERR_WRONGSEC)
|
||||
#define nfserr_delay cpu_to_be32(NFS4ERR_DELAY)
|
||||
#define nfserr_badiomode cpu_to_be32(NFS4ERR_BADIOMODE)
|
||||
#define nfserr_badlayout cpu_to_be32(NFS4ERR_BADLAYOUT)
|
||||
#define nfserr_bad_session_digest cpu_to_be32(NFS4ERR_BAD_SESSION_DIGEST)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user