aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-07-27 13:53:53 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-07-27 13:53:53 -0400
commitf45b7ddd2bae1dc98e35c3611b55cba6d2a8da9e (patch)
treeb2c498fc65855cb0f7ec17b9e2a42200aae633af
parentae4a382004fc6cf229c51deaf69910410d313e0b (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.c3
-rw-r--r--fs/gfs2/glops.c22
-rw-r--r--fs/gfs2/ops_fstype.c5
-rw-r--r--fs/gfs2/super.c69
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
166static 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)
507struct gfs2_glock_operations gfs2_meta_glops = { 496struct 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
162static 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
174static 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
168int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) 217int 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