diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 7 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 5 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 24 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
5 files changed, 28 insertions, 10 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5bee453d36d6..a3549ce72ab2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -5304,6 +5304,12 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
5304 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, | 5304 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, |
5305 | &lgp->res.seq_res, 0, task)) | 5305 | &lgp->res.seq_res, 0, task)) |
5306 | return; | 5306 | return; |
5307 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, | ||
5308 | NFS_I(lgp->args.inode)->layout, | ||
5309 | lgp->args.ctx->state)) { | ||
5310 | rpc_exit(task, NFS4_OK); | ||
5311 | return; | ||
5312 | } | ||
5307 | rpc_call_start(task); | 5313 | rpc_call_start(task); |
5308 | } | 5314 | } |
5309 | 5315 | ||
@@ -5338,7 +5344,6 @@ static void nfs4_layoutget_release(void *calldata) | |||
5338 | struct nfs4_layoutget *lgp = calldata; | 5344 | struct nfs4_layoutget *lgp = calldata; |
5339 | 5345 | ||
5340 | dprintk("--> %s\n", __func__); | 5346 | dprintk("--> %s\n", __func__); |
5341 | put_layout_hdr(lgp->args.inode); | ||
5342 | if (lgp->res.layout.buf != NULL) | 5347 | if (lgp->res.layout.buf != NULL) |
5343 | free_page((unsigned long) lgp->res.layout.buf); | 5348 | free_page((unsigned long) lgp->res.layout.buf); |
5344 | put_nfs_open_context(lgp->args.ctx); | 5349 | put_nfs_open_context(lgp->args.ctx); |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 4e28242360d6..3cbdd0c80a2d 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1787,7 +1787,6 @@ encode_layoutget(struct xdr_stream *xdr, | |||
1787 | const struct nfs4_layoutget_args *args, | 1787 | const struct nfs4_layoutget_args *args, |
1788 | struct compound_hdr *hdr) | 1788 | struct compound_hdr *hdr) |
1789 | { | 1789 | { |
1790 | nfs4_stateid stateid; | ||
1791 | __be32 *p; | 1790 | __be32 *p; |
1792 | 1791 | ||
1793 | p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); | 1792 | p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); |
@@ -1798,9 +1797,7 @@ encode_layoutget(struct xdr_stream *xdr, | |||
1798 | p = xdr_encode_hyper(p, args->range.offset); | 1797 | p = xdr_encode_hyper(p, args->range.offset); |
1799 | p = xdr_encode_hyper(p, args->range.length); | 1798 | p = xdr_encode_hyper(p, args->range.length); |
1800 | p = xdr_encode_hyper(p, args->minlength); | 1799 | p = xdr_encode_hyper(p, args->minlength); |
1801 | pnfs_choose_layoutget_stateid(&stateid, NFS_I(args->inode)->layout, | 1800 | p = xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE); |
1802 | args->ctx->state); | ||
1803 | p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE); | ||
1804 | *p = cpu_to_be32(args->maxcount); | 1801 | *p = cpu_to_be32(args->maxcount); |
1805 | 1802 | ||
1806 | dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", | 1803 | dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", |
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); |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 787253e6fca3..698380da24cc 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -69,6 +69,7 @@ struct pnfs_layout_hdr { | |||
69 | struct list_head plh_layouts; /* other client layouts */ | 69 | struct list_head plh_layouts; /* other client layouts */ |
70 | struct list_head plh_segs; /* layout segments list */ | 70 | struct list_head plh_segs; /* layout segments list */ |
71 | nfs4_stateid plh_stateid; | 71 | nfs4_stateid plh_stateid; |
72 | atomic_t plh_outstanding; /* number of RPCs out */ | ||
72 | unsigned long plh_flags; | 73 | unsigned long plh_flags; |
73 | struct inode *plh_inode; | 74 | struct inode *plh_inode; |
74 | }; | 75 | }; |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 8fcc54267bba..83d36d3a12e6 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -208,6 +208,7 @@ struct nfs4_layoutget_args { | |||
208 | struct inode *inode; | 208 | struct inode *inode; |
209 | struct nfs_open_context *ctx; | 209 | struct nfs_open_context *ctx; |
210 | struct nfs4_sequence_args seq_args; | 210 | struct nfs4_sequence_args seq_args; |
211 | nfs4_stateid stateid; | ||
211 | }; | 212 | }; |
212 | 213 | ||
213 | struct nfs4_layoutget_res { | 214 | struct nfs4_layoutget_res { |