Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2: (22 commits) nilfs2: support contiguous lookup of blocks nilfs2: add sync_page method to page caches of meta data nilfs2: use device's backing_dev_info for btree node caches nilfs2: return EBUSY against delete request on snapshot nilfs2: modify list of unsupported features in caveats nilfs2: enable sync_page method nilfs2: set bio unplug flag for the last bio in segment nilfs2: allow future expansion of metadata read out via get info ioctl NILFS2: Pagecache usage optimization on NILFS2 nilfs2: remove nilfs_btree_operations from btree mapping nilfs2: remove nilfs_direct_operations from direct mapping nilfs2: remove bmap pointer operations nilfs2: remove useless b_low and b_high fields from nilfs_bmap struct nilfs2: remove pointless NULL check of bpop_commit_alloc_ptr function nilfs2: move get block functions in bmap.c into btree codes nilfs2: remove nilfs_bmap_delete_block nilfs2: remove nilfs_bmap_put_block nilfs2: remove header file for segment list operations nilfs2: eliminate removal list of segments nilfs2: add sufile function that can modify multiple segment usages ...
This commit is contained in:
commit
9c7cb99a82
|
@ -39,9 +39,8 @@ Features which NILFS2 does not support yet:
|
|||
- extended attributes
|
||||
- POSIX ACLs
|
||||
- quotas
|
||||
- writable snapshots
|
||||
- remote backup (CDP)
|
||||
- data integrity
|
||||
- fsck
|
||||
- resize
|
||||
- defragmentation
|
||||
|
||||
Mount options
|
||||
|
|
278
fs/nilfs2/bmap.c
278
fs/nilfs2/bmap.c
|
@ -31,21 +31,26 @@
|
|||
#include "dat.h"
|
||||
#include "alloc.h"
|
||||
|
||||
struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
|
||||
{
|
||||
return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
|
||||
}
|
||||
|
||||
int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
|
||||
__u64 *ptrp)
|
||||
{
|
||||
__u64 ptr;
|
||||
sector_t blocknr;
|
||||
int ret;
|
||||
|
||||
down_read(&bmap->b_sem);
|
||||
ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (bmap->b_pops->bpop_translate != NULL) {
|
||||
ret = bmap->b_pops->bpop_translate(bmap, *ptrp, &ptr);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
*ptrp = ptr;
|
||||
if (NILFS_BMAP_USE_VBN(bmap)) {
|
||||
ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
|
||||
&blocknr);
|
||||
if (!ret)
|
||||
*ptrp = blocknr;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -53,6 +58,16 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
|
|||
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
|
||||
|
@ -101,8 +116,7 @@ static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
|
|||
if (n < 0)
|
||||
return n;
|
||||
ret = nilfs_btree_convert_and_insert(
|
||||
bmap, key, ptr, keys, ptrs, n,
|
||||
NILFS_BMAP_LARGE_LOW, NILFS_BMAP_LARGE_HIGH);
|
||||
bmap, key, ptr, keys, ptrs, n);
|
||||
if (ret == 0)
|
||||
bmap->b_u.u_flags |= NILFS_BMAP_LARGE;
|
||||
|
||||
|
@ -158,8 +172,7 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
|
|||
if (n < 0)
|
||||
return n;
|
||||
ret = nilfs_direct_delete_and_convert(
|
||||
bmap, key, keys, ptrs, n,
|
||||
NILFS_BMAP_SMALL_LOW, NILFS_BMAP_SMALL_HIGH);
|
||||
bmap, key, keys, ptrs, n);
|
||||
if (ret == 0)
|
||||
bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE;
|
||||
|
||||
|
@ -417,38 +430,6 @@ void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
|
|||
mark_inode_dirty(bmap->b_inode);
|
||||
}
|
||||
|
||||
int nilfs_bmap_get_block(const struct nilfs_bmap *bmap, __u64 ptr,
|
||||
struct buffer_head **bhp)
|
||||
{
|
||||
return nilfs_btnode_get(&NILFS_BMAP_I(bmap)->i_btnode_cache,
|
||||
ptr, 0, bhp, 0);
|
||||
}
|
||||
|
||||
void nilfs_bmap_put_block(const struct nilfs_bmap *bmap,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
brelse(bh);
|
||||
}
|
||||
|
||||
int nilfs_bmap_get_new_block(const struct nilfs_bmap *bmap, __u64 ptr,
|
||||
struct buffer_head **bhp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nilfs_btnode_get(&NILFS_BMAP_I(bmap)->i_btnode_cache,
|
||||
ptr, 0, bhp, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
set_buffer_nilfs_volatile(*bhp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nilfs_bmap_delete_block(const struct nilfs_bmap *bmap,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
nilfs_btnode_delete(bh);
|
||||
}
|
||||
|
||||
__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
|
||||
const struct buffer_head *bh)
|
||||
{
|
||||
|
@ -476,11 +457,6 @@ __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key)
|
|||
return NILFS_BMAP_INVALID_PTR;
|
||||
}
|
||||
|
||||
static struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
|
||||
{
|
||||
return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
|
||||
}
|
||||
|
||||
#define NILFS_BMAP_GROUP_DIV 8
|
||||
__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
|
||||
{
|
||||
|
@ -493,64 +469,51 @@ __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
|
|||
(entries_per_group / NILFS_BMAP_GROUP_DIV);
|
||||
}
|
||||
|
||||
static int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
return nilfs_dat_prepare_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
|
||||
}
|
||||
|
||||
static void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
nilfs_dat_commit_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
|
||||
}
|
||||
|
||||
static void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
nilfs_dat_abort_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
|
||||
}
|
||||
|
||||
static int nilfs_bmap_prepare_start_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
int nilfs_bmap_start_v(struct nilfs_bmap *bmap, union nilfs_bmap_ptr_req *req,
|
||||
sector_t blocknr)
|
||||
{
|
||||
return nilfs_dat_prepare_start(nilfs_bmap_get_dat(bmap), &req->bpr_req);
|
||||
struct inode *dat = nilfs_bmap_get_dat(bmap);
|
||||
int ret;
|
||||
|
||||
ret = nilfs_dat_prepare_start(dat, &req->bpr_req);
|
||||
if (likely(!ret))
|
||||
nilfs_dat_commit_start(dat, &req->bpr_req, blocknr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nilfs_bmap_commit_start_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req,
|
||||
sector_t blocknr)
|
||||
{
|
||||
nilfs_dat_commit_start(nilfs_bmap_get_dat(bmap), &req->bpr_req,
|
||||
blocknr);
|
||||
}
|
||||
|
||||
static void nilfs_bmap_abort_start_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
nilfs_dat_abort_start(nilfs_bmap_get_dat(bmap), &req->bpr_req);
|
||||
}
|
||||
|
||||
static int nilfs_bmap_prepare_end_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
int nilfs_bmap_prepare_end_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
return nilfs_dat_prepare_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
|
||||
}
|
||||
|
||||
static void nilfs_bmap_commit_end_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
void nilfs_bmap_commit_end_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req, 0);
|
||||
nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req,
|
||||
bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
|
||||
}
|
||||
|
||||
static void nilfs_bmap_commit_end_vmdt(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req, 1);
|
||||
}
|
||||
|
||||
static void nilfs_bmap_abort_end_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
void nilfs_bmap_abort_end_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
nilfs_dat_abort_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
|
||||
}
|
||||
|
@ -566,128 +529,44 @@ int nilfs_bmap_mark_dirty(const struct nilfs_bmap *bmap, __u64 vblocknr)
|
|||
return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), vblocknr);
|
||||
}
|
||||
|
||||
int nilfs_bmap_prepare_update(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *oldreq,
|
||||
union nilfs_bmap_ptr_req *newreq)
|
||||
int nilfs_bmap_prepare_update_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *oldreq,
|
||||
union nilfs_bmap_ptr_req *newreq)
|
||||
{
|
||||
struct inode *dat = nilfs_bmap_get_dat(bmap);
|
||||
int ret;
|
||||
|
||||
ret = bmap->b_pops->bpop_prepare_end_ptr(bmap, oldreq);
|
||||
ret = nilfs_dat_prepare_end(dat, &oldreq->bpr_req);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = bmap->b_pops->bpop_prepare_alloc_ptr(bmap, newreq);
|
||||
ret = nilfs_dat_prepare_alloc(dat, &newreq->bpr_req);
|
||||
if (ret < 0)
|
||||
bmap->b_pops->bpop_abort_end_ptr(bmap, oldreq);
|
||||
nilfs_dat_abort_end(dat, &oldreq->bpr_req);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void nilfs_bmap_commit_update(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *oldreq,
|
||||
union nilfs_bmap_ptr_req *newreq)
|
||||
void nilfs_bmap_commit_update_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *oldreq,
|
||||
union nilfs_bmap_ptr_req *newreq)
|
||||
{
|
||||
bmap->b_pops->bpop_commit_end_ptr(bmap, oldreq);
|
||||
bmap->b_pops->bpop_commit_alloc_ptr(bmap, newreq);
|
||||
struct inode *dat = nilfs_bmap_get_dat(bmap);
|
||||
|
||||
nilfs_dat_commit_end(dat, &oldreq->bpr_req,
|
||||
bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
|
||||
nilfs_dat_commit_alloc(dat, &newreq->bpr_req);
|
||||
}
|
||||
|
||||
void nilfs_bmap_abort_update(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *oldreq,
|
||||
union nilfs_bmap_ptr_req *newreq)
|
||||
void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *oldreq,
|
||||
union nilfs_bmap_ptr_req *newreq)
|
||||
{
|
||||
bmap->b_pops->bpop_abort_end_ptr(bmap, oldreq);
|
||||
bmap->b_pops->bpop_abort_alloc_ptr(bmap, newreq);
|
||||
struct inode *dat = nilfs_bmap_get_dat(bmap);
|
||||
|
||||
nilfs_dat_abort_end(dat, &oldreq->bpr_req);
|
||||
nilfs_dat_abort_alloc(dat, &newreq->bpr_req);
|
||||
}
|
||||
|
||||
static int nilfs_bmap_translate_v(const struct nilfs_bmap *bmap, __u64 ptr,
|
||||
__u64 *ptrp)
|
||||
{
|
||||
sector_t blocknr;
|
||||
int ret;
|
||||
|
||||
ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), ptr, &blocknr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ptrp != NULL)
|
||||
*ptrp = blocknr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nilfs_bmap_prepare_alloc_p(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
/* ignore target ptr */
|
||||
req->bpr_ptr = bmap->b_last_allocated_ptr++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nilfs_bmap_commit_alloc_p(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static void nilfs_bmap_abort_alloc_p(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
bmap->b_last_allocated_ptr--;
|
||||
}
|
||||
|
||||
static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_v = {
|
||||
.bpop_prepare_alloc_ptr = nilfs_bmap_prepare_alloc_v,
|
||||
.bpop_commit_alloc_ptr = nilfs_bmap_commit_alloc_v,
|
||||
.bpop_abort_alloc_ptr = nilfs_bmap_abort_alloc_v,
|
||||
.bpop_prepare_start_ptr = nilfs_bmap_prepare_start_v,
|
||||
.bpop_commit_start_ptr = nilfs_bmap_commit_start_v,
|
||||
.bpop_abort_start_ptr = nilfs_bmap_abort_start_v,
|
||||
.bpop_prepare_end_ptr = nilfs_bmap_prepare_end_v,
|
||||
.bpop_commit_end_ptr = nilfs_bmap_commit_end_v,
|
||||
.bpop_abort_end_ptr = nilfs_bmap_abort_end_v,
|
||||
|
||||
.bpop_translate = nilfs_bmap_translate_v,
|
||||
};
|
||||
|
||||
static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_vmdt = {
|
||||
.bpop_prepare_alloc_ptr = nilfs_bmap_prepare_alloc_v,
|
||||
.bpop_commit_alloc_ptr = nilfs_bmap_commit_alloc_v,
|
||||
.bpop_abort_alloc_ptr = nilfs_bmap_abort_alloc_v,
|
||||
.bpop_prepare_start_ptr = nilfs_bmap_prepare_start_v,
|
||||
.bpop_commit_start_ptr = nilfs_bmap_commit_start_v,
|
||||
.bpop_abort_start_ptr = nilfs_bmap_abort_start_v,
|
||||
.bpop_prepare_end_ptr = nilfs_bmap_prepare_end_v,
|
||||
.bpop_commit_end_ptr = nilfs_bmap_commit_end_vmdt,
|
||||
.bpop_abort_end_ptr = nilfs_bmap_abort_end_v,
|
||||
|
||||
.bpop_translate = nilfs_bmap_translate_v,
|
||||
};
|
||||
|
||||
static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_p = {
|
||||
.bpop_prepare_alloc_ptr = nilfs_bmap_prepare_alloc_p,
|
||||
.bpop_commit_alloc_ptr = nilfs_bmap_commit_alloc_p,
|
||||
.bpop_abort_alloc_ptr = nilfs_bmap_abort_alloc_p,
|
||||
.bpop_prepare_start_ptr = NULL,
|
||||
.bpop_commit_start_ptr = NULL,
|
||||
.bpop_abort_start_ptr = NULL,
|
||||
.bpop_prepare_end_ptr = NULL,
|
||||
.bpop_commit_end_ptr = NULL,
|
||||
.bpop_abort_end_ptr = NULL,
|
||||
|
||||
.bpop_translate = NULL,
|
||||
};
|
||||
|
||||
static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_gc = {
|
||||
.bpop_prepare_alloc_ptr = NULL,
|
||||
.bpop_commit_alloc_ptr = NULL,
|
||||
.bpop_abort_alloc_ptr = NULL,
|
||||
.bpop_prepare_start_ptr = NULL,
|
||||
.bpop_commit_start_ptr = NULL,
|
||||
.bpop_abort_start_ptr = NULL,
|
||||
.bpop_prepare_end_ptr = NULL,
|
||||
.bpop_commit_end_ptr = NULL,
|
||||
.bpop_abort_end_ptr = NULL,
|
||||
|
||||
.bpop_translate = NULL,
|
||||
};
|
||||
|
||||
static struct lock_class_key nilfs_bmap_dat_lock_key;
|
||||
|
||||
/**
|
||||
|
@ -714,31 +593,26 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
|
|||
bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
|
||||
switch (bmap->b_inode->i_ino) {
|
||||
case NILFS_DAT_INO:
|
||||
bmap->b_pops = &nilfs_bmap_ptr_ops_p;
|
||||
bmap->b_last_allocated_key = 0; /* XXX: use macro */
|
||||
bmap->b_ptr_type = NILFS_BMAP_PTR_P;
|
||||
bmap->b_last_allocated_key = 0;
|
||||
bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
|
||||
lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
|
||||
break;
|
||||
case NILFS_CPFILE_INO:
|
||||
case NILFS_SUFILE_INO:
|
||||
bmap->b_pops = &nilfs_bmap_ptr_ops_vmdt;
|
||||
bmap->b_last_allocated_key = 0; /* XXX: use macro */
|
||||
bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
|
||||
bmap->b_last_allocated_key = 0;
|
||||
bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
|
||||
break;
|
||||
default:
|
||||
bmap->b_pops = &nilfs_bmap_ptr_ops_v;
|
||||
bmap->b_last_allocated_key = 0; /* XXX: use macro */
|
||||
bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
|
||||
bmap->b_last_allocated_key = 0;
|
||||
bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
|
||||
break;
|
||||
}
|
||||
|
||||
return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ?
|
||||
nilfs_btree_init(bmap,
|
||||
NILFS_BMAP_LARGE_LOW,
|
||||
NILFS_BMAP_LARGE_HIGH) :
|
||||
nilfs_direct_init(bmap,
|
||||
NILFS_BMAP_SMALL_LOW,
|
||||
NILFS_BMAP_SMALL_HIGH);
|
||||
nilfs_btree_init(bmap) : nilfs_direct_init(bmap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -764,7 +638,7 @@ void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
|
|||
memset(&bmap->b_u, 0, NILFS_BMAP_SIZE);
|
||||
init_rwsem(&bmap->b_sem);
|
||||
bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
|
||||
bmap->b_pops = &nilfs_bmap_ptr_ops_gc;
|
||||
bmap->b_ptr_type = NILFS_BMAP_PTR_U;
|
||||
bmap->b_last_allocated_key = 0;
|
||||
bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
|
||||
bmap->b_state = 0;
|
||||
|
|
135
fs/nilfs2/bmap.h
135
fs/nilfs2/bmap.h
|
@ -64,6 +64,8 @@ struct nilfs_bmap_stats {
|
|||
*/
|
||||
struct nilfs_bmap_operations {
|
||||
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_delete)(struct nilfs_bmap *, __u64);
|
||||
void (*bop_clear)(struct nilfs_bmap *);
|
||||
|
@ -86,34 +88,6 @@ struct nilfs_bmap_operations {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct nilfs_bmap_ptr_operations - bmap ptr operation table
|
||||
*/
|
||||
struct nilfs_bmap_ptr_operations {
|
||||
int (*bpop_prepare_alloc_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void (*bpop_commit_alloc_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void (*bpop_abort_alloc_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
int (*bpop_prepare_start_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void (*bpop_commit_start_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *,
|
||||
sector_t);
|
||||
void (*bpop_abort_start_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
int (*bpop_prepare_end_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void (*bpop_commit_end_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void (*bpop_abort_end_ptr)(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
|
||||
int (*bpop_translate)(const struct nilfs_bmap *, __u64, __u64 *);
|
||||
};
|
||||
|
||||
|
||||
#define NILFS_BMAP_SIZE (NILFS_INODE_BMAP_SIZE * sizeof(__le64))
|
||||
#define NILFS_BMAP_KEY_BIT (sizeof(unsigned long) * 8 /* CHAR_BIT */)
|
||||
#define NILFS_BMAP_NEW_PTR_INIT \
|
||||
|
@ -131,11 +105,9 @@ static inline int nilfs_bmap_is_new_ptr(unsigned long ptr)
|
|||
* @b_sem: semaphore
|
||||
* @b_inode: owner of bmap
|
||||
* @b_ops: bmap operation table
|
||||
* @b_pops: bmap ptr operation table
|
||||
* @b_low: low watermark of conversion
|
||||
* @b_high: high watermark of conversion
|
||||
* @b_last_allocated_key: last allocated key for data block
|
||||
* @b_last_allocated_ptr: last allocated ptr for data block
|
||||
* @b_ptr_type: pointer type
|
||||
* @b_state: state
|
||||
*/
|
||||
struct nilfs_bmap {
|
||||
|
@ -146,14 +118,22 @@ struct nilfs_bmap {
|
|||
struct rw_semaphore b_sem;
|
||||
struct inode *b_inode;
|
||||
const struct nilfs_bmap_operations *b_ops;
|
||||
const struct nilfs_bmap_ptr_operations *b_pops;
|
||||
__u64 b_low;
|
||||
__u64 b_high;
|
||||
__u64 b_last_allocated_key;
|
||||
__u64 b_last_allocated_ptr;
|
||||
int b_ptr_type;
|
||||
int b_state;
|
||||
};
|
||||
|
||||
/* pointer type */
|
||||
#define NILFS_BMAP_PTR_P 0 /* physical block number (i.e. LBN) */
|
||||
#define NILFS_BMAP_PTR_VS 1 /* virtual block number (single
|
||||
version) */
|
||||
#define NILFS_BMAP_PTR_VM 2 /* virtual block number (has multiple
|
||||
versions) */
|
||||
#define NILFS_BMAP_PTR_U (-1) /* never perform pointer operations */
|
||||
|
||||
#define NILFS_BMAP_USE_VBN(bmap) ((bmap)->b_ptr_type > 0)
|
||||
|
||||
/* state */
|
||||
#define NILFS_BMAP_DIRTY 0x00000001
|
||||
|
||||
|
@ -162,6 +142,7 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
|
|||
int nilfs_bmap_read(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_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned);
|
||||
int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long);
|
||||
int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long);
|
||||
int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *);
|
||||
|
@ -182,7 +163,67 @@ void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
|
|||
/*
|
||||
* Internal use only
|
||||
*/
|
||||
struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *);
|
||||
int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
|
||||
static inline int nilfs_bmap_prepare_alloc_ptr(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
if (NILFS_BMAP_USE_VBN(bmap))
|
||||
return nilfs_bmap_prepare_alloc_v(bmap, req);
|
||||
/* ignore target ptr */
|
||||
req->bpr_ptr = bmap->b_last_allocated_ptr++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void nilfs_bmap_commit_alloc_ptr(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
if (NILFS_BMAP_USE_VBN(bmap))
|
||||
nilfs_bmap_commit_alloc_v(bmap, req);
|
||||
}
|
||||
|
||||
static inline void nilfs_bmap_abort_alloc_ptr(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
if (NILFS_BMAP_USE_VBN(bmap))
|
||||
nilfs_bmap_abort_alloc_v(bmap, req);
|
||||
else
|
||||
bmap->b_last_allocated_ptr--;
|
||||
}
|
||||
|
||||
int nilfs_bmap_prepare_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_commit_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_abort_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *);
|
||||
|
||||
static inline int nilfs_bmap_prepare_end_ptr(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
return NILFS_BMAP_USE_VBN(bmap) ?
|
||||
nilfs_bmap_prepare_end_v(bmap, req) : 0;
|
||||
}
|
||||
|
||||
static inline void nilfs_bmap_commit_end_ptr(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
if (NILFS_BMAP_USE_VBN(bmap))
|
||||
nilfs_bmap_commit_end_v(bmap, req);
|
||||
}
|
||||
|
||||
static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap,
|
||||
union nilfs_bmap_ptr_req *req)
|
||||
{
|
||||
if (NILFS_BMAP_USE_VBN(bmap))
|
||||
nilfs_bmap_abort_end_v(bmap, req);
|
||||
}
|
||||
|
||||
int nilfs_bmap_start_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *,
|
||||
sector_t);
|
||||
int nilfs_bmap_move_v(const struct nilfs_bmap *, __u64, sector_t);
|
||||
int nilfs_bmap_mark_dirty(const struct nilfs_bmap *, __u64);
|
||||
|
||||
|
@ -193,28 +234,20 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
|
|||
__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
|
||||
__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
|
||||
|
||||
int nilfs_bmap_prepare_update(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_commit_update(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_abort_update(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
int nilfs_bmap_prepare_update_v(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_commit_update_v(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
void nilfs_bmap_abort_update_v(struct nilfs_bmap *,
|
||||
union nilfs_bmap_ptr_req *,
|
||||
union nilfs_bmap_ptr_req *);
|
||||
|
||||
void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int);
|
||||
void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
|
||||
|
||||
|
||||
int nilfs_bmap_get_block(const struct nilfs_bmap *, __u64,
|
||||
struct buffer_head **);
|
||||
void nilfs_bmap_put_block(const struct nilfs_bmap *, struct buffer_head *);
|
||||
int nilfs_bmap_get_new_block(const struct nilfs_bmap *, __u64,
|
||||
struct buffer_head **);
|
||||
void nilfs_bmap_delete_block(const struct nilfs_bmap *, struct buffer_head *);
|
||||
|
||||
|
||||
/* Assume that bmap semaphore is locked. */
|
||||
static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap)
|
||||
{
|
||||
|
|
|
@ -46,15 +46,18 @@ void nilfs_btnode_cache_init_once(struct address_space *btnc)
|
|||
INIT_LIST_HEAD(&btnc->i_mmap_nonlinear);
|
||||
}
|
||||
|
||||
static struct address_space_operations def_btnode_aops;
|
||||
static struct address_space_operations def_btnode_aops = {
|
||||
.sync_page = block_sync_page,
|
||||
};
|
||||
|
||||
void nilfs_btnode_cache_init(struct address_space *btnc)
|
||||
void nilfs_btnode_cache_init(struct address_space *btnc,
|
||||
struct backing_dev_info *bdi)
|
||||
{
|
||||
btnc->host = NULL; /* can safely set to host inode ? */
|
||||
btnc->flags = 0;
|
||||
mapping_set_gfp_mask(btnc, GFP_NOFS);
|
||||
btnc->assoc_mapping = NULL;
|
||||
btnc->backing_dev_info = &default_backing_dev_info;
|
||||
btnc->backing_dev_info = bdi;
|
||||
btnc->a_ops = &def_btnode_aops;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ struct nilfs_btnode_chkey_ctxt {
|
|||
};
|
||||
|
||||
void nilfs_btnode_cache_init_once(struct address_space *);
|
||||
void nilfs_btnode_cache_init(struct address_space *);
|
||||
void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *);
|
||||
void nilfs_btnode_cache_clear(struct address_space *);
|
||||
int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t,
|
||||
struct buffer_head **, int);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "btnode.h"
|
||||
#include "btree.h"
|
||||
#include "alloc.h"
|
||||
#include "dat.h"
|
||||
|
||||
/**
|
||||
* struct nilfs_btree_path - A path on which B-tree operations are executed
|
||||
|
@ -109,8 +110,7 @@ static void nilfs_btree_clear_path(const struct nilfs_btree *btree,
|
|||
level < NILFS_BTREE_LEVEL_MAX;
|
||||
level++) {
|
||||
if (path[level].bp_bh != NULL) {
|
||||
nilfs_bmap_put_block(&btree->bt_bmap,
|
||||
path[level].bp_bh);
|
||||
brelse(path[level].bp_bh);
|
||||
path[level].bp_bh = NULL;
|
||||
}
|
||||
/* sib_bh is released or deleted by prepare or commit
|
||||
|
@ -123,10 +123,29 @@ static void nilfs_btree_clear_path(const struct nilfs_btree *btree,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* B-tree node operations
|
||||
*/
|
||||
static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
|
||||
struct buffer_head **bhp)
|
||||
{
|
||||
struct address_space *btnc =
|
||||
&NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
|
||||
return nilfs_btnode_get(btnc, ptr, 0, bhp, 0);
|
||||
}
|
||||
|
||||
static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
|
||||
__u64 ptr, struct buffer_head **bhp)
|
||||
{
|
||||
struct address_space *btnc =
|
||||
&NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
|
||||
int ret;
|
||||
|
||||
ret = nilfs_btnode_get(btnc, ptr, 0, bhp, 1);
|
||||
if (!ret)
|
||||
set_buffer_nilfs_volatile(*bhp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nilfs_btree_node_get_flags(const struct nilfs_btree *btree,
|
||||
|
@ -488,8 +507,7 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
|
|||
path[level].bp_index = index;
|
||||
|
||||
for (level--; level >= minlevel; level--) {
|
||||
ret = nilfs_bmap_get_block(&btree->bt_bmap, ptr,
|
||||
&path[level].bp_bh);
|
||||
ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
node = nilfs_btree_get_nonroot_node(btree, path, level);
|
||||
|
@ -535,8 +553,7 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
|
|||
path[level].bp_index = index;
|
||||
|
||||
for (level--; level > 0; level--) {
|
||||
ret = nilfs_bmap_get_block(&btree->bt_bmap, ptr,
|
||||
&path[level].bp_bh);
|
||||
ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
node = nilfs_btree_get_nonroot_node(btree, path, level);
|
||||
|
@ -579,6 +596,87 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
|
|||
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,
|
||||
struct nilfs_btree_path *path,
|
||||
int level, __u64 key)
|
||||
|
@ -669,13 +767,13 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree,
|
|||
nilfs_btree_node_get_key(btree, node, 0));
|
||||
|
||||
if (move) {
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_bh);
|
||||
brelse(path[level].bp_bh);
|
||||
path[level].bp_bh = path[level].bp_sib_bh;
|
||||
path[level].bp_sib_bh = NULL;
|
||||
path[level].bp_index += lnchildren;
|
||||
path[level + 1].bp_index--;
|
||||
} else {
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
brelse(path[level].bp_sib_bh);
|
||||
path[level].bp_sib_bh = NULL;
|
||||
path[level].bp_index -= n;
|
||||
}
|
||||
|
@ -722,14 +820,14 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree,
|
|||
path[level + 1].bp_index--;
|
||||
|
||||
if (move) {
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_bh);
|
||||
brelse(path[level].bp_bh);
|
||||
path[level].bp_bh = path[level].bp_sib_bh;
|
||||
path[level].bp_sib_bh = NULL;
|
||||
path[level].bp_index -=
|
||||
nilfs_btree_node_get_nchildren(btree, node);
|
||||
path[level + 1].bp_index++;
|
||||
} else {
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
brelse(path[level].bp_sib_bh);
|
||||
path[level].bp_sib_bh = NULL;
|
||||
}
|
||||
|
||||
|
@ -781,7 +879,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
|
|||
*keyp = nilfs_btree_node_get_key(btree, right, 0);
|
||||
*ptrp = path[level].bp_newreq.bpr_ptr;
|
||||
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_bh);
|
||||
brelse(path[level].bp_bh);
|
||||
path[level].bp_bh = path[level].bp_sib_bh;
|
||||
path[level].bp_sib_bh = NULL;
|
||||
} else {
|
||||
|
@ -790,7 +888,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
|
|||
*keyp = nilfs_btree_node_get_key(btree, right, 0);
|
||||
*ptrp = path[level].bp_newreq.bpr_ptr;
|
||||
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
brelse(path[level].bp_sib_bh);
|
||||
path[level].bp_sib_bh = NULL;
|
||||
}
|
||||
|
||||
|
@ -897,12 +995,12 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
|
|||
level = NILFS_BTREE_LEVEL_DATA;
|
||||
|
||||
/* allocate a new ptr for data block */
|
||||
if (btree->bt_ops->btop_find_target != NULL)
|
||||
if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
|
||||
path[level].bp_newreq.bpr_ptr =
|
||||
btree->bt_ops->btop_find_target(btree, path, key);
|
||||
nilfs_btree_find_target_v(btree, path, key);
|
||||
|
||||
ret = btree->bt_bmap.b_pops->bpop_prepare_alloc_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_newreq);
|
||||
ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_newreq);
|
||||
if (ret < 0)
|
||||
goto err_out_data;
|
||||
|
||||
|
@ -924,8 +1022,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
|
|||
if (pindex > 0) {
|
||||
sibptr = nilfs_btree_node_get_ptr(btree, parent,
|
||||
pindex - 1);
|
||||
ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr,
|
||||
&bh);
|
||||
ret = nilfs_btree_get_block(btree, sibptr, &bh);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
sib = (struct nilfs_btree_node *)bh->b_data;
|
||||
|
@ -936,7 +1033,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
|
|||
stats->bs_nblocks++;
|
||||
goto out;
|
||||
} else
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, bh);
|
||||
brelse(bh);
|
||||
}
|
||||
|
||||
/* right sibling */
|
||||
|
@ -944,8 +1041,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
|
|||
nilfs_btree_node_get_nchildren(btree, parent) - 1) {
|
||||
sibptr = nilfs_btree_node_get_ptr(btree, parent,
|
||||
pindex + 1);
|
||||
ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr,
|
||||
&bh);
|
||||
ret = nilfs_btree_get_block(btree, sibptr, &bh);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
sib = (struct nilfs_btree_node *)bh->b_data;
|
||||
|
@ -956,19 +1052,19 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
|
|||
stats->bs_nblocks++;
|
||||
goto out;
|
||||
} else
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, bh);
|
||||
brelse(bh);
|
||||
}
|
||||
|
||||
/* split */
|
||||
path[level].bp_newreq.bpr_ptr =
|
||||
path[level - 1].bp_newreq.bpr_ptr + 1;
|
||||
ret = btree->bt_bmap.b_pops->bpop_prepare_alloc_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_newreq);
|
||||
ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_newreq);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
ret = nilfs_bmap_get_new_block(&btree->bt_bmap,
|
||||
path[level].bp_newreq.bpr_ptr,
|
||||
&bh);
|
||||
ret = nilfs_btree_get_new_block(btree,
|
||||
path[level].bp_newreq.bpr_ptr,
|
||||
&bh);
|
||||
if (ret < 0)
|
||||
goto err_out_curr_node;
|
||||
|
||||
|
@ -994,12 +1090,12 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
|
|||
|
||||
/* grow */
|
||||
path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
|
||||
ret = btree->bt_bmap.b_pops->bpop_prepare_alloc_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_newreq);
|
||||
ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_newreq);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
ret = nilfs_bmap_get_new_block(&btree->bt_bmap,
|
||||
path[level].bp_newreq.bpr_ptr, &bh);
|
||||
ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
|
||||
&bh);
|
||||
if (ret < 0)
|
||||
goto err_out_curr_node;
|
||||
|
||||
|
@ -1023,18 +1119,16 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
|
|||
|
||||
/* error */
|
||||
err_out_curr_node:
|
||||
btree->bt_bmap.b_pops->bpop_abort_alloc_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_newreq);
|
||||
nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
|
||||
err_out_child_node:
|
||||
for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
|
||||
nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
btree->bt_bmap.b_pops->bpop_abort_alloc_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_newreq);
|
||||
nilfs_btnode_delete(path[level].bp_sib_bh);
|
||||
nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_newreq);
|
||||
|
||||
}
|
||||
|
||||
btree->bt_bmap.b_pops->bpop_abort_alloc_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_newreq);
|
||||
nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
|
||||
err_out_data:
|
||||
*levelp = level;
|
||||
stats->bs_nblocks = 0;
|
||||
|
@ -1049,14 +1143,12 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
|
|||
|
||||
set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
|
||||
ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
|
||||
if (btree->bt_ops->btop_set_target != NULL)
|
||||
btree->bt_ops->btop_set_target(btree, key, ptr);
|
||||
if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
|
||||
nilfs_btree_set_target_v(btree, key, ptr);
|
||||
|
||||
for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
|
||||
if (btree->bt_bmap.b_pops->bpop_commit_alloc_ptr != NULL) {
|
||||
btree->bt_bmap.b_pops->bpop_commit_alloc_ptr(
|
||||
&btree->bt_bmap, &path[level - 1].bp_newreq);
|
||||
}
|
||||
nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
|
||||
&path[level - 1].bp_newreq);
|
||||
path[level].bp_op(btree, path, level, &key, &ptr);
|
||||
}
|
||||
|
||||
|
@ -1153,7 +1245,7 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
|
|||
nilfs_btree_promote_key(btree, path, level + 1,
|
||||
nilfs_btree_node_get_key(btree, node, 0));
|
||||
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
brelse(path[level].bp_sib_bh);
|
||||
path[level].bp_sib_bh = NULL;
|
||||
path[level].bp_index += n;
|
||||
}
|
||||
|
@ -1192,7 +1284,7 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
|
|||
nilfs_btree_node_get_key(btree, right, 0));
|
||||
path[level + 1].bp_index--;
|
||||
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
brelse(path[level].bp_sib_bh);
|
||||
path[level].bp_sib_bh = NULL;
|
||||
}
|
||||
|
||||
|
@ -1221,7 +1313,7 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree,
|
|||
unlock_buffer(path[level].bp_bh);
|
||||
unlock_buffer(path[level].bp_sib_bh);
|
||||
|
||||
nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_bh);
|
||||
nilfs_btnode_delete(path[level].bp_bh);
|
||||
path[level].bp_bh = path[level].bp_sib_bh;
|
||||
path[level].bp_sib_bh = NULL;
|
||||
path[level].bp_index += nilfs_btree_node_get_nchildren(btree, left);
|
||||
|
@ -1252,7 +1344,7 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree,
|
|||
unlock_buffer(path[level].bp_bh);
|
||||
unlock_buffer(path[level].bp_sib_bh);
|
||||
|
||||
nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
nilfs_btnode_delete(path[level].bp_sib_bh);
|
||||
path[level].bp_sib_bh = NULL;
|
||||
path[level + 1].bp_index++;
|
||||
}
|
||||
|
@ -1276,7 +1368,7 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree,
|
|||
nilfs_btree_node_move_left(btree, root, child, n);
|
||||
unlock_buffer(path[level].bp_bh);
|
||||
|
||||
nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_bh);
|
||||
nilfs_btnode_delete(path[level].bp_bh);
|
||||
path[level].bp_bh = NULL;
|
||||
}
|
||||
|
||||
|
@ -1300,12 +1392,10 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
|
|||
path[level].bp_oldreq.bpr_ptr =
|
||||
nilfs_btree_node_get_ptr(btree, node,
|
||||
path[level].bp_index);
|
||||
if (btree->bt_bmap.b_pops->bpop_prepare_end_ptr != NULL) {
|
||||
ret = btree->bt_bmap.b_pops->bpop_prepare_end_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_oldreq);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
}
|
||||
ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
|
||||
if (nilfs_btree_node_get_nchildren(btree, node) >
|
||||
nilfs_btree_node_nchildren_min(btree, node)) {
|
||||
|
@ -1321,8 +1411,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
|
|||
/* left sibling */
|
||||
sibptr = nilfs_btree_node_get_ptr(btree, parent,
|
||||
pindex - 1);
|
||||
ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr,
|
||||
&bh);
|
||||
ret = nilfs_btree_get_block(btree, sibptr, &bh);
|
||||
if (ret < 0)
|
||||
goto err_out_curr_node;
|
||||
sib = (struct nilfs_btree_node *)bh->b_data;
|
||||
|
@ -1343,8 +1432,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
|
|||
/* right sibling */
|
||||
sibptr = nilfs_btree_node_get_ptr(btree, parent,
|
||||
pindex + 1);
|
||||
ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr,
|
||||
&bh);
|
||||
ret = nilfs_btree_get_block(btree, sibptr, &bh);
|
||||
if (ret < 0)
|
||||
goto err_out_curr_node;
|
||||
sib = (struct nilfs_btree_node *)bh->b_data;
|
||||
|
@ -1381,12 +1469,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
|
|||
node = nilfs_btree_get_root(btree);
|
||||
path[level].bp_oldreq.bpr_ptr =
|
||||
nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
|
||||
if (btree->bt_bmap.b_pops->bpop_prepare_end_ptr != NULL) {
|
||||
ret = btree->bt_bmap.b_pops->bpop_prepare_end_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_oldreq);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
}
|
||||
|
||||
ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq);
|
||||
if (ret < 0)
|
||||
goto err_out_child_node;
|
||||
|
||||
/* child of the root node is deleted */
|
||||
path[level].bp_op = nilfs_btree_do_delete;
|
||||
stats->bs_nblocks++;
|
||||
|
@ -1398,15 +1486,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
|
|||
|
||||
/* error */
|
||||
err_out_curr_node:
|
||||
if (btree->bt_bmap.b_pops->bpop_abort_end_ptr != NULL)
|
||||
btree->bt_bmap.b_pops->bpop_abort_end_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_oldreq);
|
||||
nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq);
|
||||
err_out_child_node:
|
||||
for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh);
|
||||
if (btree->bt_bmap.b_pops->bpop_abort_end_ptr != NULL)
|
||||
btree->bt_bmap.b_pops->bpop_abort_end_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_oldreq);
|
||||
brelse(path[level].bp_sib_bh);
|
||||
nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq);
|
||||
}
|
||||
*levelp = level;
|
||||
stats->bs_nblocks = 0;
|
||||
|
@ -1420,9 +1505,8 @@ static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
|
|||
int level;
|
||||
|
||||
for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
|
||||
if (btree->bt_bmap.b_pops->bpop_commit_end_ptr != NULL)
|
||||
btree->bt_bmap.b_pops->bpop_commit_end_ptr(
|
||||
&btree->bt_bmap, &path[level].bp_oldreq);
|
||||
nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq);
|
||||
path[level].bp_op(btree, path, level, NULL, NULL);
|
||||
}
|
||||
|
||||
|
@ -1501,7 +1585,7 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
|
|||
if (nchildren > 1)
|
||||
return 0;
|
||||
ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
|
||||
ret = nilfs_bmap_get_block(bmap, ptr, &bh);
|
||||
ret = nilfs_btree_get_block(btree, ptr, &bh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
node = (struct nilfs_btree_node *)bh->b_data;
|
||||
|
@ -1515,9 +1599,9 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
|
|||
nextmaxkey = (nchildren > 1) ?
|
||||
nilfs_btree_node_get_key(btree, node, nchildren - 2) : 0;
|
||||
if (bh != NULL)
|
||||
nilfs_bmap_put_block(bmap, bh);
|
||||
brelse(bh);
|
||||
|
||||
return (maxkey == key) && (nextmaxkey < bmap->b_low);
|
||||
return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
|
||||
}
|
||||
|
||||
static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
|
||||
|
@ -1542,7 +1626,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
|
|||
nchildren = nilfs_btree_node_get_nchildren(btree, root);
|
||||
WARN_ON(nchildren > 1);
|
||||
ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
|
||||
ret = nilfs_bmap_get_block(bmap, ptr, &bh);
|
||||
ret = nilfs_btree_get_block(btree, ptr, &bh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
node = (struct nilfs_btree_node *)bh->b_data;
|
||||
|
@ -1563,7 +1647,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
|
|||
}
|
||||
|
||||
if (bh != NULL)
|
||||
nilfs_bmap_put_block(bmap, bh);
|
||||
brelse(bh);
|
||||
|
||||
return nitems;
|
||||
}
|
||||
|
@ -1584,10 +1668,10 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
|
|||
|
||||
/* for data */
|
||||
/* cannot find near ptr */
|
||||
if (btree->bt_ops->btop_find_target != NULL)
|
||||
dreq->bpr_ptr
|
||||
= btree->bt_ops->btop_find_target(btree, NULL, key);
|
||||
ret = bmap->b_pops->bpop_prepare_alloc_ptr(bmap, dreq);
|
||||
if (NILFS_BMAP_USE_VBN(bmap))
|
||||
dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
|
||||
|
||||
ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1595,11 +1679,11 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
|
|||
stats->bs_nblocks++;
|
||||
if (nreq != NULL) {
|
||||
nreq->bpr_ptr = dreq->bpr_ptr + 1;
|
||||
ret = bmap->b_pops->bpop_prepare_alloc_ptr(bmap, nreq);
|
||||
ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq);
|
||||
if (ret < 0)
|
||||
goto err_out_dreq;
|
||||
|
||||
ret = nilfs_bmap_get_new_block(bmap, nreq->bpr_ptr, &bh);
|
||||
ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
|
||||
if (ret < 0)
|
||||
goto err_out_nreq;
|
||||
|
||||
|
@ -1612,9 +1696,9 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
|
|||
|
||||
/* error */
|
||||
err_out_nreq:
|
||||
bmap->b_pops->bpop_abort_alloc_ptr(bmap, nreq);
|
||||
nilfs_bmap_abort_alloc_ptr(bmap, nreq);
|
||||
err_out_dreq:
|
||||
bmap->b_pops->bpop_abort_alloc_ptr(bmap, dreq);
|
||||
nilfs_bmap_abort_alloc_ptr(bmap, dreq);
|
||||
stats->bs_nblocks = 0;
|
||||
return ret;
|
||||
|
||||
|
@ -1624,7 +1708,7 @@ static void
|
|||
nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
|
||||
__u64 key, __u64 ptr,
|
||||
const __u64 *keys, const __u64 *ptrs,
|
||||
int n, __u64 low, __u64 high,
|
||||
int n,
|
||||
union nilfs_bmap_ptr_req *dreq,
|
||||
union nilfs_bmap_ptr_req *nreq,
|
||||
struct buffer_head *bh)
|
||||
|
@ -1642,12 +1726,10 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
|
|||
|
||||
/* convert and insert */
|
||||
btree = (struct nilfs_btree *)bmap;
|
||||
nilfs_btree_init(bmap, low, high);
|
||||
nilfs_btree_init(bmap);
|
||||
if (nreq != NULL) {
|
||||
if (bmap->b_pops->bpop_commit_alloc_ptr != NULL) {
|
||||
bmap->b_pops->bpop_commit_alloc_ptr(bmap, dreq);
|
||||
bmap->b_pops->bpop_commit_alloc_ptr(bmap, nreq);
|
||||
}
|
||||
nilfs_bmap_commit_alloc_ptr(bmap, dreq);
|
||||
nilfs_bmap_commit_alloc_ptr(bmap, nreq);
|
||||
|
||||
/* create child node at level 1 */
|
||||
lock_buffer(bh);
|
||||
|
@ -1661,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
|
|||
nilfs_bmap_set_dirty(bmap);
|
||||
|
||||
unlock_buffer(bh);
|
||||
nilfs_bmap_put_block(bmap, bh);
|
||||
brelse(bh);
|
||||
|
||||
/* create root node at level 2 */
|
||||
node = nilfs_btree_get_root(btree);
|
||||
|
@ -1669,8 +1751,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
|
|||
nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
|
||||
2, 1, &keys[0], &tmpptr);
|
||||
} else {
|
||||
if (bmap->b_pops->bpop_commit_alloc_ptr != NULL)
|
||||
bmap->b_pops->bpop_commit_alloc_ptr(bmap, dreq);
|
||||
nilfs_bmap_commit_alloc_ptr(bmap, dreq);
|
||||
|
||||
/* create root node at level 1 */
|
||||
node = nilfs_btree_get_root(btree);
|
||||
|
@ -1682,8 +1763,8 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
|
|||
nilfs_bmap_set_dirty(bmap);
|
||||
}
|
||||
|
||||
if (btree->bt_ops->btop_set_target != NULL)
|
||||
btree->bt_ops->btop_set_target(btree, key, dreq->bpr_ptr);
|
||||
if (NILFS_BMAP_USE_VBN(bmap))
|
||||
nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1694,13 +1775,10 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
|
|||
* @keys:
|
||||
* @ptrs:
|
||||
* @n:
|
||||
* @low:
|
||||
* @high:
|
||||
*/
|
||||
int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
|
||||
__u64 key, __u64 ptr,
|
||||
const __u64 *keys, const __u64 *ptrs,
|
||||
int n, __u64 low, __u64 high)
|
||||
const __u64 *keys, const __u64 *ptrs, int n)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
|
||||
|
@ -1725,7 +1803,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
|
||||
low, high, di, ni, bh);
|
||||
di, ni, bh);
|
||||
nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1754,9 +1832,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
|
|||
nilfs_btree_node_get_ptr(btree, parent,
|
||||
path[level + 1].bp_index);
|
||||
path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
|
||||
ret = nilfs_bmap_prepare_update(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
ret = nilfs_bmap_prepare_update_v(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1768,9 +1846,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
|
|||
&NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
|
||||
&path[level].bp_ctxt);
|
||||
if (ret < 0) {
|
||||
nilfs_bmap_abort_update(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
nilfs_bmap_abort_update_v(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -1784,9 +1862,9 @@ static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
|
|||
{
|
||||
struct nilfs_btree_node *parent;
|
||||
|
||||
nilfs_bmap_commit_update(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
nilfs_bmap_commit_update_v(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
|
||||
if (buffer_nilfs_node(path[level].bp_bh)) {
|
||||
nilfs_btnode_commit_change_key(
|
||||
|
@ -1805,9 +1883,9 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
|
|||
struct nilfs_btree_path *path,
|
||||
int level)
|
||||
{
|
||||
nilfs_bmap_abort_update(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
nilfs_bmap_abort_update_v(&btree->bt_bmap,
|
||||
&path[level].bp_oldreq,
|
||||
&path[level].bp_newreq);
|
||||
if (buffer_nilfs_node(path[level].bp_bh))
|
||||
nilfs_btnode_abort_change_key(
|
||||
&NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
|
||||
|
@ -1930,7 +2008,9 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = btree->bt_ops->btop_propagate(btree, path, level, bh);
|
||||
ret = NILFS_BMAP_USE_VBN(bmap) ?
|
||||
nilfs_btree_propagate_v(btree, path, level, bh) :
|
||||
nilfs_btree_propagate_p(btree, path, level, bh);
|
||||
|
||||
out:
|
||||
nilfs_btree_clear_path(btree, path);
|
||||
|
@ -2066,12 +2146,9 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree,
|
|||
ptr = nilfs_btree_node_get_ptr(btree, parent,
|
||||
path[level + 1].bp_index);
|
||||
req.bpr_ptr = ptr;
|
||||
ret = btree->bt_bmap.b_pops->bpop_prepare_start_ptr(&btree->bt_bmap,
|
||||
&req);
|
||||
if (ret < 0)
|
||||
ret = nilfs_bmap_start_v(&btree->bt_bmap, &req, blocknr);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
btree->bt_bmap.b_pops->bpop_commit_start_ptr(&btree->bt_bmap,
|
||||
&req, blocknr);
|
||||
|
||||
key = nilfs_btree_node_get_key(btree, parent,
|
||||
path[level + 1].bp_index);
|
||||
|
@ -2114,8 +2191,9 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = btree->bt_ops->btop_assign(btree, path, level, bh,
|
||||
blocknr, binfo);
|
||||
ret = NILFS_BMAP_USE_VBN(bmap) ?
|
||||
nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
|
||||
nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
|
||||
|
||||
out:
|
||||
nilfs_btree_clear_path(btree, path);
|
||||
|
@ -2171,7 +2249,7 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
|
|||
WARN_ON(ret == -ENOENT);
|
||||
goto out;
|
||||
}
|
||||
ret = nilfs_bmap_get_block(&btree->bt_bmap, ptr, &bh);
|
||||
ret = nilfs_btree_get_block(btree, ptr, &bh);
|
||||
if (ret < 0) {
|
||||
WARN_ON(ret == -ENOENT);
|
||||
goto out;
|
||||
|
@ -2179,7 +2257,7 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
|
|||
|
||||
if (!buffer_dirty(bh))
|
||||
nilfs_btnode_mark_dirty(bh);
|
||||
nilfs_bmap_put_block(&btree->bt_bmap, bh);
|
||||
brelse(bh);
|
||||
if (!nilfs_bmap_dirty(&btree->bt_bmap))
|
||||
nilfs_bmap_set_dirty(&btree->bt_bmap);
|
||||
|
||||
|
@ -2191,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 = {
|
||||
.bop_lookup = nilfs_btree_lookup,
|
||||
.bop_lookup_contig = nilfs_btree_lookup_contig,
|
||||
.bop_insert = nilfs_btree_insert,
|
||||
.bop_delete = nilfs_btree_delete,
|
||||
.bop_clear = NULL,
|
||||
|
@ -2210,6 +2289,7 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = {
|
|||
|
||||
static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
|
||||
.bop_lookup = NULL,
|
||||
.bop_lookup_contig = NULL,
|
||||
.bop_insert = NULL,
|
||||
.bop_delete = NULL,
|
||||
.bop_clear = NULL,
|
||||
|
@ -2227,43 +2307,13 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
|
|||
.bop_gather_data = NULL,
|
||||
};
|
||||
|
||||
static const struct nilfs_btree_operations nilfs_btree_ops_v = {
|
||||
.btop_find_target = nilfs_btree_find_target_v,
|
||||
.btop_set_target = nilfs_btree_set_target_v,
|
||||
.btop_propagate = nilfs_btree_propagate_v,
|
||||
.btop_assign = nilfs_btree_assign_v,
|
||||
};
|
||||
|
||||
static const struct nilfs_btree_operations nilfs_btree_ops_p = {
|
||||
.btop_find_target = NULL,
|
||||
.btop_set_target = NULL,
|
||||
.btop_propagate = nilfs_btree_propagate_p,
|
||||
.btop_assign = nilfs_btree_assign_p,
|
||||
};
|
||||
|
||||
int nilfs_btree_init(struct nilfs_bmap *bmap, __u64 low, __u64 high)
|
||||
int nilfs_btree_init(struct nilfs_bmap *bmap)
|
||||
{
|
||||
struct nilfs_btree *btree;
|
||||
|
||||
btree = (struct nilfs_btree *)bmap;
|
||||
bmap->b_ops = &nilfs_btree_ops;
|
||||
bmap->b_low = low;
|
||||
bmap->b_high = high;
|
||||
switch (bmap->b_inode->i_ino) {
|
||||
case NILFS_DAT_INO:
|
||||
btree->bt_ops = &nilfs_btree_ops_p;
|
||||
break;
|
||||
default:
|
||||
btree->bt_ops = &nilfs_btree_ops_v;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
|
||||
{
|
||||
bmap->b_low = NILFS_BMAP_LARGE_LOW;
|
||||
bmap->b_high = NILFS_BMAP_LARGE_HIGH;
|
||||
bmap->b_ops = &nilfs_btree_ops_gc;
|
||||
}
|
||||
|
|
|
@ -33,28 +33,6 @@
|
|||
struct nilfs_btree;
|
||||
struct nilfs_btree_path;
|
||||
|
||||
/**
|
||||
* struct nilfs_btree_operations - B-tree operation table
|
||||
*/
|
||||
struct nilfs_btree_operations {
|
||||
__u64 (*btop_find_target)(const struct nilfs_btree *,
|
||||
const struct nilfs_btree_path *, __u64);
|
||||
void (*btop_set_target)(struct nilfs_btree *, __u64, __u64);
|
||||
|
||||
struct the_nilfs *(*btop_get_nilfs)(struct nilfs_btree *);
|
||||
|
||||
int (*btop_propagate)(struct nilfs_btree *,
|
||||
struct nilfs_btree_path *,
|
||||
int,
|
||||
struct buffer_head *);
|
||||
int (*btop_assign)(struct nilfs_btree *,
|
||||
struct nilfs_btree_path *,
|
||||
int,
|
||||
struct buffer_head **,
|
||||
sector_t,
|
||||
union nilfs_binfo *);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct nilfs_btree_node - B-tree node
|
||||
* @bn_flags: flags
|
||||
|
@ -80,13 +58,9 @@ struct nilfs_btree_node {
|
|||
/**
|
||||
* struct nilfs_btree - B-tree structure
|
||||
* @bt_bmap: bmap base structure
|
||||
* @bt_ops: B-tree operation table
|
||||
*/
|
||||
struct nilfs_btree {
|
||||
struct nilfs_bmap bt_bmap;
|
||||
|
||||
/* B-tree-specific members */
|
||||
const struct nilfs_btree_operations *bt_ops;
|
||||
};
|
||||
|
||||
|
||||
|
@ -108,10 +82,9 @@ struct nilfs_btree {
|
|||
|
||||
int nilfs_btree_path_cache_init(void);
|
||||
void nilfs_btree_path_cache_destroy(void);
|
||||
int nilfs_btree_init(struct nilfs_bmap *, __u64, __u64);
|
||||
int nilfs_btree_init(struct nilfs_bmap *);
|
||||
int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64,
|
||||
const __u64 *, const __u64 *,
|
||||
int, __u64, __u64);
|
||||
const __u64 *, const __u64 *, int);
|
||||
void nilfs_btree_init_gc(struct nilfs_bmap *);
|
||||
|
||||
#endif /* _NILFS_BTREE_H */
|
||||
|
|
|
@ -295,10 +295,6 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* cannot delete the latest checkpoint */
|
||||
if (start == nilfs_mdt_cno(cpfile) - 1)
|
||||
return -EPERM;
|
||||
|
||||
down_write(&NILFS_MDT(cpfile)->mi_sem);
|
||||
|
||||
ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
|
||||
|
@ -384,9 +380,10 @@ static void nilfs_cpfile_checkpoint_to_cpinfo(struct inode *cpfile,
|
|||
}
|
||||
|
||||
static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
|
||||
struct nilfs_cpinfo *ci, size_t nci)
|
||||
void *buf, unsigned cisz, size_t nci)
|
||||
{
|
||||
struct nilfs_checkpoint *cp;
|
||||
struct nilfs_cpinfo *ci = buf;
|
||||
struct buffer_head *bh;
|
||||
size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size;
|
||||
__u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop;
|
||||
|
@ -410,17 +407,22 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
|
|||
kaddr = kmap_atomic(bh->b_page, KM_USER0);
|
||||
cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
|
||||
for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) {
|
||||
if (!nilfs_checkpoint_invalid(cp))
|
||||
nilfs_cpfile_checkpoint_to_cpinfo(
|
||||
cpfile, cp, &ci[n++]);
|
||||
if (!nilfs_checkpoint_invalid(cp)) {
|
||||
nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp,
|
||||
ci);
|
||||
ci = (void *)ci + cisz;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
brelse(bh);
|
||||
}
|
||||
|
||||
ret = n;
|
||||
if (n > 0)
|
||||
*cnop = ci[n - 1].ci_cno + 1;
|
||||
if (n > 0) {
|
||||
ci = (void *)ci - cisz;
|
||||
*cnop = ci->ci_cno + 1;
|
||||
}
|
||||
|
||||
out:
|
||||
up_read(&NILFS_MDT(cpfile)->mi_sem);
|
||||
|
@ -428,11 +430,12 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
|
|||
}
|
||||
|
||||
static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
|
||||
struct nilfs_cpinfo *ci, size_t nci)
|
||||
void *buf, unsigned cisz, size_t nci)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
struct nilfs_cpfile_header *header;
|
||||
struct nilfs_checkpoint *cp;
|
||||
struct nilfs_cpinfo *ci = buf;
|
||||
__u64 curr = *cnop, next;
|
||||
unsigned long curr_blkoff, next_blkoff;
|
||||
void *kaddr;
|
||||
|
@ -472,7 +475,9 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
|
|||
if (unlikely(nilfs_checkpoint_invalid(cp) ||
|
||||
!nilfs_checkpoint_snapshot(cp)))
|
||||
break;
|
||||
nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n++]);
|
||||
nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, ci);
|
||||
ci = (void *)ci + cisz;
|
||||
n++;
|
||||
next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
|
||||
if (next == 0)
|
||||
break; /* reach end of the snapshot list */
|
||||
|
@ -511,13 +516,13 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
|
|||
*/
|
||||
|
||||
ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode,
|
||||
struct nilfs_cpinfo *ci, size_t nci)
|
||||
void *buf, unsigned cisz, size_t nci)
|
||||
{
|
||||
switch (mode) {
|
||||
case NILFS_CHECKPOINT:
|
||||
return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, ci, nci);
|
||||
return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, buf, cisz, nci);
|
||||
case NILFS_SNAPSHOT:
|
||||
return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, ci, nci);
|
||||
return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, buf, cisz, nci);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -533,20 +538,14 @@ int nilfs_cpfile_delete_checkpoint(struct inode *cpfile, __u64 cno)
|
|||
struct nilfs_cpinfo ci;
|
||||
__u64 tcno = cno;
|
||||
ssize_t nci;
|
||||
int ret;
|
||||
|
||||
nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, 1);
|
||||
nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, sizeof(ci), 1);
|
||||
if (nci < 0)
|
||||
return nci;
|
||||
else if (nci == 0 || ci.ci_cno != cno)
|
||||
return -ENOENT;
|
||||
|
||||
/* cannot delete the latest checkpoint nor snapshots */
|
||||
ret = nilfs_cpinfo_snapshot(&ci);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret > 0 || cno == nilfs_mdt_cno(cpfile) - 1)
|
||||
return -EPERM;
|
||||
else if (nilfs_cpinfo_snapshot(&ci))
|
||||
return -EBUSY;
|
||||
|
||||
return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ int nilfs_cpfile_delete_checkpoint(struct inode *, __u64);
|
|||
int nilfs_cpfile_change_cpmode(struct inode *, __u64, int);
|
||||
int nilfs_cpfile_is_snapshot(struct inode *, __u64);
|
||||
int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *);
|
||||
ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int,
|
||||
struct nilfs_cpinfo *, size_t);
|
||||
ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned,
|
||||
size_t);
|
||||
|
||||
#endif /* _NILFS_CPFILE_H */
|
||||
|
|
|
@ -92,21 +92,6 @@ void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req)
|
|||
nilfs_palloc_abort_alloc_entry(dat, req);
|
||||
}
|
||||
|
||||
int nilfs_dat_prepare_free(struct inode *dat, struct nilfs_palloc_req *req)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nilfs_palloc_prepare_free_entry(dat, req);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = nilfs_dat_prepare_entry(dat, req, 0);
|
||||
if (ret < 0) {
|
||||
nilfs_palloc_abort_free_entry(dat, req);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req)
|
||||
{
|
||||
struct nilfs_dat_entry *entry;
|
||||
|
@ -391,36 +376,37 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ssize_t nilfs_dat_get_vinfo(struct inode *dat, struct nilfs_vinfo *vinfo,
|
||||
ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
|
||||
size_t nvi)
|
||||
{
|
||||
struct buffer_head *entry_bh;
|
||||
struct nilfs_dat_entry *entry;
|
||||
struct nilfs_vinfo *vinfo = buf;
|
||||
__u64 first, last;
|
||||
void *kaddr;
|
||||
unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block;
|
||||
int i, j, n, ret;
|
||||
|
||||
for (i = 0; i < nvi; i += n) {
|
||||
ret = nilfs_palloc_get_entry_block(dat, vinfo[i].vi_vblocknr,
|
||||
ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr,
|
||||
0, &entry_bh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
|
||||
/* last virtual block number in this block */
|
||||
first = vinfo[i].vi_vblocknr;
|
||||
first = vinfo->vi_vblocknr;
|
||||
do_div(first, entries_per_block);
|
||||
first *= entries_per_block;
|
||||
last = first + entries_per_block - 1;
|
||||
for (j = i, n = 0;
|
||||
j < nvi && vinfo[j].vi_vblocknr >= first &&
|
||||
vinfo[j].vi_vblocknr <= last;
|
||||
j++, n++) {
|
||||
j < nvi && vinfo->vi_vblocknr >= first &&
|
||||
vinfo->vi_vblocknr <= last;
|
||||
j++, n++, vinfo = (void *)vinfo + visz) {
|
||||
entry = nilfs_palloc_block_get_entry(
|
||||
dat, vinfo[j].vi_vblocknr, entry_bh, kaddr);
|
||||
vinfo[j].vi_start = le64_to_cpu(entry->de_start);
|
||||
vinfo[j].vi_end = le64_to_cpu(entry->de_end);
|
||||
vinfo[j].vi_blocknr = le64_to_cpu(entry->de_blocknr);
|
||||
dat, vinfo->vi_vblocknr, entry_bh, kaddr);
|
||||
vinfo->vi_start = le64_to_cpu(entry->de_start);
|
||||
vinfo->vi_end = le64_to_cpu(entry->de_end);
|
||||
vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
|
||||
}
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
brelse(entry_bh);
|
||||
|
|
|
@ -47,6 +47,6 @@ void nilfs_dat_abort_end(struct inode *, struct nilfs_palloc_req *);
|
|||
int nilfs_dat_mark_dirty(struct inode *, __u64);
|
||||
int nilfs_dat_freev(struct inode *, __u64 *, size_t);
|
||||
int nilfs_dat_move(struct inode *, __u64, sector_t);
|
||||
ssize_t nilfs_dat_get_vinfo(struct inode *, struct nilfs_vinfo *, size_t);
|
||||
ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t);
|
||||
|
||||
#endif /* _NILFS_DAT_H */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "page.h"
|
||||
#include "direct.h"
|
||||
#include "alloc.h"
|
||||
#include "dat.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key)
|
||||
{
|
||||
|
@ -90,10 +132,9 @@ static int nilfs_direct_prepare_insert(struct nilfs_direct *direct,
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (direct->d_ops->dop_find_target != NULL)
|
||||
req->bpr_ptr = direct->d_ops->dop_find_target(direct, key);
|
||||
ret = direct->d_bmap.b_pops->bpop_prepare_alloc_ptr(&direct->d_bmap,
|
||||
req);
|
||||
if (NILFS_BMAP_USE_VBN(&direct->d_bmap))
|
||||
req->bpr_ptr = nilfs_direct_find_target_v(direct, key);
|
||||
ret = nilfs_bmap_prepare_alloc_ptr(&direct->d_bmap, req);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -111,16 +152,14 @@ static void nilfs_direct_commit_insert(struct nilfs_direct *direct,
|
|||
bh = (struct buffer_head *)((unsigned long)ptr);
|
||||
set_buffer_nilfs_volatile(bh);
|
||||
|
||||
if (direct->d_bmap.b_pops->bpop_commit_alloc_ptr != NULL)
|
||||
direct->d_bmap.b_pops->bpop_commit_alloc_ptr(
|
||||
&direct->d_bmap, req);
|
||||
nilfs_bmap_commit_alloc_ptr(&direct->d_bmap, req);
|
||||
nilfs_direct_set_ptr(direct, key, req->bpr_ptr);
|
||||
|
||||
if (!nilfs_bmap_dirty(&direct->d_bmap))
|
||||
nilfs_bmap_set_dirty(&direct->d_bmap);
|
||||
|
||||
if (direct->d_ops->dop_set_target != NULL)
|
||||
direct->d_ops->dop_set_target(direct, key, req->bpr_ptr);
|
||||
if (NILFS_BMAP_USE_VBN(&direct->d_bmap))
|
||||
nilfs_direct_set_target_v(direct, key, req->bpr_ptr);
|
||||
}
|
||||
|
||||
static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
|
||||
|
@ -152,25 +191,18 @@ static int nilfs_direct_prepare_delete(struct nilfs_direct *direct,
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (direct->d_bmap.b_pops->bpop_prepare_end_ptr != NULL) {
|
||||
req->bpr_ptr = nilfs_direct_get_ptr(direct, key);
|
||||
ret = direct->d_bmap.b_pops->bpop_prepare_end_ptr(
|
||||
&direct->d_bmap, req);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
stats->bs_nblocks = 1;
|
||||
return 0;
|
||||
req->bpr_ptr = nilfs_direct_get_ptr(direct, key);
|
||||
ret = nilfs_bmap_prepare_end_ptr(&direct->d_bmap, req);
|
||||
if (!ret)
|
||||
stats->bs_nblocks = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nilfs_direct_commit_delete(struct nilfs_direct *direct,
|
||||
union nilfs_bmap_ptr_req *req,
|
||||
__u64 key)
|
||||
{
|
||||
if (direct->d_bmap.b_pops->bpop_commit_end_ptr != NULL)
|
||||
direct->d_bmap.b_pops->bpop_commit_end_ptr(
|
||||
&direct->d_bmap, req);
|
||||
nilfs_bmap_commit_end_ptr(&direct->d_bmap, req);
|
||||
nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR);
|
||||
}
|
||||
|
||||
|
@ -244,8 +276,7 @@ static int nilfs_direct_gather_data(struct nilfs_bmap *bmap,
|
|||
}
|
||||
|
||||
int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
|
||||
__u64 key, __u64 *keys, __u64 *ptrs,
|
||||
int n, __u64 low, __u64 high)
|
||||
__u64 key, __u64 *keys, __u64 *ptrs, int n)
|
||||
{
|
||||
struct nilfs_direct *direct;
|
||||
__le64 *dptrs;
|
||||
|
@ -275,8 +306,7 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
|
|||
dptrs[i] = NILFS_BMAP_INVALID_PTR;
|
||||
}
|
||||
|
||||
nilfs_direct_init(bmap, low, high);
|
||||
|
||||
nilfs_direct_init(bmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -293,11 +323,11 @@ static int nilfs_direct_propagate_v(struct nilfs_direct *direct,
|
|||
if (!buffer_nilfs_volatile(bh)) {
|
||||
oldreq.bpr_ptr = ptr;
|
||||
newreq.bpr_ptr = ptr;
|
||||
ret = nilfs_bmap_prepare_update(&direct->d_bmap, &oldreq,
|
||||
&newreq);
|
||||
ret = nilfs_bmap_prepare_update_v(&direct->d_bmap, &oldreq,
|
||||
&newreq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
nilfs_bmap_commit_update(&direct->d_bmap, &oldreq, &newreq);
|
||||
nilfs_bmap_commit_update_v(&direct->d_bmap, &oldreq, &newreq);
|
||||
set_buffer_nilfs_volatile(bh);
|
||||
nilfs_direct_set_ptr(direct, key, newreq.bpr_ptr);
|
||||
} else
|
||||
|
@ -309,12 +339,10 @@ static int nilfs_direct_propagate_v(struct nilfs_direct *direct,
|
|||
static int nilfs_direct_propagate(const struct nilfs_bmap *bmap,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
struct nilfs_direct *direct;
|
||||
struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
|
||||
|
||||
direct = (struct nilfs_direct *)bmap;
|
||||
return (direct->d_ops->dop_propagate != NULL) ?
|
||||
direct->d_ops->dop_propagate(direct, bh) :
|
||||
0;
|
||||
return NILFS_BMAP_USE_VBN(bmap) ?
|
||||
nilfs_direct_propagate_v(direct, bh) : 0;
|
||||
}
|
||||
|
||||
static int nilfs_direct_assign_v(struct nilfs_direct *direct,
|
||||
|
@ -327,12 +355,9 @@ static int nilfs_direct_assign_v(struct nilfs_direct *direct,
|
|||
int ret;
|
||||
|
||||
req.bpr_ptr = ptr;
|
||||
ret = direct->d_bmap.b_pops->bpop_prepare_start_ptr(
|
||||
&direct->d_bmap, &req);
|
||||
if (ret < 0)
|
||||
ret = nilfs_bmap_start_v(&direct->d_bmap, &req, blocknr);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
direct->d_bmap.b_pops->bpop_commit_start_ptr(&direct->d_bmap,
|
||||
&req, blocknr);
|
||||
|
||||
binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
|
||||
binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
|
||||
|
@ -377,12 +402,14 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
return direct->d_ops->dop_assign(direct, key, ptr, bh,
|
||||
blocknr, binfo);
|
||||
return NILFS_BMAP_USE_VBN(bmap) ?
|
||||
nilfs_direct_assign_v(direct, key, ptr, bh, blocknr, binfo) :
|
||||
nilfs_direct_assign_p(direct, key, ptr, bh, blocknr, binfo);
|
||||
}
|
||||
|
||||
static const struct nilfs_bmap_operations nilfs_direct_ops = {
|
||||
.bop_lookup = nilfs_direct_lookup,
|
||||
.bop_lookup_contig = nilfs_direct_lookup_contig,
|
||||
.bop_insert = nilfs_direct_insert,
|
||||
.bop_delete = nilfs_direct_delete,
|
||||
.bop_clear = NULL,
|
||||
|
@ -401,36 +428,8 @@ static const struct nilfs_bmap_operations nilfs_direct_ops = {
|
|||
};
|
||||
|
||||
|
||||
static const struct nilfs_direct_operations nilfs_direct_ops_v = {
|
||||
.dop_find_target = nilfs_direct_find_target_v,
|
||||
.dop_set_target = nilfs_direct_set_target_v,
|
||||
.dop_propagate = nilfs_direct_propagate_v,
|
||||
.dop_assign = nilfs_direct_assign_v,
|
||||
};
|
||||
|
||||
static const struct nilfs_direct_operations nilfs_direct_ops_p = {
|
||||
.dop_find_target = NULL,
|
||||
.dop_set_target = NULL,
|
||||
.dop_propagate = NULL,
|
||||
.dop_assign = nilfs_direct_assign_p,
|
||||
};
|
||||
|
||||
int nilfs_direct_init(struct nilfs_bmap *bmap, __u64 low, __u64 high)
|
||||
int nilfs_direct_init(struct nilfs_bmap *bmap)
|
||||
{
|
||||
struct nilfs_direct *direct;
|
||||
|
||||
direct = (struct nilfs_direct *)bmap;
|
||||
bmap->b_ops = &nilfs_direct_ops;
|
||||
bmap->b_low = low;
|
||||
bmap->b_high = high;
|
||||
switch (bmap->b_inode->i_ino) {
|
||||
case NILFS_DAT_INO:
|
||||
direct->d_ops = &nilfs_direct_ops_p;
|
||||
break;
|
||||
default:
|
||||
direct->d_ops = &nilfs_direct_ops_v;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,18 +30,6 @@
|
|||
|
||||
struct nilfs_direct;
|
||||
|
||||
/**
|
||||
* struct nilfs_direct_operations - direct mapping operation table
|
||||
*/
|
||||
struct nilfs_direct_operations {
|
||||
__u64 (*dop_find_target)(const struct nilfs_direct *, __u64);
|
||||
void (*dop_set_target)(struct nilfs_direct *, __u64, __u64);
|
||||
int (*dop_propagate)(struct nilfs_direct *, struct buffer_head *);
|
||||
int (*dop_assign)(struct nilfs_direct *, __u64, __u64,
|
||||
struct buffer_head **, sector_t,
|
||||
union nilfs_binfo *);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct nilfs_direct_node - direct node
|
||||
* @dn_flags: flags
|
||||
|
@ -55,13 +43,9 @@ struct nilfs_direct_node {
|
|||
/**
|
||||
* struct nilfs_direct - direct mapping
|
||||
* @d_bmap: bmap structure
|
||||
* @d_ops: direct mapping operation table
|
||||
*/
|
||||
struct nilfs_direct {
|
||||
struct nilfs_bmap d_bmap;
|
||||
|
||||
/* direct-mapping-specific members */
|
||||
const struct nilfs_direct_operations *d_ops;
|
||||
};
|
||||
|
||||
|
||||
|
@ -70,9 +54,9 @@ struct nilfs_direct {
|
|||
#define NILFS_DIRECT_KEY_MAX (NILFS_DIRECT_NBLOCKS - 1)
|
||||
|
||||
|
||||
int nilfs_direct_init(struct nilfs_bmap *, __u64, __u64);
|
||||
int nilfs_direct_init(struct nilfs_bmap *);
|
||||
int nilfs_direct_delete_and_convert(struct nilfs_bmap *, __u64, __u64 *,
|
||||
__u64 *, int, __u64, __u64);
|
||||
__u64 *, int);
|
||||
|
||||
|
||||
#endif /* _NILFS_DIRECT_H */
|
||||
|
|
|
@ -52,8 +52,9 @@
|
|||
#include "dat.h"
|
||||
#include "ifile.h"
|
||||
|
||||
static struct address_space_operations def_gcinode_aops = {};
|
||||
/* XXX need def_gcinode_iops/fops? */
|
||||
static struct address_space_operations def_gcinode_aops = {
|
||||
.sync_page = block_sync_page,
|
||||
};
|
||||
|
||||
/*
|
||||
* nilfs_gccache_submit_read_data() - add data buffer and submit read request
|
||||
|
|
|
@ -43,22 +43,23 @@
|
|||
*
|
||||
* This function does not issue actual read request of the specified data
|
||||
* 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,
|
||||
struct buffer_head *bh_result, int create)
|
||||
{
|
||||
struct nilfs_inode_info *ii = NILFS_I(inode);
|
||||
unsigned long blknum = 0;
|
||||
__u64 blknum = 0;
|
||||
int err = 0, ret;
|
||||
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); /* XXX */
|
||||
ret = nilfs_bmap_lookup(ii->i_bmap, (unsigned long)blkoff, &blknum);
|
||||
up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */
|
||||
if (ret == 0) { /* found */
|
||||
down_read(&NILFS_MDT(dat)->mi_sem);
|
||||
ret = nilfs_bmap_lookup_contig(ii->i_bmap, blkoff, &blknum, maxblocks);
|
||||
up_read(&NILFS_MDT(dat)->mi_sem);
|
||||
if (ret >= 0) { /* found */
|
||||
map_bh(bh_result, inode->i_sb, blknum);
|
||||
if (ret > 0)
|
||||
bh_result->b_size = (ret << inode->i_blkbits);
|
||||
goto out;
|
||||
}
|
||||
/* data block was not found */
|
||||
|
@ -240,7 +241,7 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
|
|||
struct address_space_operations nilfs_aops = {
|
||||
.writepage = nilfs_writepage,
|
||||
.readpage = nilfs_readpage,
|
||||
/* .sync_page = nilfs_sync_page, */
|
||||
.sync_page = block_sync_page,
|
||||
.writepages = nilfs_writepages,
|
||||
.set_page_dirty = nilfs_set_page_dirty,
|
||||
.readpages = nilfs_readpages,
|
||||
|
@ -249,6 +250,7 @@ struct address_space_operations nilfs_aops = {
|
|||
/* .releasepage = nilfs_releasepage, */
|
||||
.invalidatepage = block_invalidatepage,
|
||||
.direct_IO = nilfs_direct_IO,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
};
|
||||
|
||||
struct inode *nilfs_new_inode(struct inode *dir, int mode)
|
||||
|
|
|
@ -152,7 +152,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
|
|||
|
||||
down_read(&nilfs->ns_segctor_sem);
|
||||
ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
|
||||
nmembs);
|
||||
size, nmembs);
|
||||
up_read(&nilfs->ns_segctor_sem);
|
||||
return ret;
|
||||
}
|
||||
|
@ -182,7 +182,8 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
|
|||
int ret;
|
||||
|
||||
down_read(&nilfs->ns_segctor_sem);
|
||||
ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, nmembs);
|
||||
ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
|
||||
nmembs);
|
||||
up_read(&nilfs->ns_segctor_sem);
|
||||
return ret;
|
||||
}
|
||||
|
@ -212,7 +213,7 @@ nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
|
|||
int ret;
|
||||
|
||||
down_read(&nilfs->ns_segctor_sem);
|
||||
ret = nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs);
|
||||
ret = nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, size, nmembs);
|
||||
up_read(&nilfs->ns_segctor_sem);
|
||||
return ret;
|
||||
}
|
||||
|
@ -435,24 +436,6 @@ static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
|
|||
return nmembs;
|
||||
}
|
||||
|
||||
static int nilfs_ioctl_free_segments(struct the_nilfs *nilfs,
|
||||
struct nilfs_argv *argv, void *buf)
|
||||
{
|
||||
size_t nmembs = argv->v_nmembs;
|
||||
struct nilfs_sb_info *sbi = nilfs->ns_writer;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!sbi)) {
|
||||
/* never happens because called for a writable mount */
|
||||
WARN_ON(1);
|
||||
return -EROFS;
|
||||
}
|
||||
ret = nilfs_segctor_add_segments_to_be_freed(
|
||||
NILFS_SC(sbi), buf, nmembs);
|
||||
|
||||
return (ret < 0) ? ret : nmembs;
|
||||
}
|
||||
|
||||
int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
|
||||
struct nilfs_argv *argv, void **kbufs)
|
||||
{
|
||||
|
@ -491,14 +474,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
|
|||
msg = "cannot mark copying blocks dirty";
|
||||
goto failed;
|
||||
}
|
||||
ret = nilfs_ioctl_free_segments(nilfs, &argv[4], kbufs[4]);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* can safely abort because this operation is atomic.
|
||||
*/
|
||||
msg = "cannot set segments to be freed";
|
||||
goto failed;
|
||||
}
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
|
@ -615,7 +590,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
|
|||
if (copy_from_user(&argv, argp, sizeof(argv)))
|
||||
return -EFAULT;
|
||||
|
||||
if (argv.v_size != membsz)
|
||||
if (argv.v_size < membsz)
|
||||
return -EINVAL;
|
||||
|
||||
ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
|
||||
|
|
|
@ -430,6 +430,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
|
|||
|
||||
static struct address_space_operations def_mdt_aops = {
|
||||
.writepage = nilfs_mdt_write_page,
|
||||
.sync_page = block_sync_page,
|
||||
};
|
||||
|
||||
static struct inode_operations def_mdt_iops;
|
||||
|
@ -449,7 +450,7 @@ struct inode *
|
|||
nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb,
|
||||
ino_t ino, gfp_t gfp_mask)
|
||||
{
|
||||
struct inode *inode = nilfs_alloc_inode(sb);
|
||||
struct inode *inode = nilfs_alloc_inode_common(nilfs);
|
||||
|
||||
if (!inode)
|
||||
return NULL;
|
||||
|
|
|
@ -263,6 +263,7 @@ extern void nilfs_dirty_inode(struct inode *);
|
|||
extern struct dentry *nilfs_get_parent(struct dentry *);
|
||||
|
||||
/* super.c */
|
||||
extern struct inode *nilfs_alloc_inode_common(struct the_nilfs *);
|
||||
extern struct inode *nilfs_alloc_inode(struct super_block *);
|
||||
extern void nilfs_destroy_inode(struct inode *);
|
||||
extern void nilfs_error(struct super_block *, const char *, const char *, ...)
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "segment.h"
|
||||
#include "sufile.h"
|
||||
#include "page.h"
|
||||
#include "seglist.h"
|
||||
#include "segbuf.h"
|
||||
|
||||
/*
|
||||
|
@ -395,6 +394,24 @@ static void dispose_recovery_list(struct list_head *head)
|
|||
}
|
||||
}
|
||||
|
||||
struct nilfs_segment_entry {
|
||||
struct list_head list;
|
||||
__u64 segnum;
|
||||
};
|
||||
|
||||
static int nilfs_segment_list_add(struct list_head *head, __u64 segnum)
|
||||
{
|
||||
struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS);
|
||||
|
||||
if (unlikely(!ent))
|
||||
return -ENOMEM;
|
||||
|
||||
ent->segnum = segnum;
|
||||
INIT_LIST_HEAD(&ent->list);
|
||||
list_add_tail(&ent->list, head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nilfs_dispose_segment_list(struct list_head *head)
|
||||
{
|
||||
while (!list_empty(head)) {
|
||||
|
@ -402,7 +419,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
|
|||
= list_entry(head->next,
|
||||
struct nilfs_segment_entry, list);
|
||||
list_del(&ent->list);
|
||||
nilfs_free_segment_entry(ent);
|
||||
kfree(ent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,12 +448,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
|
|||
if (unlikely(err))
|
||||
goto failed;
|
||||
|
||||
err = -ENOMEM;
|
||||
for (i = 1; i < 4; i++) {
|
||||
ent = nilfs_alloc_segment_entry(segnum[i]);
|
||||
if (unlikely(!ent))
|
||||
err = nilfs_segment_list_add(head, segnum[i]);
|
||||
if (unlikely(err))
|
||||
goto failed;
|
||||
list_add_tail(&ent->list, head);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -450,7 +465,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
|
|||
goto failed;
|
||||
}
|
||||
list_del(&ent->list);
|
||||
nilfs_free_segment_entry(ent);
|
||||
kfree(ent);
|
||||
}
|
||||
|
||||
/* Allocate new segments for recovery */
|
||||
|
@ -791,7 +806,6 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi,
|
|||
u64 seg_seq;
|
||||
__u64 segnum, nextnum = 0;
|
||||
__u64 cno;
|
||||
struct nilfs_segment_entry *ent;
|
||||
LIST_HEAD(segments);
|
||||
int empty_seg = 0, scan_newer = 0;
|
||||
int ret;
|
||||
|
@ -892,12 +906,9 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi,
|
|||
if (empty_seg++)
|
||||
goto super_root_found; /* found a valid super root */
|
||||
|
||||
ent = nilfs_alloc_segment_entry(segnum);
|
||||
if (unlikely(!ent)) {
|
||||
ret = -ENOMEM;
|
||||
ret = nilfs_segment_list_add(&segments, segnum);
|
||||
if (unlikely(ret))
|
||||
goto failed;
|
||||
}
|
||||
list_add_tail(&ent->list, &segments);
|
||||
|
||||
seg_seq++;
|
||||
segnum = nextnum;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <linux/crc32.h>
|
||||
#include "page.h"
|
||||
#include "segbuf.h"
|
||||
#include "seglist.h"
|
||||
|
||||
|
||||
static struct kmem_cache *nilfs_segbuf_cachep;
|
||||
|
@ -394,7 +393,7 @@ int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf,
|
|||
* Last BIO is always sent through the following
|
||||
* submission.
|
||||
*/
|
||||
rw |= (1 << BIO_RW_SYNCIO);
|
||||
rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
|
||||
res = nilfs_submit_seg_bio(wi, rw);
|
||||
if (unlikely(res))
|
||||
goto failed_bio;
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* seglist.h - expediential structure and routines to handle list of segments
|
||||
* (would be removed in a future release)
|
||||
*
|
||||
* Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Written by Ryusuke Konishi <ryusuke@osrg.net>
|
||||
*
|
||||
*/
|
||||
#ifndef _NILFS_SEGLIST_H
|
||||
#define _NILFS_SEGLIST_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/nilfs2_fs.h>
|
||||
#include "sufile.h"
|
||||
|
||||
struct nilfs_segment_entry {
|
||||
__u64 segnum;
|
||||
|
||||
#define NILFS_SLH_FREED 0x0001 /* The segment was freed provisonally.
|
||||
It must be cancelled if
|
||||
construction aborted */
|
||||
|
||||
unsigned flags;
|
||||
struct list_head list;
|
||||
struct buffer_head *bh_su;
|
||||
struct nilfs_segment_usage *raw_su;
|
||||
};
|
||||
|
||||
|
||||
void nilfs_dispose_segment_list(struct list_head *);
|
||||
|
||||
static inline struct nilfs_segment_entry *
|
||||
nilfs_alloc_segment_entry(__u64 segnum)
|
||||
{
|
||||
struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS);
|
||||
|
||||
if (likely(ent)) {
|
||||
ent->segnum = segnum;
|
||||
ent->flags = 0;
|
||||
ent->bh_su = NULL;
|
||||
ent->raw_su = NULL;
|
||||
INIT_LIST_HEAD(&ent->list);
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
static inline int nilfs_open_segment_entry(struct nilfs_segment_entry *ent,
|
||||
struct inode *sufile)
|
||||
{
|
||||
return nilfs_sufile_get_segment_usage(sufile, ent->segnum,
|
||||
&ent->raw_su, &ent->bh_su);
|
||||
}
|
||||
|
||||
static inline void nilfs_close_segment_entry(struct nilfs_segment_entry *ent,
|
||||
struct inode *sufile)
|
||||
{
|
||||
if (!ent->bh_su)
|
||||
return;
|
||||
nilfs_sufile_put_segment_usage(sufile, ent->segnum, ent->bh_su);
|
||||
ent->bh_su = NULL;
|
||||
ent->raw_su = NULL;
|
||||
}
|
||||
|
||||
static inline void nilfs_free_segment_entry(struct nilfs_segment_entry *ent)
|
||||
{
|
||||
kfree(ent);
|
||||
}
|
||||
|
||||
#endif /* _NILFS_SEGLIST_H */
|
|
@ -39,7 +39,6 @@
|
|||
#include "sufile.h"
|
||||
#include "cpfile.h"
|
||||
#include "ifile.h"
|
||||
#include "seglist.h"
|
||||
#include "segbuf.h"
|
||||
|
||||
|
||||
|
@ -79,7 +78,8 @@ enum {
|
|||
/* State flags of collection */
|
||||
#define NILFS_CF_NODE 0x0001 /* Collecting node blocks */
|
||||
#define NILFS_CF_IFILE_STARTED 0x0002 /* IFILE stage has started */
|
||||
#define NILFS_CF_HISTORY_MASK (NILFS_CF_IFILE_STARTED)
|
||||
#define NILFS_CF_SUFREED 0x0004 /* segment usages has been freed */
|
||||
#define NILFS_CF_HISTORY_MASK (NILFS_CF_IFILE_STARTED | NILFS_CF_SUFREED)
|
||||
|
||||
/* Operations depending on the construction mode and file type */
|
||||
struct nilfs_sc_operations {
|
||||
|
@ -810,7 +810,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci)
|
|||
{
|
||||
return list_empty(&sci->sc_dirty_files) &&
|
||||
!test_bit(NILFS_SC_DIRTY, &sci->sc_flags) &&
|
||||
list_empty(&sci->sc_cleaning_segments) &&
|
||||
sci->sc_nfreesegs == 0 &&
|
||||
(!nilfs_doing_gc() || list_empty(&sci->sc_gc_inodes));
|
||||
}
|
||||
|
||||
|
@ -1005,44 +1005,6 @@ static void nilfs_drop_collected_inodes(struct list_head *head)
|
|||
}
|
||||
}
|
||||
|
||||
static void nilfs_segctor_cancel_free_segments(struct nilfs_sc_info *sci,
|
||||
struct inode *sufile)
|
||||
|
||||
{
|
||||
struct list_head *head = &sci->sc_cleaning_segments;
|
||||
struct nilfs_segment_entry *ent;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(ent, head, list) {
|
||||
if (!(ent->flags & NILFS_SLH_FREED))
|
||||
break;
|
||||
err = nilfs_sufile_cancel_free(sufile, ent->segnum);
|
||||
WARN_ON(err); /* do not happen */
|
||||
ent->flags &= ~NILFS_SLH_FREED;
|
||||
}
|
||||
}
|
||||
|
||||
static int nilfs_segctor_prepare_free_segments(struct nilfs_sc_info *sci,
|
||||
struct inode *sufile)
|
||||
{
|
||||
struct list_head *head = &sci->sc_cleaning_segments;
|
||||
struct nilfs_segment_entry *ent;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(ent, head, list) {
|
||||
err = nilfs_sufile_free(sufile, ent->segnum);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
ent->flags |= NILFS_SLH_FREED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nilfs_segctor_commit_free_segments(struct nilfs_sc_info *sci)
|
||||
{
|
||||
nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
|
||||
}
|
||||
|
||||
static int nilfs_segctor_apply_buffers(struct nilfs_sc_info *sci,
|
||||
struct inode *inode,
|
||||
struct list_head *listp,
|
||||
|
@ -1161,6 +1123,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
|
|||
struct the_nilfs *nilfs = sbi->s_nilfs;
|
||||
struct list_head *head;
|
||||
struct nilfs_inode_info *ii;
|
||||
size_t ndone;
|
||||
int err = 0;
|
||||
|
||||
switch (sci->sc_stage.scnt) {
|
||||
|
@ -1250,10 +1213,16 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
|
|||
break;
|
||||
sci->sc_stage.scnt++; /* Fall through */
|
||||
case NILFS_ST_SUFILE:
|
||||
err = nilfs_segctor_prepare_free_segments(sci,
|
||||
nilfs->ns_sufile);
|
||||
if (unlikely(err))
|
||||
err = nilfs_sufile_freev(nilfs->ns_sufile, sci->sc_freesegs,
|
||||
sci->sc_nfreesegs, &ndone);
|
||||
if (unlikely(err)) {
|
||||
nilfs_sufile_cancel_freev(nilfs->ns_sufile,
|
||||
sci->sc_freesegs, ndone,
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
sci->sc_stage.flags |= NILFS_CF_SUFREED;
|
||||
|
||||
err = nilfs_segctor_scan_file(sci, nilfs->ns_sufile,
|
||||
&nilfs_sc_file_ops);
|
||||
if (unlikely(err))
|
||||
|
@ -1486,7 +1455,15 @@ static void nilfs_segctor_end_construction(struct nilfs_sc_info *sci,
|
|||
{
|
||||
if (unlikely(err)) {
|
||||
nilfs_segctor_free_incomplete_segments(sci, nilfs);
|
||||
nilfs_segctor_cancel_free_segments(sci, nilfs->ns_sufile);
|
||||
if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
|
||||
int ret;
|
||||
|
||||
ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
|
||||
sci->sc_freesegs,
|
||||
sci->sc_nfreesegs,
|
||||
NULL);
|
||||
WARN_ON(ret); /* do not happen */
|
||||
}
|
||||
}
|
||||
nilfs_segctor_clear_segment_buffers(sci);
|
||||
}
|
||||
|
@ -1585,7 +1562,13 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
|
|||
if (mode != SC_LSEG_SR || sci->sc_stage.scnt < NILFS_ST_CPFILE)
|
||||
break;
|
||||
|
||||
nilfs_segctor_cancel_free_segments(sci, nilfs->ns_sufile);
|
||||
if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
|
||||
err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
|
||||
sci->sc_freesegs,
|
||||
sci->sc_nfreesegs,
|
||||
NULL);
|
||||
WARN_ON(err); /* do not happen */
|
||||
}
|
||||
nilfs_segctor_clear_segment_buffers(sci);
|
||||
|
||||
err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
|
||||
|
@ -2224,10 +2207,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
|
|||
nilfs_segctor_complete_write(sci);
|
||||
|
||||
/* Commit segments */
|
||||
if (has_sr) {
|
||||
nilfs_segctor_commit_free_segments(sci);
|
||||
if (has_sr)
|
||||
nilfs_segctor_clear_metadata_dirty(sci);
|
||||
}
|
||||
|
||||
nilfs_segctor_end_construction(sci, nilfs, 0);
|
||||
|
||||
|
@ -2301,48 +2282,6 @@ void nilfs_flush_segment(struct super_block *sb, ino_t ino)
|
|||
/* assign bit 0 to data files */
|
||||
}
|
||||
|
||||
int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *sci,
|
||||
__u64 *segnum, size_t nsegs)
|
||||
{
|
||||
struct nilfs_segment_entry *ent;
|
||||
struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
|
||||
struct inode *sufile = nilfs->ns_sufile;
|
||||
LIST_HEAD(list);
|
||||
__u64 *pnum;
|
||||
size_t i;
|
||||
int err;
|
||||
|
||||
for (pnum = segnum, i = 0; i < nsegs; pnum++, i++) {
|
||||
ent = nilfs_alloc_segment_entry(*pnum);
|
||||
if (unlikely(!ent)) {
|
||||
err = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
list_add_tail(&ent->list, &list);
|
||||
|
||||
err = nilfs_open_segment_entry(ent, sufile);
|
||||
if (unlikely(err))
|
||||
goto failed;
|
||||
|
||||
if (unlikely(!nilfs_segment_usage_dirty(ent->raw_su)))
|
||||
printk(KERN_WARNING "NILFS: unused segment is "
|
||||
"requested to be cleaned (segnum=%llu)\n",
|
||||
(unsigned long long)ent->segnum);
|
||||
nilfs_close_segment_entry(ent, sufile);
|
||||
}
|
||||
list_splice(&list, sci->sc_cleaning_segments.prev);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
nilfs_dispose_segment_list(&list);
|
||||
return err;
|
||||
}
|
||||
|
||||
void nilfs_segctor_clear_segments_to_be_freed(struct nilfs_sc_info *sci)
|
||||
{
|
||||
nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
|
||||
}
|
||||
|
||||
struct nilfs_segctor_wait_request {
|
||||
wait_queue_t wq;
|
||||
__u32 seq;
|
||||
|
@ -2607,10 +2546,13 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
|
|||
err = nilfs_init_gcdat_inode(nilfs);
|
||||
if (unlikely(err))
|
||||
goto out_unlock;
|
||||
|
||||
err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
|
||||
if (unlikely(err))
|
||||
goto out_unlock;
|
||||
|
||||
sci->sc_freesegs = kbufs[4];
|
||||
sci->sc_nfreesegs = argv[4].v_nmembs;
|
||||
list_splice_init(&nilfs->ns_gc_inodes, sci->sc_gc_inodes.prev);
|
||||
|
||||
for (;;) {
|
||||
|
@ -2629,6 +2571,8 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
|
|||
}
|
||||
|
||||
out_unlock:
|
||||
sci->sc_freesegs = NULL;
|
||||
sci->sc_nfreesegs = 0;
|
||||
nilfs_clear_gcdat_inode(nilfs);
|
||||
nilfs_transaction_unlock(sbi);
|
||||
return err;
|
||||
|
@ -2835,7 +2779,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi)
|
|||
INIT_LIST_HEAD(&sci->sc_dirty_files);
|
||||
INIT_LIST_HEAD(&sci->sc_segbufs);
|
||||
INIT_LIST_HEAD(&sci->sc_gc_inodes);
|
||||
INIT_LIST_HEAD(&sci->sc_cleaning_segments);
|
||||
INIT_LIST_HEAD(&sci->sc_copied_buffers);
|
||||
|
||||
sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
|
||||
|
@ -2901,9 +2844,6 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
|
|||
nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1);
|
||||
}
|
||||
|
||||
if (!list_empty(&sci->sc_cleaning_segments))
|
||||
nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
|
||||
|
||||
WARN_ON(!list_empty(&sci->sc_segbufs));
|
||||
|
||||
down_write(&sbi->s_nilfs->ns_segctor_sem);
|
||||
|
|
|
@ -90,8 +90,9 @@ struct nilfs_segsum_pointer {
|
|||
* @sc_nblk_inc: Block count of current generation
|
||||
* @sc_dirty_files: List of files to be written
|
||||
* @sc_gc_inodes: List of GC inodes having blocks to be written
|
||||
* @sc_cleaning_segments: List of segments to be freed through construction
|
||||
* @sc_copied_buffers: List of copied buffers (buffer heads) to freeze data
|
||||
* @sc_freesegs: array of segment numbers to be freed
|
||||
* @sc_nfreesegs: number of segments on @sc_freesegs
|
||||
* @sc_dsync_inode: inode whose data pages are written for a sync operation
|
||||
* @sc_dsync_start: start byte offset of data pages
|
||||
* @sc_dsync_end: end byte offset of data pages (inclusive)
|
||||
|
@ -131,9 +132,11 @@ struct nilfs_sc_info {
|
|||
|
||||
struct list_head sc_dirty_files;
|
||||
struct list_head sc_gc_inodes;
|
||||
struct list_head sc_cleaning_segments;
|
||||
struct list_head sc_copied_buffers;
|
||||
|
||||
__u64 *sc_freesegs;
|
||||
size_t sc_nfreesegs;
|
||||
|
||||
struct nilfs_inode_info *sc_dsync_inode;
|
||||
loff_t sc_dsync_start;
|
||||
loff_t sc_dsync_end;
|
||||
|
@ -225,10 +228,6 @@ extern void nilfs_flush_segment(struct super_block *, ino_t);
|
|||
extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
|
||||
void **);
|
||||
|
||||
extern int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *,
|
||||
__u64 *, size_t);
|
||||
extern void nilfs_segctor_clear_segments_to_be_freed(struct nilfs_sc_info *);
|
||||
|
||||
extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *);
|
||||
extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
|
||||
|
||||
|
@ -240,5 +239,6 @@ extern int nilfs_search_super_root(struct the_nilfs *, struct nilfs_sb_info *,
|
|||
extern int nilfs_recover_logical_segments(struct the_nilfs *,
|
||||
struct nilfs_sb_info *,
|
||||
struct nilfs_recovery_info *);
|
||||
extern void nilfs_dispose_segment_list(struct list_head *);
|
||||
|
||||
#endif /* _NILFS_SEGMENT_H */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Written by Koji Sato <koji@osrg.net>.
|
||||
* Rivised by Ryusuke Konishi <ryusuke@osrg.net>.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -108,6 +109,102 @@ static void nilfs_sufile_mod_counter(struct buffer_head *header_bh,
|
|||
nilfs_mdt_mark_buffer_dirty(header_bh);
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_sufile_updatev - modify multiple segment usages at a time
|
||||
* @sufile: inode of segment usage file
|
||||
* @segnumv: array of segment numbers
|
||||
* @nsegs: size of @segnumv array
|
||||
* @create: creation flag
|
||||
* @ndone: place to store number of modified segments on @segnumv
|
||||
* @dofunc: primitive operation for the update
|
||||
*
|
||||
* Description: nilfs_sufile_updatev() repeatedly calls @dofunc
|
||||
* against the given array of segments. The @dofunc is called with
|
||||
* buffers of a header block and the sufile block in which the target
|
||||
* segment usage entry is contained. If @ndone is given, the number
|
||||
* of successfully modified segments from the head is stored in the
|
||||
* place @ndone points to.
|
||||
*
|
||||
* Return Value: On success, zero is returned. On error, one of the
|
||||
* following negative error codes is returned.
|
||||
*
|
||||
* %-EIO - I/O error.
|
||||
*
|
||||
* %-ENOMEM - Insufficient amount of memory available.
|
||||
*
|
||||
* %-ENOENT - Given segment usage is in hole block (may be returned if
|
||||
* @create is zero)
|
||||
*
|
||||
* %-EINVAL - Invalid segment usage number
|
||||
*/
|
||||
int nilfs_sufile_updatev(struct inode *sufile, __u64 *segnumv, size_t nsegs,
|
||||
int create, size_t *ndone,
|
||||
void (*dofunc)(struct inode *, __u64,
|
||||
struct buffer_head *,
|
||||
struct buffer_head *))
|
||||
{
|
||||
struct buffer_head *header_bh, *bh;
|
||||
unsigned long blkoff, prev_blkoff;
|
||||
__u64 *seg;
|
||||
size_t nerr = 0, n = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(nsegs == 0))
|
||||
goto out;
|
||||
|
||||
down_write(&NILFS_MDT(sufile)->mi_sem);
|
||||
for (seg = segnumv; seg < segnumv + nsegs; seg++) {
|
||||
if (unlikely(*seg >= nilfs_sufile_get_nsegments(sufile))) {
|
||||
printk(KERN_WARNING
|
||||
"%s: invalid segment number: %llu\n", __func__,
|
||||
(unsigned long long)*seg);
|
||||
nerr++;
|
||||
}
|
||||
}
|
||||
if (nerr > 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_sem;
|
||||
}
|
||||
|
||||
ret = nilfs_sufile_get_header_block(sufile, &header_bh);
|
||||
if (ret < 0)
|
||||
goto out_sem;
|
||||
|
||||
seg = segnumv;
|
||||
blkoff = nilfs_sufile_get_blkoff(sufile, *seg);
|
||||
ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh);
|
||||
if (ret < 0)
|
||||
goto out_header;
|
||||
|
||||
for (;;) {
|
||||
dofunc(sufile, *seg, header_bh, bh);
|
||||
|
||||
if (++seg >= segnumv + nsegs)
|
||||
break;
|
||||
prev_blkoff = blkoff;
|
||||
blkoff = nilfs_sufile_get_blkoff(sufile, *seg);
|
||||
if (blkoff == prev_blkoff)
|
||||
continue;
|
||||
|
||||
/* get different block */
|
||||
brelse(bh);
|
||||
ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh);
|
||||
if (unlikely(ret < 0))
|
||||
goto out_header;
|
||||
}
|
||||
brelse(bh);
|
||||
|
||||
out_header:
|
||||
n = seg - segnumv;
|
||||
brelse(header_bh);
|
||||
out_sem:
|
||||
up_write(&NILFS_MDT(sufile)->mi_sem);
|
||||
out:
|
||||
if (ndone)
|
||||
*ndone = n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create,
|
||||
void (*dofunc)(struct inode *, __u64,
|
||||
struct buffer_head *,
|
||||
|
@ -490,7 +587,8 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum,
|
|||
* nilfs_sufile_get_suinfo -
|
||||
* @sufile: inode of segment usage file
|
||||
* @segnum: segment number to start looking
|
||||
* @si: array of suinfo
|
||||
* @buf: array of suinfo
|
||||
* @sisz: byte size of suinfo
|
||||
* @nsi: size of suinfo array
|
||||
*
|
||||
* Description:
|
||||
|
@ -502,11 +600,12 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum,
|
|||
*
|
||||
* %-ENOMEM - Insufficient amount of memory available.
|
||||
*/
|
||||
ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum,
|
||||
struct nilfs_suinfo *si, size_t nsi)
|
||||
ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
|
||||
unsigned sisz, size_t nsi)
|
||||
{
|
||||
struct buffer_head *su_bh;
|
||||
struct nilfs_segment_usage *su;
|
||||
struct nilfs_suinfo *si = buf;
|
||||
size_t susz = NILFS_MDT(sufile)->mi_entry_size;
|
||||
struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs;
|
||||
void *kaddr;
|
||||
|
@ -531,20 +630,22 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum,
|
|||
if (ret != -ENOENT)
|
||||
goto out;
|
||||
/* hole */
|
||||
memset(&si[i], 0, sizeof(struct nilfs_suinfo) * n);
|
||||
memset(si, 0, sisz * n);
|
||||
si = (void *)si + sisz * n;
|
||||
continue;
|
||||
}
|
||||
|
||||
kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
|
||||
su = nilfs_sufile_block_get_segment_usage(
|
||||
sufile, segnum, su_bh, kaddr);
|
||||
for (j = 0; j < n; j++, su = (void *)su + susz) {
|
||||
si[i + j].sui_lastmod = le64_to_cpu(su->su_lastmod);
|
||||
si[i + j].sui_nblocks = le32_to_cpu(su->su_nblocks);
|
||||
si[i + j].sui_flags = le32_to_cpu(su->su_flags) &
|
||||
for (j = 0; j < n;
|
||||
j++, su = (void *)su + susz, si = (void *)si + sisz) {
|
||||
si->sui_lastmod = le64_to_cpu(su->su_lastmod);
|
||||
si->sui_nblocks = le32_to_cpu(su->su_nblocks);
|
||||
si->sui_flags = le32_to_cpu(su->su_flags) &
|
||||
~(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
|
||||
if (nilfs_segment_is_active(nilfs, segnum + j))
|
||||
si[i + j].sui_flags |=
|
||||
si->sui_flags |=
|
||||
(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
|
||||
}
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
|
|
|
@ -43,42 +43,26 @@ void nilfs_sufile_put_segment_usage(struct inode *, __u64,
|
|||
struct buffer_head *);
|
||||
int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
|
||||
int nilfs_sufile_get_ncleansegs(struct inode *, unsigned long *);
|
||||
ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, struct nilfs_suinfo *,
|
||||
ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned,
|
||||
size_t);
|
||||
|
||||
int nilfs_sufile_updatev(struct inode *, __u64 *, size_t, int, size_t *,
|
||||
void (*dofunc)(struct inode *, __u64,
|
||||
struct buffer_head *,
|
||||
struct buffer_head *));
|
||||
int nilfs_sufile_update(struct inode *, __u64, int,
|
||||
void (*dofunc)(struct inode *, __u64,
|
||||
struct buffer_head *,
|
||||
struct buffer_head *));
|
||||
void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
|
||||
struct buffer_head *);
|
||||
void nilfs_sufile_do_scrap(struct inode *, __u64, struct buffer_head *,
|
||||
struct buffer_head *);
|
||||
void nilfs_sufile_do_free(struct inode *, __u64, struct buffer_head *,
|
||||
struct buffer_head *);
|
||||
void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
|
||||
struct buffer_head *);
|
||||
void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *,
|
||||
struct buffer_head *);
|
||||
|
||||
/**
|
||||
* nilfs_sufile_cancel_free -
|
||||
* @sufile: inode of segment usage file
|
||||
* @segnum: segment number
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Return Value: On success, 0 is returned. On error, one of the following
|
||||
* negative error codes is returned.
|
||||
*
|
||||
* %-EIO - I/O error.
|
||||
*
|
||||
* %-ENOMEM - Insufficient amount of memory available.
|
||||
*/
|
||||
static inline int nilfs_sufile_cancel_free(struct inode *sufile, __u64 segnum)
|
||||
{
|
||||
return nilfs_sufile_update(sufile, segnum, 0,
|
||||
nilfs_sufile_do_cancel_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_sufile_scrap - make a segment garbage
|
||||
* @sufile: inode of segment usage file
|
||||
|
@ -99,6 +83,38 @@ static inline int nilfs_sufile_free(struct inode *sufile, __u64 segnum)
|
|||
return nilfs_sufile_update(sufile, segnum, 0, nilfs_sufile_do_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_sufile_freev - free segments
|
||||
* @sufile: inode of segment usage file
|
||||
* @segnumv: array of segment numbers
|
||||
* @nsegs: size of @segnumv array
|
||||
* @ndone: place to store the number of freed segments
|
||||
*/
|
||||
static inline int nilfs_sufile_freev(struct inode *sufile, __u64 *segnumv,
|
||||
size_t nsegs, size_t *ndone)
|
||||
{
|
||||
return nilfs_sufile_updatev(sufile, segnumv, nsegs, 0, ndone,
|
||||
nilfs_sufile_do_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_sufile_cancel_freev - reallocate freeing segments
|
||||
* @sufile: inode of segment usage file
|
||||
* @segnumv: array of segment numbers
|
||||
* @nsegs: size of @segnumv array
|
||||
* @ndone: place to store the number of cancelled segments
|
||||
*
|
||||
* Return Value: On success, 0 is returned. On error, a negative error codes
|
||||
* is returned.
|
||||
*/
|
||||
static inline int nilfs_sufile_cancel_freev(struct inode *sufile,
|
||||
__u64 *segnumv, size_t nsegs,
|
||||
size_t *ndone)
|
||||
{
|
||||
return nilfs_sufile_updatev(sufile, segnumv, nsegs, 0, ndone,
|
||||
nilfs_sufile_do_cancel_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_sufile_set_error - mark a segment as erroneous
|
||||
* @sufile: inode of segment usage file
|
||||
|
|
|
@ -133,7 +133,7 @@ void nilfs_warning(struct super_block *sb, const char *function,
|
|||
|
||||
static struct kmem_cache *nilfs_inode_cachep;
|
||||
|
||||
struct inode *nilfs_alloc_inode(struct super_block *sb)
|
||||
struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs)
|
||||
{
|
||||
struct nilfs_inode_info *ii;
|
||||
|
||||
|
@ -143,10 +143,15 @@ struct inode *nilfs_alloc_inode(struct super_block *sb)
|
|||
ii->i_bh = NULL;
|
||||
ii->i_state = 0;
|
||||
ii->vfs_inode.i_version = 1;
|
||||
nilfs_btnode_cache_init(&ii->i_btnode_cache);
|
||||
nilfs_btnode_cache_init(&ii->i_btnode_cache, nilfs->ns_bdi);
|
||||
return &ii->vfs_inode;
|
||||
}
|
||||
|
||||
struct inode *nilfs_alloc_inode(struct super_block *sb)
|
||||
{
|
||||
return nilfs_alloc_inode_common(NILFS_SB(sb)->s_nilfs);
|
||||
}
|
||||
|
||||
void nilfs_destroy_inode(struct inode *inode)
|
||||
{
|
||||
kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode));
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "cpfile.h"
|
||||
#include "sufile.h"
|
||||
#include "dat.h"
|
||||
#include "seglist.h"
|
||||
#include "segbuf.h"
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue