aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c24
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 */
375static bool
376pnfs_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
374int 382int
375pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, 383pnfs_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);
620out: 634out:
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);