diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-07-27 13:53:53 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-07-27 13:53:53 -0400 |
commit | f45b7ddd2bae1dc98e35c3611b55cba6d2a8da9e (patch) | |
tree | b2c498fc65855cb0f7ec17b9e2a42200aae633af | |
parent | ae4a382004fc6cf229c51deaf69910410d313e0b (diff) |
[GFS2] Use a bio to read the superblock
This means that we don't need to create a special inode just to contain
a struct address_space in order to read a single disk block. Instead
we read the disk block directly. Its slightly faster, and uses slightly
less memory, but the real reason for doing this is that it removes a
special case from the glock code.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r-- | fs/gfs2/glock.c | 3 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 22 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 5 | ||||
-rw-r--r-- | fs/gfs2/super.c | 69 |
4 files changed, 64 insertions, 35 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 0381d4cc4146..91ac9c9d4a96 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -311,8 +311,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, uint64_t number, | |||
311 | /* If this glock protects actual on-disk data or metadata blocks, | 311 | /* If this glock protects actual on-disk data or metadata blocks, |
312 | create a VFS inode to manage the pages/buffers holding them. */ | 312 | create a VFS inode to manage the pages/buffers holding them. */ |
313 | if (glops == &gfs2_inode_glops || | 313 | if (glops == &gfs2_inode_glops || |
314 | glops == &gfs2_rgrp_glops || | 314 | glops == &gfs2_rgrp_glops) { |
315 | glops == &gfs2_meta_glops) { | ||
316 | gl->gl_aspace = gfs2_aspace_get(sdp); | 315 | gl->gl_aspace = gfs2_aspace_get(sdp); |
317 | if (!gl->gl_aspace) { | 316 | if (!gl->gl_aspace) { |
318 | error = -ENOMEM; | 317 | error = -ENOMEM; |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 3f909a81a071..75d4c50cff45 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -157,18 +157,6 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags) | |||
157 | } | 157 | } |
158 | 158 | ||
159 | /** | 159 | /** |
160 | * meta_go_demote_ok - Check to see if it's ok to unlock a glock | ||
161 | * @gl: the glock | ||
162 | * | ||
163 | * Returns: 1 if we have no cached data; ok to demote meta glock | ||
164 | */ | ||
165 | |||
166 | static int meta_go_demote_ok(struct gfs2_glock *gl) | ||
167 | { | ||
168 | return !gl->gl_aspace->i_mapping->nrpages; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * inode_go_xmote_th - promote/demote a glock | 160 | * inode_go_xmote_th - promote/demote a glock |
173 | * @gl: the glock | 161 | * @gl: the glock |
174 | * @state: the requested state | 162 | * @state: the requested state |
@@ -338,11 +326,12 @@ static void inode_go_unlock(struct gfs2_holder *gh) | |||
338 | struct gfs2_glock *gl = gh->gh_gl; | 326 | struct gfs2_glock *gl = gh->gh_gl; |
339 | struct gfs2_inode *ip = gl->gl_object; | 327 | struct gfs2_inode *ip = gl->gl_object; |
340 | 328 | ||
341 | if (ip && test_bit(GLF_DIRTY, &gl->gl_flags)) | 329 | if (ip) { |
342 | gfs2_inode_attr_in(ip); | 330 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) |
331 | gfs2_inode_attr_in(ip); | ||
343 | 332 | ||
344 | if (ip) | ||
345 | gfs2_meta_cache_flush(ip); | 333 | gfs2_meta_cache_flush(ip); |
334 | } | ||
346 | } | 335 | } |
347 | 336 | ||
348 | /** | 337 | /** |
@@ -507,9 +496,6 @@ static int quota_go_demote_ok(struct gfs2_glock *gl) | |||
507 | struct gfs2_glock_operations gfs2_meta_glops = { | 496 | struct gfs2_glock_operations gfs2_meta_glops = { |
508 | .go_xmote_th = gfs2_glock_xmote_th, | 497 | .go_xmote_th = gfs2_glock_xmote_th, |
509 | .go_drop_th = gfs2_glock_drop_th, | 498 | .go_drop_th = gfs2_glock_drop_th, |
510 | .go_sync = meta_go_sync, | ||
511 | .go_inval = meta_go_inval, | ||
512 | .go_demote_ok = meta_go_demote_ok, | ||
513 | .go_type = LM_TYPE_META | 499 | .go_type = LM_TYPE_META |
514 | }; | 500 | }; |
515 | 501 | ||
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index a86ce67949db..de18923eea70 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -310,11 +310,6 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) | |||
310 | sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE); | 310 | sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE); |
311 | goto out; | 311 | goto out; |
312 | } | 312 | } |
313 | |||
314 | /* Get rid of buffers from the original block size */ | ||
315 | sb_gh.gh_gl->gl_ops->go_inval(sb_gh.gh_gl, DIO_METADATA | DIO_DATA); | ||
316 | sb_gh.gh_gl->gl_aspace->i_blkbits = sdp->sd_sb.sb_bsize_shift; | ||
317 | |||
318 | sb_set_blocksize(sb, sdp->sd_sb.sb_bsize); | 313 | sb_set_blocksize(sb, sdp->sd_sb.sb_bsize); |
319 | 314 | ||
320 | /* Get the root inode */ | 315 | /* Get the root inode */ |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index f2d287660cc9..48fd4cb49c1e 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/crc32.h> | 15 | #include <linux/crc32.h> |
16 | #include <linux/gfs2_ondisk.h> | 16 | #include <linux/gfs2_ondisk.h> |
17 | #include <linux/bio.h> | ||
17 | 18 | ||
18 | #include "gfs2.h" | 19 | #include "gfs2.h" |
19 | #include "lm_interface.h" | 20 | #include "lm_interface.h" |
@@ -157,6 +158,54 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent) | |||
157 | return 0; | 158 | return 0; |
158 | } | 159 | } |
159 | 160 | ||
161 | |||
162 | static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) | ||
163 | { | ||
164 | struct page *page = bio->bi_private; | ||
165 | if (bio->bi_size) | ||
166 | return 1; | ||
167 | |||
168 | if (!error) | ||
169 | SetPageUptodate(page); | ||
170 | unlock_page(page); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static struct page *gfs2_read_super(struct super_block *sb, sector_t sector) | ||
175 | { | ||
176 | struct page *page; | ||
177 | struct bio *bio; | ||
178 | |||
179 | page = alloc_page(GFP_KERNEL); | ||
180 | if (unlikely(!page)) | ||
181 | return NULL; | ||
182 | |||
183 | ClearPageUptodate(page); | ||
184 | ClearPageDirty(page); | ||
185 | lock_page(page); | ||
186 | |||
187 | bio = bio_alloc(GFP_KERNEL, 1); | ||
188 | if (unlikely(!bio)) { | ||
189 | __free_page(page); | ||
190 | return NULL; | ||
191 | } | ||
192 | |||
193 | bio->bi_sector = sector; | ||
194 | bio->bi_bdev = sb->s_bdev; | ||
195 | bio_add_page(bio, page, PAGE_SIZE, 0); | ||
196 | |||
197 | bio->bi_end_io = end_bio_io_page; | ||
198 | bio->bi_private = page; | ||
199 | submit_bio(READ | BIO_RW_SYNC, bio); | ||
200 | wait_on_page_locked(page); | ||
201 | bio_put(bio); | ||
202 | if (!PageUptodate(page)) { | ||
203 | __free_page(page); | ||
204 | return NULL; | ||
205 | } | ||
206 | return page; | ||
207 | } | ||
208 | |||
160 | /** | 209 | /** |
161 | * gfs2_read_sb - Read super block | 210 | * gfs2_read_sb - Read super block |
162 | * @sdp: The GFS2 superblock | 211 | * @sdp: The GFS2 superblock |
@@ -167,23 +216,23 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent) | |||
167 | 216 | ||
168 | int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) | 217 | int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) |
169 | { | 218 | { |
170 | struct buffer_head *bh; | ||
171 | uint32_t hash_blocks, ind_blocks, leaf_blocks; | 219 | uint32_t hash_blocks, ind_blocks, leaf_blocks; |
172 | uint32_t tmp_blocks; | 220 | uint32_t tmp_blocks; |
173 | unsigned int x; | 221 | unsigned int x; |
174 | int error; | 222 | int error; |
223 | struct page *page; | ||
224 | char *sb; | ||
175 | 225 | ||
176 | error = gfs2_meta_read(gl, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift, | 226 | page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); |
177 | DIO_FORCE | DIO_START | DIO_WAIT, &bh); | 227 | if (!page) { |
178 | if (error) { | ||
179 | if (!silent) | 228 | if (!silent) |
180 | fs_err(sdp, "can't read superblock\n"); | 229 | fs_err(sdp, "can't read superblock\n"); |
181 | return error; | 230 | return -EIO; |
182 | } | 231 | } |
183 | 232 | sb = kmap(page); | |
184 | gfs2_assert(sdp, sizeof(struct gfs2_sb) <= bh->b_size); | 233 | gfs2_sb_in(&sdp->sd_sb, sb); |
185 | gfs2_sb_in(&sdp->sd_sb, bh->b_data); | 234 | kunmap(page); |
186 | brelse(bh); | 235 | __free_page(page); |
187 | 236 | ||
188 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); | 237 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); |
189 | if (error) | 238 | if (error) |
@@ -202,7 +251,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) | |||
202 | sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t); | 251 | sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t); |
203 | sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize - | 252 | sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize - |
204 | sizeof(struct gfs2_meta_header)) / | 253 | sizeof(struct gfs2_meta_header)) / |
205 | sizeof(struct gfs2_quota_change); | 254 | sizeof(struct gfs2_quota_change); |
206 | 255 | ||
207 | /* Compute maximum reservation required to add a entry to a directory */ | 256 | /* Compute maximum reservation required to add a entry to a directory */ |
208 | 257 | ||