[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>
This commit is contained in:
parent
ae4a382004
commit
f45b7ddd2b
|
@ -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,
|
/* If this glock protects actual on-disk data or metadata blocks,
|
||||||
create a VFS inode to manage the pages/buffers holding them. */
|
create a VFS inode to manage the pages/buffers holding them. */
|
||||||
if (glops == &gfs2_inode_glops ||
|
if (glops == &gfs2_inode_glops ||
|
||||||
glops == &gfs2_rgrp_glops ||
|
glops == &gfs2_rgrp_glops) {
|
||||||
glops == &gfs2_meta_glops) {
|
|
||||||
gl->gl_aspace = gfs2_aspace_get(sdp);
|
gl->gl_aspace = gfs2_aspace_get(sdp);
|
||||||
if (!gl->gl_aspace) {
|
if (!gl->gl_aspace) {
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
|
|
|
@ -156,18 +156,6 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags)
|
||||||
gl->gl_vn++;
|
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
|
* inode_go_xmote_th - promote/demote a glock
|
||||||
* @gl: the 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_glock *gl = gh->gh_gl;
|
||||||
struct gfs2_inode *ip = gl->gl_object;
|
struct gfs2_inode *ip = gl->gl_object;
|
||||||
|
|
||||||
if (ip && test_bit(GLF_DIRTY, &gl->gl_flags))
|
if (ip) {
|
||||||
gfs2_inode_attr_in(ip);
|
if (test_bit(GLF_DIRTY, &gl->gl_flags))
|
||||||
|
gfs2_inode_attr_in(ip);
|
||||||
|
|
||||||
if (ip)
|
|
||||||
gfs2_meta_cache_flush(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 = {
|
struct gfs2_glock_operations gfs2_meta_glops = {
|
||||||
.go_xmote_th = gfs2_glock_xmote_th,
|
.go_xmote_th = gfs2_glock_xmote_th,
|
||||||
.go_drop_th = gfs2_glock_drop_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
|
.go_type = LM_TYPE_META
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE);
|
||||||
goto out;
|
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);
|
sb_set_blocksize(sb, sdp->sd_sb.sb_bsize);
|
||||||
|
|
||||||
/* Get the root inode */
|
/* Get the root inode */
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
#include <linux/gfs2_ondisk.h>
|
#include <linux/gfs2_ondisk.h>
|
||||||
|
#include <linux/bio.h>
|
||||||
|
|
||||||
#include "gfs2.h"
|
#include "gfs2.h"
|
||||||
#include "lm_interface.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;
|
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
|
* gfs2_read_sb - Read super block
|
||||||
* @sdp: The GFS2 superblock
|
* @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)
|
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 hash_blocks, ind_blocks, leaf_blocks;
|
||||||
uint32_t tmp_blocks;
|
uint32_t tmp_blocks;
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
int error;
|
int error;
|
||||||
|
struct page *page;
|
||||||
|
char *sb;
|
||||||
|
|
||||||
error = gfs2_meta_read(gl, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift,
|
page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
|
||||||
DIO_FORCE | DIO_START | DIO_WAIT, &bh);
|
if (!page) {
|
||||||
if (error) {
|
|
||||||
if (!silent)
|
if (!silent)
|
||||||
fs_err(sdp, "can't read superblock\n");
|
fs_err(sdp, "can't read superblock\n");
|
||||||
return error;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
sb = kmap(page);
|
||||||
gfs2_assert(sdp, sizeof(struct gfs2_sb) <= bh->b_size);
|
gfs2_sb_in(&sdp->sd_sb, sb);
|
||||||
gfs2_sb_in(&sdp->sd_sb, bh->b_data);
|
kunmap(page);
|
||||||
brelse(bh);
|
__free_page(page);
|
||||||
|
|
||||||
error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
|
error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
|
||||||
if (error)
|
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_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
|
||||||
sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
|
sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
|
||||||
sizeof(struct gfs2_meta_header)) /
|
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 */
|
/* Compute maximum reservation required to add a entry to a directory */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue