Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Sergey Bashirov and committed by
Chuck Lever
26d05e1c 48aab160

+73 -27
+12 -8
fs/nfsd/blocklayout.c
··· 178 178 { 179 179 struct iomap *iomaps; 180 180 int nr_iomaps; 181 + __be32 nfserr; 181 182 182 - nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout, 183 - lcp->lc_up_len, &iomaps, i_blocksize(inode)); 184 - if (nr_iomaps < 0) 185 - return nfserrno(nr_iomaps); 183 + nfserr = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout, 184 + lcp->lc_up_len, &iomaps, &nr_iomaps, 185 + i_blocksize(inode)); 186 + if (nfserr != nfs_ok) 187 + return nfserr; 186 188 187 189 return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps); 188 190 } ··· 318 316 { 319 317 struct iomap *iomaps; 320 318 int nr_iomaps; 319 + __be32 nfserr; 321 320 322 - nr_iomaps = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout, 323 - lcp->lc_up_len, &iomaps, i_blocksize(inode)); 324 - if (nr_iomaps < 0) 325 - return nfserrno(nr_iomaps); 321 + nfserr = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout, 322 + lcp->lc_up_len, &iomaps, &nr_iomaps, 323 + i_blocksize(inode)); 324 + if (nfserr != nfs_ok) 325 + return nfserr; 326 326 327 327 return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps); 328 328 }
+56 -15
fs/nfsd/blocklayoutxdr.c
··· 112 112 return 0; 113 113 } 114 114 115 - int 115 + /** 116 + * nfsd4_block_decode_layoutupdate - decode the block layout extent array 117 + * @p: pointer to the xdr data 118 + * @len: number of bytes to decode 119 + * @iomapp: pointer to store the decoded extent array 120 + * @nr_iomapsp: pointer to store the number of extents 121 + * @block_size: alignment of extent offset and length 122 + * 123 + * This function decodes the opaque field of the layoutupdate4 structure 124 + * in a layoutcommit request for the block layout driver. The field is 125 + * actually an array of extents sent by the client. It also checks that 126 + * the file offset, storage offset and length of each extent are aligned 127 + * by @block_size. 128 + * 129 + * Return values: 130 + * %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid 131 + * %nfserr_bad_xdr: The encoded array in @p is invalid 132 + * %nfserr_inval: An unaligned extent found 133 + * %nfserr_delay: Failed to allocate memory for @iomapp 134 + */ 135 + __be32 116 136 nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, 117 - u32 block_size) 137 + int *nr_iomapsp, u32 block_size) 118 138 { 119 139 struct iomap *iomaps; 120 140 u32 nr_iomaps, i; 121 141 122 142 if (len < sizeof(u32)) { 123 143 dprintk("%s: extent array too small: %u\n", __func__, len); 124 - return -EINVAL; 144 + return nfserr_bad_xdr; 125 145 } 126 146 len -= sizeof(u32); 127 147 if (len % PNFS_BLOCK_EXTENT_SIZE) { 128 148 dprintk("%s: extent array invalid: %u\n", __func__, len); 129 - return -EINVAL; 149 + return nfserr_bad_xdr; 130 150 } 131 151 132 152 nr_iomaps = be32_to_cpup(p++); 133 153 if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) { 134 154 dprintk("%s: extent array size mismatch: %u/%u\n", 135 155 __func__, len, nr_iomaps); 136 - return -EINVAL; 156 + return nfserr_bad_xdr; 137 157 } 138 158 139 159 iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL); 140 160 if (!iomaps) { 141 161 dprintk("%s: failed to allocate extent array\n", __func__); 142 - return -ENOMEM; 162 + return nfserr_delay; 143 163 } 144 164 145 165 for (i = 0; i < nr_iomaps; i++) { ··· 198 178 } 199 179 200 180 *iomapp = iomaps; 201 - return nr_iomaps; 181 + *nr_iomapsp = nr_iomaps; 182 + return nfs_ok; 202 183 fail: 203 184 kfree(iomaps); 204 - return -EINVAL; 185 + return nfserr_inval; 205 186 } 206 187 207 - int 188 + /** 189 + * nfsd4_scsi_decode_layoutupdate - decode the scsi layout extent array 190 + * @p: pointer to the xdr data 191 + * @len: number of bytes to decode 192 + * @iomapp: pointer to store the decoded extent array 193 + * @nr_iomapsp: pointer to store the number of extents 194 + * @block_size: alignment of extent offset and length 195 + * 196 + * This function decodes the opaque field of the layoutupdate4 structure 197 + * in a layoutcommit request for the scsi layout driver. The field is 198 + * actually an array of extents sent by the client. It also checks that 199 + * the offset and length of each extent are aligned by @block_size. 200 + * 201 + * Return values: 202 + * %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid 203 + * %nfserr_bad_xdr: The encoded array in @p is invalid 204 + * %nfserr_inval: An unaligned extent found 205 + * %nfserr_delay: Failed to allocate memory for @iomapp 206 + */ 207 + __be32 208 208 nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, 209 - u32 block_size) 209 + int *nr_iomapsp, u32 block_size) 210 210 { 211 211 struct iomap *iomaps; 212 212 u32 nr_iomaps, expected, i; 213 213 214 214 if (len < sizeof(u32)) { 215 215 dprintk("%s: extent array too small: %u\n", __func__, len); 216 - return -EINVAL; 216 + return nfserr_bad_xdr; 217 217 } 218 218 219 219 nr_iomaps = be32_to_cpup(p++); ··· 241 201 if (len != expected) { 242 202 dprintk("%s: extent array size mismatch: %u/%u\n", 243 203 __func__, len, expected); 244 - return -EINVAL; 204 + return nfserr_bad_xdr; 245 205 } 246 206 247 207 iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL); 248 208 if (!iomaps) { 249 209 dprintk("%s: failed to allocate extent array\n", __func__); 250 - return -ENOMEM; 210 + return nfserr_delay; 251 211 } 252 212 253 213 for (i = 0; i < nr_iomaps; i++) { ··· 269 229 } 270 230 271 231 *iomapp = iomaps; 272 - return nr_iomaps; 232 + *nr_iomapsp = nr_iomaps; 233 + return nfs_ok; 273 234 fail: 274 235 kfree(iomaps); 275 - return -EINVAL; 236 + return nfserr_inval; 276 237 }
+4 -4
fs/nfsd/blocklayoutxdr.h
··· 54 54 const struct nfsd4_getdeviceinfo *gdp); 55 55 __be32 nfsd4_block_encode_layoutget(struct xdr_stream *xdr, 56 56 const struct nfsd4_layoutget *lgp); 57 - int nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, 58 - u32 block_size); 59 - int nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, 60 - u32 block_size); 57 + __be32 nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, 58 + struct iomap **iomapp, int *nr_iomapsp, u32 block_size); 59 + __be32 nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, 60 + struct iomap **iomapp, int *nr_iomapsp, u32 block_size); 61 61 62 62 #endif /* _NFSD_BLOCKLAYOUTXDR_H */
+1
fs/nfsd/nfsd.h
··· 280 280 #define nfserr_cb_path_down cpu_to_be32(NFSERR_CB_PATH_DOWN) 281 281 #define nfserr_locked cpu_to_be32(NFSERR_LOCKED) 282 282 #define nfserr_wrongsec cpu_to_be32(NFSERR_WRONGSEC) 283 + #define nfserr_delay cpu_to_be32(NFS4ERR_DELAY) 283 284 #define nfserr_badiomode cpu_to_be32(NFS4ERR_BADIOMODE) 284 285 #define nfserr_badlayout cpu_to_be32(NFS4ERR_BADLAYOUT) 285 286 #define nfserr_bad_session_digest cpu_to_be32(NFS4ERR_BAD_SESSION_DIGEST)