mirror of https://gitee.com/openkylin/linux.git
nilfs2: support contiguous lookup of blocks
Although get_block() callback function can return extent of contiguous blocks with bh->b_size, nilfs_get_block() function did not support this feature. This adds contiguous lookup feature to the block mapping codes of nilfs, and allows the nilfs_get_blocks() function to return the extent information by applying the feature. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
This commit is contained in:
parent
fa032744ad
commit
c3a7abf06c
|
@ -31,7 +31,7 @@
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
|
|
||||||
static struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
|
struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
|
||||||
{
|
{
|
||||||
return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
|
return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,16 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
|
||||||
|
unsigned maxblocks)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
down_read(&bmap->b_sem);
|
||||||
|
ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
|
||||||
|
up_read(&bmap->b_sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nilfs_bmap_lookup - find a record
|
* nilfs_bmap_lookup - find a record
|
||||||
|
|
|
@ -64,6 +64,8 @@ struct nilfs_bmap_stats {
|
||||||
*/
|
*/
|
||||||
struct nilfs_bmap_operations {
|
struct nilfs_bmap_operations {
|
||||||
int (*bop_lookup)(const struct nilfs_bmap *, __u64, int, __u64 *);
|
int (*bop_lookup)(const struct nilfs_bmap *, __u64, int, __u64 *);
|
||||||
|
int (*bop_lookup_contig)(const struct nilfs_bmap *, __u64, __u64 *,
|
||||||
|
unsigned);
|
||||||
int (*bop_insert)(struct nilfs_bmap *, __u64, __u64);
|
int (*bop_insert)(struct nilfs_bmap *, __u64, __u64);
|
||||||
int (*bop_delete)(struct nilfs_bmap *, __u64);
|
int (*bop_delete)(struct nilfs_bmap *, __u64);
|
||||||
void (*bop_clear)(struct nilfs_bmap *);
|
void (*bop_clear)(struct nilfs_bmap *);
|
||||||
|
@ -140,6 +142,7 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
|
||||||
int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
|
int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
|
||||||
void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *);
|
void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *);
|
||||||
int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *);
|
int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *);
|
||||||
|
int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned);
|
||||||
int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long);
|
int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long);
|
||||||
int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long);
|
int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long);
|
||||||
int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *);
|
int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *);
|
||||||
|
@ -160,6 +163,7 @@ void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
|
||||||
/*
|
/*
|
||||||
* Internal use only
|
* Internal use only
|
||||||
*/
|
*/
|
||||||
|
struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *);
|
||||||
int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *,
|
int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *,
|
||||||
union nilfs_bmap_ptr_req *);
|
union nilfs_bmap_ptr_req *);
|
||||||
void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *,
|
void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *,
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "btnode.h"
|
#include "btnode.h"
|
||||||
#include "btree.h"
|
#include "btree.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
|
#include "dat.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct nilfs_btree_path - A path on which B-tree operations are executed
|
* struct nilfs_btree_path - A path on which B-tree operations are executed
|
||||||
|
@ -595,6 +596,87 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
|
||||||
|
__u64 key, __u64 *ptrp, unsigned maxblocks)
|
||||||
|
{
|
||||||
|
struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
|
||||||
|
struct nilfs_btree_path *path;
|
||||||
|
struct nilfs_btree_node *node;
|
||||||
|
struct inode *dat = NULL;
|
||||||
|
__u64 ptr, ptr2;
|
||||||
|
sector_t blocknr;
|
||||||
|
int level = NILFS_BTREE_LEVEL_NODE_MIN;
|
||||||
|
int ret, cnt, index, maxlevel;
|
||||||
|
|
||||||
|
path = nilfs_btree_alloc_path(btree);
|
||||||
|
if (path == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
nilfs_btree_init_path(btree, path);
|
||||||
|
ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (NILFS_BMAP_USE_VBN(bmap)) {
|
||||||
|
dat = nilfs_bmap_get_dat(bmap);
|
||||||
|
ret = nilfs_dat_translate(dat, ptr, &blocknr);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
ptr = blocknr;
|
||||||
|
}
|
||||||
|
cnt = 1;
|
||||||
|
if (cnt == maxblocks)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
maxlevel = nilfs_btree_height(btree) - 1;
|
||||||
|
node = nilfs_btree_get_node(btree, path, level);
|
||||||
|
index = path[level].bp_index + 1;
|
||||||
|
for (;;) {
|
||||||
|
while (index < nilfs_btree_node_get_nchildren(btree, node)) {
|
||||||
|
if (nilfs_btree_node_get_key(btree, node, index) !=
|
||||||
|
key + cnt)
|
||||||
|
goto end;
|
||||||
|
ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
|
||||||
|
if (dat) {
|
||||||
|
ret = nilfs_dat_translate(dat, ptr2, &blocknr);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
ptr2 = blocknr;
|
||||||
|
}
|
||||||
|
if (ptr2 != ptr + cnt || ++cnt == maxblocks)
|
||||||
|
goto end;
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (level == maxlevel)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* look-up right sibling node */
|
||||||
|
node = nilfs_btree_get_node(btree, path, level + 1);
|
||||||
|
index = path[level + 1].bp_index + 1;
|
||||||
|
if (index >= nilfs_btree_node_get_nchildren(btree, node) ||
|
||||||
|
nilfs_btree_node_get_key(btree, node, index) != key + cnt)
|
||||||
|
break;
|
||||||
|
ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
|
||||||
|
path[level + 1].bp_index = index;
|
||||||
|
|
||||||
|
brelse(path[level].bp_bh);
|
||||||
|
path[level].bp_bh = NULL;
|
||||||
|
ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
node = nilfs_btree_get_nonroot_node(btree, path, level);
|
||||||
|
index = 0;
|
||||||
|
path[level].bp_index = index;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
*ptrp = ptr;
|
||||||
|
ret = cnt;
|
||||||
|
out:
|
||||||
|
nilfs_btree_clear_path(btree, path);
|
||||||
|
nilfs_btree_free_path(btree, path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void nilfs_btree_promote_key(struct nilfs_btree *btree,
|
static void nilfs_btree_promote_key(struct nilfs_btree *btree,
|
||||||
struct nilfs_btree_path *path,
|
struct nilfs_btree_path *path,
|
||||||
int level, __u64 key)
|
int level, __u64 key)
|
||||||
|
@ -2187,6 +2269,7 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
|
||||||
|
|
||||||
static const struct nilfs_bmap_operations nilfs_btree_ops = {
|
static const struct nilfs_bmap_operations nilfs_btree_ops = {
|
||||||
.bop_lookup = nilfs_btree_lookup,
|
.bop_lookup = nilfs_btree_lookup,
|
||||||
|
.bop_lookup_contig = nilfs_btree_lookup_contig,
|
||||||
.bop_insert = nilfs_btree_insert,
|
.bop_insert = nilfs_btree_insert,
|
||||||
.bop_delete = nilfs_btree_delete,
|
.bop_delete = nilfs_btree_delete,
|
||||||
.bop_clear = NULL,
|
.bop_clear = NULL,
|
||||||
|
@ -2206,6 +2289,7 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = {
|
||||||
|
|
||||||
static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
|
static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
|
||||||
.bop_lookup = NULL,
|
.bop_lookup = NULL,
|
||||||
|
.bop_lookup_contig = NULL,
|
||||||
.bop_insert = NULL,
|
.bop_insert = NULL,
|
||||||
.bop_delete = NULL,
|
.bop_delete = NULL,
|
||||||
.bop_clear = NULL,
|
.bop_clear = NULL,
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "page.h"
|
#include "page.h"
|
||||||
#include "direct.h"
|
#include "direct.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
|
#include "dat.h"
|
||||||
|
|
||||||
static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct)
|
static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +63,47 @@ static int nilfs_direct_lookup(const struct nilfs_bmap *bmap,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap,
|
||||||
|
__u64 key, __u64 *ptrp,
|
||||||
|
unsigned maxblocks)
|
||||||
|
{
|
||||||
|
struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
|
||||||
|
struct inode *dat = NULL;
|
||||||
|
__u64 ptr, ptr2;
|
||||||
|
sector_t blocknr;
|
||||||
|
int ret, cnt;
|
||||||
|
|
||||||
|
if (key > NILFS_DIRECT_KEY_MAX ||
|
||||||
|
(ptr = nilfs_direct_get_ptr(direct, key)) ==
|
||||||
|
NILFS_BMAP_INVALID_PTR)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
if (NILFS_BMAP_USE_VBN(bmap)) {
|
||||||
|
dat = nilfs_bmap_get_dat(bmap);
|
||||||
|
ret = nilfs_dat_translate(dat, ptr, &blocknr);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
ptr = blocknr;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxblocks = min_t(unsigned, maxblocks, NILFS_DIRECT_KEY_MAX - key + 1);
|
||||||
|
for (cnt = 1; cnt < maxblocks &&
|
||||||
|
(ptr2 = nilfs_direct_get_ptr(direct, key + cnt)) !=
|
||||||
|
NILFS_BMAP_INVALID_PTR;
|
||||||
|
cnt++) {
|
||||||
|
if (dat) {
|
||||||
|
ret = nilfs_dat_translate(dat, ptr2, &blocknr);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
ptr2 = blocknr;
|
||||||
|
}
|
||||||
|
if (ptr2 != ptr + cnt)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*ptrp = ptr;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
static __u64
|
static __u64
|
||||||
nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key)
|
nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key)
|
||||||
{
|
{
|
||||||
|
@ -367,6 +409,7 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap,
|
||||||
|
|
||||||
static const struct nilfs_bmap_operations nilfs_direct_ops = {
|
static const struct nilfs_bmap_operations nilfs_direct_ops = {
|
||||||
.bop_lookup = nilfs_direct_lookup,
|
.bop_lookup = nilfs_direct_lookup,
|
||||||
|
.bop_lookup_contig = nilfs_direct_lookup_contig,
|
||||||
.bop_insert = nilfs_direct_insert,
|
.bop_insert = nilfs_direct_insert,
|
||||||
.bop_delete = nilfs_direct_delete,
|
.bop_delete = nilfs_direct_delete,
|
||||||
.bop_clear = NULL,
|
.bop_clear = NULL,
|
||||||
|
|
|
@ -43,22 +43,23 @@
|
||||||
*
|
*
|
||||||
* This function does not issue actual read request of the specified data
|
* This function does not issue actual read request of the specified data
|
||||||
* block. It is done by VFS.
|
* block. It is done by VFS.
|
||||||
* Bulk read for direct-io is not supported yet. (should be supported)
|
|
||||||
*/
|
*/
|
||||||
int nilfs_get_block(struct inode *inode, sector_t blkoff,
|
int nilfs_get_block(struct inode *inode, sector_t blkoff,
|
||||||
struct buffer_head *bh_result, int create)
|
struct buffer_head *bh_result, int create)
|
||||||
{
|
{
|
||||||
struct nilfs_inode_info *ii = NILFS_I(inode);
|
struct nilfs_inode_info *ii = NILFS_I(inode);
|
||||||
unsigned long blknum = 0;
|
__u64 blknum = 0;
|
||||||
int err = 0, ret;
|
int err = 0, ret;
|
||||||
struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode));
|
struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode));
|
||||||
|
unsigned maxblocks = bh_result->b_size >> inode->i_blkbits;
|
||||||
|
|
||||||
/* This exclusion control is a workaround; should be revised */
|
down_read(&NILFS_MDT(dat)->mi_sem);
|
||||||
down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */
|
ret = nilfs_bmap_lookup_contig(ii->i_bmap, blkoff, &blknum, maxblocks);
|
||||||
ret = nilfs_bmap_lookup(ii->i_bmap, (unsigned long)blkoff, &blknum);
|
up_read(&NILFS_MDT(dat)->mi_sem);
|
||||||
up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */
|
if (ret >= 0) { /* found */
|
||||||
if (ret == 0) { /* found */
|
|
||||||
map_bh(bh_result, inode->i_sb, blknum);
|
map_bh(bh_result, inode->i_sb, blknum);
|
||||||
|
if (ret > 0)
|
||||||
|
bh_result->b_size = (ret << inode->i_blkbits);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* data block was not found */
|
/* data block was not found */
|
||||||
|
|
Loading…
Reference in New Issue