aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-06-22 04:50:08 -0400
committerBen Myers <bpm@sgi.com>2012-07-01 15:50:04 -0400
commitcbb7baab285a540f173ef1ec3d5bcf9d0ad29d16 (patch)
tree33b570bfdf1a9e50482968823b05dd7c99b1e665
parent77c1a08fc9ece4cb130b9fd279738e799f0c2864 (diff)
xfs: separate buffer indexing from block map
To support discontiguous buffers in the buffer cache, we need to separate the cache index variables from the I/O map. While this is currently a 1:1 mapping, discontiguous buffer support will break this relationship. However, for caching purposes, we can still treat them the same as a contiguous buffer - the block number of the first block and the length of the buffer - as that is still a unique representation. Also, the only way we will ever access the discontiguous regions of buffers is via bulding the complete buffer in the first place, so using the initial block number and entire buffer length is a sane way to index the buffers. Add a block mapping vector construct to the xfs_buf and use it in the places where we are doing IO instead of the current b_bn/b_length variables. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_buf.c21
-rw-r--r--fs/xfs/xfs_buf.h27
2 files changed, 35 insertions, 13 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index a4beb421018a..a843873b0954 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -202,6 +202,8 @@ xfs_buf_alloc(
202 bp->b_io_length = numblks; 202 bp->b_io_length = numblks;
203 bp->b_flags = flags; 203 bp->b_flags = flags;
204 bp->b_bn = blkno; 204 bp->b_bn = blkno;
205 bp->b_map.bm_bn = blkno;
206 bp->b_map.bm_len = numblks;
205 atomic_set(&bp->b_pin_count, 0); 207 atomic_set(&bp->b_pin_count, 0);
206 init_waitqueue_head(&bp->b_waiters); 208 init_waitqueue_head(&bp->b_waiters);
207 209
@@ -327,8 +329,9 @@ xfs_buf_allocate_memory(
327 } 329 }
328 330
329use_alloc_page: 331use_alloc_page:
330 start = BBTOB(bp->b_bn) >> PAGE_SHIFT; 332 start = BBTOB(bp->b_map.bm_bn) >> PAGE_SHIFT;
331 end = (BBTOB(bp->b_bn + bp->b_length) + PAGE_SIZE - 1) >> PAGE_SHIFT; 333 end = (BBTOB(bp->b_map.bm_bn + bp->b_length) + PAGE_SIZE - 1)
334 >> PAGE_SHIFT;
332 page_count = end - start; 335 page_count = end - start;
333 error = _xfs_buf_get_pages(bp, page_count, flags); 336 error = _xfs_buf_get_pages(bp, page_count, flags);
334 if (unlikely(error)) 337 if (unlikely(error))
@@ -560,8 +563,6 @@ xfs_buf_get(
560 if (bp != new_bp) 563 if (bp != new_bp)
561 xfs_buf_free(new_bp); 564 xfs_buf_free(new_bp);
562 565
563 bp->b_io_length = bp->b_length;
564
565found: 566found:
566 if (!bp->b_addr) { 567 if (!bp->b_addr) {
567 error = _xfs_buf_map_pages(bp, flags); 568 error = _xfs_buf_map_pages(bp, flags);
@@ -584,7 +585,7 @@ _xfs_buf_read(
584 xfs_buf_flags_t flags) 585 xfs_buf_flags_t flags)
585{ 586{
586 ASSERT(!(flags & XBF_WRITE)); 587 ASSERT(!(flags & XBF_WRITE));
587 ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); 588 ASSERT(bp->b_map.bm_bn != XFS_BUF_DADDR_NULL);
588 589
589 bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD); 590 bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD);
590 bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); 591 bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD);
@@ -665,8 +666,8 @@ xfs_buf_read_uncached(
665 return NULL; 666 return NULL;
666 667
667 /* set up the buffer for a read IO */ 668 /* set up the buffer for a read IO */
668 XFS_BUF_SET_ADDR(bp, daddr); 669 bp->b_map.bm_bn = daddr;
669 XFS_BUF_READ(bp); 670 bp->b_flags |= XBF_READ;
670 671
671 xfsbdstrat(target->bt_mount, bp); 672 xfsbdstrat(target->bt_mount, bp);
672 error = xfs_buf_iowait(bp); 673 error = xfs_buf_iowait(bp);
@@ -695,6 +696,8 @@ xfs_buf_set_empty(
695 bp->b_length = numblks; 696 bp->b_length = numblks;
696 bp->b_io_length = numblks; 697 bp->b_io_length = numblks;
697 bp->b_bn = XFS_BUF_DADDR_NULL; 698 bp->b_bn = XFS_BUF_DADDR_NULL;
699 bp->b_map.bm_bn = XFS_BUF_DADDR_NULL;
700 bp->b_map.bm_len = bp->b_length;
698} 701}
699 702
700static inline struct page * 703static inline struct page *
@@ -1159,7 +1162,7 @@ _xfs_buf_ioapply(
1159 struct bio *bio; 1162 struct bio *bio;
1160 int offset = bp->b_offset; 1163 int offset = bp->b_offset;
1161 int size = BBTOB(bp->b_io_length); 1164 int size = BBTOB(bp->b_io_length);
1162 sector_t sector = bp->b_bn; 1165 sector_t sector = bp->b_map.bm_bn;
1163 1166
1164 total_nr_pages = bp->b_page_count; 1167 total_nr_pages = bp->b_page_count;
1165 map_i = 0; 1168 map_i = 0;
@@ -1564,7 +1567,7 @@ xfs_buf_cmp(
1564 struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list); 1567 struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list);
1565 xfs_daddr_t diff; 1568 xfs_daddr_t diff;
1566 1569
1567 diff = ap->b_bn - bp->b_bn; 1570 diff = ap->b_map.bm_bn - bp->b_map.bm_bn;
1568 if (diff < 0) 1571 if (diff < 0)
1569 return -1; 1572 return -1;
1570 if (diff > 0) 1573 if (diff > 0)
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index 7f1d1392ce37..c9c2ba90c53c 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -58,6 +58,7 @@ typedef enum {
58#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */ 58#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */
59#define _XBF_KMEM (1 << 21)/* backed by heap memory */ 59#define _XBF_KMEM (1 << 21)/* backed by heap memory */
60#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ 60#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
61#define _XBF_COMPOUND (1 << 23)/* compound buffer */
61 62
62typedef unsigned int xfs_buf_flags_t; 63typedef unsigned int xfs_buf_flags_t;
63 64
@@ -75,7 +76,8 @@ typedef unsigned int xfs_buf_flags_t;
75 { XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\ 76 { XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\
76 { _XBF_PAGES, "PAGES" }, \ 77 { _XBF_PAGES, "PAGES" }, \
77 { _XBF_KMEM, "KMEM" }, \ 78 { _XBF_KMEM, "KMEM" }, \
78 { _XBF_DELWRI_Q, "DELWRI_Q" } 79 { _XBF_DELWRI_Q, "DELWRI_Q" }, \
80 { _XBF_COMPOUND, "COMPOUND" }
79 81
80typedef struct xfs_buftarg { 82typedef struct xfs_buftarg {
81 dev_t bt_dev; 83 dev_t bt_dev;
@@ -98,6 +100,11 @@ typedef void (*xfs_buf_iodone_t)(struct xfs_buf *);
98 100
99#define XB_PAGES 2 101#define XB_PAGES 2
100 102
103struct xfs_buf_map {
104 xfs_daddr_t bm_bn; /* block number for I/O */
105 int bm_len; /* size of I/O */
106};
107
101typedef struct xfs_buf { 108typedef struct xfs_buf {
102 /* 109 /*
103 * first cacheline holds all the fields needed for an uncontended cache 110 * first cacheline holds all the fields needed for an uncontended cache
@@ -107,7 +114,7 @@ typedef struct xfs_buf {
107 * fast-path on locking. 114 * fast-path on locking.
108 */ 115 */
109 struct rb_node b_rbnode; /* rbtree node */ 116 struct rb_node b_rbnode; /* rbtree node */
110 xfs_daddr_t b_bn; /* block number for I/O */ 117 xfs_daddr_t b_bn; /* block number of buffer */
111 int b_length; /* size of buffer in BBs */ 118 int b_length; /* size of buffer in BBs */
112 atomic_t b_hold; /* reference count */ 119 atomic_t b_hold; /* reference count */
113 atomic_t b_lru_ref; /* lru reclaim ref count */ 120 atomic_t b_lru_ref; /* lru reclaim ref count */
@@ -127,12 +134,14 @@ typedef struct xfs_buf {
127 struct xfs_trans *b_transp; 134 struct xfs_trans *b_transp;
128 struct page **b_pages; /* array of page pointers */ 135 struct page **b_pages; /* array of page pointers */
129 struct page *b_page_array[XB_PAGES]; /* inline pages */ 136 struct page *b_page_array[XB_PAGES]; /* inline pages */
137 struct xfs_buf_map b_map; /* compound buffer map */
130 int b_io_length; /* IO size in BBs */ 138 int b_io_length; /* IO size in BBs */
131 atomic_t b_pin_count; /* pin count */ 139 atomic_t b_pin_count; /* pin count */
132 atomic_t b_io_remaining; /* #outstanding I/O requests */ 140 atomic_t b_io_remaining; /* #outstanding I/O requests */
133 unsigned int b_page_count; /* size of page array */ 141 unsigned int b_page_count; /* size of page array */
134 unsigned int b_offset; /* page offset in first page */ 142 unsigned int b_offset; /* page offset in first page */
135 unsigned short b_error; /* error code on I/O */ 143 unsigned short b_error; /* error code on I/O */
144
136#ifdef XFS_BUF_LOCK_TRACKING 145#ifdef XFS_BUF_LOCK_TRACKING
137 int b_last_holder; 146 int b_last_holder;
138#endif 147#endif
@@ -233,8 +242,18 @@ void xfs_buf_stale(struct xfs_buf *bp);
233#define XFS_BUF_UNWRITE(bp) ((bp)->b_flags &= ~XBF_WRITE) 242#define XFS_BUF_UNWRITE(bp) ((bp)->b_flags &= ~XBF_WRITE)
234#define XFS_BUF_ISWRITE(bp) ((bp)->b_flags & XBF_WRITE) 243#define XFS_BUF_ISWRITE(bp) ((bp)->b_flags & XBF_WRITE)
235 244
236#define XFS_BUF_ADDR(bp) ((bp)->b_bn) 245/*
237#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_bn = (xfs_daddr_t)(bno)) 246 * These macros use the IO block map rather than b_bn. b_bn is now really
247 * just for the buffer cache index for cached buffers. As IO does not use b_bn
248 * anymore, uncached buffers do not use b_bn at all and hence must modify the IO
249 * map directly. Uncached buffers are not allowed to be discontiguous, so this
250 * is safe to do.
251 *
252 * In future, uncached buffers will pass the block number directly to the io
253 * request function and hence these macros will go away at that point.
254 */
255#define XFS_BUF_ADDR(bp) ((bp)->b_map.bm_bn)
256#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_map.bm_bn = (xfs_daddr_t)(bno))
238 257
239static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) 258static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
240{ 259{