aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_address.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-09-18 17:18:23 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-09-18 17:18:23 -0400
commit7a6bbacbb8dec6fbd1242c959250388f907d429e (patch)
tree8e314f0b3fd6e54154562c0a9b20173d539470a2 /fs/gfs2/ops_address.c
parent65952fb4e91c159d253bd28ceaf028a86dbb0b02 (diff)
[GFS2] Map multiple blocks at once where possible
This is a tidy up of the GFS2 bmap code. The main change is that the bh is passed to gfs2_block_map allowing the flags to be set directly rather than having to repeat that code several times in ops_address.c. At the same time, the extent mapping code from gfs2_extent_map has been moved into gfs2_block_map. This allows all calls to gfs2_block_map to map extents in the case that no allocation is taking place. As a result reads and non-allocating writes should be faster. A quick test with postmark appears to support this. There is a limit on the number of blocks mapped in a single bmap call in that it will only ever map blocks which are pointed to from a single pointer block. So in other words, it will never try to do additional i/o in order to satisfy read-ahead. The maximum number of blocks is thus somewhat less than 512 (the GFS2 4k block size minus the header divided by sizeof(u64)). I've further limited the mapping of "normal" blocks to 32 blocks (to avoid extra work) since readpages() will currently read a maximum of 32 blocks ahead (128k). Some further work will probably be needed to set a suitable value for DIO as well, but for now thats left at the maximum 512 (see ops_address.c:gfs2_get_block_direct). There is probably a lot more that can be done to improve bmap for GFS2, but this is a good first step. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r--fs/gfs2/ops_address.c68
1 files changed, 14 insertions, 54 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index d44d42fb4163..6f9ac5e6e3f6 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -65,29 +65,11 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
65int gfs2_get_block(struct inode *inode, sector_t lblock, 65int gfs2_get_block(struct inode *inode, sector_t lblock,
66 struct buffer_head *bh_result, int create) 66 struct buffer_head *bh_result, int create)
67{ 67{
68 int new = create; 68 return gfs2_block_map(inode, lblock, create, bh_result, 32);
69 u64 dblock;
70 int error;
71 int boundary;
72
73 error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary);
74 if (error)
75 return error;
76
77 if (!dblock)
78 return 0;
79
80 map_bh(bh_result, inode->i_sb, dblock);
81 if (new)
82 set_buffer_new(bh_result);
83 if (boundary)
84 set_buffer_boundary(bh_result);
85
86 return 0;
87} 69}
88 70
89/** 71/**
90 * get_block_noalloc - Fills in a buffer head with details about a block 72 * gfs2_get_block_noalloc - Fills in a buffer head with details about a block
91 * @inode: The inode 73 * @inode: The inode
92 * @lblock: The block number to look up 74 * @lblock: The block number to look up
93 * @bh_result: The buffer head to return the result in 75 * @bh_result: The buffer head to return the result in
@@ -96,47 +78,25 @@ int gfs2_get_block(struct inode *inode, sector_t lblock,
96 * Returns: errno 78 * Returns: errno
97 */ 79 */
98 80
99static int get_block_noalloc(struct inode *inode, sector_t lblock, 81static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock,
100 struct buffer_head *bh_result, int create) 82 struct buffer_head *bh_result, int create)
101{ 83{
102 int new = 0;
103 u64 dblock;
104 int error; 84 int error;
105 int boundary;
106 85
107 error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary); 86 error = gfs2_block_map(inode, lblock, 0, bh_result, 1);
108 if (error) 87 if (error)
109 return error; 88 return error;
110 89 if (bh_result->b_blocknr == 0)
111 if (dblock) 90 return -EIO;
112 map_bh(bh_result, inode->i_sb, dblock); 91 return 0;
113 else if (gfs2_assert_withdraw(GFS2_SB(inode), !create))
114 error = -EIO;
115 if (boundary)
116 set_buffer_boundary(bh_result);
117
118 return error;
119} 92}
120 93
121static int get_block_direct(struct inode *inode, sector_t lblock, 94static int gfs2_get_block_direct(struct inode *inode, sector_t lblock,
122 struct buffer_head *bh_result, int create) 95 struct buffer_head *bh_result, int create)
123{ 96{
124 int new = 0; 97 return gfs2_block_map(inode, lblock, 0, bh_result, 512);
125 u64 dblock;
126 int error, boundary;
127
128 error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary);
129 if (error)
130 return error;
131
132 if (dblock) {
133 map_bh(bh_result, inode->i_sb, dblock);
134 if (boundary)
135 set_buffer_boundary(bh_result);
136 }
137
138 return 0;
139} 98}
99
140/** 100/**
141 * gfs2_writepage - Write complete page 101 * gfs2_writepage - Write complete page
142 * @page: Page to write 102 * @page: Page to write
@@ -184,7 +144,7 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
184 gfs2_page_add_databufs(ip, page, 0, sdp->sd_vfs->s_blocksize-1); 144 gfs2_page_add_databufs(ip, page, 0, sdp->sd_vfs->s_blocksize-1);
185 done_trans = 1; 145 done_trans = 1;
186 } 146 }
187 error = block_write_full_page(page, get_block_noalloc, wbc); 147 error = block_write_full_page(page, gfs2_get_block_noalloc, wbc);
188 if (done_trans) 148 if (done_trans)
189 gfs2_trans_end(sdp); 149 gfs2_trans_end(sdp);
190 gfs2_meta_cache_flush(ip); 150 gfs2_meta_cache_flush(ip);
@@ -680,7 +640,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
680 rv = blockdev_direct_IO_own_locking(rw, iocb, inode, 640 rv = blockdev_direct_IO_own_locking(rw, iocb, inode,
681 inode->i_sb->s_bdev, 641 inode->i_sb->s_bdev,
682 iov, offset, nr_segs, 642 iov, offset, nr_segs,
683 get_block_direct, NULL); 643 gfs2_get_block_direct, NULL);
684out: 644out:
685 gfs2_glock_dq_m(1, &gh); 645 gfs2_glock_dq_m(1, &gh);
686 gfs2_holder_uninit(&gh); 646 gfs2_holder_uninit(&gh);