diff options
-rw-r--r-- | fs/nfsd/nfs4proc.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index dadff09b0b0c..844813a7e12a 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -230,17 +230,16 @@ static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate | |||
230 | } | 230 | } |
231 | 231 | ||
232 | static __be32 | 232 | static __be32 |
233 | do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open) | 233 | do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh **resfh) |
234 | { | 234 | { |
235 | struct svc_fh *current_fh = &cstate->current_fh; | 235 | struct svc_fh *current_fh = &cstate->current_fh; |
236 | struct svc_fh *resfh; | ||
237 | int accmode; | 236 | int accmode; |
238 | __be32 status; | 237 | __be32 status; |
239 | 238 | ||
240 | resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); | 239 | *resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); |
241 | if (!resfh) | 240 | if (!*resfh) |
242 | return nfserr_jukebox; | 241 | return nfserr_jukebox; |
243 | fh_init(resfh, NFS4_FHSIZE); | 242 | fh_init(*resfh, NFS4_FHSIZE); |
244 | open->op_truncate = 0; | 243 | open->op_truncate = 0; |
245 | 244 | ||
246 | if (open->op_create) { | 245 | if (open->op_create) { |
@@ -265,12 +264,12 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru | |||
265 | */ | 264 | */ |
266 | status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, | 265 | status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, |
267 | open->op_fname.len, &open->op_iattr, | 266 | open->op_fname.len, &open->op_iattr, |
268 | resfh, open->op_createmode, | 267 | *resfh, open->op_createmode, |
269 | (u32 *)open->op_verf.data, | 268 | (u32 *)open->op_verf.data, |
270 | &open->op_truncate, &open->op_created); | 269 | &open->op_truncate, &open->op_created); |
271 | 270 | ||
272 | if (!status && open->op_label.len) | 271 | if (!status && open->op_label.len) |
273 | nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval); | 272 | nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval); |
274 | 273 | ||
275 | /* | 274 | /* |
276 | * Following rfc 3530 14.2.16, use the returned bitmask | 275 | * Following rfc 3530 14.2.16, use the returned bitmask |
@@ -282,29 +281,26 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru | |||
282 | FATTR4_WORD1_TIME_MODIFY); | 281 | FATTR4_WORD1_TIME_MODIFY); |
283 | } else { | 282 | } else { |
284 | status = nfsd_lookup(rqstp, current_fh, | 283 | status = nfsd_lookup(rqstp, current_fh, |
285 | open->op_fname.data, open->op_fname.len, resfh); | 284 | open->op_fname.data, open->op_fname.len, *resfh); |
286 | fh_unlock(current_fh); | 285 | fh_unlock(current_fh); |
287 | } | 286 | } |
288 | if (status) | 287 | if (status) |
289 | goto out; | 288 | goto out; |
290 | status = nfsd_check_obj_isreg(resfh); | 289 | status = nfsd_check_obj_isreg(*resfh); |
291 | if (status) | 290 | if (status) |
292 | goto out; | 291 | goto out; |
293 | 292 | ||
294 | if (is_create_with_attrs(open) && open->op_acl != NULL) | 293 | if (is_create_with_attrs(open) && open->op_acl != NULL) |
295 | do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval); | 294 | do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval); |
296 | 295 | ||
297 | nfsd4_set_open_owner_reply_cache(cstate, open, resfh); | 296 | nfsd4_set_open_owner_reply_cache(cstate, open, *resfh); |
298 | accmode = NFSD_MAY_NOP; | 297 | accmode = NFSD_MAY_NOP; |
299 | if (open->op_created || | 298 | if (open->op_created || |
300 | open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR) | 299 | open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR) |
301 | accmode |= NFSD_MAY_OWNER_OVERRIDE; | 300 | accmode |= NFSD_MAY_OWNER_OVERRIDE; |
302 | status = do_open_permission(rqstp, resfh, open, accmode); | 301 | status = do_open_permission(rqstp, *resfh, open, accmode); |
303 | set_change_info(&open->op_cinfo, current_fh); | 302 | set_change_info(&open->op_cinfo, current_fh); |
304 | fh_dup2(current_fh, resfh); | ||
305 | out: | 303 | out: |
306 | fh_put(resfh); | ||
307 | kfree(resfh); | ||
308 | return status; | 304 | return status; |
309 | } | 305 | } |
310 | 306 | ||
@@ -357,6 +353,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
357 | struct nfsd4_open *open) | 353 | struct nfsd4_open *open) |
358 | { | 354 | { |
359 | __be32 status; | 355 | __be32 status; |
356 | struct svc_fh *resfh = NULL; | ||
360 | struct nfsd4_compoundres *resp; | 357 | struct nfsd4_compoundres *resp; |
361 | struct net *net = SVC_NET(rqstp); | 358 | struct net *net = SVC_NET(rqstp); |
362 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 359 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
@@ -423,7 +420,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
423 | switch (open->op_claim_type) { | 420 | switch (open->op_claim_type) { |
424 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: | 421 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: |
425 | case NFS4_OPEN_CLAIM_NULL: | 422 | case NFS4_OPEN_CLAIM_NULL: |
426 | status = do_open_lookup(rqstp, cstate, open); | 423 | status = do_open_lookup(rqstp, cstate, open, &resfh); |
427 | if (status) | 424 | if (status) |
428 | goto out; | 425 | goto out; |
429 | break; | 426 | break; |
@@ -439,6 +436,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
439 | status = do_open_fhandle(rqstp, cstate, open); | 436 | status = do_open_fhandle(rqstp, cstate, open); |
440 | if (status) | 437 | if (status) |
441 | goto out; | 438 | goto out; |
439 | resfh = &cstate->current_fh; | ||
442 | break; | 440 | break; |
443 | case NFS4_OPEN_CLAIM_DELEG_PREV_FH: | 441 | case NFS4_OPEN_CLAIM_DELEG_PREV_FH: |
444 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: | 442 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: |
@@ -458,9 +456,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
458 | * successful, it (1) truncates the file if open->op_truncate was | 456 | * successful, it (1) truncates the file if open->op_truncate was |
459 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. | 457 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. |
460 | */ | 458 | */ |
461 | status = nfsd4_process_open2(rqstp, &cstate->current_fh, open); | 459 | status = nfsd4_process_open2(rqstp, resfh, open); |
462 | WARN_ON(status && open->op_created); | 460 | WARN_ON(status && open->op_created); |
463 | out: | 461 | out: |
462 | if (resfh && resfh != &cstate->current_fh) { | ||
463 | fh_dup2(&cstate->current_fh, resfh); | ||
464 | fh_put(resfh); | ||
465 | kfree(resfh); | ||
466 | } | ||
464 | nfsd4_cleanup_open_state(open, status); | 467 | nfsd4_cleanup_open_state(open, status); |
465 | if (open->op_openowner && !nfsd4_has_session(cstate)) | 468 | if (open->op_openowner && !nfsd4_has_session(cstate)) |
466 | cstate->replay_owner = &open->op_openowner->oo_owner; | 469 | cstate->replay_owner = &open->op_openowner->oo_owner; |