aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorBenny Halevy <benny@tonian.com>2012-02-16 13:57:17 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-02-17 18:38:53 -0500
commitd24433cdc91c0ed15938d2a6ee9e3e1b00fcfaa3 (patch)
tree7e8d0b0f71f9cc11bc5ac95694532f1759f30851 /fs/nfsd
parent03cfb42025a16dc45195dbdd6d368daaa8367429 (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.c60
-rw-r--r--fs/nfsd/nfs4xdr.c14
-rw-r--r--fs/nfsd/xdr4.h1
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));
2909out: 2909out:
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;
2916out_free: 2937out_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 3020nodeleg:
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));
2997out: 3025out:
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 */