From f45b7ddd2bae1dc98e35c3611b55cba6d2a8da9e Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 27 Jul 2006 13:53:53 -0400 Subject: [PATCH] [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 --- fs/gfs2/glock.c | 3 +- fs/gfs2/glops.c | 22 +++----------- fs/gfs2/ops_fstype.c | 5 ---- 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, /* If this glock protects actual on-disk data or metadata blocks, create a VFS inode to manage the pages/buffers holding them. */ if (glops == &gfs2_inode_glops || - glops == &gfs2_rgrp_glops || - glops == &gfs2_meta_glops) { + glops == &gfs2_rgrp_glops) { gl->gl_aspace = gfs2_aspace_get(sdp); if (!gl->gl_aspace) { 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 @@ -156,18 +156,6 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags) gl->gl_vn++; } -/** - * meta_go_demote_ok - Check to see if it's ok to unlock a glock - * @gl: the glock - * - * Returns: 1 if we have no cached data; ok to demote meta glock - */ - -static int meta_go_demote_ok(struct gfs2_glock *gl) -{ - return !gl->gl_aspace->i_mapping->nrpages; -} - /** * inode_go_xmote_th - promote/demote a glock * @gl: the glock @@ -338,11 +326,12 @@ static void inode_go_unlock(struct gfs2_holder *gh) struct gfs2_glock *gl = gh->gh_gl; struct gfs2_inode *ip = gl->gl_object; - if (ip && test_bit(GLF_DIRTY, &gl->gl_flags)) - gfs2_inode_attr_in(ip); + if (ip) { + if (test_bit(GLF_DIRTY, &gl->gl_flags)) + gfs2_inode_attr_in(ip); - if (ip) gfs2_meta_cache_flush(ip); + } } /** @@ -507,9 +496,6 @@ static int quota_go_demote_ok(struct gfs2_glock *gl) struct gfs2_glock_operations gfs2_meta_glops = { .go_xmote_th = gfs2_glock_xmote_th, .go_drop_th = gfs2_glock_drop_th, - .go_sync = meta_go_sync, - .go_inval = meta_go_inval, - .go_demote_ok = meta_go_demote_ok, .go_type = LM_TYPE_META }; 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) sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE); goto out; } - - /* Get rid of buffers from the original block size */ - sb_gh.gh_gl->gl_ops->go_inval(sb_gh.gh_gl, DIO_METADATA | DIO_DATA); - sb_gh.gh_gl->gl_aspace->i_blkbits = sdp->sd_sb.sb_bsize_shift; - sb_set_blocksize(sb, sdp->sd_sb.sb_bsize); /* 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 @@ #include #include #include +#include #include "gfs2.h" #include "lm_interface.h" @@ -157,6 +158,54 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent) return 0; } + +static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) +{ + struct page *page = bio->bi_private; + if (bio->bi_size) + return 1; + + if (!error) + SetPageUptodate(page); + unlock_page(page); + return 0; +} + +static struct page *gfs2_read_super(struct super_block *sb, sector_t sector) +{ + struct page *page; + struct bio *bio; + + page = alloc_page(GFP_KERNEL); + if (unlikely(!page)) + return NULL; + + ClearPageUptodate(page); + ClearPageDirty(page); + lock_page(page); + + bio = bio_alloc(GFP_KERNEL, 1); + if (unlikely(!bio)) { + __free_page(page); + return NULL; + } + + bio->bi_sector = sector; + bio->bi_bdev = sb->s_bdev; + bio_add_page(bio, page, PAGE_SIZE, 0); + + bio->bi_end_io = end_bio_io_page; + bio->bi_private = page; + submit_bio(READ | BIO_RW_SYNC, bio); + wait_on_page_locked(page); + bio_put(bio); + if (!PageUptodate(page)) { + __free_page(page); + return NULL; + } + return page; +} + /** * gfs2_read_sb - Read super block * @sdp: The GFS2 superblock @@ -167,23 +216,23 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent) int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) { - struct buffer_head *bh; uint32_t hash_blocks, ind_blocks, leaf_blocks; uint32_t tmp_blocks; unsigned int x; int error; + struct page *page; + char *sb; - error = gfs2_meta_read(gl, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift, - DIO_FORCE | DIO_START | DIO_WAIT, &bh); - if (error) { + page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); + if (!page) { if (!silent) fs_err(sdp, "can't read superblock\n"); - return error; + return -EIO; } - - gfs2_assert(sdp, sizeof(struct gfs2_sb) <= bh->b_size); - gfs2_sb_in(&sdp->sd_sb, bh->b_data); - brelse(bh); + sb = kmap(page); + gfs2_sb_in(&sdp->sd_sb, sb); + kunmap(page); + __free_page(page); error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); if (error) @@ -202,7 +251,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t); sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / - sizeof(struct gfs2_quota_change); + sizeof(struct gfs2_quota_change); /* Compute maximum reservation required to add a entry to a directory */ -- GitLab