[GFS2] Use a bio to read the superblock
authorSteven Whitehouse <swhiteho@redhat.com>
Thu, 27 Jul 2006 17:53:53 +0000 (13:53 -0400)
committerSteven Whitehouse <swhiteho@redhat.com>
Thu, 27 Jul 2006 17:53:53 +0000 (13:53 -0400)
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>
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/ops_fstype.c
fs/gfs2/super.c

index 0381d4c..91ac9c9 100644 (file)
@@ -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;
index 3f909a8..75d4c50 100644 (file)
@@ -157,18 +157,6 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags)
 }
 
 /**
- * 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
  * @state: the requested state
@@ -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
 };
 
index a86ce67..de18923 100644 (file)
@@ -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 */
index f2d2876..48fd4cb 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/buffer_head.h>
 #include <linux/crc32.h>
 #include <linux/gfs2_ondisk.h>
+#include <linux/bio.h>
 
 #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 */