diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-01-30 17:18:38 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-05-30 17:31:49 -0400 |
commit | d0a381dd0eda1cc769a5762d0eed4d0d662219f2 (patch) | |
tree | 05f80bdf7d0ebfa0c119430fa4f895021e58af42 | |
parent | 082d4bd72a4527c6568f53f4a5de74e804666fa7 (diff) |
nfsd4: teach encoders to handle reserve_space failures
We've tried to prevent running out of space with COMPOUND_SLACK_SPACE
and special checking in those operations (getattr) whose result can vary
enormously.
However:
- COMPOUND_SLACK_SPACE may be difficult to maintain as we add
more protocol.
- BUG_ON or page faulting on failure seems overly fragile.
- Especially in the 4.1 case, we prefer not to fail compounds
just because the returned result came *close* to session
limits. (Though perfect enforcement here may be difficult.)
- I'd prefer encoding to be uniform for all encoders instead of
having special exceptions for encoders containing, for
example, attributes.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | fs/nfsd/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 247 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 2 |
3 files changed, 185 insertions, 66 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index ef3952ac65b9..6a5b701961a4 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -1400,7 +1400,7 @@ encode_op: | |||
1400 | } | 1400 | } |
1401 | if (op->status == nfserr_replay_me) { | 1401 | if (op->status == nfserr_replay_me) { |
1402 | op->replay = &cstate->replay_owner->so_replay; | 1402 | op->replay = &cstate->replay_owner->so_replay; |
1403 | nfsd4_encode_replay(resp, op); | 1403 | nfsd4_encode_replay(&resp->xdr, op); |
1404 | status = op->status = op->replay->rp_status; | 1404 | status = op->status = op->replay->rp_status; |
1405 | } else { | 1405 | } else { |
1406 | nfsd4_encode_operation(resp, op); | 1406 | nfsd4_encode_operation(resp, op); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 37a73c8cda61..799a90479487 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1746,11 +1746,6 @@ static void write_cinfo(__be32 **p, struct nfsd4_change_info *c) | |||
1746 | } | 1746 | } |
1747 | } | 1747 | } |
1748 | 1748 | ||
1749 | #define RESERVE_SPACE(nbytes) do { \ | ||
1750 | p = xdr_reserve_space(&resp->xdr, nbytes); \ | ||
1751 | BUG_ON(!p); \ | ||
1752 | } while (0) | ||
1753 | |||
1754 | /* Encode as an array of strings the string given with components | 1749 | /* Encode as an array of strings the string given with components |
1755 | * separated @sep, escaped with esc_enter and esc_exit. | 1750 | * separated @sep, escaped with esc_enter and esc_exit. |
1756 | */ | 1751 | */ |
@@ -2737,23 +2732,29 @@ fail: | |||
2737 | return -EINVAL; | 2732 | return -EINVAL; |
2738 | } | 2733 | } |
2739 | 2734 | ||
2740 | static void | 2735 | static __be32 |
2741 | nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid) | 2736 | nfsd4_encode_stateid(struct xdr_stream *xdr, stateid_t *sid) |
2742 | { | 2737 | { |
2743 | __be32 *p; | 2738 | __be32 *p; |
2744 | 2739 | ||
2745 | RESERVE_SPACE(sizeof(stateid_t)); | 2740 | p = xdr_reserve_space(xdr, sizeof(stateid_t)); |
2741 | if (!p) | ||
2742 | return nfserr_resource; | ||
2746 | WRITE32(sid->si_generation); | 2743 | WRITE32(sid->si_generation); |
2747 | WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); | 2744 | WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); |
2745 | return 0; | ||
2748 | } | 2746 | } |
2749 | 2747 | ||
2750 | static __be32 | 2748 | static __be32 |
2751 | nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access) | 2749 | nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access) |
2752 | { | 2750 | { |
2751 | struct xdr_stream *xdr = &resp->xdr; | ||
2753 | __be32 *p; | 2752 | __be32 *p; |
2754 | 2753 | ||
2755 | if (!nfserr) { | 2754 | if (!nfserr) { |
2756 | RESERVE_SPACE(8); | 2755 | p = xdr_reserve_space(xdr, 8); |
2756 | if (!p) | ||
2757 | return nfserr_resource; | ||
2757 | WRITE32(access->ac_supported); | 2758 | WRITE32(access->ac_supported); |
2758 | WRITE32(access->ac_resp_access); | 2759 | WRITE32(access->ac_resp_access); |
2759 | } | 2760 | } |
@@ -2762,10 +2763,13 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
2762 | 2763 | ||
2763 | static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts) | 2764 | static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts) |
2764 | { | 2765 | { |
2766 | struct xdr_stream *xdr = &resp->xdr; | ||
2765 | __be32 *p; | 2767 | __be32 *p; |
2766 | 2768 | ||
2767 | if (!nfserr) { | 2769 | if (!nfserr) { |
2768 | RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); | 2770 | p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 8); |
2771 | if (!p) | ||
2772 | return nfserr_resource; | ||
2769 | WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); | 2773 | WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); |
2770 | WRITE32(bcts->dir); | 2774 | WRITE32(bcts->dir); |
2771 | /* Sorry, we do not yet support RDMA over 4.1: */ | 2775 | /* Sorry, we do not yet support RDMA over 4.1: */ |
@@ -2777,8 +2781,10 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, | |||
2777 | static __be32 | 2781 | static __be32 |
2778 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) | 2782 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) |
2779 | { | 2783 | { |
2784 | struct xdr_stream *xdr = &resp->xdr; | ||
2785 | |||
2780 | if (!nfserr) | 2786 | if (!nfserr) |
2781 | nfsd4_encode_stateid(resp, &close->cl_stateid); | 2787 | nfserr = nfsd4_encode_stateid(xdr, &close->cl_stateid); |
2782 | 2788 | ||
2783 | return nfserr; | 2789 | return nfserr; |
2784 | } | 2790 | } |
@@ -2787,10 +2793,13 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c | |||
2787 | static __be32 | 2793 | static __be32 |
2788 | nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit) | 2794 | nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit) |
2789 | { | 2795 | { |
2796 | struct xdr_stream *xdr = &resp->xdr; | ||
2790 | __be32 *p; | 2797 | __be32 *p; |
2791 | 2798 | ||
2792 | if (!nfserr) { | 2799 | if (!nfserr) { |
2793 | RESERVE_SPACE(NFS4_VERIFIER_SIZE); | 2800 | p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); |
2801 | if (!p) | ||
2802 | return nfserr_resource; | ||
2794 | WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE); | 2803 | WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE); |
2795 | } | 2804 | } |
2796 | return nfserr; | 2805 | return nfserr; |
@@ -2799,10 +2808,13 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
2799 | static __be32 | 2808 | static __be32 |
2800 | nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create) | 2809 | nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create) |
2801 | { | 2810 | { |
2811 | struct xdr_stream *xdr = &resp->xdr; | ||
2802 | __be32 *p; | 2812 | __be32 *p; |
2803 | 2813 | ||
2804 | if (!nfserr) { | 2814 | if (!nfserr) { |
2805 | RESERVE_SPACE(32); | 2815 | p = xdr_reserve_space(xdr, 32); |
2816 | if (!p) | ||
2817 | return nfserr_resource; | ||
2806 | write_cinfo(&p, &create->cr_cinfo); | 2818 | write_cinfo(&p, &create->cr_cinfo); |
2807 | WRITE32(2); | 2819 | WRITE32(2); |
2808 | WRITE32(create->cr_bmval[0]); | 2820 | WRITE32(create->cr_bmval[0]); |
@@ -2829,13 +2841,16 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 | |||
2829 | static __be32 | 2841 | static __be32 |
2830 | nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp) | 2842 | nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp) |
2831 | { | 2843 | { |
2844 | struct xdr_stream *xdr = &resp->xdr; | ||
2832 | struct svc_fh *fhp = *fhpp; | 2845 | struct svc_fh *fhp = *fhpp; |
2833 | unsigned int len; | 2846 | unsigned int len; |
2834 | __be32 *p; | 2847 | __be32 *p; |
2835 | 2848 | ||
2836 | if (!nfserr) { | 2849 | if (!nfserr) { |
2837 | len = fhp->fh_handle.fh_size; | 2850 | len = fhp->fh_handle.fh_size; |
2838 | RESERVE_SPACE(len + 4); | 2851 | p = xdr_reserve_space(xdr, len + 4); |
2852 | if (!p) | ||
2853 | return nfserr_resource; | ||
2839 | WRITE32(len); | 2854 | WRITE32(len); |
2840 | WRITEMEM(&fhp->fh_handle.fh_base, len); | 2855 | WRITEMEM(&fhp->fh_handle.fh_base, len); |
2841 | } | 2856 | } |
@@ -2846,13 +2861,15 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh | |||
2846 | * Including all fields other than the name, a LOCK4denied structure requires | 2861 | * Including all fields other than the name, a LOCK4denied structure requires |
2847 | * 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes. | 2862 | * 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes. |
2848 | */ | 2863 | */ |
2849 | static void | 2864 | static __be32 |
2850 | nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld) | 2865 | nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld) |
2851 | { | 2866 | { |
2852 | struct xdr_netobj *conf = &ld->ld_owner; | 2867 | struct xdr_netobj *conf = &ld->ld_owner; |
2853 | __be32 *p; | 2868 | __be32 *p; |
2854 | 2869 | ||
2855 | RESERVE_SPACE(32 + XDR_LEN(conf->len)); | 2870 | p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len)); |
2871 | if (!p) | ||
2872 | return nfserr_resource; | ||
2856 | WRITE64(ld->ld_start); | 2873 | WRITE64(ld->ld_start); |
2857 | WRITE64(ld->ld_length); | 2874 | WRITE64(ld->ld_length); |
2858 | WRITE32(ld->ld_type); | 2875 | WRITE32(ld->ld_type); |
@@ -2865,15 +2882,18 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie | |||
2865 | WRITE64((u64)0); /* clientid */ | 2882 | WRITE64((u64)0); /* clientid */ |
2866 | WRITE32(0); /* length of owner name */ | 2883 | WRITE32(0); /* length of owner name */ |
2867 | } | 2884 | } |
2885 | return nfserr_denied; | ||
2868 | } | 2886 | } |
2869 | 2887 | ||
2870 | static __be32 | 2888 | static __be32 |
2871 | nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) | 2889 | nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) |
2872 | { | 2890 | { |
2891 | struct xdr_stream *xdr = &resp->xdr; | ||
2892 | |||
2873 | if (!nfserr) | 2893 | if (!nfserr) |
2874 | nfsd4_encode_stateid(resp, &lock->lk_resp_stateid); | 2894 | nfserr = nfsd4_encode_stateid(xdr, &lock->lk_resp_stateid); |
2875 | else if (nfserr == nfserr_denied) | 2895 | else if (nfserr == nfserr_denied) |
2876 | nfsd4_encode_lock_denied(resp, &lock->lk_denied); | 2896 | nfserr = nfsd4_encode_lock_denied(xdr, &lock->lk_denied); |
2877 | 2897 | ||
2878 | return nfserr; | 2898 | return nfserr; |
2879 | } | 2899 | } |
@@ -2881,16 +2901,20 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lo | |||
2881 | static __be32 | 2901 | static __be32 |
2882 | nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt) | 2902 | nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt) |
2883 | { | 2903 | { |
2904 | struct xdr_stream *xdr = &resp->xdr; | ||
2905 | |||
2884 | if (nfserr == nfserr_denied) | 2906 | if (nfserr == nfserr_denied) |
2885 | nfsd4_encode_lock_denied(resp, &lockt->lt_denied); | 2907 | nfsd4_encode_lock_denied(xdr, &lockt->lt_denied); |
2886 | return nfserr; | 2908 | return nfserr; |
2887 | } | 2909 | } |
2888 | 2910 | ||
2889 | static __be32 | 2911 | static __be32 |
2890 | nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) | 2912 | nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) |
2891 | { | 2913 | { |
2914 | struct xdr_stream *xdr = &resp->xdr; | ||
2915 | |||
2892 | if (!nfserr) | 2916 | if (!nfserr) |
2893 | nfsd4_encode_stateid(resp, &locku->lu_stateid); | 2917 | nfserr = nfsd4_encode_stateid(xdr, &locku->lu_stateid); |
2894 | 2918 | ||
2895 | return nfserr; | 2919 | return nfserr; |
2896 | } | 2920 | } |
@@ -2899,10 +2923,13 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l | |||
2899 | static __be32 | 2923 | static __be32 |
2900 | nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link) | 2924 | nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link) |
2901 | { | 2925 | { |
2926 | struct xdr_stream *xdr = &resp->xdr; | ||
2902 | __be32 *p; | 2927 | __be32 *p; |
2903 | 2928 | ||
2904 | if (!nfserr) { | 2929 | if (!nfserr) { |
2905 | RESERVE_SPACE(20); | 2930 | p = xdr_reserve_space(xdr, 20); |
2931 | if (!p) | ||
2932 | return nfserr_resource; | ||
2906 | write_cinfo(&p, &link->li_cinfo); | 2933 | write_cinfo(&p, &link->li_cinfo); |
2907 | } | 2934 | } |
2908 | return nfserr; | 2935 | return nfserr; |
@@ -2912,13 +2939,18 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li | |||
2912 | static __be32 | 2939 | static __be32 |
2913 | nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) | 2940 | nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) |
2914 | { | 2941 | { |
2942 | struct xdr_stream *xdr = &resp->xdr; | ||
2915 | __be32 *p; | 2943 | __be32 *p; |
2916 | 2944 | ||
2917 | if (nfserr) | 2945 | if (nfserr) |
2918 | goto out; | 2946 | goto out; |
2919 | 2947 | ||
2920 | nfsd4_encode_stateid(resp, &open->op_stateid); | 2948 | nfserr = nfsd4_encode_stateid(xdr, &open->op_stateid); |
2921 | RESERVE_SPACE(40); | 2949 | if (nfserr) |
2950 | goto out; | ||
2951 | p = xdr_reserve_space(xdr, 40); | ||
2952 | if (!p) | ||
2953 | return nfserr_resource; | ||
2922 | write_cinfo(&p, &open->op_cinfo); | 2954 | write_cinfo(&p, &open->op_cinfo); |
2923 | WRITE32(open->op_rflags); | 2955 | WRITE32(open->op_rflags); |
2924 | WRITE32(2); | 2956 | WRITE32(2); |
@@ -2930,8 +2962,12 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op | |||
2930 | case NFS4_OPEN_DELEGATE_NONE: | 2962 | case NFS4_OPEN_DELEGATE_NONE: |
2931 | break; | 2963 | break; |
2932 | case NFS4_OPEN_DELEGATE_READ: | 2964 | case NFS4_OPEN_DELEGATE_READ: |
2933 | nfsd4_encode_stateid(resp, &open->op_delegate_stateid); | 2965 | nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid); |
2934 | RESERVE_SPACE(20); | 2966 | if (nfserr) |
2967 | return nfserr; | ||
2968 | p = xdr_reserve_space(xdr, 20); | ||
2969 | if (!p) | ||
2970 | return nfserr_resource; | ||
2935 | WRITE32(open->op_recall); | 2971 | WRITE32(open->op_recall); |
2936 | 2972 | ||
2937 | /* | 2973 | /* |
@@ -2943,8 +2979,12 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op | |||
2943 | WRITE32(0); /* XXX: is NULL principal ok? */ | 2979 | WRITE32(0); /* XXX: is NULL principal ok? */ |
2944 | break; | 2980 | break; |
2945 | case NFS4_OPEN_DELEGATE_WRITE: | 2981 | case NFS4_OPEN_DELEGATE_WRITE: |
2946 | nfsd4_encode_stateid(resp, &open->op_delegate_stateid); | 2982 | nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid); |
2947 | RESERVE_SPACE(32); | 2983 | if (nfserr) |
2984 | return nfserr; | ||
2985 | p = xdr_reserve_space(xdr, 32); | ||
2986 | if (!p) | ||
2987 | return nfserr_resource; | ||
2948 | WRITE32(0); | 2988 | WRITE32(0); |
2949 | 2989 | ||
2950 | /* | 2990 | /* |
@@ -2966,12 +3006,16 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op | |||
2966 | switch (open->op_why_no_deleg) { | 3006 | switch (open->op_why_no_deleg) { |
2967 | case WND4_CONTENTION: | 3007 | case WND4_CONTENTION: |
2968 | case WND4_RESOURCE: | 3008 | case WND4_RESOURCE: |
2969 | RESERVE_SPACE(8); | 3009 | p = xdr_reserve_space(xdr, 8); |
3010 | if (!p) | ||
3011 | return nfserr_resource; | ||
2970 | WRITE32(open->op_why_no_deleg); | 3012 | WRITE32(open->op_why_no_deleg); |
2971 | WRITE32(0); /* deleg signaling not supported yet */ | 3013 | WRITE32(0); /* deleg signaling not supported yet */ |
2972 | break; | 3014 | break; |
2973 | default: | 3015 | default: |
2974 | RESERVE_SPACE(4); | 3016 | p = xdr_reserve_space(xdr, 4); |
3017 | if (!p) | ||
3018 | return nfserr_resource; | ||
2975 | WRITE32(open->op_why_no_deleg); | 3019 | WRITE32(open->op_why_no_deleg); |
2976 | } | 3020 | } |
2977 | break; | 3021 | break; |
@@ -2986,8 +3030,10 @@ out: | |||
2986 | static __be32 | 3030 | static __be32 |
2987 | nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) | 3031 | nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) |
2988 | { | 3032 | { |
3033 | struct xdr_stream *xdr = &resp->xdr; | ||
3034 | |||
2989 | if (!nfserr) | 3035 | if (!nfserr) |
2990 | nfsd4_encode_stateid(resp, &oc->oc_resp_stateid); | 3036 | nfserr = nfsd4_encode_stateid(xdr, &oc->oc_resp_stateid); |
2991 | 3037 | ||
2992 | return nfserr; | 3038 | return nfserr; |
2993 | } | 3039 | } |
@@ -2995,8 +3041,10 @@ nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct | |||
2995 | static __be32 | 3041 | static __be32 |
2996 | nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) | 3042 | nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) |
2997 | { | 3043 | { |
3044 | struct xdr_stream *xdr = &resp->xdr; | ||
3045 | |||
2998 | if (!nfserr) | 3046 | if (!nfserr) |
2999 | nfsd4_encode_stateid(resp, &od->od_stateid); | 3047 | nfserr = nfsd4_encode_stateid(xdr, &od->od_stateid); |
3000 | 3048 | ||
3001 | return nfserr; | 3049 | return nfserr; |
3002 | } | 3050 | } |
@@ -3019,7 +3067,9 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3019 | if (resp->xdr.buf->page_len) | 3067 | if (resp->xdr.buf->page_len) |
3020 | return nfserr_resource; | 3068 | return nfserr_resource; |
3021 | 3069 | ||
3022 | RESERVE_SPACE(8); /* eof flag and byte count */ | 3070 | p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */ |
3071 | if (!p) | ||
3072 | return nfserr_resource; | ||
3023 | 3073 | ||
3024 | maxcount = svc_max_payload(resp->rqstp); | 3074 | maxcount = svc_max_payload(resp->rqstp); |
3025 | if (maxcount > read->rd_length) | 3075 | if (maxcount > read->rd_length) |
@@ -3071,7 +3121,9 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3071 | resp->xdr.buf->tail[0].iov_base = p; | 3121 | resp->xdr.buf->tail[0].iov_base = p; |
3072 | resp->xdr.buf->tail[0].iov_len = 0; | 3122 | resp->xdr.buf->tail[0].iov_len = 0; |
3073 | if (maxcount&3) { | 3123 | if (maxcount&3) { |
3074 | RESERVE_SPACE(4); | 3124 | p = xdr_reserve_space(xdr, 4); |
3125 | if (!p) | ||
3126 | return nfserr_resource; | ||
3075 | WRITE32(0); | 3127 | WRITE32(0); |
3076 | resp->xdr.buf->tail[0].iov_base += maxcount&3; | 3128 | resp->xdr.buf->tail[0].iov_base += maxcount&3; |
3077 | resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); | 3129 | resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); |
@@ -3099,7 +3151,10 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd | |||
3099 | page = page_address(*(resp->rqstp->rq_next_page++)); | 3151 | page = page_address(*(resp->rqstp->rq_next_page++)); |
3100 | 3152 | ||
3101 | maxcount = PAGE_SIZE; | 3153 | maxcount = PAGE_SIZE; |
3102 | RESERVE_SPACE(4); | 3154 | |
3155 | p = xdr_reserve_space(xdr, 4); | ||
3156 | if (!p) | ||
3157 | return nfserr_resource; | ||
3103 | 3158 | ||
3104 | /* | 3159 | /* |
3105 | * XXX: By default, the ->readlink() VFS op will truncate symlinks | 3160 | * XXX: By default, the ->readlink() VFS op will truncate symlinks |
@@ -3126,7 +3181,9 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd | |||
3126 | resp->xdr.buf->tail[0].iov_base = p; | 3181 | resp->xdr.buf->tail[0].iov_base = p; |
3127 | resp->xdr.buf->tail[0].iov_len = 0; | 3182 | resp->xdr.buf->tail[0].iov_len = 0; |
3128 | if (maxcount&3) { | 3183 | if (maxcount&3) { |
3129 | RESERVE_SPACE(4); | 3184 | p = xdr_reserve_space(xdr, 4); |
3185 | if (!p) | ||
3186 | return nfserr_resource; | ||
3130 | WRITE32(0); | 3187 | WRITE32(0); |
3131 | resp->xdr.buf->tail[0].iov_base += maxcount&3; | 3188 | resp->xdr.buf->tail[0].iov_base += maxcount&3; |
3132 | resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); | 3189 | resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); |
@@ -3151,7 +3208,9 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 | |||
3151 | if (!*resp->rqstp->rq_next_page) | 3208 | if (!*resp->rqstp->rq_next_page) |
3152 | return nfserr_resource; | 3209 | return nfserr_resource; |
3153 | 3210 | ||
3154 | RESERVE_SPACE(NFS4_VERIFIER_SIZE); | 3211 | p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); |
3212 | if (!p) | ||
3213 | return nfserr_resource; | ||
3155 | 3214 | ||
3156 | /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ | 3215 | /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ |
3157 | WRITE32(0); | 3216 | WRITE32(0); |
@@ -3220,10 +3279,13 @@ err_no_verf: | |||
3220 | static __be32 | 3279 | static __be32 |
3221 | nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove) | 3280 | nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove) |
3222 | { | 3281 | { |
3282 | struct xdr_stream *xdr = &resp->xdr; | ||
3223 | __be32 *p; | 3283 | __be32 *p; |
3224 | 3284 | ||
3225 | if (!nfserr) { | 3285 | if (!nfserr) { |
3226 | RESERVE_SPACE(20); | 3286 | p = xdr_reserve_space(xdr, 20); |
3287 | if (!p) | ||
3288 | return nfserr_resource; | ||
3227 | write_cinfo(&p, &remove->rm_cinfo); | 3289 | write_cinfo(&p, &remove->rm_cinfo); |
3228 | } | 3290 | } |
3229 | return nfserr; | 3291 | return nfserr; |
@@ -3232,10 +3294,13 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
3232 | static __be32 | 3294 | static __be32 |
3233 | nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename) | 3295 | nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename) |
3234 | { | 3296 | { |
3297 | struct xdr_stream *xdr = &resp->xdr; | ||
3235 | __be32 *p; | 3298 | __be32 *p; |
3236 | 3299 | ||
3237 | if (!nfserr) { | 3300 | if (!nfserr) { |
3238 | RESERVE_SPACE(40); | 3301 | p = xdr_reserve_space(xdr, 40); |
3302 | if (!p) | ||
3303 | return nfserr_resource; | ||
3239 | write_cinfo(&p, &rename->rn_sinfo); | 3304 | write_cinfo(&p, &rename->rn_sinfo); |
3240 | write_cinfo(&p, &rename->rn_tinfo); | 3305 | write_cinfo(&p, &rename->rn_tinfo); |
3241 | } | 3306 | } |
@@ -3243,7 +3308,7 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
3243 | } | 3308 | } |
3244 | 3309 | ||
3245 | static __be32 | 3310 | static __be32 |
3246 | nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | 3311 | nfsd4_do_encode_secinfo(struct xdr_stream *xdr, |
3247 | __be32 nfserr, struct svc_export *exp) | 3312 | __be32 nfserr, struct svc_export *exp) |
3248 | { | 3313 | { |
3249 | u32 i, nflavs, supported; | 3314 | u32 i, nflavs, supported; |
@@ -3254,6 +3319,7 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3254 | 3319 | ||
3255 | if (nfserr) | 3320 | if (nfserr) |
3256 | goto out; | 3321 | goto out; |
3322 | nfserr = nfserr_resource; | ||
3257 | if (exp->ex_nflavors) { | 3323 | if (exp->ex_nflavors) { |
3258 | flavs = exp->ex_flavors; | 3324 | flavs = exp->ex_flavors; |
3259 | nflavs = exp->ex_nflavors; | 3325 | nflavs = exp->ex_nflavors; |
@@ -3275,7 +3341,9 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3275 | } | 3341 | } |
3276 | 3342 | ||
3277 | supported = 0; | 3343 | supported = 0; |
3278 | RESERVE_SPACE(4); | 3344 | p = xdr_reserve_space(xdr, 4); |
3345 | if (!p) | ||
3346 | goto out; | ||
3279 | flavorsp = p++; /* to be backfilled later */ | 3347 | flavorsp = p++; /* to be backfilled later */ |
3280 | 3348 | ||
3281 | for (i = 0; i < nflavs; i++) { | 3349 | for (i = 0; i < nflavs; i++) { |
@@ -3284,7 +3352,10 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3284 | 3352 | ||
3285 | if (rpcauth_get_gssinfo(pf, &info) == 0) { | 3353 | if (rpcauth_get_gssinfo(pf, &info) == 0) { |
3286 | supported++; | 3354 | supported++; |
3287 | RESERVE_SPACE(4 + 4 + XDR_LEN(info.oid.len) + 4 + 4); | 3355 | p = xdr_reserve_space(xdr, 4 + 4 + |
3356 | XDR_LEN(info.oid.len) + 4 + 4); | ||
3357 | if (!p) | ||
3358 | goto out; | ||
3288 | WRITE32(RPC_AUTH_GSS); | 3359 | WRITE32(RPC_AUTH_GSS); |
3289 | WRITE32(info.oid.len); | 3360 | WRITE32(info.oid.len); |
3290 | WRITEMEM(info.oid.data, info.oid.len); | 3361 | WRITEMEM(info.oid.data, info.oid.len); |
@@ -3292,7 +3363,9 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3292 | WRITE32(info.service); | 3363 | WRITE32(info.service); |
3293 | } else if (pf < RPC_AUTH_MAXFLAVOR) { | 3364 | } else if (pf < RPC_AUTH_MAXFLAVOR) { |
3294 | supported++; | 3365 | supported++; |
3295 | RESERVE_SPACE(4); | 3366 | p = xdr_reserve_space(xdr, 4); |
3367 | if (!p) | ||
3368 | goto out; | ||
3296 | WRITE32(pf); | 3369 | WRITE32(pf); |
3297 | } else { | 3370 | } else { |
3298 | if (report) | 3371 | if (report) |
@@ -3304,7 +3377,7 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, | |||
3304 | if (nflavs != supported) | 3377 | if (nflavs != supported) |
3305 | report = false; | 3378 | report = false; |
3306 | *flavorsp = htonl(supported); | 3379 | *flavorsp = htonl(supported); |
3307 | 3380 | nfserr = 0; | |
3308 | out: | 3381 | out: |
3309 | if (exp) | 3382 | if (exp) |
3310 | exp_put(exp); | 3383 | exp_put(exp); |
@@ -3315,14 +3388,18 @@ static __be32 | |||
3315 | nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, | 3388 | nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, |
3316 | struct nfsd4_secinfo *secinfo) | 3389 | struct nfsd4_secinfo *secinfo) |
3317 | { | 3390 | { |
3318 | return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->si_exp); | 3391 | struct xdr_stream *xdr = &resp->xdr; |
3392 | |||
3393 | return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->si_exp); | ||
3319 | } | 3394 | } |
3320 | 3395 | ||
3321 | static __be32 | 3396 | static __be32 |
3322 | nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr, | 3397 | nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr, |
3323 | struct nfsd4_secinfo_no_name *secinfo) | 3398 | struct nfsd4_secinfo_no_name *secinfo) |
3324 | { | 3399 | { |
3325 | return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->sin_exp); | 3400 | struct xdr_stream *xdr = &resp->xdr; |
3401 | |||
3402 | return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->sin_exp); | ||
3326 | } | 3403 | } |
3327 | 3404 | ||
3328 | /* | 3405 | /* |
@@ -3332,9 +3409,12 @@ nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3332 | static __be32 | 3409 | static __be32 |
3333 | nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr) | 3410 | nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr) |
3334 | { | 3411 | { |
3412 | struct xdr_stream *xdr = &resp->xdr; | ||
3335 | __be32 *p; | 3413 | __be32 *p; |
3336 | 3414 | ||
3337 | RESERVE_SPACE(16); | 3415 | p = xdr_reserve_space(xdr, 16); |
3416 | if (!p) | ||
3417 | return nfserr_resource; | ||
3338 | if (nfserr) { | 3418 | if (nfserr) { |
3339 | WRITE32(3); | 3419 | WRITE32(3); |
3340 | WRITE32(0); | 3420 | WRITE32(0); |
@@ -3353,15 +3433,20 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 | |||
3353 | static __be32 | 3433 | static __be32 |
3354 | nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd) | 3434 | nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd) |
3355 | { | 3435 | { |
3436 | struct xdr_stream *xdr = &resp->xdr; | ||
3356 | __be32 *p; | 3437 | __be32 *p; |
3357 | 3438 | ||
3358 | if (!nfserr) { | 3439 | if (!nfserr) { |
3359 | RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE); | 3440 | p = xdr_reserve_space(xdr, 8 + NFS4_VERIFIER_SIZE); |
3441 | if (!p) | ||
3442 | return nfserr_resource; | ||
3360 | WRITEMEM(&scd->se_clientid, 8); | 3443 | WRITEMEM(&scd->se_clientid, 8); |
3361 | WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE); | 3444 | WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE); |
3362 | } | 3445 | } |
3363 | else if (nfserr == nfserr_clid_inuse) { | 3446 | else if (nfserr == nfserr_clid_inuse) { |
3364 | RESERVE_SPACE(8); | 3447 | p = xdr_reserve_space(xdr, 8); |
3448 | if (!p) | ||
3449 | return nfserr_resource; | ||
3365 | WRITE32(0); | 3450 | WRITE32(0); |
3366 | WRITE32(0); | 3451 | WRITE32(0); |
3367 | } | 3452 | } |
@@ -3371,10 +3456,13 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n | |||
3371 | static __be32 | 3456 | static __be32 |
3372 | nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write) | 3457 | nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write) |
3373 | { | 3458 | { |
3459 | struct xdr_stream *xdr = &resp->xdr; | ||
3374 | __be32 *p; | 3460 | __be32 *p; |
3375 | 3461 | ||
3376 | if (!nfserr) { | 3462 | if (!nfserr) { |
3377 | RESERVE_SPACE(16); | 3463 | p = xdr_reserve_space(xdr, 16); |
3464 | if (!p) | ||
3465 | return nfserr_resource; | ||
3378 | WRITE32(write->wr_bytes_written); | 3466 | WRITE32(write->wr_bytes_written); |
3379 | WRITE32(write->wr_how_written); | 3467 | WRITE32(write->wr_how_written); |
3380 | WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE); | 3468 | WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE); |
@@ -3394,6 +3482,7 @@ static __be32 | |||
3394 | nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | 3482 | nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, |
3395 | struct nfsd4_exchange_id *exid) | 3483 | struct nfsd4_exchange_id *exid) |
3396 | { | 3484 | { |
3485 | struct xdr_stream *xdr = &resp->xdr; | ||
3397 | __be32 *p; | 3486 | __be32 *p; |
3398 | char *major_id; | 3487 | char *major_id; |
3399 | char *server_scope; | 3488 | char *server_scope; |
@@ -3409,11 +3498,13 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3409 | server_scope = utsname()->nodename; | 3498 | server_scope = utsname()->nodename; |
3410 | server_scope_sz = strlen(server_scope); | 3499 | server_scope_sz = strlen(server_scope); |
3411 | 3500 | ||
3412 | RESERVE_SPACE( | 3501 | p = xdr_reserve_space(xdr, |
3413 | 8 /* eir_clientid */ + | 3502 | 8 /* eir_clientid */ + |
3414 | 4 /* eir_sequenceid */ + | 3503 | 4 /* eir_sequenceid */ + |
3415 | 4 /* eir_flags */ + | 3504 | 4 /* eir_flags */ + |
3416 | 4 /* spr_how */); | 3505 | 4 /* spr_how */); |
3506 | if (!p) | ||
3507 | return nfserr_resource; | ||
3417 | 3508 | ||
3418 | WRITEMEM(&exid->clientid, 8); | 3509 | WRITEMEM(&exid->clientid, 8); |
3419 | WRITE32(exid->seqid); | 3510 | WRITE32(exid->seqid); |
@@ -3426,7 +3517,9 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3426 | break; | 3517 | break; |
3427 | case SP4_MACH_CRED: | 3518 | case SP4_MACH_CRED: |
3428 | /* spo_must_enforce, spo_must_allow */ | 3519 | /* spo_must_enforce, spo_must_allow */ |
3429 | RESERVE_SPACE(16); | 3520 | p = xdr_reserve_space(xdr, 16); |
3521 | if (!p) | ||
3522 | return nfserr_resource; | ||
3430 | 3523 | ||
3431 | /* spo_must_enforce bitmap: */ | 3524 | /* spo_must_enforce bitmap: */ |
3432 | WRITE32(2); | 3525 | WRITE32(2); |
@@ -3440,13 +3533,15 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3440 | WARN_ON_ONCE(1); | 3533 | WARN_ON_ONCE(1); |
3441 | } | 3534 | } |
3442 | 3535 | ||
3443 | RESERVE_SPACE( | 3536 | p = xdr_reserve_space(xdr, |
3444 | 8 /* so_minor_id */ + | 3537 | 8 /* so_minor_id */ + |
3445 | 4 /* so_major_id.len */ + | 3538 | 4 /* so_major_id.len */ + |
3446 | (XDR_QUADLEN(major_id_sz) * 4) + | 3539 | (XDR_QUADLEN(major_id_sz) * 4) + |
3447 | 4 /* eir_server_scope.len */ + | 3540 | 4 /* eir_server_scope.len */ + |
3448 | (XDR_QUADLEN(server_scope_sz) * 4) + | 3541 | (XDR_QUADLEN(server_scope_sz) * 4) + |
3449 | 4 /* eir_server_impl_id.count (0) */); | 3542 | 4 /* eir_server_impl_id.count (0) */); |
3543 | if (!p) | ||
3544 | return nfserr_resource; | ||
3450 | 3545 | ||
3451 | /* The server_owner struct */ | 3546 | /* The server_owner struct */ |
3452 | WRITE64(minor_id); /* Minor id */ | 3547 | WRITE64(minor_id); /* Minor id */ |
@@ -3467,17 +3562,22 @@ static __be32 | |||
3467 | nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, | 3562 | nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, |
3468 | struct nfsd4_create_session *sess) | 3563 | struct nfsd4_create_session *sess) |
3469 | { | 3564 | { |
3565 | struct xdr_stream *xdr = &resp->xdr; | ||
3470 | __be32 *p; | 3566 | __be32 *p; |
3471 | 3567 | ||
3472 | if (nfserr) | 3568 | if (nfserr) |
3473 | return nfserr; | 3569 | return nfserr; |
3474 | 3570 | ||
3475 | RESERVE_SPACE(24); | 3571 | p = xdr_reserve_space(xdr, 24); |
3572 | if (!p) | ||
3573 | return nfserr_resource; | ||
3476 | WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN); | 3574 | WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN); |
3477 | WRITE32(sess->seqid); | 3575 | WRITE32(sess->seqid); |
3478 | WRITE32(sess->flags); | 3576 | WRITE32(sess->flags); |
3479 | 3577 | ||
3480 | RESERVE_SPACE(28); | 3578 | p = xdr_reserve_space(xdr, 28); |
3579 | if (!p) | ||
3580 | return nfserr_resource; | ||
3481 | WRITE32(0); /* headerpadsz */ | 3581 | WRITE32(0); /* headerpadsz */ |
3482 | WRITE32(sess->fore_channel.maxreq_sz); | 3582 | WRITE32(sess->fore_channel.maxreq_sz); |
3483 | WRITE32(sess->fore_channel.maxresp_sz); | 3583 | WRITE32(sess->fore_channel.maxresp_sz); |
@@ -3487,11 +3587,15 @@ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3487 | WRITE32(sess->fore_channel.nr_rdma_attrs); | 3587 | WRITE32(sess->fore_channel.nr_rdma_attrs); |
3488 | 3588 | ||
3489 | if (sess->fore_channel.nr_rdma_attrs) { | 3589 | if (sess->fore_channel.nr_rdma_attrs) { |
3490 | RESERVE_SPACE(4); | 3590 | p = xdr_reserve_space(xdr, 4); |
3591 | if (!p) | ||
3592 | return nfserr_resource; | ||
3491 | WRITE32(sess->fore_channel.rdma_attrs); | 3593 | WRITE32(sess->fore_channel.rdma_attrs); |
3492 | } | 3594 | } |
3493 | 3595 | ||
3494 | RESERVE_SPACE(28); | 3596 | p = xdr_reserve_space(xdr, 28); |
3597 | if (!p) | ||
3598 | return nfserr_resource; | ||
3495 | WRITE32(0); /* headerpadsz */ | 3599 | WRITE32(0); /* headerpadsz */ |
3496 | WRITE32(sess->back_channel.maxreq_sz); | 3600 | WRITE32(sess->back_channel.maxreq_sz); |
3497 | WRITE32(sess->back_channel.maxresp_sz); | 3601 | WRITE32(sess->back_channel.maxresp_sz); |
@@ -3501,7 +3605,9 @@ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3501 | WRITE32(sess->back_channel.nr_rdma_attrs); | 3605 | WRITE32(sess->back_channel.nr_rdma_attrs); |
3502 | 3606 | ||
3503 | if (sess->back_channel.nr_rdma_attrs) { | 3607 | if (sess->back_channel.nr_rdma_attrs) { |
3504 | RESERVE_SPACE(4); | 3608 | p = xdr_reserve_space(xdr, 4); |
3609 | if (!p) | ||
3610 | return nfserr_resource; | ||
3505 | WRITE32(sess->back_channel.rdma_attrs); | 3611 | WRITE32(sess->back_channel.rdma_attrs); |
3506 | } | 3612 | } |
3507 | return 0; | 3613 | return 0; |
@@ -3511,12 +3617,15 @@ static __be32 | |||
3511 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, | 3617 | nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, |
3512 | struct nfsd4_sequence *seq) | 3618 | struct nfsd4_sequence *seq) |
3513 | { | 3619 | { |
3620 | struct xdr_stream *xdr = &resp->xdr; | ||
3514 | __be32 *p; | 3621 | __be32 *p; |
3515 | 3622 | ||
3516 | if (nfserr) | 3623 | if (nfserr) |
3517 | return nfserr; | 3624 | return nfserr; |
3518 | 3625 | ||
3519 | RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 20); | 3626 | p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 20); |
3627 | if (!p) | ||
3628 | return nfserr_resource; | ||
3520 | WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN); | 3629 | WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN); |
3521 | WRITE32(seq->seqid); | 3630 | WRITE32(seq->seqid); |
3522 | WRITE32(seq->slotid); | 3631 | WRITE32(seq->slotid); |
@@ -3533,13 +3642,16 @@ static __be32 | |||
3533 | nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, | 3642 | nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, |
3534 | struct nfsd4_test_stateid *test_stateid) | 3643 | struct nfsd4_test_stateid *test_stateid) |
3535 | { | 3644 | { |
3645 | struct xdr_stream *xdr = &resp->xdr; | ||
3536 | struct nfsd4_test_stateid_id *stateid, *next; | 3646 | struct nfsd4_test_stateid_id *stateid, *next; |
3537 | __be32 *p; | 3647 | __be32 *p; |
3538 | 3648 | ||
3539 | if (nfserr) | 3649 | if (nfserr) |
3540 | return nfserr; | 3650 | return nfserr; |
3541 | 3651 | ||
3542 | RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); | 3652 | p = xdr_reserve_space(xdr, 4 + (4 * test_stateid->ts_num_ids)); |
3653 | if (!p) | ||
3654 | return nfserr_resource; | ||
3543 | *p++ = htonl(test_stateid->ts_num_ids); | 3655 | *p++ = htonl(test_stateid->ts_num_ids); |
3544 | 3656 | ||
3545 | list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { | 3657 | list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { |
@@ -3678,7 +3790,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | |||
3678 | nfsd4_enc encoder; | 3790 | nfsd4_enc encoder; |
3679 | __be32 *p; | 3791 | __be32 *p; |
3680 | 3792 | ||
3681 | RESERVE_SPACE(8); | 3793 | p = xdr_reserve_space(xdr, 8); |
3794 | if (!p) { | ||
3795 | WARN_ON_ONCE(1); | ||
3796 | return; | ||
3797 | } | ||
3682 | WRITE32(op->opnum); | 3798 | WRITE32(op->opnum); |
3683 | post_err_offset = xdr->buf->len; | 3799 | post_err_offset = xdr->buf->len; |
3684 | 3800 | ||
@@ -3730,18 +3846,21 @@ status: | |||
3730 | * called with nfs4_lock_state() held | 3846 | * called with nfs4_lock_state() held |
3731 | */ | 3847 | */ |
3732 | void | 3848 | void |
3733 | nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | 3849 | nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op) |
3734 | { | 3850 | { |
3735 | __be32 *p; | 3851 | __be32 *p; |
3736 | struct nfs4_replay *rp = op->replay; | 3852 | struct nfs4_replay *rp = op->replay; |
3737 | 3853 | ||
3738 | BUG_ON(!rp); | 3854 | BUG_ON(!rp); |
3739 | 3855 | ||
3740 | RESERVE_SPACE(8); | 3856 | p = xdr_reserve_space(xdr, 8 + rp->rp_buflen); |
3857 | if (!p) { | ||
3858 | WARN_ON_ONCE(1); | ||
3859 | return; | ||
3860 | } | ||
3741 | WRITE32(op->opnum); | 3861 | WRITE32(op->opnum); |
3742 | *p++ = rp->rp_status; /* already xdr'ed */ | 3862 | *p++ = rp->rp_status; /* already xdr'ed */ |
3743 | 3863 | ||
3744 | RESERVE_SPACE(rp->rp_buflen); | ||
3745 | WRITEMEM(rp->rp_buf, rp->rp_buflen); | 3864 | WRITEMEM(rp->rp_buf, rp->rp_buflen); |
3746 | } | 3865 | } |
3747 | 3866 | ||
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 15ca47797a82..ea5ad5db655b 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -563,7 +563,7 @@ int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *, | |||
563 | struct nfsd4_compoundres *); | 563 | struct nfsd4_compoundres *); |
564 | __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32); | 564 | __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32); |
565 | void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); | 565 | void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); |
566 | void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op); | 566 | void nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op); |
567 | __be32 nfsd4_encode_fattr_to_buf(__be32 **p, int words, | 567 | __be32 nfsd4_encode_fattr_to_buf(__be32 **p, int words, |
568 | struct svc_fh *fhp, struct svc_export *exp, | 568 | struct svc_fh *fhp, struct svc_export *exp, |
569 | struct dentry *dentry, | 569 | struct dentry *dentry, |