diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 212cbc22c59d..59ed68bf79fa 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -371,6 +371,14 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, | |||
371 | memcpy(&lo->plh_stateid, &new->stateid, sizeof(new->stateid)); | 371 | memcpy(&lo->plh_stateid, &new->stateid, sizeof(new->stateid)); |
372 | } | 372 | } |
373 | 373 | ||
374 | /* lget is set to 1 if called from inside send_layoutget call chain */ | ||
375 | static bool | ||
376 | pnfs_layoutgets_blocked(struct pnfs_layout_hdr *lo, int lget) | ||
377 | { | ||
378 | return (list_empty(&lo->plh_segs) && | ||
379 | (atomic_read(&lo->plh_outstanding) > lget)); | ||
380 | } | ||
381 | |||
374 | int | 382 | int |
375 | pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, | 383 | pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, |
376 | struct nfs4_state *open_state) | 384 | struct nfs4_state *open_state) |
@@ -379,7 +387,9 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, | |||
379 | 387 | ||
380 | dprintk("--> %s\n", __func__); | 388 | dprintk("--> %s\n", __func__); |
381 | spin_lock(&lo->plh_inode->i_lock); | 389 | spin_lock(&lo->plh_inode->i_lock); |
382 | if (list_empty(&lo->plh_segs)) { | 390 | if (pnfs_layoutgets_blocked(lo, 1)) { |
391 | status = -EAGAIN; | ||
392 | } else if (list_empty(&lo->plh_segs)) { | ||
383 | int seq; | 393 | int seq; |
384 | 394 | ||
385 | do { | 395 | do { |
@@ -414,10 +424,8 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
414 | 424 | ||
415 | BUG_ON(ctx == NULL); | 425 | BUG_ON(ctx == NULL); |
416 | lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); | 426 | lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); |
417 | if (lgp == NULL) { | 427 | if (lgp == NULL) |
418 | put_layout_hdr(lo->plh_inode); | ||
419 | return NULL; | 428 | return NULL; |
420 | } | ||
421 | lgp->args.minlength = NFS4_MAX_UINT64; | 429 | lgp->args.minlength = NFS4_MAX_UINT64; |
422 | lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; | 430 | lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; |
423 | lgp->args.range.iomode = iomode; | 431 | lgp->args.range.iomode = iomode; |
@@ -613,10 +621,16 @@ pnfs_update_layout(struct inode *ino, | |||
613 | if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags)) | 621 | if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags)) |
614 | goto out_unlock; | 622 | goto out_unlock; |
615 | 623 | ||
616 | get_layout_hdr_locked(lo); /* Matched in nfs4_layoutget_release */ | 624 | if (pnfs_layoutgets_blocked(lo, 0)) |
625 | goto out_unlock; | ||
626 | atomic_inc(&lo->plh_outstanding); | ||
627 | |||
628 | get_layout_hdr_locked(lo); | ||
617 | spin_unlock(&ino->i_lock); | 629 | spin_unlock(&ino->i_lock); |
618 | 630 | ||
619 | lseg = send_layoutget(lo, ctx, iomode); | 631 | lseg = send_layoutget(lo, ctx, iomode); |
632 | atomic_dec(&lo->plh_outstanding); | ||
633 | put_layout_hdr(ino); | ||
620 | out: | 634 | out: |
621 | dprintk("%s end, state 0x%lx lseg %p\n", __func__, | 635 | dprintk("%s end, state 0x%lx lseg %p\n", __func__, |
622 | nfsi->layout->plh_flags, lseg); | 636 | nfsi->layout->plh_flags, lseg); |