@@ -4452,85 +4452,83 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr,
44524452 return nfserr ;
44534453}
44544454
4455- static __be32
4456- nfsd4_encode_readdir ( struct nfsd4_compoundres * resp , __be32 nfserr ,
4457- union nfsd4_op_u * u )
4455+ static __be32 nfsd4_encode_dirlist4 ( struct xdr_stream * xdr ,
4456+ struct nfsd4_readdir * readdir ,
4457+ u32 max_payload )
44584458{
4459- struct nfsd4_readdir * readdir = & u -> readdir ;
4460- int maxcount ;
4461- int bytes_left ;
4459+ int bytes_left , maxcount , starting_len = xdr -> buf -> len ;
44624460 loff_t offset ;
4463- struct xdr_stream * xdr = resp -> xdr ;
4464- int starting_len = xdr -> buf -> len ;
4465- __be32 * p ;
4466-
4467- nfserr = nfsd4_encode_verifier4 (xdr , & readdir -> rd_verf );
4468- if (nfserr != nfs_ok )
4469- return nfserr ;
4461+ __be32 status ;
44704462
44714463 /*
44724464 * Number of bytes left for directory entries allowing for the
4473- * final 8 bytes of the readdir and a following failed op:
4465+ * final 8 bytes of the readdir and a following failed op.
44744466 */
4475- bytes_left = xdr -> buf -> buflen - xdr -> buf -> len
4476- - COMPOUND_ERR_SLACK_SPACE - 8 ;
4477- if (bytes_left < 0 ) {
4478- nfserr = nfserr_resource ;
4479- goto err_no_verf ;
4480- }
4481- maxcount = svc_max_payload (resp -> rqstp );
4482- maxcount = min_t (u32 , readdir -> rd_maxcount , maxcount );
4467+ bytes_left = xdr -> buf -> buflen - xdr -> buf -> len -
4468+ COMPOUND_ERR_SLACK_SPACE - XDR_UNIT * 2 ;
4469+ if (bytes_left < 0 )
4470+ return nfserr_resource ;
4471+ maxcount = min_t (u32 , readdir -> rd_maxcount , max_payload );
4472+
44834473 /*
4484- * Note the rfc defines rd_maxcount as the size of the
4485- * READDIR4resok structure, which includes the verifier above
4486- * and the 8 bytes encoded at the end of this function:
4474+ * The RFC defines rd_maxcount as the size of the
4475+ * READDIR4resok structure, which includes the verifier
4476+ * and the 8 bytes encoded at the end of this function.
44874477 */
4488- if (maxcount < 16 ) {
4489- nfserr = nfserr_toosmall ;
4490- goto err_no_verf ;
4491- }
4492- maxcount = min_t (int , maxcount - 16 , bytes_left );
4478+ if (maxcount < XDR_UNIT * 4 )
4479+ return nfserr_toosmall ;
4480+ maxcount = min_t (int , maxcount - XDR_UNIT * 4 , bytes_left );
44934481
4494- /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */
4482+ /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0 */
44954483 if (!readdir -> rd_dircount )
4496- readdir -> rd_dircount = svc_max_payload ( resp -> rqstp ) ;
4484+ readdir -> rd_dircount = max_payload ;
44974485
4486+ /* *entries */
44984487 readdir -> xdr = xdr ;
44994488 readdir -> rd_maxcount = maxcount ;
45004489 readdir -> common .err = 0 ;
45014490 readdir -> cookie_offset = 0 ;
4502-
45034491 offset = readdir -> rd_cookie ;
4504- nfserr = nfsd_readdir (readdir -> rd_rqstp , readdir -> rd_fhp , & offset ,
4492+ status = nfsd_readdir (readdir -> rd_rqstp , readdir -> rd_fhp , & offset ,
45054493 & readdir -> common , nfsd4_encode_entry4 );
4506- if (nfserr == nfs_ok &&
4507- readdir -> common . err == nfserr_toosmall &&
4508- xdr -> buf -> len == starting_len + 8 ) {
4509- /* nothing encoded; which limit did we hit?: */
4510- if ( maxcount - 16 < bytes_left )
4511- /* It was the fault of rd_maxcount: */
4512- nfserr = nfserr_toosmall ;
4513- else
4514- /* We ran out of buffer space: */
4515- nfserr = nfserr_resource ;
4494+ if (status )
4495+ return status ;
4496+ if ( readdir -> common . err == nfserr_toosmall &&
4497+ xdr -> buf -> len == starting_len ) {
4498+ /* No entries were encoded. Which limit did we hit? */
4499+ if ( maxcount - XDR_UNIT * 4 < bytes_left )
4500+ /* It was the fault of rd_maxcount */
4501+ return nfserr_toosmall ;
4502+ /* We ran out of buffer space */
4503+ return nfserr_resource ;
45164504 }
4517- if (nfserr )
4518- goto err_no_verf ;
4519-
45204505 /* Encode the final entry's cookie value */
45214506 nfsd4_encode_entry4_nfs_cookie4 (readdir , offset );
4507+ /* No entries follow */
4508+ if (xdr_stream_encode_item_absent (xdr ) != XDR_UNIT )
4509+ return nfserr_resource ;
45224510
4523- p = xdr_reserve_space (xdr , 8 );
4524- if (!p ) {
4525- WARN_ON_ONCE (1 );
4526- goto err_no_verf ;
4527- }
4528- * p ++ = 0 ; /* no more entries */
4529- * p ++ = htonl (readdir -> common .err == nfserr_eof );
4511+ /* eof */
4512+ return nfsd4_encode_bool (xdr , readdir -> common .err == nfserr_eof );
4513+ }
45304514
4531- return 0 ;
4532- err_no_verf :
4533- xdr_truncate_encode (xdr , starting_len );
4515+ static __be32
4516+ nfsd4_encode_readdir (struct nfsd4_compoundres * resp , __be32 nfserr ,
4517+ union nfsd4_op_u * u )
4518+ {
4519+ struct nfsd4_readdir * readdir = & u -> readdir ;
4520+ struct xdr_stream * xdr = resp -> xdr ;
4521+ int starting_len = xdr -> buf -> len ;
4522+
4523+ /* cookieverf */
4524+ nfserr = nfsd4_encode_verifier4 (xdr , & readdir -> rd_verf );
4525+ if (nfserr != nfs_ok )
4526+ return nfserr ;
4527+
4528+ /* reply */
4529+ nfserr = nfsd4_encode_dirlist4 (xdr , readdir , svc_max_payload (resp -> rqstp ));
4530+ if (nfserr != nfs_ok )
4531+ xdr_truncate_encode (xdr , starting_len );
45344532 return nfserr ;
45354533}
45364534
0 commit comments