aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/nfs4state.c78
1 files changed, 34 insertions, 44 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 44dcea96bfcb..fcc0610fe308 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -364,19 +364,12 @@ static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp)
364} 364}
365 365
366static struct nfs4_delegation * 366static struct nfs4_delegation *
367alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh, u32 type) 367alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh)
368{ 368{
369 struct nfs4_delegation *dp; 369 struct nfs4_delegation *dp;
370 struct nfs4_file *fp = stp->st_file; 370 struct nfs4_file *fp = stp->st_file;
371 371
372 dprintk("NFSD alloc_init_deleg\n"); 372 dprintk("NFSD alloc_init_deleg\n");
373 /*
374 * Major work on the lease subsystem (for example, to support
375 * calbacks on stat) will be required before we can support
376 * write delegations properly.
377 */
378 if (type != NFS4_OPEN_DELEGATE_READ)
379 return NULL;
380 if (fp->fi_had_conflict) 373 if (fp->fi_had_conflict)
381 return NULL; 374 return NULL;
382 if (num_delegations > max_delegations) 375 if (num_delegations > max_delegations)
@@ -397,7 +390,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
397 INIT_LIST_HEAD(&dp->dl_recall_lru); 390 INIT_LIST_HEAD(&dp->dl_recall_lru);
398 get_nfs4_file(fp); 391 get_nfs4_file(fp);
399 dp->dl_file = fp; 392 dp->dl_file = fp;
400 dp->dl_type = type; 393 dp->dl_type = NFS4_OPEN_DELEGATE_READ;
401 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle); 394 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
402 dp->dl_time = 0; 395 dp->dl_time = 0;
403 atomic_set(&dp->dl_count, 1); 396 atomic_set(&dp->dl_count, 1);
@@ -3020,13 +3013,13 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int f
3020 return fl; 3013 return fl;
3021} 3014}
3022 3015
3023static int nfs4_setlease(struct nfs4_delegation *dp, int flag) 3016static int nfs4_setlease(struct nfs4_delegation *dp)
3024{ 3017{
3025 struct nfs4_file *fp = dp->dl_file; 3018 struct nfs4_file *fp = dp->dl_file;
3026 struct file_lock *fl; 3019 struct file_lock *fl;
3027 int status; 3020 int status;
3028 3021
3029 fl = nfs4_alloc_init_lease(dp, flag); 3022 fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
3030 if (!fl) 3023 if (!fl)
3031 return -ENOMEM; 3024 return -ENOMEM;
3032 fl->fl_file = find_readable_file(fp); 3025 fl->fl_file = find_readable_file(fp);
@@ -3044,12 +3037,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp, int flag)
3044 return 0; 3037 return 0;
3045} 3038}
3046 3039
3047static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) 3040static int nfs4_set_delegation(struct nfs4_delegation *dp)
3048{ 3041{
3049 struct nfs4_file *fp = dp->dl_file; 3042 struct nfs4_file *fp = dp->dl_file;
3050 3043
3051 if (!fp->fi_lease) 3044 if (!fp->fi_lease)
3052 return nfs4_setlease(dp, flag); 3045 return nfs4_setlease(dp);
3053 spin_lock(&recall_lock); 3046 spin_lock(&recall_lock);
3054 if (fp->fi_had_conflict) { 3047 if (fp->fi_had_conflict) {
3055 spin_unlock(&recall_lock); 3048 spin_unlock(&recall_lock);
@@ -3085,6 +3078,9 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
3085 3078
3086/* 3079/*
3087 * Attempt to hand out a delegation. 3080 * Attempt to hand out a delegation.
3081 *
3082 * Note we don't support write delegations, and won't until the vfs has
3083 * proper support for them.
3088 */ 3084 */
3089static void 3085static void
3090nfs4_open_delegation(struct net *net, struct svc_fh *fh, 3086nfs4_open_delegation(struct net *net, struct svc_fh *fh,
@@ -3093,26 +3089,26 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3093 struct nfs4_delegation *dp; 3089 struct nfs4_delegation *dp;
3094 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); 3090 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
3095 int cb_up; 3091 int cb_up;
3096 int status = 0, flag = 0; 3092 int status = 0;
3097 3093
3098 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); 3094 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
3099 flag = NFS4_OPEN_DELEGATE_NONE;
3100 open->op_recall = 0; 3095 open->op_recall = 0;
3101 switch (open->op_claim_type) { 3096 switch (open->op_claim_type) {
3102 case NFS4_OPEN_CLAIM_PREVIOUS: 3097 case NFS4_OPEN_CLAIM_PREVIOUS:
3103 if (!cb_up) 3098 if (!cb_up)
3104 open->op_recall = 1; 3099 open->op_recall = 1;
3105 flag = open->op_delegate_type; 3100 if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
3106 if (flag == NFS4_OPEN_DELEGATE_NONE) 3101 goto out_no_deleg;
3107 goto out;
3108 break; 3102 break;
3109 case NFS4_OPEN_CLAIM_NULL: 3103 case NFS4_OPEN_CLAIM_NULL:
3110 /* Let's not give out any delegations till everyone's 3104 /*
3111 * had the chance to reclaim theirs.... */ 3105 * Let's not give out any delegations till everyone's
3106 * had the chance to reclaim theirs....
3107 */
3112 if (locks_in_grace(net)) 3108 if (locks_in_grace(net))
3113 goto out; 3109 goto out_no_deleg;
3114 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) 3110 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
3115 goto out; 3111 goto out_no_deleg;
3116 /* 3112 /*
3117 * Also, if the file was opened for write or 3113 * Also, if the file was opened for write or
3118 * create, there's a good chance the client's 3114 * create, there's a good chance the client's
@@ -3121,20 +3117,17 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3121 * write delegations): 3117 * write delegations):
3122 */ 3118 */
3123 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 3119 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
3124 flag = NFS4_OPEN_DELEGATE_WRITE; 3120 goto out_no_deleg;
3125 else if (open->op_create == NFS4_OPEN_CREATE) 3121 if (open->op_create == NFS4_OPEN_CREATE)
3126 flag = NFS4_OPEN_DELEGATE_WRITE; 3122 goto out_no_deleg;
3127 else
3128 flag = NFS4_OPEN_DELEGATE_READ;
3129 break; 3123 break;
3130 default: 3124 default:
3131 goto out; 3125 goto out_no_deleg;
3132 } 3126 }
3133 3127 dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh);
3134 dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh, flag);
3135 if (dp == NULL) 3128 if (dp == NULL)
3136 goto out_no_deleg; 3129 goto out_no_deleg;
3137 status = nfs4_set_delegation(dp, flag); 3130 status = nfs4_set_delegation(dp);
3138 if (status) 3131 if (status)
3139 goto out_free; 3132 goto out_free;
3140 3133
@@ -3142,24 +3135,21 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3142 3135
3143 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", 3136 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
3144 STATEID_VAL(&dp->dl_stid.sc_stateid)); 3137 STATEID_VAL(&dp->dl_stid.sc_stateid));
3145out: 3138 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
3146 open->op_delegate_type = flag;
3147 if (flag == NFS4_OPEN_DELEGATE_NONE) {
3148 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
3149 open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
3150 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
3151
3152 /* 4.1 client asking for a delegation? */
3153 if (open->op_deleg_want)
3154 nfsd4_open_deleg_none_ext(open, status);
3155 }
3156 return; 3139 return;
3157out_free: 3140out_free:
3158 unhash_stid(&dp->dl_stid); 3141 unhash_stid(&dp->dl_stid);
3159 nfs4_put_delegation(dp); 3142 nfs4_put_delegation(dp);
3160out_no_deleg: 3143out_no_deleg:
3161 flag = NFS4_OPEN_DELEGATE_NONE; 3144 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
3162 goto out; 3145 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
3146 open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
3147 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
3148
3149 /* 4.1 client asking for a delegation? */
3150 if (open->op_deleg_want)
3151 nfsd4_open_deleg_none_ext(open, status);
3152 return;
3163} 3153}
3164 3154
3165static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, 3155static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,