diff options
author | Fred Isaman <iisaman@netapp.com> | 2011-01-06 06:36:25 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-01-06 14:46:31 -0500 |
commit | cf7d63f1f9895713551df2e6d18b006f8af26e91 (patch) | |
tree | fc3dbfc12332878a832c11b5ae47ff259bb1bc32 /fs/nfs/pnfs.c | |
parent | c31663d4a1fac5ce1954d656cbcf80eb883b814a (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.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); |