aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2011-05-22 12:47:26 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-05-29 13:52:32 -0400
commitfb3296eb4636763918edef2d22e45b85b15d4518 (patch)
tree31c85255ccfa03cbca2d1e4e52028e489276a73b
parentf7da7a129d57bfe0f74573dc03531c63e1360fae (diff)
pnfs: Use byte-range for layoutget
Add offset and count parameters to pnfs_update_layout and use them to get the layout in the pageio path. Order cache layout segments in the following order: * offset (ascending) * length (descending) * iomode (RW before READ) Test byte range against the layout segment in use in pnfs_{read,write}_pg_test so not to coalesce pages not using the same layout segment. [fix lseg ordering] [clean up pnfs_find_lseg lseg arg] [remove unnecessary FIXME] [fix ordering in pnfs_insert_layout] [clean up pnfs_insert_layout] Signed-off-by: Benny Halevy <bhalevy@panasas.com>
-rw-r--r--fs/nfs/pnfs.c165
-rw-r--r--fs/nfs/pnfs.h6
-rw-r--r--fs/nfs/read.c8
-rw-r--r--fs/nfs/write.c8
4 files changed, 142 insertions, 45 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index f57f5281a520..c2f09e9b670e 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -261,6 +261,65 @@ put_lseg(struct pnfs_layout_segment *lseg)
261} 261}
262EXPORT_SYMBOL_GPL(put_lseg); 262EXPORT_SYMBOL_GPL(put_lseg);
263 263
264static inline u64
265end_offset(u64 start, u64 len)
266{
267 u64 end;
268
269 end = start + len;
270 return end >= start ? end : NFS4_MAX_UINT64;
271}
272
273/* last octet in a range */
274static inline u64
275last_byte_offset(u64 start, u64 len)
276{
277 u64 end;
278
279 BUG_ON(!len);
280 end = start + len;
281 return end > start ? end - 1 : NFS4_MAX_UINT64;
282}
283
284/*
285 * is l2 fully contained in l1?
286 * start1 end1
287 * [----------------------------------)
288 * start2 end2
289 * [----------------)
290 */
291static inline int
292lo_seg_contained(struct pnfs_layout_range *l1,
293 struct pnfs_layout_range *l2)
294{
295 u64 start1 = l1->offset;
296 u64 end1 = end_offset(start1, l1->length);
297 u64 start2 = l2->offset;
298 u64 end2 = end_offset(start2, l2->length);
299
300 return (start1 <= start2) && (end1 >= end2);
301}
302
303/*
304 * is l1 and l2 intersecting?
305 * start1 end1
306 * [----------------------------------)
307 * start2 end2
308 * [----------------)
309 */
310static inline int
311lo_seg_intersecting(struct pnfs_layout_range *l1,
312 struct pnfs_layout_range *l2)
313{
314 u64 start1 = l1->offset;
315 u64 end1 = end_offset(start1, l1->length);
316 u64 start2 = l2->offset;
317 u64 end2 = end_offset(start2, l2->length);
318
319 return (end1 == NFS4_MAX_UINT64 || end1 > start2) &&
320 (end2 == NFS4_MAX_UINT64 || end2 > start1);
321}
322
264static bool 323static bool
265should_free_lseg(u32 lseg_iomode, u32 recall_iomode) 324should_free_lseg(u32 lseg_iomode, u32 recall_iomode)
266{ 325{
@@ -467,7 +526,7 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
467static struct pnfs_layout_segment * 526static struct pnfs_layout_segment *
468send_layoutget(struct pnfs_layout_hdr *lo, 527send_layoutget(struct pnfs_layout_hdr *lo,
469 struct nfs_open_context *ctx, 528 struct nfs_open_context *ctx,
470 u32 iomode, 529 struct pnfs_layout_range *range,
471 gfp_t gfp_flags) 530 gfp_t gfp_flags)
472{ 531{
473 struct inode *ino = lo->plh_inode; 532 struct inode *ino = lo->plh_inode;
@@ -499,11 +558,11 @@ send_layoutget(struct pnfs_layout_hdr *lo,
499 goto out_err_free; 558 goto out_err_free;
500 } 559 }
501 560
502 lgp->args.minlength = NFS4_MAX_UINT64; 561 lgp->args.minlength = PAGE_CACHE_SIZE;
562 if (lgp->args.minlength > range->length)
563 lgp->args.minlength = range->length;
503 lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; 564 lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
504 lgp->args.range.iomode = iomode; 565 lgp->args.range = *range;
505 lgp->args.range.offset = 0;
506 lgp->args.range.length = NFS4_MAX_UINT64;
507 lgp->args.type = server->pnfs_curr_ld->id; 566 lgp->args.type = server->pnfs_curr_ld->id;
508 lgp->args.inode = ino; 567 lgp->args.inode = ino;
509 lgp->args.ctx = get_nfs_open_context(ctx); 568 lgp->args.ctx = get_nfs_open_context(ctx);
@@ -518,7 +577,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
518 nfs4_proc_layoutget(lgp); 577 nfs4_proc_layoutget(lgp);
519 if (!lseg) { 578 if (!lseg) {
520 /* remember that LAYOUTGET failed and suspend trying */ 579 /* remember that LAYOUTGET failed and suspend trying */
521 set_bit(lo_fail_bit(iomode), &lo->plh_flags); 580 set_bit(lo_fail_bit(range->iomode), &lo->plh_flags);
522 } 581 }
523 582
524 /* free xdr pages */ 583 /* free xdr pages */
@@ -625,10 +684,23 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier)
625 * are seen first. 684 * are seen first.
626 */ 685 */
627static s64 686static s64
628cmp_layout(u32 iomode1, u32 iomode2) 687cmp_layout(struct pnfs_layout_range *l1,
688 struct pnfs_layout_range *l2)
629{ 689{
690 s64 d;
691
692 /* high offset > low offset */
693 d = l1->offset - l2->offset;
694 if (d)
695 return d;
696
697 /* short length > long length */
698 d = l2->length - l1->length;
699 if (d)
700 return d;
701
630 /* read > read/write */ 702 /* read > read/write */
631 return (int)(iomode2 == IOMODE_READ) - (int)(iomode1 == IOMODE_READ); 703 return (int)(l1->iomode == IOMODE_READ) - (int)(l2->iomode == IOMODE_READ);
632} 704}
633 705
634static void 706static void
@@ -636,13 +708,12 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
636 struct pnfs_layout_segment *lseg) 708 struct pnfs_layout_segment *lseg)
637{ 709{
638 struct pnfs_layout_segment *lp; 710 struct pnfs_layout_segment *lp;
639 int found = 0;
640 711
641 dprintk("%s:Begin\n", __func__); 712 dprintk("%s:Begin\n", __func__);
642 713
643 assert_spin_locked(&lo->plh_inode->i_lock); 714 assert_spin_locked(&lo->plh_inode->i_lock);
644 list_for_each_entry(lp, &lo->plh_segs, pls_list) { 715 list_for_each_entry(lp, &lo->plh_segs, pls_list) {
645 if (cmp_layout(lp->pls_range.iomode, lseg->pls_range.iomode) > 0) 716 if (cmp_layout(&lseg->pls_range, &lp->pls_range) > 0)
646 continue; 717 continue;
647 list_add_tail(&lseg->pls_list, &lp->pls_list); 718 list_add_tail(&lseg->pls_list, &lp->pls_list);
648 dprintk("%s: inserted lseg %p " 719 dprintk("%s: inserted lseg %p "
@@ -652,16 +723,14 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
652 lseg->pls_range.offset, lseg->pls_range.length, 723 lseg->pls_range.offset, lseg->pls_range.length,
653 lp, lp->pls_range.iomode, lp->pls_range.offset, 724 lp, lp->pls_range.iomode, lp->pls_range.offset,
654 lp->pls_range.length); 725 lp->pls_range.length);
655 found = 1; 726 goto out;
656 break;
657 }
658 if (!found) {
659 list_add_tail(&lseg->pls_list, &lo->plh_segs);
660 dprintk("%s: inserted lseg %p "
661 "iomode %d offset %llu length %llu at tail\n",
662 __func__, lseg, lseg->pls_range.iomode,
663 lseg->pls_range.offset, lseg->pls_range.length);
664 } 727 }
728 list_add_tail(&lseg->pls_list, &lo->plh_segs);
729 dprintk("%s: inserted lseg %p "
730 "iomode %d offset %llu length %llu at tail\n",
731 __func__, lseg, lseg->pls_range.iomode,
732 lseg->pls_range.offset, lseg->pls_range.length);
733out:
665 get_layout_hdr(lo); 734 get_layout_hdr(lo);
666 735
667 dprintk("%s:Return\n", __func__); 736 dprintk("%s:Return\n", __func__);
@@ -721,16 +790,28 @@ pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)
721 * READ RW true 790 * READ RW true
722 */ 791 */
723static int 792static int
724is_matching_lseg(struct pnfs_layout_segment *lseg, u32 iomode) 793is_matching_lseg(struct pnfs_layout_range *ls_range,
794 struct pnfs_layout_range *range)
725{ 795{
726 return (iomode != IOMODE_RW || lseg->pls_range.iomode == IOMODE_RW); 796 struct pnfs_layout_range range1;
797
798 if ((range->iomode == IOMODE_RW &&
799 ls_range->iomode != IOMODE_RW) ||