aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2011-01-06 06:36:25 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-01-06 14:46:31 -0500
commitcf7d63f1f9895713551df2e6d18b006f8af26e91 (patch)
treefc3dbfc12332878a832c11b5ae47ff259bb1bc32 /fs/nfs/pnfs.c
parentc31663d4a1fac5ce1954d656cbcf80eb883b814a (diff)
pnfs: serialize LAYOUTGET(openstateid)
We shouldn't send a LAYOUTGET(openstateid) unless all outstanding RPCs using the previous stateid are completed. This requires choosing the stateid to encode earlier, so we can abort if one is not available (we want to use the open stateid, but a LAYOUTGET is already out using it), and adding a count of the number of outstanding rpc calls using layout state (which for now consist solely of LAYOUTGETs). Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
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);