[GFS2] Readpages support

This adds readpages support (and also corrects a small bug in
the readpage error path at the same time). Hopefully this will
improve performance by allowing GFS to submit larger lumps of
I/O at a time.

In order to simplify the setting of BH_Boundary, it currently gets
set when we hit the end of a indirect pointer block. There is
always a boundary at this point with the current allocation code.
It doesn't get all the boundaries right though, so there is still
room for improvement in this.

See comments in fs/gfs2/ops_address.c for further information about
readpages with GFS2.

Signed-off-by: Steven Whitehouse
This commit is contained in:
Steven Whitehouse 2006-05-05 16:59:11 -04:00
parent 5bb76af1e0
commit fd88de569b
13 changed files with 254 additions and 129 deletions

View File

@ -314,13 +314,17 @@ static void find_metapath(struct gfs2_inode *ip, uint64_t block,
* metadata tree. * metadata tree.
*/ */
static inline uint64_t *metapointer(struct buffer_head *bh, static inline u64 *metapointer(struct buffer_head *bh, int *boundary,
unsigned int height, struct metapath *mp) unsigned int height, const struct metapath *mp)
{ {
unsigned int head_size = (height > 0) ? unsigned int head_size = (height > 0) ?
sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
u64 *ptr;
return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height]; *boundary = 0;
ptr = ((u64 *)(bh->b_data + head_size)) + mp->mp_list[height];
if (ptr + 1 == (u64*)(bh->b_data + bh->b_size))
*boundary = 1;
return ptr;
} }
/** /**
@ -339,24 +343,24 @@ static inline uint64_t *metapointer(struct buffer_head *bh,
* *
*/ */
static void lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
unsigned int height, struct metapath *mp, int create, unsigned int height, struct metapath *mp, int create,
int *new, uint64_t *block) int *new, uint64_t *block)
{ {
uint64_t *ptr = metapointer(bh, height, mp); int boundary;
uint64_t *ptr = metapointer(bh, &boundary, height, mp);
if (*ptr) { if (*ptr) {
*block = be64_to_cpu(*ptr); *block = be64_to_cpu(*ptr);
return; return boundary;
} }
*block = 0; *block = 0;
if (!create) if (!create)
return; return 0;
if (height == ip->i_di.di_height - 1 && if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip))
!gfs2_is_dir(ip))
*block = gfs2_alloc_data(ip); *block = gfs2_alloc_data(ip);
else else
*block = gfs2_alloc_meta(ip); *block = gfs2_alloc_meta(ip);
@ -367,15 +371,16 @@ static void lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
ip->i_di.di_blocks++; ip->i_di.di_blocks++;
*new = 1; *new = 1;
return 0;
} }
/** /**
* gfs2_block_map - Map a block from an inode to a disk block * gfs2_block_pointers - Map a block from an inode to a disk block
* @ip: The GFS2 inode * @inode: The inode
* @lblock: The logical block number * @lblock: The logical block number
* @new: Value/Result argument (1 = may create/did create new blocks) * @new: Value/Result argument (1 = may create/did create new blocks)
* @dblock: the disk block number of the start of an extent * @boundary: gets set if we've hit a block boundary
* @extlen: the size of the extent * @mp: metapath to use
* *
* Find the block number on the current device which corresponds to an * Find the block number on the current device which corresponds to an
* inode's block. If the block had to be created, "new" will be set. * inode's block. If the block had to be created, "new" will be set.
@ -383,12 +388,14 @@ static void lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
* Returns: errno * Returns: errno
*/ */
int gfs2_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new, static struct buffer_head *gfs2_block_pointers(struct inode *inode, u64 lblock,
uint64_t *dblock, uint32_t *extlen) int *new, u64 *dblock,
int *boundary,
struct metapath *mp)
{ {
struct gfs2_inode *ip = inode->u.generic_ip;
struct gfs2_sbd *sdp = ip->i_sbd; struct gfs2_sbd *sdp = ip->i_sbd;
struct buffer_head *bh; struct buffer_head *bh;
struct metapath mp;
int create = *new; int create = *new;
unsigned int bsize; unsigned int bsize;
unsigned int height; unsigned int height;
@ -398,13 +405,6 @@ int gfs2_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
*new = 0; *new = 0;
*dblock = 0; *dblock = 0;
if (extlen)
*extlen = 0;
if (create)
down_write(&ip->i_rw_mutex);
else
down_read(&ip->i_rw_mutex);
if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
goto out; goto out;
@ -421,7 +421,7 @@ int gfs2_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
goto out; goto out;
} }
find_metapath(ip, lblock, &mp); find_metapath(ip, lblock, mp);
end_of_metadata = ip->i_di.di_height - 1; end_of_metadata = ip->i_di.di_height - 1;
error = gfs2_meta_inode_buffer(ip, &bh); error = gfs2_meta_inode_buffer(ip, &bh);
@ -429,7 +429,7 @@ int gfs2_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
goto out; goto out;
for (x = 0; x < end_of_metadata; x++) { for (x = 0; x < end_of_metadata; x++) {
lookup_block(ip, bh, x, &mp, create, new, dblock); lookup_block(ip, bh, x, mp, create, new, dblock);
brelse(bh); brelse(bh);
if (!*dblock) if (!*dblock)
goto out; goto out;
@ -439,49 +439,95 @@ int gfs2_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
goto out; goto out;
} }
lookup_block(ip, bh, end_of_metadata, &mp, create, new, dblock); *boundary = lookup_block(ip, bh, end_of_metadata, mp, create, new, dblock);
if (extlen && *dblock) {
*extlen = 1;
if (!*new) {
uint64_t tmp_dblock;
int tmp_new;
unsigned int nptrs;
nptrs = (end_of_metadata) ? sdp->sd_inptrs :
sdp->sd_diptrs;
while (++mp.mp_list[end_of_metadata] < nptrs) {
lookup_block(ip, bh, end_of_metadata, &mp,
0, &tmp_new, &tmp_dblock);
if (*dblock + *extlen != tmp_dblock)
break;
(*extlen)++;
}
}
}
brelse(bh);
if (*new) { if (*new) {
error = gfs2_meta_inode_buffer(ip, &bh); struct buffer_head *dibh;
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) { if (!error) {
gfs2_trans_add_bh(ip->i_gl, bh, 1); gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(&ip->i_di, bh->b_data); gfs2_dinode_out(&ip->i_di, dibh->b_data);
brelse(bh); brelse(dibh);
} }
} }
return bh;
out:
return ERR_PTR(error);
}
out:
static inline void bmap_lock(struct inode *inode, int create)
{
struct gfs2_inode *ip = inode->u.generic_ip;
if (create)
down_write(&ip->i_rw_mutex);
else
down_read(&ip->i_rw_mutex);
}
static inline void bmap_unlock(struct inode *inode, int create)
{
struct gfs2_inode *ip = inode->u.generic_ip;
if (create) if (create)
up_write(&ip->i_rw_mutex); up_write(&ip->i_rw_mutex);
else else
up_read(&ip->i_rw_mutex); up_read(&ip->i_rw_mutex);
}
return error; int gfs2_block_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, int *boundary)
{
struct metapath mp;
struct buffer_head *bh;
int create = *new;
bmap_lock(inode, create);
bh = gfs2_block_pointers(inode, lblock, new, dblock, boundary, &mp);
bmap_unlock(inode, create);
if (!bh)
return 0;
if (IS_ERR(bh))
return PTR_ERR(bh);
brelse(bh);
return 0;
}
int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
{
struct gfs2_inode *ip = inode->u.generic_ip;
struct gfs2_sbd *sdp = ip->i_sbd;
struct metapath mp;
struct buffer_head *bh;
int boundary;
int create = *new;
BUG_ON(!extlen);
BUG_ON(!dblock);
BUG_ON(!new);
bmap_lock(inode, create);
bh = gfs2_block_pointers(inode, lblock, new, dblock, &boundary, &mp);
*extlen = 1;
if (bh && !IS_ERR(bh) && *dblock && !*new) {
u64 tmp_dblock;
int tmp_new;
unsigned int nptrs;
unsigned end_of_metadata = ip->i_di.di_height - 1;
nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
while (++mp.mp_list[end_of_metadata] < nptrs) {
lookup_block(ip, bh, end_of_metadata, &mp, 0, &tmp_new, &tmp_dblock);
if (*dblock + *extlen != tmp_dblock)
break;
(*extlen)++;
}
}
bmap_unlock(inode, create);
if (!bh)
return 0;
if (IS_ERR(bh))
return PTR_ERR(bh);
brelse(bh);
return 0;
} }
/** /**
@ -1053,7 +1099,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, uint64_t offset,
} }
for (; lblock < lblock_stop; lblock += extlen) { for (; lblock < lblock_stop; lblock += extlen) {
error = gfs2_block_map(ip, lblock, &new, &dblock, &extlen); error = gfs2_extent_map(ip->i_vnode, lblock, &new, &dblock, &extlen);
if (error) if (error)
return error; return error;

View File

@ -16,9 +16,8 @@ typedef int (*gfs2_unstuffer_t) (struct gfs2_inode * ip,
int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer,
void *private); void *private);
int gfs2_block_map(struct gfs2_inode *ip, int gfs2_block_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, int *boundary);
uint64_t lblock, int *new, int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
uint64_t *dblock, uint32_t *extlen);
int gfs2_truncatei(struct gfs2_inode *ip, uint64_t size); int gfs2_truncatei(struct gfs2_inode *ip, uint64_t size);
int gfs2_truncatei_resume(struct gfs2_inode *ip); int gfs2_truncatei_resume(struct gfs2_inode *ip);

View File

@ -197,8 +197,8 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
if (!extlen) { if (!extlen) {
new = 1; new = 1;
error = gfs2_block_map(ip, lblock, &new, &dblock, error = gfs2_extent_map(ip->i_vnode, lblock, &new,
&extlen); &dblock, &extlen);
if (error) if (error)
goto fail; goto fail;
error = -EIO; error = -EIO;
@ -314,8 +314,8 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
if (!extlen) { if (!extlen) {
new = 0; new = 0;
error = gfs2_block_map(ip, lblock, &new, &dblock, error = gfs2_extent_map(ip->i_vnode, lblock, &new,
&extlen); &dblock, &extlen);
if (error) if (error)
goto fail; goto fail;
} }

View File

@ -2125,7 +2125,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait)
mutex_lock(&sdp->sd_invalidate_inodes_mutex); mutex_lock(&sdp->sd_invalidate_inodes_mutex);
invalidate_inodes(sdp->sd_vfs); invalidate_inodes(sdp->sd_vfs);
mutex_unlock(&sdp->sd_invalidate_inodes_mutex); mutex_unlock(&sdp->sd_invalidate_inodes_mutex);
yield(); msleep(10);
} }
} }

View File

@ -1606,9 +1606,8 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
curtime = get_seconds(); curtime = get_seconds();
if (curtime - ip->i_di.di_atime >= quantum) { if (curtime - ip->i_di.di_atime >= quantum) {
gfs2_glock_dq(gh); gfs2_glock_dq(gh);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
gh->gh_flags & ~LM_FLAG_ANY, gh);
gh);
error = gfs2_glock_nq(gh); error = gfs2_glock_nq(gh);
if (error) if (error)
return error; return error;

View File

@ -211,9 +211,9 @@ static uint64_t log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
int new = 0; int new = 0;
uint64_t dbn; uint64_t dbn;
int error; int error;
int bdy;
error = gfs2_block_map(sdp->sd_jdesc->jd_inode->u.generic_ip, error = gfs2_block_map(sdp->sd_jdesc->jd_inode, lbn, &new, &dbn, &bdy);
lbn, &new, &dbn, NULL);
gfs2_assert_withdraw(sdp, !error && dbn); gfs2_assert_withdraw(sdp, !error && dbn);
return dbn; return dbn;

View File

@ -13,6 +13,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/pagevec.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/gfs2_ondisk.h> #include <linux/gfs2_ondisk.h>
@ -47,12 +48,12 @@
int gfs2_get_block(struct inode *inode, sector_t lblock, int gfs2_get_block(struct inode *inode, sector_t lblock,
struct buffer_head *bh_result, int create) struct buffer_head *bh_result, int create)
{ {
struct gfs2_inode *ip = inode->u.generic_ip;
int new = create; int new = create;
uint64_t dblock; uint64_t dblock;
int error; int error;
int boundary;
error = gfs2_block_map(ip, lblock, &new, &dblock, NULL); error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary);
if (error) if (error)
return error; return error;
@ -62,6 +63,8 @@ int gfs2_get_block(struct inode *inode, sector_t lblock,
map_bh(bh_result, inode->i_sb, dblock); map_bh(bh_result, inode->i_sb, dblock);
if (new) if (new)
set_buffer_new(bh_result); set_buffer_new(bh_result);
if (boundary)
set_buffer_boundary(bh_result);
return 0; return 0;
} }
@ -83,8 +86,9 @@ static int get_block_noalloc(struct inode *inode, sector_t lblock,
int new = 0; int new = 0;
uint64_t dblock; uint64_t dblock;
int error; int error;
int boundary;
error = gfs2_block_map(ip, lblock, &new, &dblock, NULL); error = gfs2_block_map(inode, lblock, &new, &dblock, &boundary);
if (error) if (error)
return error; return error;
@ -92,6 +96,8 @@ static int get_block_noalloc(struct inode *inode, sector_t lblock,
map_bh(bh_result, inode->i_sb, dblock); map_bh(bh_result, inode->i_sb, dblock);
else if (gfs2_assert_withdraw(ip->i_sbd, !create)) else if (gfs2_assert_withdraw(ip->i_sbd, !create))
error = -EIO; error = -EIO;
if (boundary)
set_buffer_boundary(bh_result);
return error; return error;
} }
@ -151,6 +157,19 @@ out_ignore:
return 0; return 0;
} }
static int zero_readpage(struct page *page)
{
void *kaddr;
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, PAGE_CACHE_SIZE);
kunmap_atomic(page, KM_USER0);
SetPageUptodate(page);
return 0;
}
/** /**
* stuffed_readpage - Fill in a Linux page with stuffed file data * stuffed_readpage - Fill in a Linux page with stuffed file data
* @ip: the inode * @ip: the inode
@ -165,17 +184,18 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
void *kaddr; void *kaddr;
int error; int error;
/* Only the first page of a stuffed file might contain data */
if (unlikely(page->index))
return zero_readpage(page);
error = gfs2_meta_inode_buffer(ip, &dibh); error = gfs2_meta_inode_buffer(ip, &dibh);
if (error) if (error)
return error; return error;
kaddr = kmap_atomic(page, KM_USER0); kaddr = kmap_atomic(page, KM_USER0);
memcpy((char *)kaddr, memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode),
dibh->b_data + sizeof(struct gfs2_dinode),
ip->i_di.di_size); ip->i_di.di_size);
memset((char *)kaddr + ip->i_di.di_size, memset(kaddr + ip->i_di.di_size, 0, PAGE_CACHE_SIZE - ip->i_di.di_size);
0,
PAGE_CACHE_SIZE - ip->i_di.di_size);
kunmap_atomic(page, KM_USER0); kunmap_atomic(page, KM_USER0);
brelse(dibh); brelse(dibh);
@ -185,19 +205,6 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
return 0; return 0;
} }
static int zero_readpage(struct page *page)
{
void *kaddr;
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, PAGE_CACHE_SIZE);
kunmap_atomic(page, KM_USER0);
SetPageUptodate(page);
unlock_page(page);
return 0;
}
/** /**
* gfs2_readpage - readpage with locking * gfs2_readpage - readpage with locking
@ -215,19 +222,16 @@ static int gfs2_readpage(struct file *file, struct page *page)
struct gfs2_holder gh; struct gfs2_holder gh;
int error; int error;
if (file != &gfs2_internal_file_sentinal) { if (likely(file != &gfs2_internal_file_sentinal)) {
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|GL_AOP, &gh); gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|GL_AOP, &gh);
error = gfs2_glock_nq_m_atime(1, &gh); error = gfs2_glock_nq_m_atime(1, &gh);
if (error) if (unlikely(error))
goto out_unlock; goto out_unlock;
} }
if (gfs2_is_stuffed(ip)) { if (gfs2_is_stuffed(ip)) {
if (!page->index) { error = stuffed_readpage(ip, page);
error = stuffed_readpage(ip, page); unlock_page(page);
unlock_page(page);
} else
error = zero_readpage(page);
} else } else
error = mpage_readpage(page, gfs2_get_block); error = mpage_readpage(page, gfs2_get_block);
@ -242,6 +246,90 @@ out:
return error; return error;
out_unlock: out_unlock:
unlock_page(page); unlock_page(page);
if (file != &gfs2_internal_file_sentinal)
gfs2_holder_uninit(&gh);
goto out;
}
#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
/**
* gfs2_readpages - Read a bunch of pages at once
*
* Some notes:
* 1. This is only for readahead, so we can simply ignore any things
* which are slightly inconvenient (such as locking conflicts between
* the page lock and the glock) and return having done no I/O. Its
* obviously not something we'd want to do on too regular a basis.
* Any I/O we ignore at this time will be done via readpage later.
* 2. We have to handle stuffed files here too.
* 3. mpage_readpages() does most of the heavy lifting in the common case.
* 4. gfs2_get_block() is relied upon to set BH_Boundary in the right places.
* 5. We use LM_FLAG_TRY_1CB here, effectively we then have lock-ahead as
* well as read-ahead.
*/
static int gfs2_readpages(struct file *file, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages)
{
struct inode *inode = mapping->host;
struct gfs2_inode *ip = inode->u.generic_ip;
struct gfs2_sbd *sdp = ip->i_sbd;
struct gfs2_holder gh;
unsigned page_idx;
int ret;
if (likely(file != &gfs2_internal_file_sentinal)) {
gfs2_holder_init(ip->i_gl, LM_ST_SHARED,
LM_FLAG_TRY_1CB|GL_ATIME|GL_AOP, &gh);
ret = gfs2_glock_nq_m_atime(1, &gh);
if (ret == GLR_TRYFAILED)
goto out_noerror;
if (unlikely(ret))
goto out_unlock;
}
if (gfs2_is_stuffed(ip)) {
struct pagevec lru_pvec;
pagevec_init(&lru_pvec, 0);
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_to_page(pages);
list_del(&page->lru);
if (!add_to_page_cache(page, mapping,
page->index, GFP_KERNEL)) {
ret = stuffed_readpage(ip, page);
unlock_page(page);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
}
page_cache_release(page);
}
pagevec_lru_add(&lru_pvec);
ret = 0;
} else {
/* What we really want to do .... */
ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block);
}
if (likely(file != &gfs2_internal_file_sentinal)) {
gfs2_glock_dq_m(1, &gh);
gfs2_holder_uninit(&gh);
}
out:
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
ret = -EIO;
return ret;
out_noerror:
ret = 0;
out_unlock:
/* unlock all pages, we can't do any I/O right now */
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_to_page(pages);
list_del(&page->lru);
unlock_page(page);
page_cache_release(page);
}
if (likely(file != &gfs2_internal_file_sentinal))
gfs2_holder_uninit(&gh);
goto out; goto out;
} }
@ -572,6 +660,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
struct address_space_operations gfs2_file_aops = { struct address_space_operations gfs2_file_aops = {
.writepage = gfs2_writepage, .writepage = gfs2_writepage,
.readpage = gfs2_readpage, .readpage = gfs2_readpage,
.readpages = gfs2_readpages,
.sync_page = block_sync_page, .sync_page = block_sync_page,
.prepare_write = gfs2_prepare_write, .prepare_write = gfs2_prepare_write,
.commit_write = gfs2_commit_write, .commit_write = gfs2_commit_write,

View File

@ -92,7 +92,6 @@ static void gfs2_put_super(struct super_block *sb)
if (error) if (error)
gfs2_io_error(sdp); gfs2_io_error(sdp);
} }
/* At this point, we're through modifying the disk */ /* At this point, we're through modifying the disk */
/* Release stuff */ /* Release stuff */
@ -125,12 +124,10 @@ static void gfs2_put_super(struct super_block *sb)
gfs2_jindex_free(sdp); gfs2_jindex_free(sdp);
/* Take apart glock structures and buffer lists */ /* Take apart glock structures and buffer lists */
gfs2_gl_hash_clear(sdp, WAIT); gfs2_gl_hash_clear(sdp, WAIT);
/* Unmount the locking protocol */ /* Unmount the locking protocol */
gfs2_lm_unmount(sdp); gfs2_lm_unmount(sdp);
/* At this point, we're through participating in the lockspace */ /* At this point, we're through participating in the lockspace */
gfs2_sys_fs_del(sdp); gfs2_sys_fs_del(sdp);
vfree(sdp); vfree(sdp);
sb->s_fs_info = NULL; sb->s_fs_info = NULL;

View File

@ -90,8 +90,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
if (error) if (error)
goto out_gunlock_q; goto out_gunlock_q;
gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
&data_blocks, &ind_blocks);
al->al_requested = data_blocks + ind_blocks; al->al_requested = data_blocks + ind_blocks;
@ -99,8 +98,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
if (error) if (error)
goto out_gunlock_q; goto out_gunlock_q;
error = gfs2_trans_begin(sdp, error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length +
al->al_rgd->rd_ri.ri_length +
ind_blocks + RES_DINODE + ind_blocks + RES_DINODE +
RES_STATFS + RES_QUOTA, 0); RES_STATFS + RES_QUOTA, 0);
if (error) if (error)
@ -117,7 +115,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
unsigned int extlen; unsigned int extlen;
int new = 1; int new = 1;
error = gfs2_block_map(ip, lblock, &new, &dblock, &extlen); error = gfs2_extent_map(ip->i_vnode, lblock, &new, &dblock, &extlen);
if (error) if (error)
goto out_trans; goto out_trans;

View File

@ -255,6 +255,7 @@ static int bh_get(struct gfs2_quota_data *qd)
int new = 0; int new = 0;
struct buffer_head *bh; struct buffer_head *bh;
int error; int error;
int boundary;
mutex_lock(&sdp->sd_quota_mutex); mutex_lock(&sdp->sd_quota_mutex);
@ -266,7 +267,7 @@ static int bh_get(struct gfs2_quota_data *qd)
block = qd->qd_slot / sdp->sd_qc_per_block; block = qd->qd_slot / sdp->sd_qc_per_block;
offset = qd->qd_slot % sdp->sd_qc_per_block;; offset = qd->qd_slot % sdp->sd_qc_per_block;;
error = gfs2_block_map(ip, block, &new, &dblock, NULL); error = gfs2_block_map(ip->i_vnode, block, &new, &dblock, &boundary);
if (error) if (error)
goto fail; goto fail;
error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh); error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh);
@ -1162,7 +1163,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
if (!extlen) { if (!extlen) {
int new = 0; int new = 0;
error = gfs2_block_map(ip, x, &new, &dblock, &extlen); error = gfs2_extent_map(ip->i_vnode, x, &new, &dblock, &extlen);
if (error) if (error)
goto fail; goto fail;
} }

View File

@ -40,8 +40,7 @@ int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
uint32_t extlen; uint32_t extlen;
int error; int error;
error = gfs2_block_map(ip, blk, &new, &dblock, error = gfs2_extent_map(ip->i_vnode, blk, &new, &dblock, &extlen);
&extlen);
if (error) if (error)
return error; return error;
if (!dblock) { if (!dblock) {
@ -378,10 +377,11 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header *head)
uint32_t hash; uint32_t hash;
struct buffer_head *bh; struct buffer_head *bh;
int error; int error;
int boundary;
lblock = head->lh_blkno; lblock = head->lh_blkno;
gfs2_replay_incr_blk(sdp, &lblock); gfs2_replay_incr_blk(sdp, &lblock);
error = gfs2_block_map(ip, lblock, &new, &dblock, NULL); error = gfs2_block_map(ip->i_vnode, lblock, &new, &dblock, &boundary);
if (error) if (error)
return error; return error;
if (!dblock) { if (!dblock) {

View File

@ -956,8 +956,7 @@ static uint32_t rgblk_search(struct gfs2_rgrpd *rgd, uint32_t goal,
search in the first part of our first-searched bit block. */ search in the first part of our first-searched bit block. */
for (x = 0; x <= length; x++) { for (x = 0; x <= length; x++) {
if (bi->bi_clone) if (bi->bi_clone)
blk = gfs2_bitfit(rgd, blk = gfs2_bitfit(rgd, bi->bi_clone + bi->bi_offset,
bi->bi_clone + bi->bi_offset,
bi->bi_len, goal, old_state); bi->bi_len, goal, old_state);
else else
blk = gfs2_bitfit(rgd, blk = gfs2_bitfit(rgd,
@ -976,12 +975,10 @@ static uint32_t rgblk_search(struct gfs2_rgrpd *rgd, uint32_t goal,
blk = 0; blk = 0;
gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
gfs2_setbit(rgd, gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
bi->bi_bh->b_data + bi->bi_offset,
bi->bi_len, blk, new_state); bi->bi_len, blk, new_state);
if (bi->bi_clone) if (bi->bi_clone)
gfs2_setbit(rgd, gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
bi->bi_clone + bi->bi_offset,
bi->bi_len, blk, new_state); bi->bi_len, blk, new_state);
return bi->bi_start * GFS2_NBBY + blk; return bi->bi_start * GFS2_NBBY + blk;
@ -1064,8 +1061,7 @@ uint64_t gfs2_alloc_data(struct gfs2_inode *ip)
else else
goal = rgd->rd_last_alloc_data; goal = rgd->rd_last_alloc_data;
blk = rgblk_search(rgd, goal, blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
GFS2_BLKST_FREE, GFS2_BLKST_USED);
rgd->rd_last_alloc_data = blk; rgd->rd_last_alloc_data = blk;
block = rgd->rd_ri.ri_data0 + blk; block = rgd->rd_ri.ri_data0 + blk;
@ -1109,8 +1105,7 @@ uint64_t gfs2_alloc_meta(struct gfs2_inode *ip)
else else
goal = rgd->rd_last_alloc_meta; goal = rgd->rd_last_alloc_meta;
blk = rgblk_search(rgd, goal, blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
GFS2_BLKST_FREE, GFS2_BLKST_USED);
rgd->rd_last_alloc_meta = blk; rgd->rd_last_alloc_meta = blk;
block = rgd->rd_ri.ri_data0 + blk; block = rgd->rd_ri.ri_data0 + blk;

View File

@ -35,11 +35,12 @@ static int munge_ondisk(struct gfs2_sbd *sdp, unsigned int slot,
int new = 0; int new = 0;
struct buffer_head *bh; struct buffer_head *bh;
int error; int error;
int boundary;
block = slot / sdp->sd_ut_per_block; block = slot / sdp->sd_ut_per_block;
offset = slot % sdp->sd_ut_per_block; offset = slot % sdp->sd_ut_per_block;
error = gfs2_block_map(ip, block, &new, &dblock, NULL); error = gfs2_block_map(ip->i_vnode, block, &new, &dblock, &boundary);
if (error) if (error)
return error; return error;
error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh); error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT, &bh);
@ -354,7 +355,7 @@ int gfs2_unlinked_init(struct gfs2_sbd *sdp)
if (!extlen) { if (!extlen) {
int new = 0; int new = 0;
error = gfs2_block_map(ip, x, &new, &dblock, &extlen); error = gfs2_extent_map(ip->i_vnode, x, &new, &dblock, &extlen);
if (error) if (error)
goto fail; goto fail;
} }