diff options
| -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(str | ||
