@@ -112,34 +112,54 @@ nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
112112 return 0 ;
113113}
114114
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
116136nfsd4_block_decode_layoutupdate (__be32 * p , u32 len , struct iomap * * iomapp ,
117- u32 block_size )
137+ int * nr_iomapsp , u32 block_size )
118138{
119139 struct iomap * iomaps ;
120140 u32 nr_iomaps , i ;
121141
122142 if (len < sizeof (u32 )) {
123143 dprintk ("%s: extent array too small: %u\n" , __func__ , len );
124- return - EINVAL ;
144+ return nfserr_bad_xdr ;
125145 }
126146 len -= sizeof (u32 );
127147 if (len % PNFS_BLOCK_EXTENT_SIZE ) {
128148 dprintk ("%s: extent array invalid: %u\n" , __func__ , len );
129- return - EINVAL ;
149+ return nfserr_bad_xdr ;
130150 }
131151
132152 nr_iomaps = be32_to_cpup (p ++ );
133153 if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE ) {
134154 dprintk ("%s: extent array size mismatch: %u/%u\n" ,
135155 __func__ , len , nr_iomaps );
136- return - EINVAL ;
156+ return nfserr_bad_xdr ;
137157 }
138158
139159 iomaps = kcalloc (nr_iomaps , sizeof (* iomaps ), GFP_KERNEL );
140160 if (!iomaps ) {
141161 dprintk ("%s: failed to allocate extent array\n" , __func__ );
142- return - ENOMEM ;
162+ return nfserr_delay ;
143163 }
144164
145165 for (i = 0 ; i < nr_iomaps ; i ++ ) {
@@ -178,36 +198,56 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
178198 }
179199
180200 * iomapp = iomaps ;
181- return nr_iomaps ;
201+ * nr_iomapsp = nr_iomaps ;
202+ return nfs_ok ;
182203fail :
183204 kfree (iomaps );
184- return - EINVAL ;
205+ return nfserr_inval ;
185206}
186207
187- int
208+ /**
209+ * nfsd4_scsi_decode_layoutupdate - decode the scsi layout extent array
210+ * @p: pointer to the xdr data
211+ * @len: number of bytes to decode
212+ * @iomapp: pointer to store the decoded extent array
213+ * @nr_iomapsp: pointer to store the number of extents
214+ * @block_size: alignment of extent offset and length
215+ *
216+ * This function decodes the opaque field of the layoutupdate4 structure
217+ * in a layoutcommit request for the scsi layout driver. The field is
218+ * actually an array of extents sent by the client. It also checks that
219+ * the offset and length of each extent are aligned by @block_size.
220+ *
221+ * Return values:
222+ * %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
223+ * %nfserr_bad_xdr: The encoded array in @p is invalid
224+ * %nfserr_inval: An unaligned extent found
225+ * %nfserr_delay: Failed to allocate memory for @iomapp
226+ */
227+ __be32
188228nfsd4_scsi_decode_layoutupdate (__be32 * p , u32 len , struct iomap * * iomapp ,
189- u32 block_size )
229+ int * nr_iomapsp , u32 block_size )
190230{
191231 struct iomap * iomaps ;
192232 u32 nr_iomaps , expected , i ;
193233
194234 if (len < sizeof (u32 )) {
195235 dprintk ("%s: extent array too small: %u\n" , __func__ , len );
196- return - EINVAL ;
236+ return nfserr_bad_xdr ;
197237 }
198238
199239 nr_iomaps = be32_to_cpup (p ++ );
200240 expected = sizeof (__be32 ) + nr_iomaps * PNFS_SCSI_RANGE_SIZE ;
201241 if (len != expected ) {
202242 dprintk ("%s: extent array size mismatch: %u/%u\n" ,
203243 __func__ , len , expected );
204- return - EINVAL ;
244+ return nfserr_bad_xdr ;
205245 }
206246
207247 iomaps = kcalloc (nr_iomaps , sizeof (* iomaps ), GFP_KERNEL );
208248 if (!iomaps ) {
209249 dprintk ("%s: failed to allocate extent array\n" , __func__ );
210- return - ENOMEM ;
250+ return nfserr_delay ;
211251 }
212252
213253 for (i = 0 ; i < nr_iomaps ; i ++ ) {
@@ -229,8 +269,9 @@ nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
229269 }
230270
231271 * iomapp = iomaps ;
232- return nr_iomaps ;
272+ * nr_iomapsp = nr_iomaps ;
273+ return nfs_ok ;
233274fail :
234275 kfree (iomaps );
235- return - EINVAL ;
276+ return nfserr_inval ;
236277}
0 commit comments