diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 132 |
1 files changed, 65 insertions, 67 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 0ec5a1b9700e..bcd8904ab1e3 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -133,22 +133,6 @@ xdr_error: \ | |||
133 | } \ | 133 | } \ |
134 | } while (0) | 134 | } while (0) |
135 | 135 | ||
136 | static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep) | ||
137 | { | ||
138 | savep->p = argp->p; | ||
139 | savep->end = argp->end; | ||
140 | savep->pagelen = argp->pagelen; | ||
141 | savep->pagelist = argp->pagelist; | ||
142 | } | ||
143 | |||
144 | static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep) | ||
145 | { | ||
146 | argp->p = savep->p; | ||
147 | argp->end = savep->end; | ||
148 | argp->pagelen = savep->pagelen; | ||
149 | argp->pagelist = savep->pagelist; | ||
150 | } | ||
151 | |||
152 | static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) | 136 | static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) |
153 | { | 137 | { |
154 | /* We want more bytes than seem to be available. | 138 | /* We want more bytes than seem to be available. |
@@ -638,14 +622,18 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup | |||
638 | DECODE_TAIL; | 622 | DECODE_TAIL; |
639 | } | 623 | } |
640 | 624 | ||
641 | static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x) | 625 | static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when) |
642 | { | 626 | { |
643 | __be32 *p; | 627 | __be32 *p; |
644 | u32 w; | 628 | u32 w; |
645 | 629 | ||
646 | READ_BUF(4); | 630 | READ_BUF(4); |
647 | READ32(w); | 631 | READ32(w); |
648 | *x = w; | 632 | *share_access = w & NFS4_SHARE_ACCESS_MASK; |
633 | *deleg_want = w & NFS4_SHARE_WANT_MASK; | ||
634 | if (deleg_when) | ||
635 | *deleg_when = w & NFS4_SHARE_WHEN_MASK; | ||
636 | |||
649 | switch (w & NFS4_SHARE_ACCESS_MASK) { | 637 | switch (w & NFS4_SHARE_ACCESS_MASK) { |
650 | case NFS4_SHARE_ACCESS_READ: | 638 | case NFS4_SHARE_ACCESS_READ: |
651 | case NFS4_SHARE_ACCESS_WRITE: | 639 | case NFS4_SHARE_ACCESS_WRITE: |
@@ -673,6 +661,9 @@ static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x) | |||
673 | w &= ~NFS4_SHARE_WANT_MASK; | 661 | w &= ~NFS4_SHARE_WANT_MASK; |
674 | if (!w) | 662 | if (!w) |
675 | return nfs_ok; | 663 | return nfs_ok; |
664 | |||
665 | if (!deleg_when) /* open_downgrade */ | ||
666 | return nfserr_inval; | ||
676 | switch (w) { | 667 | switch (w) { |
677 | case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL: | 668 | case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL: |
678 | case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED: | 669 | case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED: |
@@ -719,6 +710,7 @@ static __be32 | |||
719 | nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) | 710 | nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) |
720 | { | 711 | { |
721 | DECODE_HEAD; | 712 | DECODE_HEAD; |
713 | u32 dummy; | ||
722 | 714 | ||
723 | memset(open->op_bmval, 0, sizeof(open->op_bmval)); | 715 | memset(open->op_bmval, 0, sizeof(open->op_bmval)); |
724 | open->op_iattr.ia_valid = 0; | 716 | open->op_iattr.ia_valid = 0; |
@@ -727,7 +719,9 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) | |||
727 | /* seqid, share_access, share_deny, clientid, ownerlen */ | 719 | /* seqid, share_access, share_deny, clientid, ownerlen */ |
728 | READ_BUF(4); | 720 | READ_BUF(4); |
729 | READ32(open->op_seqid); | 721 | READ32(open->op_seqid); |
730 | status = nfsd4_decode_share_access(argp, &open->op_share_access); | 722 | /* decode, yet ignore deleg_when until supported */ |
723 | status = nfsd4_decode_share_access(argp, &open->op_share_access, | ||
724 | &open->op_deleg_want, &dummy); | ||
731 | if (status) | 725 | if (status) |
732 | goto xdr_error; | 726 | goto xdr_error; |
733 | status = nfsd4_decode_share_deny(argp, &open->op_share_deny); | 727 | status = nfsd4_decode_share_deny(argp, &open->op_share_deny); |
@@ -755,14 +749,14 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) | |||
755 | goto out; | 749 | goto out; |
756 | break; | 750 | break; |
757 | case NFS4_CREATE_EXCLUSIVE: | 751 | case NFS4_CREATE_EXCLUSIVE: |
758 | READ_BUF(8); | 752 | READ_BUF(NFS4_VERIFIER_SIZE); |
759 | COPYMEM(open->op_verf.data, 8); | 753 | COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); |
760 | break; | 754 | break; |
761 | case NFS4_CREATE_EXCLUSIVE4_1: | 755 | case NFS4_CREATE_EXCLUSIVE4_1: |
762 | if (argp->minorversion < 1) | 756 | if (argp->minorversion < 1) |
763 | goto xdr_error; | 757 | goto xdr_error; |
764 | READ_BUF(8); | 758 | READ_BUF(NFS4_VERIFIER_SIZE); |
765 | COPYMEM(open->op_verf.data, 8); | 759 | COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); |
766 | status = nfsd4_decode_fattr(argp, open->op_bmval, | 760 | status = nfsd4_decode_fattr(argp, open->op_bmval, |
767 | &open->op_iattr, &open->op_acl); | 761 | &open->op_iattr, &open->op_acl); |
768 | if (status) | 762 | if (status) |
@@ -848,7 +842,8 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d | |||
848 | return status; | 842 | return status; |
849 | READ_BUF(4); | 843 | READ_BUF(4); |
850 | READ32(open_down->od_seqid); | 844 | READ32(open_down->od_seqid); |
851 | status = nfsd4_decode_share_access(argp, &open_down->od_share_access); | 845 | status = nfsd4_decode_share_access(argp, &open_down->od_share_access, |
846 | &open_down->od_deleg_want, NULL); | ||
852 | if (status) | 847 | if (status) |
853 | return status; | 848 | return status; |
854 | status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny); | 849 | status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny); |
@@ -994,8 +989,8 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient | |||
994 | { | 989 | { |
995 | DECODE_HEAD; | 990 | DECODE_HEAD; |
996 | 991 | ||
997 | READ_BUF(8); | 992 | READ_BUF(NFS4_VERIFIER_SIZE); |
998 | COPYMEM(setclientid->se_verf.data, 8); | 993 | COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE); |
999 | 994 | ||
1000 | status = nfsd4_decode_opaque(argp, &setclientid->se_name); | 995 | status = nfsd4_decode_opaque(argp, &setclientid->se_name); |
1001 | if (status) | 996 | if (status) |
@@ -1020,9 +1015,9 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s | |||
1020 | { | 1015 | { |
1021 | DECODE_HEAD; | 1016 | DECODE_HEAD; |
1022 | 1017 | ||
1023 | READ_BUF(8 + sizeof(nfs4_verifier)); | 1018 | READ_BUF(8 + NFS4_VERIFIER_SIZE); |
1024 | COPYMEM(&scd_c->sc_clientid, 8); | 1019 | COPYMEM(&scd_c->sc_clientid, 8); |
1025 | COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier)); | 1020 | COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE); |
1026 | 1021 | ||
1027 | DECODE_TAIL; | 1022 | DECODE_TAIL; |
1028 | } | 1023 | } |
@@ -1385,26 +1380,29 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp, | |||
1385 | static __be32 | 1380 | static __be32 |
1386 | nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid) | 1381 | nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid) |
1387 | { | 1382 | { |
1388 | unsigned int nbytes; | ||
1389 | stateid_t si; | ||
1390 | int i; | 1383 | int i; |
1391 | __be32 *p; | 1384 | __be32 *p, status; |
1392 | __be32 status; | 1385 | struct nfsd4_test_stateid_id *stateid; |
1393 | 1386 | ||
1394 | READ_BUF(4); | 1387 | READ_BUF(4); |
1395 | test_stateid->ts_num_ids = ntohl(*p++); | 1388 | test_stateid->ts_num_ids = ntohl(*p++); |
1396 | 1389 | ||
1397 | nbytes = test_stateid->ts_num_ids * sizeof(stateid_t); | 1390 | INIT_LIST_HEAD(&test_stateid->ts_stateid_list); |
1398 | if (nbytes > (u32)((char *)argp->end - (char *)argp->p)) | ||
1399 | goto xdr_error; | ||
1400 | |||
1401 | test_stateid->ts_saved_args = argp; | ||
1402 | save_buf(argp, &test_stateid->ts_savedp); | ||
1403 | 1391 | ||
1404 | for (i = 0; i < test_stateid->ts_num_ids; i++) { | 1392 | for (i = 0; i < test_stateid->ts_num_ids; i++) { |
1405 | status = nfsd4_decode_stateid(argp, &si); | 1393 | stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL); |
1394 | if (!stateid) { | ||
1395 | status = PTR_ERR(stateid); | ||
1396 | goto out; | ||
1397 | } | ||
1398 | |||
1399 | defer_free(argp, kfree, stateid); | ||
1400 | INIT_LIST_HEAD(&stateid->ts_id_list); | ||
1401 | list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list); | ||
1402 | |||
1403 | status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid); | ||
1406 | if (status) | 1404 | if (status) |
1407 | return status; | 1405 | goto out; |
1408 | } | 1406 | } |
1409 | 1407 | ||
1410 | status = 0; | 1408 | status = 0; |
@@ -2661,8 +2659,8 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
2661 | __be32 *p; | 2659 | __be32 *p; |
2662 | 2660 | ||
2663 | if (!nfserr) { | 2661 | if (!nfserr) { |
2664 | RESERVE_SPACE(8); | 2662 | RESERVE_SPACE(NFS4_VERIFIER_SIZE); |
2665 | WRITEMEM(commit->co_verf.data, 8); | 2663 | WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE); |
2666 | ADJUST_ARGS(); | 2664 | ADJUST_ARGS(); |
2667 | } | 2665 | } |
2668 | return nfserr; | 2666 | return nfserr; |
@@ -2851,6 +2849,20 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op | |||
2851 | WRITE32(0); /* XXX: is NULL principal ok? */ | 2849 | WRITE32(0); /* XXX: is NULL principal ok? */ |
2852 | ADJUST_ARGS(); | 2850 | ADJUST_ARGS(); |
2853 | break; | 2851 | break; |
2852 | case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */ | ||
2853 | switch (open->op_why_no_deleg) { | ||
2854 | case WND4_CONTENTION: | ||
2855 | case WND4_RESOURCE: | ||
2856 | RESERVE_SPACE(8); | ||
2857 | WRITE32(open->op_why_no_deleg); | ||
2858 | WRITE32(0); /* deleg signaling not supported yet */ | ||
2859 | break; | ||
2860 | default: | ||
2861 | RESERVE_SPACE(4); | ||
2862 | WRITE32(open->op_why_no_deleg); | ||
2863 | } | ||
2864 | ADJUST_ARGS(); | ||
2865 | break; | ||
2854 | default: | 2866 | default: |
2855 | BUG(); | 2867 | BUG(); |
2856 | } | 2868 | } |
@@ -3008,7 +3020,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 | |||
3008 | if (resp->xbuf->page_len) | 3020 | if (resp->xbuf->page_len) |
3009 | return nfserr_resource; | 3021 | return nfserr_resource; |
3010 | 3022 | ||
3011 | RESERVE_SPACE(8); /* verifier */ | 3023 | RESERVE_SPACE(NFS4_VERIFIER_SIZE); |
3012 | savep = p; | 3024 | savep = p; |
3013 | 3025 | ||
3014 | /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ | 3026 | /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ |
@@ -3209,9 +3221,9 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n | |||
3209 | __be32 *p; | 3221 | __be32 *p; |
3210 | 3222 | ||
3211 | if (!nfserr) { | 3223 | if (!nfserr) { |
3212 | RESERVE_SPACE(8 + sizeof(nfs4_verifier)); | 3224 | RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE); |
3213 | WRITEMEM(&scd->se_clientid, 8); | 3225 | WRITEMEM(&scd->se_clientid, 8); |
3214 | WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier)); | 3226 | WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE); |
3215 | ADJUST_ARGS(); | 3227 | ADJUST_ARGS(); |
3216 | } | 3228 | } |
3217 | else if (nfserr == nfserr_clid_inuse) { | 3229 | else if (nfserr == nfserr_clid_inuse) { |
@@ -3232,7 +3244,7 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w | |||
3232 | RESERVE_SPACE(16); | 3244 | RESERVE_SPACE(16); |
3233 | WRITE32(write->wr_bytes_written); | 3245 | WRITE32(write->wr_bytes_written); |
3234 | WRITE32(write->wr_how_written); | 3246 | WRITE32(write->wr_how_written); |
3235 | WRITEMEM(write->wr_verifier.data, 8); | 3247 | WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE); |
3236 | ADJUST_ARGS(); | 3248 | ADJUST_ARGS(); |
3237 | } | 3249 | } |
3238 | return nfserr; | 3250 | return nfserr; |
@@ -3391,30 +3403,17 @@ __be32 | |||
3391 | nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, | 3403 | nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, |
3392 | struct nfsd4_test_stateid *test_stateid) | 3404 | struct nfsd4_test_stateid *test_stateid) |
3393 | { | 3405 | { |
3394 | struct nfsd4_compoundargs *argp; | 3406 | struct nfsd4_test_stateid_id *stateid, *next; |
3395 | struct nfs4_client *cl = resp->cstate.session->se_client; | ||
3396 | stateid_t si; | ||
3397 | __be32 *p; | 3407 | __be32 *p; |
3398 | int i; | ||
3399 | int valid; | ||
3400 | |||
3401 | restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp); | ||
3402 | argp = test_stateid->ts_saved_args; | ||
3403 | 3408 | ||
3404 | RESERVE_SPACE(4); | 3409 | RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); |
3405 | *p++ = htonl(test_stateid->ts_num_ids); | 3410 | *p++ = htonl(test_stateid->ts_num_ids); |
3406 | resp->p = p; | ||
3407 | 3411 | ||
3408 | nfs4_lock_state(); | 3412 | list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { |
3409 | for (i = 0; i < test_stateid->ts_num_ids; i++) { | 3413 | *p++ = htonl(stateid->ts_id_status); |
3410 | nfsd4_decode_stateid(argp, &si); | ||
3411 | valid = nfs4_validate_stateid(cl, &si); | ||
3412 | RESERVE_SPACE(4); | ||
3413 | *p++ = htonl(valid); | ||
3414 | resp->p = p; | ||
3415 | } | 3414 | } |
3416 | nfs4_unlock_state(); | ||
3417 | 3415 | ||
3416 | ADJUST_ARGS(); | ||
3418 | return nfserr; | 3417 | return nfserr; |
3419 | } | 3418 | } |
3420 | 3419 | ||
@@ -3532,7 +3531,7 @@ int nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad) | |||
3532 | if (length > session->se_fchannel.maxresp_sz) | 3531 | if (length > session->se_fchannel.maxresp_sz) |
3533 | return nfserr_rep_too_big; | 3532 | return nfserr_rep_too_big; |
3534 | 3533 | ||
3535 | if (slot->sl_cachethis == 1 && | 3534 | if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) && |
3536 | length > session->se_fchannel.maxresp_cached) | 3535 | length > session->se_fchannel.maxresp_cached) |
3537 | return nfserr_rep_too_big_to_cache; | 3536 | return nfserr_rep_too_big_to_cache; |
3538 | 3537 | ||
@@ -3656,8 +3655,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo | |||
3656 | if (nfsd4_has_session(cs)) { | 3655 | if (nfsd4_has_session(cs)) { |
3657 | if (cs->status != nfserr_replay_cache) { | 3656 | if (cs->status != nfserr_replay_cache) { |
3658 | nfsd4_store_cache_entry(resp); | 3657 | nfsd4_store_cache_entry(resp); |
3659 | dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__); | 3658 | cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE; |
3660 | cs->slot->sl_inuse = false; | ||
3661 | } | 3659 | } |
3662 | /* Renew the clientid on success and on replay */ | 3660 | /* Renew the clientid on success and on replay */ |
3663 | release_session_client(cs->session); | 3661 | release_session_client(cs->session); |