diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-18 17:18:23 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-18 17:18:23 -0400 |
commit | 7a6bbacbb8dec6fbd1242c959250388f907d429e (patch) | |
tree | 8e314f0b3fd6e54154562c0a9b20173d539470a2 /fs/gfs2/ops_address.c | |
parent | 65952fb4e91c159d253bd28ceaf028a86dbb0b02 (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.c | 68 |
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, | |||
65 | int gfs2_get_block(struct inode *inode, sector_t lblock, | 65 | int 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 | ||
99 | static int get_block_noalloc(struct inode *inode, sector_t lblock, | 81 | static 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 | ||
121 | static int get_block_direct(struct inode *inode, sector_t lblock, | 94 | static 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); |
684 | out: | 644 | out: |
685 | gfs2_glock_dq_m(1, &gh); | 645 | gfs2_glock_dq_m(1, &gh); |
686 | gfs2_holder_uninit(&gh); | 646 | gfs2_holder_uninit(&gh); |