diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfs4state.c | 78 |
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 | ||
366 | static struct nfs4_delegation * | 366 | static struct nfs4_delegation * |
367 | alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh, u32 type) | 367 | alloc_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, ¤t_fh->fh_handle); | 394 | fh_copy_shallow(&dp->dl_fh, ¤t_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 | ||
3023 | static int nfs4_setlease(struct nfs4_delegation *dp, int flag) | 3016 | static 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 | ||
3047 | static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) | 3040 | static 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 | */ |
3089 | static void | 3085 | static void |
3090 | nfs4_open_delegation(struct net *net, struct svc_fh *fh, | 3086 | nfs4_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)); |
3145 | out: | 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; |
3157 | out_free: | 3140 | out_free: |
3158 | unhash_stid(&dp->dl_stid); | 3141 | unhash_stid(&dp->dl_stid); |
3159 | nfs4_put_delegation(dp); | 3142 | nfs4_put_delegation(dp); |
3160 | out_no_deleg: | 3143 | out_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 | ||
3165 | static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, | 3155 | static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, |