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

NFSD: Hoist status code encoding into XDR encoder functions

The original intent was presumably to reduce code duplication. The
trade-off was:

- No support for an NFSD proc function returning a non-success
RPC accept_stat value.
- No support for void NFS replies to non-NULL procedures.
- Everyone pays for the deduplication with a few extra conditional
branches in a hot path.

In addition, nfsd_dispatch() leaves *statp uninitialized in the
success path, unlike svc_generic_dispatch().

Address all of these problems by moving the logic for encoding
the NFS status code into the NFS XDR encoders themselves. Then
update the NFS .pc_func methods to return an RPC accept_stat
value.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Chuck Lever and committed by
J. Bruce Fields
cc028a10 4b74fd79

+145 -120
+12 -7
fs/nfsd/nfs2acl.c
··· 21 21 static __be32 22 22 nfsacld_proc_null(struct svc_rqst *rqstp) 23 23 { 24 - return nfs_ok; 24 + return rpc_success; 25 25 } 26 26 27 27 /* ··· 79 79 80 80 /* resp->acl_{access,default} are released in nfssvc_release_getacl. */ 81 81 out: 82 - return resp->status; 82 + return rpc_success; 83 83 84 84 fail: 85 85 posix_acl_release(resp->acl_access); ··· 131 131 nfssvc_decode_setaclargs. */ 132 132 posix_acl_release(argp->acl_access); 133 133 posix_acl_release(argp->acl_default); 134 - return resp->status; 134 + return rpc_success; 135 135 136 136 out_drop_lock: 137 137 fh_unlock(fh); ··· 157 157 goto out; 158 158 resp->status = fh_getattr(&resp->fh, &resp->stat); 159 159 out: 160 - return resp->status; 160 + return rpc_success; 161 161 } 162 162 163 163 /* ··· 179 179 goto out; 180 180 resp->status = fh_getattr(&resp->fh, &resp->stat); 181 181 out: 182 - return resp->status; 182 + return rpc_success; 183 183 } 184 184 185 185 /* ··· 275 275 int n; 276 276 int w; 277 277 278 + *p++ = resp->status; 278 279 if (resp->status != nfs_ok) 279 280 return xdr_ressize_check(rqstp, p); 280 281 ··· 318 317 { 319 318 struct nfsd_attrstat *resp = rqstp->rq_resp; 320 319 320 + *p++ = resp->status; 321 321 if (resp->status != nfs_ok) 322 - return xdr_ressize_check(rqstp, p); 322 + goto out; 323 323 324 324 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat); 325 + out: 325 326 return xdr_ressize_check(rqstp, p); 326 327 } 327 328 ··· 332 329 { 333 330 struct nfsd3_accessres *resp = rqstp->rq_resp; 334 331 332 + *p++ = resp->status; 335 333 if (resp->status != nfs_ok) 336 - return xdr_ressize_check(rqstp, p); 334 + goto out; 337 335 338 336 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat); 339 337 *p++ = htonl(resp->access); 338 + out: 340 339 return xdr_ressize_check(rqstp, p); 341 340 } 342 341
+5 -4
fs/nfsd/nfs3acl.c
··· 19 19 static __be32 20 20 nfsd3_proc_null(struct svc_rqst *rqstp) 21 21 { 22 - return nfs_ok; 22 + return rpc_success; 23 23 } 24 24 25 25 /* ··· 71 71 72 72 /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */ 73 73 out: 74 - return resp->status; 74 + return rpc_success; 75 75 76 76 fail: 77 77 posix_acl_release(resp->acl_access); ··· 118 118 nfs3svc_decode_setaclargs. */ 119 119 posix_acl_release(argp->acl_access); 120 120 posix_acl_release(argp->acl_default); 121 - return resp->status; 121 + return rpc_success; 122 122 } 123 123 124 124 /* ··· 173 173 struct nfsd3_getaclres *resp = rqstp->rq_resp; 174 174 struct dentry *dentry = resp->fh.fh_dentry; 175 175 176 + *p++ = resp->status; 176 177 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); 177 178 if (resp->status == 0 && dentry && d_really_is_positive(dentry)) { 178 179 struct inode *inode = d_inode(dentry); ··· 218 217 { 219 218 struct nfsd3_attrstat *resp = rqstp->rq_resp; 220 219 220 + *p++ = resp->status; 221 221 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); 222 - 223 222 return xdr_ressize_check(rqstp, p); 224 223 } 225 224
+22 -22
fs/nfsd/nfs3proc.c
··· 32 32 static __be32 33 33 nfsd3_proc_null(struct svc_rqst *rqstp) 34 34 { 35 - return nfs_ok; 35 + return rpc_success; 36 36 } 37 37 38 38 /* ··· 55 55 56 56 resp->status = fh_getattr(&resp->fh, &resp->stat); 57 57 out: 58 - return resp->status; 58 + return rpc_success; 59 59 } 60 60 61 61 /* ··· 73 73 fh_copy(&resp->fh, &argp->fh); 74 74 resp->status = nfsd_setattr(rqstp, &resp->fh, &argp->attrs, 75 75 argp->check_guard, argp->guardtime); 76 - return resp->status; 76 + return rpc_success; 77 77 } 78 78 79 79 /* ··· 96 96 resp->status = nfsd_lookup(rqstp, &resp->dirfh, 97 97 argp->name, argp->len, 98 98 &resp->fh); 99 - return resp->status; 99 + return rpc_success; 100 100 } 101 101 102 102 /* ··· 115 115 fh_copy(&resp->fh, &argp->fh); 116 116 resp->access = argp->access; 117 117 resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); 118 - return resp->status; 118 + return rpc_success; 119 119 } 120 120 121 121 /* ··· 133 133 fh_copy(&resp->fh, &argp->fh); 134 134 resp->len = NFS3_MAXPATHLEN; 135 135 resp->status = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len); 136 - return resp->status; 136 + return rpc_success; 137 137 } 138 138 139 139 /* ··· 163 163 resp->status = nfsd_read(rqstp, &resp->fh, argp->offset, 164 164 rqstp->rq_vec, argp->vlen, &resp->count, 165 165 &resp->eof); 166 - return resp->status; 166 + return rpc_success; 167 167 } 168 168 169 169 /* ··· 196 196 resp->committed, resp->verf); 197 197 resp->count = cnt; 198 198 out: 199 - return resp->status; 199 + return rpc_success; 200 200 } 201 201 202 202 /* ··· 234 234 resp->status = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, 235 235 attr, newfhp, argp->createmode, 236 236 (u32 *)argp->verf, NULL, NULL); 237 - return resp->status; 237 + return rpc_success; 238 238 } 239 239 240 240 /* ··· 257 257 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, 258 258 &argp->attrs, S_IFDIR, 0, &resp->fh); 259 259 fh_unlock(&resp->dirfh); 260 - return resp->status; 260 + return rpc_success; 261 261 } 262 262 263 263 static __be32 ··· 294 294 argp->flen, argp->tname, &resp->fh); 295 295 kfree(argp->tname); 296 296 out: 297 - return resp->status; 297 + return rpc_success; 298 298 } 299 299 300 300 /* ··· 337 337 &argp->attrs, type, rdev, &resp->fh); 338 338 fh_unlock(&resp->dirfh); 339 339 out: 340 - return resp->status; 340 + return rpc_success; 341 341 } 342 342 343 343 /* ··· 359 359 resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, 360 360 argp->name, argp->len); 361 361 fh_unlock(&resp->fh); 362 - return resp->status; 362 + return rpc_success; 363 363 } 364 364 365 365 /* ··· 380 380 resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, 381 381 argp->name, argp->len); 382 382 fh_unlock(&resp->fh); 383 - return resp->status; 383 + return rpc_success; 384 384 } 385 385 386 386 static __be32 ··· 402 402 fh_copy(&resp->tfh, &argp->tfh); 403 403 resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen, 404 404 &resp->tfh, argp->tname, argp->tlen); 405 - return resp->status; 405 + return rpc_success; 406 406 } 407 407 408 408 static __be32 ··· 422 422 fh_copy(&resp->tfh, &argp->tfh); 423 423 resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen, 424 424 &resp->fh); 425 - return resp->status; 425 + return rpc_success; 426 426 } 427 427 428 428 /* ··· 481 481 resp->offset = NULL; 482 482 } 483 483 484 - return resp->status; 484 + return rpc_success; 485 485 } 486 486 487 487 /* ··· 551 551 } 552 552 553 553 out: 554 - return resp->status; 554 + return rpc_success; 555 555 } 556 556 557 557 /* ··· 568 568 569 569 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0); 570 570 fh_put(&argp->fh); 571 - return resp->status; 571 + return rpc_success; 572 572 } 573 573 574 574 /* ··· 611 611 } 612 612 613 613 fh_put(&argp->fh); 614 - return resp->status; 614 + return rpc_success; 615 615 } 616 616 617 617 /* ··· 653 653 } 654 654 655 655 fh_put(&argp->fh); 656 - return resp->status; 656 + return rpc_success; 657 657 } 658 658 659 659 /* ··· 679 679 resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset, 680 680 argp->count, resp->verf); 681 681 out: 682 - return resp->status; 682 + return rpc_success; 683 683 } 684 684 685 685
+15 -4
fs/nfsd/nfs3xdr.c
··· 641 641 /* 642 642 * XDR encode functions 643 643 */ 644 - /* 645 - * There must be an encoding function for void results so svc_process 646 - * will work properly. 647 - */ 644 + 648 645 int 649 646 nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) 650 647 { ··· 654 657 { 655 658 struct nfsd3_attrstat *resp = rqstp->rq_resp; 656 659 660 + *p++ = resp->status; 657 661 if (resp->status == 0) { 658 662 lease_get_mtime(d_inode(resp->fh.fh_dentry), 659 663 &resp->stat.mtime); ··· 669 671 { 670 672 struct nfsd3_attrstat *resp = rqstp->rq_resp; 671 673 674 + *p++ = resp->status; 672 675 p = encode_wcc_data(rqstp, p, &resp->fh); 673 676 return xdr_ressize_check(rqstp, p); 674 677 } ··· 680 681 { 681 682 struct nfsd3_diropres *resp = rqstp->rq_resp; 682 683 684 + *p++ = resp->status; 683 685 if (resp->status == 0) { 684 686 p = encode_fh(p, &resp->fh); 685 687 p = encode_post_op_attr(rqstp, p, &resp->fh); ··· 695 695 { 696 696 struct nfsd3_accessres *resp = rqstp->rq_resp; 697 697 698 + *p++ = resp->status; 698 699 p = encode_post_op_attr(rqstp, p, &resp->fh); 699 700 if (resp->status == 0) 700 701 *p++ = htonl(resp->access); ··· 708 707 { 709 708 struct nfsd3_readlinkres *resp = rqstp->rq_resp; 710 709 710 + *p++ = resp->status; 711 711 p = encode_post_op_attr(rqstp, p, &resp->fh); 712 712 if (resp->status == 0) { 713 713 *p++ = htonl(resp->len); ··· 731 729 { 732 730 struct nfsd3_readres *resp = rqstp->rq_resp; 733 731 732 + *p++ = resp->status; 734 733 p = encode_post_op_attr(rqstp, p, &resp->fh); 735 734 if (resp->status == 0) { 736 735 *p++ = htonl(resp->count); ··· 757 754 { 758 755 struct nfsd3_writeres *resp = rqstp->rq_resp; 759 756 757 + *p++ = resp->status; 760 758 p = encode_wcc_data(rqstp, p, &resp->fh); 761 759 if (resp->status == 0) { 762 760 *p++ = htonl(resp->count); ··· 774 770 { 775 771 struct nfsd3_diropres *resp = rqstp->rq_resp; 776 772 773 + *p++ = resp->status; 777 774 if (resp->status == 0) { 778 775 *p++ = xdr_one; 779 776 p = encode_fh(p, &resp->fh); ··· 790 785 { 791 786 struct nfsd3_renameres *resp = rqstp->rq_resp; 792 787 788 + *p++ = resp->status; 793 789 p = encode_wcc_data(rqstp, p, &resp->ffh); 794 790 p = encode_wcc_data(rqstp, p, &resp->tfh); 795 791 return xdr_ressize_check(rqstp, p); ··· 802 796 { 803 797 struct nfsd3_linkres *resp = rqstp->rq_resp; 804 798 799 + *p++ = resp->status; 805 800 p = encode_post_op_attr(rqstp, p, &resp->fh); 806 801 p = encode_wcc_data(rqstp, p, &resp->tfh); 807 802 return xdr_ressize_check(rqstp, p); ··· 814 807 { 815 808 struct nfsd3_readdirres *resp = rqstp->rq_resp; 816 809 810 + *p++ = resp->status; 817 811 p = encode_post_op_attr(rqstp, p, &resp->fh); 818 812 819 813 if (resp->status == 0) { ··· 1067 1059 struct kstatfs *s = &resp->stats; 1068 1060 u64 bs = s->f_bsize; 1069 1061 1062 + *p++ = resp->status; 1070 1063 *p++ = xdr_zero; /* no post_op_attr */ 1071 1064 1072 1065 if (resp->status == 0) { ··· 1088 1079 { 1089 1080 struct nfsd3_fsinfores *resp = rqstp->rq_resp; 1090 1081 1082 + *p++ = resp->status; 1091 1083 *p++ = xdr_zero; /* no post_op_attr */ 1092 1084 1093 1085 if (resp->status == 0) { ··· 1134 1124 { 1135 1125 struct nfsd3_commitres *resp = rqstp->rq_resp; 1136 1126 1127 + *p++ = resp->status; 1137 1128 p = encode_wcc_data(rqstp, p, &resp->fh); 1138 1129 /* Write verifier */ 1139 1130 if (resp->status == 0) {
+3 -4
fs/nfsd/nfs4proc.c
··· 2165 2165 static __be32 2166 2166 nfsd4_proc_null(struct svc_rqst *rqstp) 2167 2167 { 2168 - return nfs_ok; 2168 + return rpc_success; 2169 2169 } 2170 2170 2171 2171 static inline void nfsd4_increment_op_stats(u32 opnum) ··· 2457 2457 nfsd4_increment_op_stats(op->opnum); 2458 2458 } 2459 2459 2460 - cstate->status = status; 2461 2460 fh_put(current_fh); 2462 2461 fh_put(save_fh); 2463 2462 BUG_ON(cstate->replay_owner); 2464 2463 out: 2464 + cstate->status = status; 2465 2465 /* Reset deferral mechanism for RPC deferrals */ 2466 2466 set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); 2467 - dprintk("nfsv4 compound returned %d\n", ntohl(status)); 2468 - return status; 2467 + return rpc_success; 2469 2468 } 2470 2469 2471 2470 #define op_encode_hdr_size (2)
+2 -3
fs/nfsd/nfs4xdr.c
··· 5167 5167 int 5168 5168 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p) 5169 5169 { 5170 - /* 5171 - * All that remains is to write the tag and operation count... 5172 - */ 5173 5170 struct nfsd4_compoundres *resp = rqstp->rq_resp; 5174 5171 struct xdr_buf *buf = resp->xdr.buf; 5175 5172 5176 5173 WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len + 5177 5174 buf->tail[0].iov_len); 5175 + 5176 + *p = resp->cstate.status; 5178 5177 5179 5178 rqstp->rq_next_page = resp->xdr.page_ptr + 1; 5180 5179
+57 -56
fs/nfsd/nfsproc.c
··· 16 16 static __be32 17 17 nfsd_proc_null(struct svc_rqst *rqstp) 18 18 { 19 - return nfs_ok; 19 + return rpc_success; 20 20 } 21 21 22 22 /* ··· 38 38 goto out; 39 39 resp->status = fh_getattr(&resp->fh, &resp->stat); 40 40 out: 41 - return resp->status; 41 + return rpc_success; 42 42 } 43 43 44 44 /* ··· 85 85 86 86 resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP); 87 87 if (resp->status != nfs_ok) 88 - return resp->status; 88 + goto out; 89 89 90 90 if (delta < 0) 91 91 delta = -delta; ··· 106 106 107 107 resp->status = fh_getattr(&resp->fh, &resp->stat); 108 108 out: 109 - return resp->status; 109 + return rpc_success; 110 110 } 111 111 112 112 /* Obsolete, replaced by MNTPROC_MNT. */ 113 113 static __be32 114 114 nfsd_proc_root(struct svc_rqst *rqstp) 115 115 { 116 - return nfs_ok; 116 + return rpc_success; 117 117 } 118 118 119 119 /* ··· 140 140 141 141 resp->status = fh_getattr(&resp->fh, &resp->stat); 142 142 out: 143 - return resp->status; 143 + return rpc_success; 144 144 } 145 145 146 146 /* ··· 159 159 resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len); 160 160 161 161 fh_put(&argp->fh); 162 - return resp->status; 162 + return rpc_success; 163 163 } 164 164 165 165 /* ··· 197 197 rqstp->rq_vec, argp->vlen, 198 198 &resp->count, 199 199 &eof); 200 - if (resp->status != nfs_ok) 201 - goto out; 202 - 203 - resp->status = fh_getattr(&resp->fh, &resp->stat); 204 - out: 205 - return resp->status; 200 + if (resp->status == nfs_ok) 201 + resp->status = fh_getattr(&resp->fh, &resp->stat); 202 + else if (resp->status == nfserr_jukebox) 203 + return rpc_drop_reply; 204 + return rpc_success; 206 205 } 207 206 208 207 /* Reserved */ 209 208 static __be32 210 209 nfsd_proc_writecache(struct svc_rqst *rqstp) 211 210 { 212 - return nfs_ok; 211 + return rpc_success; 213 212 } 214 213 215 214 /* ··· 237 238 resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), 238 239 argp->offset, rqstp->rq_vec, nvecs, 239 240 &cnt, NFS_DATA_SYNC, NULL); 240 - if (resp->status != nfs_ok) 241 - goto out; 242 - 243 - resp->status = fh_getattr(&resp->fh, &resp->stat); 241 + if (resp->status == nfs_ok) 242 + resp->status = fh_getattr(&resp->fh, &resp->stat); 243 + else if (resp->status == nfserr_jukebox) 244 + return rpc_drop_reply; 244 245 out: 245 - return resp->status; 246 + return rpc_success; 246 247 } 247 248 248 249 /* ··· 409 410 goto out; 410 411 resp->status = fh_getattr(&resp->fh, &resp->stat); 411 412 out: 412 - return resp->status; 413 + return rpc_success; 413 414 } 414 415 415 416 static __be32 416 417 nfsd_proc_remove(struct svc_rqst *rqstp) 417 418 { 418 419 struct nfsd_diropargs *argp = rqstp->rq_argp; 419 - __be32 nfserr; 420 + struct nfsd_stat *resp = rqstp->rq_resp; 420 421 421 422 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh), 422 423 argp->len, argp->name); 423 424 424 425 /* Unlink. -SIFDIR means file must not be a directory */ 425 - nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len); 426 + resp->status = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, 427 + argp->name, argp->len); 426 428 fh_put(&argp->fh); 427 - return nfserr; 429 + return rpc_success; 428 430 } 429 431 430 432 static __be32 431 433 nfsd_proc_rename(struct svc_rqst *rqstp) 432 434 { 433 435 struct nfsd_renameargs *argp = rqstp->rq_argp; 434 - __be32 nfserr; 436 + struct nfsd_stat *resp = rqstp->rq_resp; 435 437 436 438 dprintk("nfsd: RENAME %s %.*s -> \n", 437 439 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname); 438 440 dprintk("nfsd: -> %s %.*s\n", 439 441 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname); 440 442 441 - nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen, 442 - &argp->tfh, argp->tname, argp->tlen); 443 + resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen, 444 + &argp->tfh, argp->tname, argp->tlen); 443 445 fh_put(&argp->ffh); 444 446 fh_put(&argp->tfh); 445 - return nfserr; 447 + return rpc_success; 446 448 } 447 449 448 450 static __be32 449 451 nfsd_proc_link(struct svc_rqst *rqstp) 450 452 { 451 453 struct nfsd_linkargs *argp = rqstp->rq_argp; 452 - __be32 nfserr; 454 + struct nfsd_stat *resp = rqstp->rq_resp; 453 455 454 456 dprintk("nfsd: LINK %s ->\n", 455 457 SVCFH_fmt(&argp->ffh)); ··· 459 459 argp->tlen, 460 460 argp->tname); 461 461 462 - nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen, 463 - &argp->ffh); 462 + resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen, 463 + &argp->ffh); 464 464 fh_put(&argp->ffh); 465 465 fh_put(&argp->tfh); 466 - return nfserr; 466 + return rpc_success; 467 467 } 468 468 469 469 static __be32 470 470 nfsd_proc_symlink(struct svc_rqst *rqstp) 471 471 { 472 472 struct nfsd_symlinkargs *argp = rqstp->rq_argp; 473 + struct nfsd_stat *resp = rqstp->rq_resp; 473 474 struct svc_fh newfh; 474 - __be32 nfserr; 475 475 476 476 if (argp->tlen > NFS_MAXPATHLEN) { 477 - nfserr = nfserr_nametoolong; 477 + resp->status = nfserr_nametoolong; 478 478 goto out; 479 479 } 480 480 ··· 482 482 page_address(rqstp->rq_arg.pages[0]), 483 483 argp->tlen); 484 484 if (IS_ERR(argp->tname)) { 485 - nfserr = nfserrno(PTR_ERR(argp->tname)); 485 + resp->status = nfserrno(PTR_ERR(argp->tname)); 486 486 goto out; 487 487 } 488 488 ··· 491 491 argp->tlen, argp->tname); 492 492 493 493 fh_init(&newfh, NFS_FHSIZE); 494 - nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, 495 - argp->tname, &newfh); 494 + resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, 495 + argp->tname, &newfh); 496 496 497 497 kfree(argp->tname); 498 498 fh_put(&argp->ffh); 499 499 fh_put(&newfh); 500 500 out: 501 - return nfserr; 501 + return rpc_success; 502 502 } 503 503 504 504 /* ··· 528 528 529 529 resp->status = fh_getattr(&resp->fh, &resp->stat); 530 530 out: 531 - return resp->status; 531 + return rpc_success; 532 532 } 533 533 534 534 /* ··· 538 538 nfsd_proc_rmdir(struct svc_rqst *rqstp) 539 539 { 540 540 struct nfsd_diropargs *argp = rqstp->rq_argp; 541 - __be32 nfserr; 541 + struct nfsd_stat *resp = rqstp->rq_resp; 542 542 543 543 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); 544 544 545 - nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len); 545 + resp->status = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, 546 + argp->name, argp->len); 546 547 fh_put(&argp->fh); 547 - return nfserr; 548 + return rpc_success; 548 549 } 549 550 550 551 /* ··· 585 584 *resp->offset = htonl(offset); 586 585 587 586 fh_put(&argp->fh); 588 - return resp->status; 587 + return rpc_success; 589 588 } 590 589 591 590 /* ··· 602 601 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 603 602 NFSD_MAY_BYPASS_GSS_ON_ROOT); 604 603 fh_put(&argp->fh); 605 - return resp->status; 604 + return rpc_success; 606 605 } 607 606 608 607 /* ··· 623 622 .pc_argsize = sizeof(struct nfsd_void), 624 623 .pc_ressize = sizeof(struct nfsd_void), 625 624 .pc_cachetype = RC_NOCACHE, 626 - .pc_xdrressize = ST, 625 + .pc_xdrressize = 0, 627 626 }, 628 627 [NFSPROC_GETATTR] = { 629 628 .pc_func = nfsd_proc_getattr, ··· 652 651 .pc_argsize = sizeof(struct nfsd_void), 653 652 .pc_ressize = sizeof(struct nfsd_void), 654 653 .pc_cachetype = RC_NOCACHE, 655 - .pc_xdrressize = ST, 654 + .pc_xdrressize = 0, 656 655 }, 657 656 [NFSPROC_LOOKUP] = { 658 657 .pc_func = nfsd_proc_lookup, ··· 690 689 .pc_argsize = sizeof(struct nfsd_void), 691 690 .pc_ressize = sizeof(struct nfsd_void), 692 691 .pc_cachetype = RC_NOCACHE, 693 - .pc_xdrressize = ST, 692 + .pc_xdrressize = 0, 694 693 }, 695 694 [NFSPROC_WRITE] = { 696 695 .pc_func = nfsd_proc_write, ··· 715 714 [NFSPROC_REMOVE] = { 716 715 .pc_func = nfsd_proc_remove, 717 716 .pc_decode = nfssvc_decode_diropargs, 718 - .pc_encode = nfssvc_encode_void, 717 + .pc_encode = nfssvc_encode_stat, 719 718 .pc_argsize = sizeof(struct nfsd_diropargs), 720 - .pc_ressize = sizeof(struct nfsd_void), 719 + .pc_ressize = sizeof(struct nfsd_stat), 721 720 .pc_cachetype = RC_REPLSTAT, 722 721 .pc_xdrressize = ST, 723 722 }, 724 723 [NFSPROC_RENAME] = { 725 724 .pc_func = nfsd_proc_rename, 726 725 .pc_decode = nfssvc_decode_renameargs, 727 - .pc_encode = nfssvc_encode_void, 726 + .pc_encode = nfssvc_encode_stat, 728 727 .pc_argsize = sizeof(struct nfsd_renameargs), 729 - .pc_ressize = sizeof(struct nfsd_void), 728 + .pc_ressize = sizeof(struct nfsd_stat), 730 729 .pc_cachetype = RC_REPLSTAT, 731 730 .pc_xdrressize = ST, 732 731 }, 733 732 [NFSPROC_LINK] = { 734 733 .pc_func = nfsd_proc_link, 735 734 .pc_decode = nfssvc_decode_linkargs, 736 - .pc_encode = nfssvc_encode_void, 735 + .pc_encode = nfssvc_encode_stat, 737 736 .pc_argsize = sizeof(struct nfsd_linkargs), 738 - .pc_ressize = sizeof(struct nfsd_void), 737 + .pc_ressize = sizeof(struct nfsd_stat), 739 738 .pc_cachetype = RC_REPLSTAT, 740 739 .pc_xdrressize = ST, 741 740 }, 742 741 [NFSPROC_SYMLINK] = { 743 742 .pc_func = nfsd_proc_symlink, 744 743 .pc_decode = nfssvc_decode_symlinkargs, 745 - .pc_encode = nfssvc_encode_void, 744 + .pc_encode = nfssvc_encode_stat, 746 745 .pc_argsize = sizeof(struct nfsd_symlinkargs), 747 - .pc_ressize = sizeof(struct nfsd_void), 746 + .pc_ressize = sizeof(struct nfsd_stat), 748 747 .pc_cachetype = RC_REPLSTAT, 749 748 .pc_xdrressize = ST, 750 749 }, ··· 761 760 [NFSPROC_RMDIR] = { 762 761 .pc_func = nfsd_proc_rmdir, 763 762 .pc_decode = nfssvc_decode_diropargs, 764 - .pc_encode = nfssvc_encode_void, 763 + .pc_encode = nfssvc_encode_stat, 765 764 .pc_argsize = sizeof(struct nfsd_diropargs), 766 - .pc_ressize = sizeof(struct nfsd_void), 765 + .pc_ressize = sizeof(struct nfsd_stat), 767 766 .pc_cachetype = RC_REPLSTAT, 768 767 .pc_xdrressize = ST, 769 768 },
+5 -16
fs/nfsd/nfssvc.c
··· 960 960 return 0; 961 961 } 962 962 963 - static __be32 map_new_errors(u32 vers, __be32 nfserr) 964 - { 965 - if (nfserr == nfserr_jukebox && vers == 2) 966 - return nfserr_dropit; 967 - return nfserr; 968 - } 969 - 970 963 /* 971 964 * A write procedure can have a large argument, and a read procedure can 972 965 * have a large reply, but no NFSv2 or NFSv3 procedure has argument and ··· 1007 1014 const struct svc_procedure *proc = rqstp->rq_procinfo; 1008 1015 struct kvec *argv = &rqstp->rq_arg.head[0]; 1009 1016 struct kvec *resv = &rqstp->rq_res.head[0]; 1010 - __be32 nfserr, *nfserrp; 1017 + __be32 *p; 1011 1018 1012 1019 dprintk("nfsd_dispatch: vers %d proc %d\n", 1013 1020 rqstp->rq_vers, rqstp->rq_proc); ··· 1036 1043 * Need to grab the location to store the status, as 1037 1044 * NFSv4 does some encoding while processing 1038 1045 */ 1039 - nfserrp = resv->iov_base + resv->iov_len; 1046 + p = resv->iov_base + resv->iov_len; 1040 1047 resv->iov_len += sizeof(__be32); 1041 1048 1042 - nfserr = proc->pc_func(rqstp); 1043 - nfserr = map_new_errors(rqstp->rq_vers, nfserr); 1044 - if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) 1049 + *statp = proc->pc_func(rqstp); 1050 + if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags)) 1045 1051 goto out_update_drop; 1046 1052 1047 - if (rqstp->rq_proc != 0) 1048 - *nfserrp++ = nfserr; 1049 - 1050 - if (!proc->pc_encode(rqstp, nfserrp)) 1053 + if (!proc->pc_encode(rqstp, p)) 1051 1054 goto out_encode_err; 1052 1055 1053 1056 nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
+19 -4
fs/nfsd/nfsxdr.c
··· 430 430 } 431 431 432 432 int 433 + nfssvc_encode_stat(struct svc_rqst *rqstp, __be32 *p) 434 + { 435 + struct nfsd_stat *resp = rqstp->rq_resp; 436 + 437 + *p++ = resp->status; 438 + return xdr_ressize_check(rqstp, p); 439 + } 440 + 441 + int 433 442 nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p) 434 443 { 435 444 struct nfsd_attrstat *resp = rqstp->rq_resp; 436 445 446 + *p++ = resp->status; 437 447 if (resp->status != nfs_ok) 438 - return xdr_ressize_check(rqstp, p); 439 - 448 + goto out; 440 449 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); 450 + out: 441 451 return xdr_ressize_check(rqstp, p); 442 452 } 443 453 ··· 456 446 { 457 447 struct nfsd_diropres *resp = rqstp->rq_resp; 458 448 449 + *p++ = resp->status; 459 450 if (resp->status != nfs_ok) 460 - return xdr_ressize_check(rqstp, p); 461 - 451 + goto out; 462 452 p = encode_fh(p, &resp->fh); 463 453 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); 454 + out: 464 455 return xdr_ressize_check(rqstp, p); 465 456 } 466 457 ··· 470 459 { 471 460 struct nfsd_readlinkres *resp = rqstp->rq_resp; 472 461 462 + *p++ = resp->status; 473 463 if (resp->status != nfs_ok) 474 464 return xdr_ressize_check(rqstp, p); 475 465 ··· 491 479 { 492 480 struct nfsd_readres *resp = rqstp->rq_resp; 493 481 482 + *p++ = resp->status; 494 483 if (resp->status != nfs_ok) 495 484 return xdr_ressize_check(rqstp, p); 496 485 ··· 515 502 { 516 503 struct nfsd_readdirres *resp = rqstp->rq_resp; 517 504 505 + *p++ = resp->status; 518 506 if (resp->status != nfs_ok) 519 507 return xdr_ressize_check(rqstp, p); 520 508 ··· 534 520 struct nfsd_statfsres *resp = rqstp->rq_resp; 535 521 struct kstatfs *stat = &resp->stats; 536 522 523 + *p++ = resp->status; 537 524 if (resp->status != nfs_ok) 538 525 return xdr_ressize_check(rqstp, p); 539 526
+5
fs/nfsd/xdr.h
··· 82 82 __be32 * buffer; 83 83 }; 84 84 85 + struct nfsd_stat { 86 + __be32 status; 87 + }; 88 + 85 89 struct nfsd_attrstat { 86 90 __be32 status; 87 91 struct svc_fh fh; ··· 157 153 int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *); 158 154 int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *); 159 155 int nfssvc_encode_void(struct svc_rqst *, __be32 *); 156 + int nfssvc_encode_stat(struct svc_rqst *, __be32 *); 160 157 int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *); 161 158 int nfssvc_encode_diropres(struct svc_rqst *, __be32 *); 162 159 int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *);