diff options
author | Benny Halevy <benny@tonian.com> | 2012-02-16 13:57:17 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-02-17 18:38:53 -0500 |
commit | d24433cdc91c0ed15938d2a6ee9e3e1b00fcfaa3 (patch) | |
tree | 7e8d0b0f71f9cc11bc5ac95694532f1759f30851 /fs/nfsd | |
parent | 03cfb42025a16dc45195dbdd6d368daaa8367429 (diff) |
nfsd41: implement NFS4_SHARE_WANT_NO_DELEG, NFS4_OPEN_DELEGATE_NONE_EXT, why_no_deleg
Respect client request for not getting a delegation in NFSv4.1
Appropriately return delegation "type" NFS4_OPEN_DELEGATE_NONE_EXT
and WND4_NOT_WANTED reason.
[nfsd41: add missing break when encoding op_why_no_deleg]
Signed-off-by: Benny Halevy <bhalevy@tonian.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 60 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 14 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 1 |
3 files changed, 68 insertions, 7 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index f1b74a74ec49..967c677c2e54 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -2866,7 +2866,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_ | |||
2866 | struct nfs4_delegation *dp; | 2866 | struct nfs4_delegation *dp; |
2867 | struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); | 2867 | struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); |
2868 | int cb_up; | 2868 | int cb_up; |
2869 | int status, flag = 0; | 2869 | int status = 0, flag = 0; |
2870 | 2870 | ||
2871 | cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); | 2871 | cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); |
2872 | flag = NFS4_OPEN_DELEGATE_NONE; | 2872 | flag = NFS4_OPEN_DELEGATE_NONE; |
@@ -2907,11 +2907,32 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_ | |||
2907 | dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", | 2907 | dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", |
2908 | STATEID_VAL(&dp->dl_stid.sc_stateid)); | 2908 | STATEID_VAL(&dp->dl_stid.sc_stateid)); |
2909 | out: | 2909 | out: |
2910 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS | ||
2911 | && flag == NFS4_OPEN_DELEGATE_NONE | ||
2912 | && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) | ||
2913 | dprintk("NFSD: WARNING: refusing delegation reclaim\n"); | ||
2914 | open->op_delegate_type = flag; | 2910 | open->op_delegate_type = flag; |
2911 | if (flag == NFS4_OPEN_DELEGATE_NONE) { | ||
2912 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && | ||
2913 | open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) | ||
2914 | dprintk("NFSD: WARNING: refusing delegation reclaim\n"); | ||
2915 | |||
2916 | if (open->op_deleg_want) { | ||
2917 | open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; | ||
2918 | if (status == -EAGAIN) | ||
2919 | open->op_why_no_deleg = WND4_CONTENTION; | ||
2920 | else { | ||
2921 | open->op_why_no_deleg = WND4_RESOURCE; | ||
2922 | switch (open->op_deleg_want) { | ||
2923 | case NFS4_SHARE_WANT_READ_DELEG: | ||
2924 | case NFS4_SHARE_WANT_WRITE_DELEG: | ||
2925 | case NFS4_SHARE_WANT_ANY_DELEG: | ||
2926 | break; | ||
2927 | case NFS4_SHARE_WANT_CANCEL: | ||
2928 | open->op_why_no_deleg = WND4_CANCELLED; | ||
2929 | break; | ||
2930 | case NFS4_SHARE_WANT_NO_DELEG: | ||
2931 | BUG(); /* not supposed to get here */ | ||
2932 | } | ||
2933 | } | ||
2934 | } | ||
2935 | } | ||
2915 | return; | 2936 | return; |
2916 | out_free: | 2937 | out_free: |
2917 | nfs4_put_delegation(dp); | 2938 | nfs4_put_delegation(dp); |
@@ -2981,20 +3002,45 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
2981 | update_stateid(&stp->st_stid.sc_stateid); | 3002 | update_stateid(&stp->st_stid.sc_stateid); |
2982 | memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); | 3003 | memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
2983 | 3004 | ||
2984 | if (nfsd4_has_session(&resp->cstate)) | 3005 | if (nfsd4_has_session(&resp->cstate)) { |
2985 | open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; | 3006 | open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; |
2986 | 3007 | ||
3008 | if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { | ||
3009 | open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; | ||
3010 | open->op_why_no_deleg = WND4_NOT_WANTED; | ||
3011 | goto nodeleg; | ||
3012 | } | ||
3013 | } | ||
3014 | |||
2987 | /* | 3015 | /* |
2988 | * Attempt to hand out a delegation. No error return, because the | 3016 | * Attempt to hand out a delegation. No error return, because the |
2989 | * OPEN succeeds even if we fail. | 3017 | * OPEN succeeds even if we fail. |
2990 | */ | 3018 | */ |
2991 | nfs4_open_delegation(current_fh, open, stp); | 3019 | nfs4_open_delegation(current_fh, open, stp); |
2992 | 3020 | nodeleg: | |
2993 | status = nfs_ok; | 3021 | status = nfs_ok; |
2994 | 3022 | ||
2995 | dprintk("%s: stateid=" STATEID_FMT "\n", __func__, | 3023 | dprintk("%s: stateid=" STATEID_FMT "\n", __func__, |
2996 | STATEID_VAL(&stp->st_stid.sc_stateid)); | 3024 | STATEID_VAL(&stp->st_stid.sc_stateid)); |
2997 | out: | 3025 | out: |
3026 | /* 4.1 client trying to upgrade/downgrade delegation? */ | ||
3027 | if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp && | ||
3028 | open->op_deleg_want) { | ||
3029 | if (open->op_deleg_want == NFS4_SHARE_WANT_READ_DELEG && | ||
3030 | dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) { | ||
3031 | open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; | ||
3032 | open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE; | ||
3033 | } else if (open->op_deleg_want == NFS4_SHARE_WANT_WRITE_DELEG && | ||
3034 | dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) { | ||
3035 | open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; | ||
3036 | open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE; | ||
3037 | } | ||
3038 | /* Otherwise the client must be confused wanting a delegation | ||
3039 | * it already has, therefore we don't return | ||
3040 | * NFS4_OPEN_DELEGATE_NONE_EXT and reason. | ||
3041 | */ | ||
3042 | } | ||
3043 | |||
2998 | if (fp) | 3044 | if (fp) |
2999 | put_nfs4_file(fp); | 3045 | put_nfs4_file(fp); |
3000 | if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) | 3046 | if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index a58f2064f479..f8fcddca0414 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -2849,6 +2849,20 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op | |||
2849 | WRITE32(0); /* XXX: is NULL principal ok? */ | 2849 | WRITE32(0); /* XXX: is NULL principal ok? */ |
2850 | ADJUST_ARGS(); | 2850 | ADJUST_ARGS(); |
2851 | 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; | ||
2852 | default: | 2866 | default: |
2853 | BUG(); | 2867 | BUG(); |
2854 | } | 2868 | } |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 7110a082275f..b89781f1477a 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -223,6 +223,7 @@ struct nfsd4_open { | |||
223 | struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */ | 223 | struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */ |
224 | u32 op_delegate_type; /* request - CLAIM_PREV only */ | 224 | u32 op_delegate_type; /* request - CLAIM_PREV only */ |
225 | stateid_t op_delegate_stateid; /* request - response */ | 225 | stateid_t op_delegate_stateid; /* request - response */ |
226 | u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */ | ||
226 | u32 op_create; /* request */ | 227 | u32 op_create; /* request */ |
227 | u32 op_createmode; /* request */ | 228 | u32 op_createmode; /* request */ |
228 | u32 op_bmval[3]; /* request */ | 229 | u32 op_bmval[3]; /* request */ |