Commit af8cb8aa authored by Linus Torvalds's avatar Linus Torvalds

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: (21 commits)
  fs/Kconfig: move nilfs2 outside misc filesystems
  nilfs2: convert nilfs_bmap_lookup to an inline function
  nilfs2: allow btree code to directly call dat operations
  nilfs2: add update functions of virtual block address to dat
  nilfs2: remove individual gfp constants for each metadata file
  nilfs2: stop zero-fill of btree path just before free it
  nilfs2: remove unused btree argument from btree functions
  nilfs2: remove nilfs_dat_abort_start and nilfs_dat_abort_free
  nilfs2: shorten freeze period due to GC in write operation v3
  nilfs2: add more check routines in mount process
  nilfs2: An unassigned variable is assigned to a never used structure member
  nilfs2: use GFP_NOIO for bio_alloc instead of GFP_NOWAIT
  nilfs2: stop using periodic write_super callback
  nilfs2: clean up nilfs_write_super
  nilfs2: fix disorder of nilfs_write_super in nilfs_sync_fs
  nilfs2: remove redundant super block commit
  nilfs2: implement nilfs_show_options to display mount options in /proc/mounts
  nilfs2: always lookup disk block address before reading metadata block
  nilfs2: use semaphore to protect pointer to a writable FS-instance
  nilfs2: fix format string compile warning (ino_t)
  ...
parents 6cdb5930 41f4db0f
...@@ -43,6 +43,7 @@ source "fs/xfs/Kconfig" ...@@ -43,6 +43,7 @@ source "fs/xfs/Kconfig"
source "fs/gfs2/Kconfig" source "fs/gfs2/Kconfig"
source "fs/ocfs2/Kconfig" source "fs/ocfs2/Kconfig"
source "fs/btrfs/Kconfig" source "fs/btrfs/Kconfig"
source "fs/nilfs2/Kconfig"
endif # BLOCK endif # BLOCK
...@@ -186,7 +187,6 @@ source "fs/romfs/Kconfig" ...@@ -186,7 +187,6 @@ source "fs/romfs/Kconfig"
source "fs/sysv/Kconfig" source "fs/sysv/Kconfig"
source "fs/ufs/Kconfig" source "fs/ufs/Kconfig"
source "fs/exofs/Kconfig" source "fs/exofs/Kconfig"
source "fs/nilfs2/Kconfig"
endif # MISC_FILESYSTEMS endif # MISC_FILESYSTEMS
......
config NILFS2_FS config NILFS2_FS
tristate "NILFS2 file system support (EXPERIMENTAL)" tristate "NILFS2 file system support (EXPERIMENTAL)"
depends on BLOCK && EXPERIMENTAL depends on EXPERIMENTAL
select CRC32 select CRC32
help help
NILFS2 is a log-structured file system (LFS) supporting continuous NILFS2 is a log-structured file system (LFS) supporting continuous
......
...@@ -36,6 +36,26 @@ struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap) ...@@ -36,6 +36,26 @@ struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode)); return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
} }
/**
* nilfs_bmap_lookup_at_level - find a data block or node block
* @bmap: bmap
* @key: key
* @level: level
* @ptrp: place to store the value associated to @key
*
* Description: nilfs_bmap_lookup_at_level() finds a record whose key
* matches @key in the block at @level of the bmap.
*
* Return Value: On success, 0 is returned and the record associated with @key
* is stored in the place pointed by @ptrp. On error, one of the following
* negative error codes is returned.
*
* %-EIO - I/O error.
*
* %-ENOMEM - Insufficient amount of memory available.
*
* %-ENOENT - A record associated with @key does not exist.
*/
int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level, int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
__u64 *ptrp) __u64 *ptrp)
{ {
...@@ -69,39 +89,6 @@ int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp, ...@@ -69,39 +89,6 @@ int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
return ret; return ret;
} }
/**
* nilfs_bmap_lookup - find a record
* @bmap: bmap
* @key: key
* @recp: pointer to record
*
* Description: nilfs_bmap_lookup() finds a record whose key matches @key in
* @bmap.
*
* Return Value: On success, 0 is returned and the record associated with @key
* is stored in the place pointed by @recp. On error, one of the following
* negative error codes is returned.
*
* %-EIO - I/O error.
*
* %-ENOMEM - Insufficient amount of memory available.
*
* %-ENOENT - A record associated with @key does not exist.
*/
int nilfs_bmap_lookup(struct nilfs_bmap *bmap,
unsigned long key,
unsigned long *recp)
{
__u64 ptr;
int ret;
/* XXX: use macro for level 1 */
ret = nilfs_bmap_lookup_at_level(bmap, key, 1, &ptr);
if (recp != NULL)
*recp = ptr;
return ret;
}
static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
{ {
__u64 keys[NILFS_BMAP_SMALL_HIGH + 1]; __u64 keys[NILFS_BMAP_SMALL_HIGH + 1];
...@@ -469,104 +456,6 @@ __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap) ...@@ -469,104 +456,6 @@ __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
(entries_per_group / NILFS_BMAP_GROUP_DIV); (entries_per_group / NILFS_BMAP_GROUP_DIV);
} }
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);
}
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);
}
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);
}
int nilfs_bmap_start_v(struct nilfs_bmap *bmap, union nilfs_bmap_ptr_req *req,
sector_t blocknr)
{
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;
}
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);
}
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,
bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
}
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);
}
int nilfs_bmap_move_v(const struct nilfs_bmap *bmap, __u64 vblocknr,
sector_t blocknr)
{
return nilfs_dat_move(nilfs_bmap_get_dat(bmap), vblocknr, blocknr);
}
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_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 = nilfs_dat_prepare_end(dat, &oldreq->bpr_req);
if (ret < 0)
return ret;
ret = nilfs_dat_prepare_alloc(dat, &newreq->bpr_req);
if (ret < 0)
nilfs_dat_abort_end(dat, &oldreq->bpr_req);
return ret;
}
void nilfs_bmap_commit_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);
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_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);
nilfs_dat_abort_end(dat, &oldreq->bpr_req);
nilfs_dat_abort_alloc(dat, &newreq->bpr_req);
}
static struct lock_class_key nilfs_bmap_dat_lock_key; static struct lock_class_key nilfs_bmap_dat_lock_key;
static struct lock_class_key nilfs_bmap_mdt_lock_key; static struct lock_class_key nilfs_bmap_mdt_lock_key;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h> #include <linux/nilfs2_fs.h>
#include "alloc.h" #include "alloc.h"
#include "dat.h"
#define NILFS_BMAP_INVALID_PTR 0 #define NILFS_BMAP_INVALID_PTR 0
...@@ -141,7 +142,6 @@ struct nilfs_bmap { ...@@ -141,7 +142,6 @@ struct nilfs_bmap {
int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *);
int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *);
int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned);
int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long);
int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long);
...@@ -160,90 +160,76 @@ void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); ...@@ -160,90 +160,76 @@ void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key,
__u64 *ptr)
{
return nilfs_bmap_lookup_at_level(bmap, key, 1, ptr);
}
/* /*
* Internal use only * Internal use only
*/ */
struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *); 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, static inline int nilfs_bmap_prepare_alloc_ptr(struct nilfs_bmap *bmap,
union nilfs_bmap_ptr_req *req) union nilfs_bmap_ptr_req *req,
struct inode *dat)
{ {
if (NILFS_BMAP_USE_VBN(bmap)) if (dat)
return nilfs_bmap_prepare_alloc_v(bmap, req); return nilfs_dat_prepare_alloc(dat, &req->bpr_req);
/* ignore target ptr */ /* ignore target ptr */
req->bpr_ptr = bmap->b_last_allocated_ptr++; req->bpr_ptr = bmap->b_last_allocated_ptr++;
return 0; return 0;
} }
static inline void nilfs_bmap_commit_alloc_ptr(struct nilfs_bmap *bmap, static inline void nilfs_bmap_commit_alloc_ptr(struct nilfs_bmap *bmap,
union nilfs_bmap_ptr_req *req) union nilfs_bmap_ptr_req *req,
struct inode *dat)
{ {
if (NILFS_BMAP_USE_VBN(bmap)) if (dat)
nilfs_bmap_commit_alloc_v(bmap, req); nilfs_dat_commit_alloc(dat, &req->bpr_req);
} }
static inline void nilfs_bmap_abort_alloc_ptr(struct nilfs_bmap *bmap, static inline void nilfs_bmap_abort_alloc_ptr(struct nilfs_bmap *bmap,
union nilfs_bmap_ptr_req *req) union nilfs_bmap_ptr_req *req,
struct inode *dat)
{ {
if (NILFS_BMAP_USE_VBN(bmap)) if (dat)
nilfs_bmap_abort_alloc_v(bmap, req); nilfs_dat_abort_alloc(dat, &req->bpr_req);
else else
bmap->b_last_allocated_ptr--; 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, static inline int nilfs_bmap_prepare_end_ptr(struct nilfs_bmap *bmap,
union nilfs_bmap_ptr_req *req) union nilfs_bmap_ptr_req *req,
struct inode *dat)
{ {
return NILFS_BMAP_USE_VBN(bmap) ? return dat ? nilfs_dat_prepare_end(dat, &req->bpr_req) : 0;
nilfs_bmap_prepare_end_v(bmap, req) : 0;
} }
static inline void nilfs_bmap_commit_end_ptr(struct nilfs_bmap *bmap, static inline void nilfs_bmap_commit_end_ptr(struct nilfs_bmap *bmap,
union nilfs_bmap_ptr_req *req) union nilfs_bmap_ptr_req *req,
struct inode *dat)
{ {
if (NILFS_BMAP_USE_VBN(bmap)) if (dat)
nilfs_bmap_commit_end_v(bmap, req); nilfs_dat_commit_end(dat, &req->bpr_req,
bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
} }
static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap, static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap,
union nilfs_bmap_ptr_req *req) union nilfs_bmap_ptr_req *req,
struct inode *dat)
{ {
if (NILFS_BMAP_USE_VBN(bmap)) if (dat)
nilfs_bmap_abort_end_v(bmap, req); nilfs_dat_abort_end(dat, &req->bpr_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);
__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
const struct buffer_head *); const struct buffer_head *);
__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64); __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *); __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
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_add_blocks(const struct nilfs_bmap *, int);
void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int); void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
......
...@@ -71,21 +71,17 @@ void nilfs_btree_path_cache_destroy(void) ...@@ -71,21 +71,17 @@ void nilfs_btree_path_cache_destroy(void)
kmem_cache_destroy(nilfs_btree_path_cache); kmem_cache_destroy(nilfs_btree_path_cache);
} }
static inline struct nilfs_btree_path * static inline struct nilfs_btree_path *nilfs_btree_alloc_path(void)
nilfs_btree_alloc_path(const struct nilfs_btree *btree)
{ {
return (struct nilfs_btree_path *) return kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
} }
static inline void nilfs_btree_free_path(const struct nilfs_btree *btree, static inline void nilfs_btree_free_path(struct nilfs_btree_path *path)
struct nilfs_btree_path *path)
{ {
kmem_cache_free(nilfs_btree_path_cache, path); kmem_cache_free(nilfs_btree_path_cache, path);
} }
static void nilfs_btree_init_path(const struct nilfs_btree *btree, static void nilfs_btree_init_path(struct nilfs_btree_path *path)
struct nilfs_btree_path *path)
{ {
int level; int level;
...@@ -101,26 +97,13 @@ static void nilfs_btree_init_path(const struct nilfs_btree *btree, ...@@ -101,26 +97,13 @@ static void nilfs_btree_init_path(const struct nilfs_btree *btree,
} }
} }
static void nilfs_btree_clear_path(const struct nilfs_btree *btree, static void nilfs_btree_release_path(struct nilfs_btree_path *path)
struct nilfs_btree_path *path)
{ {
int level; int level;
for (level = NILFS_BTREE_LEVEL_DATA; for (level = NILFS_BTREE_LEVEL_DATA; level < NILFS_BTREE_LEVEL_MAX;
level < NILFS_BTREE_LEVEL_MAX; level++)
level++) {
if (path[level].bp_bh != NULL) {
brelse(path[level].bp_bh); brelse(path[level].bp_bh);
path[level].bp_bh = NULL;
}
/* sib_bh is released or deleted by prepare or commit
* operations. */
path[level].bp_sib_bh = NULL;
path[level].bp_index = 0;
path[level].bp_oldreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
path[level].bp_op = NULL;
}
} }
/* /*
...@@ -148,129 +131,110 @@ static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, ...@@ -148,129 +131,110 @@ static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
} }
static inline int static inline int
nilfs_btree_node_get_flags(const struct nilfs_btree *btree, nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
const struct nilfs_btree_node *node)
{ {
return node->bn_flags; return node->bn_flags;
} }
static inline void static inline void
nilfs_btree_node_set_flags(struct nilfs_btree *btree, nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
struct nilfs_btree_node *node,
int flags)
{ {
node->bn_flags = flags; node->bn_flags = flags;
} }
static inline int nilfs_btree_node_root(const struct nilfs_btree *btree, static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
const struct nilfs_btree_node *node)
{ {
return nilfs_btree_node_get_flags(btree, node) & NILFS_BTREE_NODE_ROOT; return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
} }
static inline int static inline int
nilfs_btree_node_get_level(const struct nilfs_btree *btree, nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
const struct nilfs_btree_node *node)
{ {
return node->bn_level; return node->bn_level;
} }
static inline void static inline void
nilfs_btree_node_set_level(struct nilfs_btree *btree, nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
struct nilfs_btree_node *node,
int level)
{ {
node->bn_level = level; node->bn_level = level;
} }
static inline int static inline int
nilfs_btree_node_get_nchildren(const struct nilfs_btree *btree, nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
const struct nilfs_btree_node *node)
{ {
return le16_to_cpu(node->bn_nchildren); return le16_to_cpu(node->bn_nchildren);
} }
static inline void static inline void
nilfs_btree_node_set_nchildren(struct nilfs_btree *btree, nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
struct nilfs_btree_node *node,
int nchildren)
{ {
node->bn_nchildren = cpu_to_le16(nchildren); node->bn_nchildren = cpu_to_le16(nchildren);
} }
static inline int static inline int nilfs_btree_node_size(const struct nilfs_btree *btree)
nilfs_btree_node_size(const struct nilfs_btree *btree)
{ {
return 1 << btree->bt_bmap.b_inode->i_blkbits; return 1 << btree->bt_bmap.b_inode->i_blkbits;
} }
static inline int static inline int
nilfs_btree_node_nchildren_min(const struct nilfs_btree *btree, nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
const struct nilfs_btree_node *node) const struct nilfs_btree *btree)
{ {
return nilfs_btree_node_root(btree, node) ? return nilfs_btree_node_root(node) ?
NILFS_BTREE_ROOT_NCHILDREN_MIN : NILFS_BTREE_ROOT_NCHILDREN_MIN :
NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
} }
static inline int static inline int
nilfs_btree_node_nchildren_max(const struct nilfs_btree *btree, nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
const struct nilfs_btree_node *node) const struct nilfs_btree *btree)
{ {
return nilfs_btree_node_root(btree, node) ? return nilfs_btree_node_root(node) ?
NILFS_BTREE_ROOT_NCHILDREN_MAX : NILFS_BTREE_ROOT_NCHILDREN_MAX :
NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree)); NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
} }
static inline __le64 * static inline __le64 *
nilfs_btree_node_dkeys(const struct nilfs_btree *btree, nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
const struct nilfs_btree_node *node)
{ {
return (__le64 *)((char *)(node + 1) + return (__le64 *)((char *)(node + 1) +
(nilfs_btree_node_root(btree, node) ? (nilfs_btree_node_root(node) ?
0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
} }
static inline __le64 * static inline __le64 *
nilfs_btree_node_dptrs(const struct nilfs_btree *btree, nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
const struct nilfs_btree_node *node) const struct nilfs_btree *btree)
{ {
return (__le64 *)(nilfs_btree_node_dkeys(btree, node) + return (__le64 *)(nilfs_btree_node_dkeys(node) +
nilfs_btree_node_nchildren_max(btree, node)); nilfs_btree_node_nchildren_max(node, btree));
} }
static inline __u64 static inline __u64
nilfs_btree_node_get_key(const struct nilfs_btree *btree, nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
const struct nilfs_btree_node *node, int index)
{ {
return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(btree, node) + return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index));
index));
} }
static inline void static inline void
nilfs_btree_node_set_key(struct nilfs_btree *btree, nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
struct nilfs_btree_node *node, int index, __u64 key)
{ {
*(nilfs_btree_node_dkeys(btree, node) + index) = *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key);
nilfs_bmap_key_to_dkey(key);
} }
static inline __u64 static inline __u64
nilfs_btree_node_get_ptr(const struct nilfs_btree *btree, nilfs_btree_node_get_ptr(const struct nilfs_btree *btree,
const struct nilfs_btree_node *node, const struct nilfs_btree_node *node, int index)
int index)
{ {
return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(btree, node) + return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) +
index)); index));
} }
static inline void static inline void
nilfs_btree_node_set_ptr(struct nilfs_btree *btree, nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
struct nilfs_btree_node *node, struct nilfs_btree_node *node, int index, __u64 ptr)
int index,
__u64 ptr)
{ {
*(nilfs_btree_node_dptrs(btree, node) + index) = *(nilfs_btree_node_dptrs(node, btree) + index) =
nilfs_bmap_ptr_to_dptr(ptr); nilfs_bmap_ptr_to_dptr(ptr);
} }
...@@ -283,12 +247,12 @@ static void nilfs_btree_node_init(struct nilfs_btree *btree, ...@@ -283,12 +247,12 @@ static void nilfs_btree_node_init(struct nilfs_btree *btree,
__le64 *dptrs; __le64 *dptrs;
int i; int i;
nilfs_btree_node_set_flags(btree, node, flags); nilfs_btree_node_set_flags(node, flags);
nilfs_btree_node_set_level(btree, node, level); nilfs_btree_node_set_level(node, level);
nilfs_btree_node_set_nchildren(btree, node, nchildren); nilfs_btree_node_set_nchildren(node, nchildren);
dkeys = nilfs_btree_node_dkeys(btree, node); dkeys = nilfs_btree_node_dkeys(node);
dptrs = nilfs_btree_node_dptrs(btree, node); dptrs = nilfs_btree_node_dptrs(node, btree);
for (i = 0; i < nchildren; i++) { for (i = 0; i < nchildren; i++) {
dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]); dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]);
dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]); dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]);
...@@ -305,13 +269,13 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree, ...@@ -305,13 +269,13 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
__le64 *ldptrs, *rdptrs; __le64 *ldptrs, *rdptrs;
int lnchildren, rnchildren; int lnchildren, rnchildren;
ldkeys = nilfs_btree_node_dkeys(btree, left); ldkeys = nilfs_btree_node_dkeys(left);
ldptrs = nilfs_btree_node_dptrs(btree, left); ldptrs = nilfs_btree_node_dptrs(left, btree);
lnchildren = nilfs_btree_node_get_nchildren(btree, left); lnchildren = nilfs_btree_node_get_nchildren(left);
rdkeys = nilfs_btree_node_dkeys(btree, right); rdkeys = nilfs_btree_node_dkeys(right);
rdptrs = nilfs_btree_node_dptrs(btree, right); rdptrs = nilfs_btree_node_dptrs(right, btree);
rnchildren = nilfs_btree_node_get_nchildren(btree, right); rnchildren = nilfs_btree_node_get_nchildren(right);
memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys)); memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs)); memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
...@@ -320,8 +284,8 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree, ...@@ -320,8 +284,8 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
lnchildren += n; lnchildren += n;
rnchildren -= n; rnchildren -= n;
nilfs_btree_node_set_nchildren(btree, left, lnchildren); nilfs_btree_node_set_nchildren(left, lnchildren);
nilfs_btree_node_set_nchildren(btree, right, rnchildren); nilfs_btree_node_set_nchildren(right, rnchildren);
} }
/* Assume that the buffer heads corresponding to left and right are locked. */ /* Assume that the buffer heads corresponding to left and right are locked. */
...@@ -334,13 +298,13 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree, ...@@ -334,13 +298,13 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
__le64 *ldptrs, *rdptrs; __le64 *ldptrs, *rdptrs;
int lnchildren, rnchildren; int lnchildren, rnchildren;
ldkeys = nilfs_btree_node_dkeys(btree, left); ldkeys = nilfs_btree_node_dkeys(left);
ldptrs = nilfs_btree_node_dptrs(btree, left); ldptrs = nilfs_btree_node_dptrs(left, btree);
lnchildren = nilfs_btree_node_get_nchildren(btree, left); lnchildren = nilfs_btree_node_get_nchildren(left);
rdkeys = nilfs_btree_node_dkeys(btree, right); rdkeys = nilfs_btree_node_dkeys(right);
rdptrs = nilfs_btree_node_dptrs(btree, right); rdptrs = nilfs_btree_node_dptrs(right, btree);
rnchildren = nilfs_btree_node_get_nchildren(btree, right); rnchildren = nilfs_btree_node_get_nchildren(right);
memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys)); memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs)); memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
...@@ -349,8 +313,8 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree, ...@@ -349,8 +313,8 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
lnchildren -= n; lnchildren -= n;
rnchildren += n; rnchildren += n;
nilfs_btree_node_set_nchildren(btree, left, lnchildren); nilfs_btree_node_set_nchildren(left, lnchildren);
nilfs_btree_node_set_nchildren(btree, right, rnchildren); nilfs_btree_node_set_nchildren(right, rnchildren);
} }
/* Assume that the buffer head corresponding to node is locked. */ /* Assume that the buffer head corresponding to node is locked. */
...@@ -362,9 +326,9 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree, ...@@ -362,9 +326,9 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree,
__le64 *dptrs; __le64 *dptrs;
int nchildren; int nchildren;
dkeys = nilfs_btree_node_dkeys(btree, node); dkeys = nilfs_btree_node_dkeys(node);
dptrs = nilfs_btree_node_dptrs(btree, node); dptrs = nilfs_btree_node_dptrs(node, btree);
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
if (index < nchildren) { if (index < nchildren) {
memmove(dkeys + index + 1, dkeys + index, memmove(dkeys + index + 1, dkeys + index,
(nchildren - index) * sizeof(*dkeys)); (nchildren - index) * sizeof(*dkeys));
...@@ -374,7 +338,7 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree, ...@@ -374,7 +338,7 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree,
dkeys[index] = nilfs_bmap_key_to_dkey(key); dkeys[index] = nilfs_bmap_key_to_dkey(key);
dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr); dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr);
nchildren++; nchildren++;
nilfs_btree_node_set_nchildren(btree, node, nchildren); nilfs_btree_node_set_nchildren(node, nchildren);
} }
/* Assume that the buffer head corresponding to node is locked. */ /* Assume that the buffer head corresponding to node is locked. */
...@@ -388,11 +352,11 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree, ...@@ -388,11 +352,11 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree,
__le64 *dptrs; __le64 *dptrs;
int nchildren; int nchildren;
dkeys = nilfs_btree_node_dkeys(btree, node); dkeys = nilfs_btree_node_dkeys(node);
dptrs = nilfs_btree_node_dptrs(btree, node); dptrs = nilfs_btree_node_dptrs(node, btree);
key = nilfs_bmap_dkey_to_key(dkeys[index]); key = nilfs_bmap_dkey_to_key(dkeys[index]);
ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]); ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]);
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
if (keyp != NULL) if (keyp != NULL)
*keyp = key; *keyp = key;
if (ptrp != NULL) if (ptrp != NULL)
...@@ -405,11 +369,10 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree, ...@@ -405,11 +369,10 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree,
(nchildren - index - 1) * sizeof(*dptrs)); (nchildren - index - 1) * sizeof(*dptrs));
} }
nchildren--; nchildren--;
nilfs_btree_node_set_nchildren(btree, node, nchildren); nilfs_btree_node_set_nchildren(node, nchildren);
} }
static int nilfs_btree_node_lookup(const struct nilfs_btree *btree, static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
const struct nilfs_btree_node *node,
__u64 key, int *indexp) __u64 key, int *indexp)
{ {
__u64 nkey; __u64 nkey;
...@@ -417,12 +380,12 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree *btree, ...@@ -417,12 +380,12 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree *btree,
/* binary search */ /* binary search */
low = 0; low = 0;
high = nilfs_btree_node_get_nchildren(btree, node) - 1; high = nilfs_btree_node_get_nchildren(node) - 1;
index = 0; index = 0;
s = 0; s = 0;
while (low <= high) { while (low <= high) {
index = (low + high) / 2; index = (low + high) / 2;
nkey = nilfs_btree_node_get_key(btree, node, index); nkey = nilfs_btree_node_get_key(node, index);
if (nkey == key) { if (nkey == key) {
s = 0; s = 0;
goto out; goto out;
...@@ -436,9 +399,8 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree *btree, ...@@ -436,9 +399,8 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree *btree,
} }
/* adjust index */ /* adjust index */
if (nilfs_btree_node_get_level(btree, node) > if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
NILFS_BTREE_LEVEL_NODE_MIN) { if (s > 0 && index > 0)
if ((s > 0) && (index > 0))
index--; index--;
} else if (s < 0) } else if (s < 0)
index++; index++;
...@@ -456,25 +418,20 @@ nilfs_btree_get_root(const struct nilfs_btree *btree) ...@@ -456,25 +418,20 @@ nilfs_btree_get_root(const struct nilfs_btree *btree)
} }
static inline struct nilfs_btree_node * static inline struct nilfs_btree_node *
nilfs_btree_get_nonroot_node(const struct nilfs_btree *btree, nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
const struct nilfs_btree_path *path,
int level)
{ {
return (struct nilfs_btree_node *)path[level].bp_bh->b_data; return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
} }
static inline struct nilfs_btree_node * static inline struct nilfs_btree_node *
nilfs_btree_get_sib_node(const struct nilfs_btree *btree, nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
const struct nilfs_btree_path *path,
int level)
{ {
return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data; return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
} }
static inline int nilfs_btree_height(const struct nilfs_btree *btree) static inline int nilfs_btree_height(const struct nilfs_btree *btree)
{ {
return nilfs_btree_node_get_level(btree, nilfs_btree_get_root(btree)) return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
+ 1;
} }
static inline struct nilfs_btree_node * static inline struct nilfs_btree_node *
...@@ -484,7 +441,7 @@ nilfs_btree_get_node(const struct nilfs_btree *btree, ...@@ -484,7 +441,7 @@ nilfs_btree_get_node(const struct nilfs_btree *btree,
{ {
return (level == nilfs_btree_height(btree) - 1) ? return (level == nilfs_btree_height(btree) - 1) ?
nilfs_btree_get_root(btree) : nilfs_btree_get_root(btree) :
nilfs_btree_get_nonroot_node(btree, path, level); nilfs_btree_get_nonroot_node(path, level);
} }
static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
...@@ -496,12 +453,11 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, ...@@ -496,12 +453,11 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
int level, index, found, ret; int level, index, found, ret;
node = nilfs_btree_get_root(btree); node = nilfs_btree_get_root(btree);
level = nilfs_btree_node_get_level(btree, node); level = nilfs_btree_node_get_level(node);
if ((level < minlevel) || if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
(nilfs_btree_node_get_nchildren(btree, node) <= 0))
return -ENOENT; return -ENOENT;
found = nilfs_btree_node_lookup(btree, node, key, &index); found = nilfs_btree_node_lookup(node, key, &index);
ptr = nilfs_btree_node_get_ptr(btree, node, index); ptr = nilfs_btree_node_get_ptr(btree, node, index);
path[level].bp_bh = NULL; path[level].bp_bh = NULL;
path[level].bp_index = index; path[level].bp_index = index;
...@@ -510,14 +466,13 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, ...@@ -510,14 +466,13 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
if (ret < 0) if (ret < 0)
return ret; return ret;
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
BUG_ON(level != nilfs_btree_node_get_level(btree, node)); BUG_ON(level != nilfs_btree_node_get_level(node));
if (!found) if (!found)
found = nilfs_btree_node_lookup(btree, node, key, found = nilfs_btree_node_lookup(node, key, &index);
&index);
else else
index = 0; index = 0;
if (index < nilfs_btree_node_nchildren_max(btree, node)) if (index < nilfs_btree_node_nchildren_max(node, btree))
ptr = nilfs_btree_node_get_ptr(btree, node, index); ptr = nilfs_btree_node_get_ptr(btree, node, index);
else { else {
WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN); WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
...@@ -544,10 +499,10 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, ...@@ -544,10 +499,10 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
int index, level, ret; int index, level, ret;
node = nilfs_btree_get_root(btree); node = nilfs_btree_get_root(btree);
index = nilfs_btree_node_get_nchildren(btree, node) - 1; index = nilfs_btree_node_get_nchildren(node) - 1;
if (index < 0) if (index < 0)
return -ENOENT; return -ENOENT;
level = nilfs_btree_node_get_level(btree, node); level = nilfs_btree_node_get_level(node);
ptr = nilfs_btree_node_get_ptr(btree, node, index); ptr = nilfs_btree_node_get_ptr(btree, node, index);
path[level].bp_bh = NULL; path[level].bp_bh = NULL;
path[level].bp_index = index; path[level].bp_index = index;
...@@ -556,15 +511,15 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, ...@@ -556,15 +511,15 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
if (ret < 0) if (ret < 0)
return ret; return ret;
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
BUG_ON(level != nilfs_btree_node_get_level(btree, node)); BUG_ON(level != nilfs_btree_node_get_level(node));
index = nilfs_btree_node_get_nchildren(btree, node) - 1; index = nilfs_btree_node_get_nchildren(node) - 1;
ptr = nilfs_btree_node_get_ptr(btree, node, index); ptr = nilfs_btree_node_get_ptr(btree, node, index);
path[level].bp_index = index; path[level].bp_index = index;
} }
if (keyp != NULL) if (keyp != NULL)
*keyp = nilfs_btree_node_get_key(btree, node, index); *keyp = nilfs_btree_node_get_key(node, index);
if (ptrp != NULL) if (ptrp != NULL)
*ptrp = ptr; *ptrp = ptr;
...@@ -580,18 +535,18 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, ...@@ -580,18 +535,18 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
int ret; int ret;
btree = (struct nilfs_btree *)bmap; btree = (struct nilfs_btree *)bmap;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
if (ptrp != NULL) if (ptrp != NULL)
*ptrp = ptr; *ptrp = ptr;
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
...@@ -608,10 +563,10 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, ...@@ -608,10 +563,10 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
int level = NILFS_BTREE_LEVEL_NODE_MIN; int level = NILFS_BTREE_LEVEL_NODE_MIN;
int ret, cnt, index, maxlevel; int ret, cnt, index, maxlevel;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -631,8 +586,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, ...@@ -631,8 +586,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
node = nilfs_btree_get_node(btree, path, level); node = nilfs_btree_get_node(btree, path, level);
index = path[level].bp_index + 1; index = path[level].bp_index + 1;
for (;;) { for (;;) {
while (index < nilfs_btree_node_get_nchildren(btree, node)) { while (index < nilfs_btree_node_get_nchildren(node)) {
if (nilfs_btree_node_get_key(btree, node, index) != if (nilfs_btree_node_get_key(node, index) !=
key + cnt) key + cnt)
goto end; goto end;
ptr2 = nilfs_btree_node_get_ptr(btree, node, index); ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
...@@ -653,8 +608,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, ...@@ -653,8 +608,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
/* look-up right sibling node */ /* look-up right sibling node */
node = nilfs_btree_get_node(btree, path, level + 1); node = nilfs_btree_get_node(btree, path, level + 1);
index = path[level + 1].bp_index + 1; index = path[level + 1].bp_index + 1;
if (index >= nilfs_btree_node_get_nchildren(btree, node) || if (index >= nilfs_btree_node_get_nchildren(node) ||
nilfs_btree_node_get_key(btree, node, index) != key + cnt) nilfs_btree_node_get_key(node, index) != key + cnt)
break; break;
ptr2 = nilfs_btree_node_get_ptr(btree, node, index); ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
path[level + 1].bp_index = index; path[level + 1].bp_index = index;
...@@ -664,7 +619,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, ...@@ -664,7 +619,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh); ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
if (ret < 0) if (ret < 0)
goto out; goto out;
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
index = 0; index = 0;
path[level].bp_index = index; path[level].bp_index = index;
} }
...@@ -672,8 +627,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, ...@@ -672,8 +627,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
*ptrp = ptr; *ptrp = ptr;
ret = cnt; ret = cnt;
out: out:
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
...@@ -685,9 +640,7 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree, ...@@ -685,9 +640,7 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree,
do { do {
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
nilfs_btree_node_set_key( nilfs_btree_node_set_key(
btree, nilfs_btree_get_nonroot_node(path, level),
nilfs_btree_get_nonroot_node(
btree, path, level),
path[level].bp_index, key); path[level].bp_index, key);
if (!buffer_dirty(path[level].bp_bh)) if (!buffer_dirty(path[level].bp_bh))
nilfs_btnode_mark_dirty(path[level].bp_bh); nilfs_btnode_mark_dirty(path[level].bp_bh);
...@@ -698,8 +651,7 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree, ...@@ -698,8 +651,7 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree,
/* root */ /* root */
if (level == nilfs_btree_height(btree) - 1) { if (level == nilfs_btree_height(btree) - 1) {
nilfs_btree_node_set_key(btree, nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
nilfs_btree_get_root(btree),
path[level].bp_index, key); path[level].bp_index, key);
} }
} }
...@@ -712,7 +664,7 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree, ...@@ -712,7 +664,7 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree,
if (level < nilfs_btree_height(btree) - 1) { if (level < nilfs_btree_height(btree) - 1) {
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
nilfs_btree_node_insert(btree, node, *keyp, *ptrp, nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
path[level].bp_index); path[level].bp_index);
if (!buffer_dirty(path[level].bp_bh)) if (!buffer_dirty(path[level].bp_bh))
...@@ -721,8 +673,8 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree, ...@@ -721,8 +673,8 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree,
if (path[level].bp_index == 0) if (path[level].bp_index == 0)
nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_promote_key(btree, path, level + 1,
nilfs_btree_node_get_key( nilfs_btree_node_get_key(node,
btree, node, 0)); 0));
} else { } else {
node = nilfs_btree_get_root(btree); node = nilfs_btree_get_root(btree);
nilfs_btree_node_insert(btree, node, *keyp, *ptrp, nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
...@@ -740,10 +692,10 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, ...@@ -740,10 +692,10 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
left = nilfs_btree_get_sib_node(btree, path, level); left = nilfs_btree_get_sib_node(path, level);
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
lnchildren = nilfs_btree_node_get_nchildren(btree, left); lnchildren = nilfs_btree_node_get_nchildren(left);
move = 0; move = 0;
n = (nchildren + lnchildren + 1) / 2 - lnchildren; n = (nchildren + lnchildren + 1) / 2 - lnchildren;
...@@ -764,7 +716,7 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, ...@@ -764,7 +716,7 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree,
unlock_buffer(path[level].bp_sib_bh); unlock_buffer(path[level].bp_sib_bh);
nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_promote_key(btree, path, level + 1,
nilfs_btree_node_get_key(btree, node, 0)); nilfs_btree_node_get_key(node, 0));
if (move) { if (move) {
brelse(path[level].bp_bh); brelse(path[level].bp_bh);
...@@ -791,10 +743,10 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, ...@@ -791,10 +743,10 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
right = nilfs_btree_get_sib_node(btree, path, level); right = nilfs_btree_get_sib_node(path, level);
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
rnchildren = nilfs_btree_node_get_nchildren(btree, right); rnchildren = nilfs_btree_node_get_nchildren(right);
move = 0; move = 0;
n = (nchildren + rnchildren + 1) / 2 - rnchildren; n = (nchildren + rnchildren + 1) / 2 - rnchildren;
...@@ -816,15 +768,14 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, ...@@ -816,15 +768,14 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree,
path[level + 1].bp_index++; path[level + 1].bp_index++;
nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_promote_key(btree, path, level + 1,
nilfs_btree_node_get_key(btree, right, 0)); nilfs_btree_node_get_key(right, 0));
path[level + 1].bp_index--; path[level + 1].bp_index--;
if (move) { if (move) {
brelse(path[level].bp_bh); brelse(path[level].bp_bh);
path[level].bp_bh = path[level].bp_sib_bh; path[level].bp_bh = path[level].bp_sib_bh;
path[level].bp_sib_bh = NULL; path[level].bp_sib_bh = NULL;
path[level].bp_index -= path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
nilfs_btree_node_get_nchildren(btree, node);
path[level + 1].bp_index++; path[level + 1].bp_index++;
} else { } else {
brelse(path[level].bp_sib_bh); brelse(path[level].bp_sib_bh);
...@@ -846,9 +797,9 @@ static void nilfs_btree_split(struct nilfs_btree *btree, ...@@ -846,9 +797,9 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
right = nilfs_btree_get_sib_node(btree, path, level); right = nilfs_btree_get_sib_node(path, level);
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
move = 0; move = 0;
n = (nchildren + 1) / 2; n = (nchildren + 1) / 2;
...@@ -867,16 +818,15 @@ static void nilfs_btree_split(struct nilfs_btree *btree, ...@@ -867,16 +818,15 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
unlock_buffer(path[level].bp_bh); unlock_buffer(path[level].bp_bh);
unlock_buffer(path[level].bp_sib_bh); unlock_buffer(path[level].bp_sib_bh);
newkey = nilfs_btree_node_get_key(btree, right, 0); newkey = nilfs_btree_node_get_key(right, 0);
newptr = path[level].bp_newreq.bpr_ptr; newptr = path[level].bp_newreq.bpr_ptr;
if (move) { if (move) {
path[level].bp_index -= path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
nilfs_btree_node_get_nchildren(btree, node);
nilfs_btree_node_insert(btree, right, *keyp, *ptrp, nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
path[level].bp_index); path[level].bp_index);
*keyp = nilfs_btree_node_get_key(btree, right, 0); *keyp = nilfs_btree_node_get_key(right, 0);
*ptrp = path[level].bp_newreq.bpr_ptr; *ptrp = path[level].bp_newreq.bpr_ptr;
brelse(path[level].bp_bh); brelse(path[level].bp_bh);
...@@ -885,7 +835,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree, ...@@ -885,7 +835,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
} else { } else {
nilfs_btree_do_insert(btree, path, level, keyp, ptrp); nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
*keyp = nilfs_btree_node_get_key(btree, right, 0); *keyp = nilfs_btree_node_get_key(right, 0);
*ptrp = path[level].bp_newreq.bpr_ptr; *ptrp = path[level].bp_newreq.bpr_ptr;
brelse(path[level].bp_sib_bh); brelse(path[level].bp_sib_bh);
...@@ -905,12 +855,12 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, ...@@ -905,12 +855,12 @@ static void nilfs_btree_grow(struct nilfs_btree *btree,
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
root = nilfs_btree_get_root(btree); root = nilfs_btree_get_root(btree);
child = nilfs_btree_get_sib_node(btree, path, level); child = nilfs_btree_get_sib_node(path, level);
n = nilfs_btree_node_get_nchildren(btree, root); n = nilfs_btree_node_get_nchildren(root);
nilfs_btree_node_move_right(btree, root, child, n); nilfs_btree_node_move_right(btree, root, child, n);
nilfs_btree_node_set_level(btree, root, level + 1); nilfs_btree_node_set_level(root, level + 1);
if (!buffer_dirty(path[level].bp_sib_bh)) if (!buffer_dirty(path[level].bp_sib_bh))
nilfs_btnode_mark_dirty(path[level].bp_sib_bh); nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
...@@ -922,7 +872,7 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, ...@@ -922,7 +872,7 @@ static void nilfs_btree_grow(struct nilfs_btree *btree,
nilfs_btree_do_insert(btree, path, level, keyp, ptrp); nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
*keyp = nilfs_btree_node_get_key(btree, child, 0); *keyp = nilfs_btree_node_get_key(child, 0);
*ptrp = path[level].bp_newreq.bpr_ptr; *ptrp = path[level].bp_newreq.bpr_ptr;
} }
...@@ -990,26 +940,29 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, ...@@ -990,26 +940,29 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
struct nilfs_btree_node *node, *parent, *sib; struct nilfs_btree_node *node, *parent, *sib;
__u64 sibptr; __u64 sibptr;
int pindex, level, ret; int pindex, level, ret;
struct inode *dat = NULL;
stats->bs_nblocks = 0; stats->bs_nblocks = 0;
level = NILFS_BTREE_LEVEL_DATA; level = NILFS_BTREE_LEVEL_DATA;
/* allocate a new ptr for data block */ /* allocate a new ptr for data block */
if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
path[level].bp_newreq.bpr_ptr = path[level].bp_newreq.bpr_ptr =
nilfs_btree_find_target_v(btree, path, key); nilfs_btree_find_target_v(btree, path, key);
dat = nilfs_bmap_get_dat(&btree->bt_bmap);
}
ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
&path[level].bp_newreq); &path[level].bp_newreq, dat);
if (ret < 0) if (ret < 0)
goto err_out_data; goto err_out_data;
for (level = NILFS_BTREE_LEVEL_NODE_MIN; for (level = NILFS_BTREE_LEVEL_NODE_MIN;
level < nilfs_btree_height(btree) - 1; level < nilfs_btree_height(btree) - 1;
level++) { level++) {
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
if (nilfs_btree_node_get_nchildren(btree, node) < if (nilfs_btree_node_get_nchildren(node) <
nilfs_btree_node_nchildren_max(btree, node)) { nilfs_btree_node_nchildren_max(node, btree)) {
path[level].bp_op = nilfs_btree_do_insert; path[level].bp_op = nilfs_btree_do_insert;
stats->bs_nblocks++; stats->bs_nblocks++;
goto out; goto out;
...@@ -1026,8 +979,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, ...@@ -1026,8 +979,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
if (ret < 0) if (ret < 0)
goto err_out_child_node; goto err_out_child_node;
sib = (struct nilfs_btree_node *)bh->b_data; sib = (struct nilfs_btree_node *)bh->b_data;
if (nilfs_btree_node_get_nchildren(btree, sib) < if (nilfs_btree_node_get_nchildren(sib) <
nilfs_btree_node_nchildren_max(btree, sib)) { nilfs_btree_node_nchildren_max(sib, btree)) {
path[level].bp_sib_bh = bh; path[level].bp_sib_bh = bh;
path[level].bp_op = nilfs_btree_carry_left; path[level].bp_op = nilfs_btree_carry_left;
stats->bs_nblocks++; stats->bs_nblocks++;
...@@ -1038,15 +991,15 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, ...@@ -1038,15 +991,15 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
/* right sibling */ /* right sibling */
if (pindex < if (pindex <
nilfs_btree_node_get_nchildren(btree, parent) - 1) { nilfs_btree_node_get_nchildren(parent) - 1) {
sibptr = nilfs_btree_node_get_ptr(btree, parent, sibptr = nilfs_btree_node_get_ptr(btree, parent,
pindex + 1); pindex + 1);
ret = nilfs_btree_get_block(btree, sibptr, &bh); ret = nilfs_btree_get_block(btree, sibptr, &bh);
if (ret < 0) if (ret < 0)
goto err_out_child_node; goto err_out_child_node;
sib = (struct nilfs_btree_node *)bh->b_data; sib = (struct nilfs_btree_node *)bh->b_data;
if (nilfs_btree_node_get_nchildren(btree, sib) < if (nilfs_btree_node_get_nchildren(sib) <
nilfs_btree_node_nchildren_max(btree, sib)) { nilfs_btree_node_nchildren_max(sib, btree)) {
path[level].bp_sib_bh = bh; path[level].bp_sib_bh = bh;
path[level].bp_op = nilfs_btree_carry_right; path[level].bp_op = nilfs_btree_carry_right;
stats->bs_nblocks++; stats->bs_nblocks++;
...@@ -1059,7 +1012,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, ...@@ -1059,7 +1012,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
path[level].bp_newreq.bpr_ptr = path[level].bp_newreq.bpr_ptr =
path[level - 1].bp_newreq.bpr_ptr + 1; path[level - 1].bp_newreq.bpr_ptr + 1;
ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
&path[level].bp_newreq); &path[level].bp_newreq, dat);
if (ret < 0) if (ret < 0)
goto err_out_child_node; goto err_out_child_node;
ret = nilfs_btree_get_new_block(btree, ret = nilfs_btree_get_new_block(btree,
...@@ -1081,8 +1034,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, ...@@ -1081,8 +1034,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
/* root */ /* root */
node = nilfs_btree_get_root(btree); node = nilfs_btree_get_root(btree);
if (nilfs_btree_node_get_nchildren(btree, node) < if (nilfs_btree_node_get_nchildren(node) <
nilfs_btree_node_nchildren_max(btree, node)) { nilfs_btree_node_nchildren_max(node, btree)) {
path[level].bp_op = nilfs_btree_do_insert; path[level].bp_op = nilfs_btree_do_insert;
stats->bs_nblocks++; stats->bs_nblocks++;
goto out; goto out;
...@@ -1091,7 +1044,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, ...@@ -1091,7 +1044,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
/* grow */ /* grow */
path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
&path[level].bp_newreq); &path[level].bp_newreq, dat);
if (ret < 0) if (ret < 0)
goto err_out_child_node; goto err_out_child_node;
ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr, ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
...@@ -1119,16 +1072,18 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, ...@@ -1119,16 +1072,18 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
/* error */ /* error */
err_out_curr_node: err_out_curr_node:
nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq); nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
dat);
err_out_child_node: err_out_child_node:
for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
nilfs_btnode_delete(path[level].bp_sib_bh); nilfs_btnode_delete(path[level].bp_sib_bh);
nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
&path[level].bp_newreq); &path[level].bp_newreq, dat);
} }
nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq); nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
dat);
err_out_data: err_out_data:
*levelp = level; *levelp = level;
stats->bs_nblocks = 0; stats->bs_nblocks = 0;
...@@ -1139,16 +1094,19 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree, ...@@ -1139,16 +1094,19 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int maxlevel, __u64 key, __u64 ptr) int maxlevel, __u64 key, __u64 ptr)
{ {
struct inode *dat = NULL;
int level; int level;
set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
nilfs_btree_set_target_v(btree, key, ptr); nilfs_btree_set_target_v(btree, key, ptr);
dat = nilfs_bmap_get_dat(&btree->bt_bmap);
}
for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap, nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
&path[level - 1].bp_newreq); &path[level - 1].bp_newreq, dat);
path[level].bp_op(btree, path, level, &key, &ptr); path[level].bp_op(btree, path, level, &key, &ptr);
} }
...@@ -1164,10 +1122,10 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) ...@@ -1164,10 +1122,10 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
int level, ret; int level, ret;
btree = (struct nilfs_btree *)bmap; btree = (struct nilfs_btree *)bmap;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
ret = nilfs_btree_do_lookup(btree, path, key, NULL, ret = nilfs_btree_do_lookup(btree, path, key, NULL,
NILFS_BTREE_LEVEL_NODE_MIN); NILFS_BTREE_LEVEL_NODE_MIN);
...@@ -1184,8 +1142,8 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) ...@@ -1184,8 +1142,8 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
out: out:
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
...@@ -1197,7 +1155,7 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree, ...@@ -1197,7 +1155,7 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree,
if (level < nilfs_btree_height(btree) - 1) { if (level < nilfs_btree_height(btree) - 1) {
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
nilfs_btree_node_delete(btree, node, keyp, ptrp, nilfs_btree_node_delete(btree, node, keyp, ptrp,
path[level].bp_index); path[level].bp_index);
if (!buffer_dirty(path[level].bp_bh)) if (!buffer_dirty(path[level].bp_bh))
...@@ -1205,7 +1163,7 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree, ...@@ -1205,7 +1163,7 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree,
unlock_buffer(path[level].bp_bh); unlock_buffer(path[level].bp_bh);
if (path[level].bp_index == 0) if (path[level].bp_index == 0)
nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_promote_key(btree, path, level + 1,
nilfs_btree_node_get_key(btree, node, 0)); nilfs_btree_node_get_key(node, 0));
} else { } else {
node = nilfs_btree_get_root(btree); node = nilfs_btree_get_root(btree);
nilfs_btree_node_delete(btree, node, keyp, ptrp, nilfs_btree_node_delete(btree, node, keyp, ptrp,
...@@ -1225,10 +1183,10 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, ...@@ -1225,10 +1183,10 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
left = nilfs_btree_get_sib_node(btree, path, level); left = nilfs_btree_get_sib_node(path, level);
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
lnchildren = nilfs_btree_node_get_nchildren(btree, left); lnchildren = nilfs_btree_node_get_nchildren(left);
n = (nchildren + lnchildren) / 2 - nchildren; n = (nchildren + lnchildren) / 2 - nchildren;
...@@ -1243,7 +1201,7 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, ...@@ -1243,7 +1201,7 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
unlock_buffer(path[level].bp_sib_bh); unlock_buffer(path[level].bp_sib_bh);
nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_promote_key(btree, path, level + 1,
nilfs_btree_node_get_key(btree, node, 0)); nilfs_btree_node_get_key(node, 0));
brelse(path[level].bp_sib_bh); brelse(path[level].bp_sib_bh);
path[level].bp_sib_bh = NULL; path[level].bp_sib_bh = NULL;
...@@ -1262,10 +1220,10 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, ...@@ -1262,10 +1220,10 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
right = nilfs_btree_get_sib_node(btree, path, level); right = nilfs_btree_get_sib_node(path, level);
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
rnchildren = nilfs_btree_node_get_nchildren(btree, right); rnchildren = nilfs_btree_node_get_nchildren(right);
n = (nchildren + rnchildren) / 2 - nchildren; n = (nchildren + rnchildren) / 2 - nchildren;
...@@ -1281,7 +1239,7 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, ...@@ -1281,7 +1239,7 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
path[level + 1].bp_index++; path[level + 1].bp_index++;
nilfs_btree_promote_key(btree, path, level + 1, nilfs_btree_promote_key(btree, path, level + 1,
nilfs_btree_node_get_key(btree, right, 0)); nilfs_btree_node_get_key(right, 0));
path[level + 1].bp_index--; path[level + 1].bp_index--;
brelse(path[level].bp_sib_bh); brelse(path[level].bp_sib_bh);
...@@ -1300,10 +1258,10 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, ...@@ -1300,10 +1258,10 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
left = nilfs_btree_get_sib_node(btree, path, level); left = nilfs_btree_get_sib_node(path, level);
n = nilfs_btree_node_get_nchildren(btree, node); n = nilfs_btree_node_get_nchildren(node);
nilfs_btree_node_move_left(btree, left, node, n); nilfs_btree_node_move_left(btree, left, node, n);
...@@ -1316,7 +1274,7 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, ...@@ -1316,7 +1274,7 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree,
nilfs_btnode_delete(path[level].bp_bh); nilfs_btnode_delete(path[level].bp_bh);
path[level].bp_bh = path[level].bp_sib_bh; path[level].bp_bh = path[level].bp_sib_bh;
path[level].bp_sib_bh = NULL; path[level].bp_sib_bh = NULL;
path[level].bp_index += nilfs_btree_node_get_nchildren(btree, left); path[level].bp_index += nilfs_btree_node_get_nchildren(left);
} }
static void nilfs_btree_concat_right(struct nilfs_btree *btree, static void nilfs_btree_concat_right(struct nilfs_btree *btree,
...@@ -1331,10 +1289,10 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree, ...@@ -1331,10 +1289,10 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
lock_buffer(path[level].bp_sib_bh); lock_buffer(path[level].bp_sib_bh);
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
right = nilfs_btree_get_sib_node(btree, path, level); right = nilfs_btree_get_sib_node(path, level);
n = nilfs_btree_node_get_nchildren(btree, right); n = nilfs_btree_node_get_nchildren(right);
nilfs_btree_node_move_left(btree, node, right, n); nilfs_btree_node_move_left(btree, node, right, n);
...@@ -1360,11 +1318,11 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree, ...@@ -1360,11 +1318,11 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree,
lock_buffer(path[level].bp_bh); lock_buffer(path[level].bp_bh);
root = nilfs_btree_get_root(btree); root = nilfs_btree_get_root(btree);
child = nilfs_btree_get_nonroot_node(btree, path, level); child = nilfs_btree_get_nonroot_node(path, level);
nilfs_btree_node_delete(btree, root, NULL, NULL, 0); nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
nilfs_btree_node_set_level(btree, root, level); nilfs_btree_node_set_level(root, level);
n = nilfs_btree_node_get_nchildren(btree, child); n = nilfs_btree_node_get_nchildren(child);
nilfs_btree_node_move_left(btree, root, child, n); nilfs_btree_node_move_left(btree, root, child, n);
unlock_buffer(path[level].bp_bh); unlock_buffer(path[level].bp_bh);
...@@ -1376,7 +1334,8 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree, ...@@ -1376,7 +1334,8 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree,
static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int *levelp, int *levelp,
struct nilfs_bmap_stats *stats) struct nilfs_bmap_stats *stats,
struct inode *dat)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct nilfs_btree_node *node, *parent, *sib; struct nilfs_btree_node *node, *parent, *sib;
...@@ -1388,17 +1347,17 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1388,17 +1347,17 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
for (level = NILFS_BTREE_LEVEL_NODE_MIN; for (level = NILFS_BTREE_LEVEL_NODE_MIN;
level < nilfs_btree_height(btree) - 1; level < nilfs_btree_height(btree) - 1;
level++) { level++) {
node = nilfs_btree_get_nonroot_node(btree, path, level); node = nilfs_btree_get_nonroot_node(path, level);
path[level].bp_oldreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr =
nilfs_btree_node_get_ptr(btree, node, nilfs_btree_node_get_ptr(btree, node,
path[level].bp_index); path[level].bp_index);
ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
&path[level].bp_oldreq); &path[level].bp_oldreq, dat);
if (ret < 0) if (ret < 0)
goto err_out_child_node; goto err_out_child_node;
if (nilfs_btree_node_get_nchildren(btree, node) > if (nilfs_btree_node_get_nchildren(node) >
nilfs_btree_node_nchildren_min(btree, node)) { nilfs_btree_node_nchildren_min(node, btree)) {
path[level].bp_op = nilfs_btree_do_delete; path[level].bp_op = nilfs_btree_do_delete;
stats->bs_nblocks++; stats->bs_nblocks++;
goto out; goto out;
...@@ -1415,8 +1374,8 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1415,8 +1374,8 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
if (ret < 0) if (ret < 0)
goto err_out_curr_node; goto err_out_curr_node;
sib = (struct nilfs_btree_node *)bh->b_data; sib = (struct nilfs_btree_node *)bh->b_data;
if (nilfs_btree_node_get_nchildren(btree, sib) > if (nilfs_btree_node_get_nchildren(sib) >
nilfs_btree_node_nchildren_min(btree, sib)) { nilfs_btree_node_nchildren_min(sib, btree)) {
path[level].bp_sib_bh = bh; path[level].bp_sib_bh = bh;
path[level].bp_op = nilfs_btree_borrow_left; path[level].bp_op = nilfs_btree_borrow_left;
stats->bs_nblocks++; stats->bs_nblocks++;
...@@ -1428,7 +1387,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1428,7 +1387,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
/* continue; */ /* continue; */
} }
} else if (pindex < } else if (pindex <
nilfs_btree_node_get_nchildren(btree, parent) - 1) { nilfs_btree_node_get_nchildren(parent) - 1) {
/* right sibling */ /* right sibling */
sibptr = nilfs_btree_node_get_ptr(btree, parent, sibptr = nilfs_btree_node_get_ptr(btree, parent,
pindex + 1); pindex + 1);
...@@ -1436,8 +1395,8 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1436,8 +1395,8 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
if (ret < 0) if (ret < 0)
goto err_out_curr_node; goto err_out_curr_node;
sib = (struct nilfs_btree_node *)bh->b_data; sib = (struct nilfs_btree_node *)bh->b_data;
if (nilfs_btree_node_get_nchildren(btree, sib) > if (nilfs_btree_node_get_nchildren(sib) >
nilfs_btree_node_nchildren_min(btree, sib)) { nilfs_btree_node_nchildren_min(sib, btree)) {
path[level].bp_sib_bh = bh; path[level].bp_sib_bh = bh;
path[level].bp_op = nilfs_btree_borrow_right; path[level].bp_op = nilfs_btree_borrow_right;
stats->bs_nblocks++; stats->bs_nblocks++;
...@@ -1452,7 +1411,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1452,7 +1411,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
/* no siblings */ /* no siblings */
/* the only child of the root node */ /* the only child of the root node */
WARN_ON(level != nilfs_btree_height(btree) - 2); WARN_ON(level != nilfs_btree_height(btree) - 2);
if (nilfs_btree_node_get_nchildren(btree, node) - 1 <= if (nilfs_btree_node_get_nchildren(node) - 1 <=
NILFS_BTREE_ROOT_NCHILDREN_MAX) { NILFS_BTREE_ROOT_NCHILDREN_MAX) {
path[level].bp_op = nilfs_btree_shrink; path[level].bp_op = nilfs_btree_shrink;
stats->bs_nblocks += 2; stats->bs_nblocks += 2;
...@@ -1471,7 +1430,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1471,7 +1430,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
nilfs_btree_node_get_ptr(btree, node, path[level].bp_index); nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
&path[level].bp_oldreq); &path[level].bp_oldreq, dat);
if (ret < 0) if (ret < 0)
goto err_out_child_node; goto err_out_child_node;
...@@ -1486,12 +1445,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1486,12 +1445,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
/* error */ /* error */
err_out_curr_node: err_out_curr_node:
nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq); nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
err_out_child_node: err_out_child_node:
for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
brelse(path[level].bp_sib_bh); brelse(path[level].bp_sib_bh);
nilfs_bmap_abort_end_ptr(&btree->bt_bmap, nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
&path[level].bp_oldreq); &path[level].bp_oldreq, dat);
} }
*levelp = level; *levelp = level;
stats->bs_nblocks = 0; stats->bs_nblocks = 0;
...@@ -1500,13 +1459,13 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, ...@@ -1500,13 +1459,13 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
static void nilfs_btree_commit_delete(struct nilfs_btree *btree, static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int maxlevel) int maxlevel, struct inode *dat)
{ {
int level; int level;
for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
nilfs_bmap_commit_end_ptr(&btree->bt_bmap, nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
&path[level].bp_oldreq); &path[level].bp_oldreq, dat);
path[level].bp_op(btree, path, level, NULL, NULL); path[level].bp_op(btree, path, level, NULL, NULL);
} }
...@@ -1520,27 +1479,32 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) ...@@ -1520,27 +1479,32 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
struct nilfs_btree *btree; struct nilfs_btree *btree;
struct nilfs_btree_path *path; struct nilfs_btree_path *path;
struct nilfs_bmap_stats stats; struct nilfs_bmap_stats stats;
struct inode *dat;
int level, ret; int level, ret;
btree = (struct nilfs_btree *)bmap; btree = (struct nilfs_btree *)bmap;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
ret = nilfs_btree_do_lookup(btree, path, key, NULL, ret = nilfs_btree_do_lookup(btree, path, key, NULL,
NILFS_BTREE_LEVEL_NODE_MIN); NILFS_BTREE_LEVEL_NODE_MIN);
if (ret < 0) if (ret < 0)
goto out; goto out;
ret = nilfs_btree_prepare_delete(btree, path, &level, &stats);
dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
if (ret < 0) if (ret < 0)
goto out; goto out;
nilfs_btree_commit_delete(btree, path, level); nilfs_btree_commit_delete(btree, path, level, dat);
nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
out: out:
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
...@@ -1551,15 +1515,15 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) ...@@ -1551,15 +1515,15 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
int ret; int ret;
btree = (struct nilfs_btree *)bmap; btree = (struct nilfs_btree *)bmap;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL); ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
...@@ -1581,7 +1545,7 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) ...@@ -1581,7 +1545,7 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
node = root; node = root;
break; break;
case 3: case 3:
nchildren = nilfs_btree_node_get_nchildren(btree, root); nchildren = nilfs_btree_node_get_nchildren(root);
if (nchildren > 1) if (nchildren > 1)
return 0; return 0;
ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
...@@ -1594,10 +1558,10 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) ...@@ -1594,10 +1558,10 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
return 0; return 0;
} }
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
maxkey = nilfs_btree_node_get_key(btree, node, nchildren - 1); maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
nextmaxkey = (nchildren > 1) ? nextmaxkey = (nchildren > 1) ?
nilfs_btree_node_get_key(btree, node, nchildren - 2) : 0; nilfs_btree_node_get_key(node, nchildren - 2) : 0;
if (bh != NULL) if (bh != NULL)
brelse(bh); brelse(bh);
...@@ -1623,7 +1587,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, ...@@ -1623,7 +1587,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
node = root; node = root;
break; break;
case 3: case 3:
nchildren = nilfs_btree_node_get_nchildren(btree, root); nchildren = nilfs_btree_node_get_nchildren(root);
WARN_ON(nchildren > 1); WARN_ON(nchildren > 1);
ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
ret = nilfs_btree_get_block(btree, ptr, &bh); ret = nilfs_btree_get_block(btree, ptr, &bh);
...@@ -1636,11 +1600,11 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, ...@@ -1636,11 +1600,11 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
return -EINVAL; return -EINVAL;
} }
nchildren = nilfs_btree_node_get_nchildren(btree, node); nchildren = nilfs_btree_node_get_nchildren(node);
if (nchildren < nitems) if (nchildren < nitems)
nitems = nchildren; nitems = nchildren;
dkeys = nilfs_btree_node_dkeys(btree, node); dkeys = nilfs_btree_node_dkeys(node);
dptrs = nilfs_btree_node_dptrs(btree, node); dptrs = nilfs_btree_node_dptrs(node, btree);
for (i = 0; i < nitems; i++) { for (i = 0; i < nitems; i++) {
keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]); keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]); ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
...@@ -1660,18 +1624,20 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, ...@@ -1660,18 +1624,20 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
struct nilfs_bmap_stats *stats) struct nilfs_bmap_stats *stats)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct nilfs_btree *btree; struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
struct inode *dat = NULL;
int ret; int ret;
btree = (struct nilfs_btree *)bmap;
stats->bs_nblocks = 0; stats->bs_nblocks = 0;
/* for data */ /* for data */
/* cannot find near ptr */ /* cannot find near ptr */
if (NILFS_BMAP_USE_VBN(bmap)) if (NILFS_BMAP_USE_VBN(bmap)) {
dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key); dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
dat = nilfs_bmap_get_dat(bmap);
}
ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq); ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1679,7 +1645,7 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, ...@@ -1679,7 +1645,7 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
stats->bs_nblocks++; stats->bs_nblocks++;
if (nreq != NULL) { if (nreq != NULL) {
nreq->bpr_ptr = dreq->bpr_ptr + 1; nreq->bpr_ptr = dreq->bpr_ptr + 1;
ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq); ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
if (ret < 0) if (ret < 0)
goto err_out_dreq; goto err_out_dreq;
...@@ -1696,9 +1662,9 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, ...@@ -1696,9 +1662,9 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
/* error */ /* error */
err_out_nreq: err_out_nreq:
nilfs_bmap_abort_alloc_ptr(bmap, nreq); nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
err_out_dreq: err_out_dreq:
nilfs_bmap_abort_alloc_ptr(bmap, dreq); nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
stats->bs_nblocks = 0; stats->bs_nblocks = 0;
return ret; return ret;
...@@ -1713,8 +1679,9 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, ...@@ -1713,8 +1679,9 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
union nilfs_bmap_ptr_req *nreq, union nilfs_bmap_ptr_req *nreq,
struct buffer_head *bh) struct buffer_head *bh)
{ {
struct nilfs_btree *btree; struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
struct nilfs_btree_node *node; struct nilfs_btree_node *node;
struct inode *dat;
__u64 tmpptr; __u64 tmpptr;
/* free resources */ /* free resources */
...@@ -1725,11 +1692,11 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, ...@@ -1725,11 +1692,11 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
/* convert and insert */ /* convert and insert */
btree = (struct nilfs_btree *)bmap; dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
nilfs_btree_init(bmap); nilfs_btree_init(bmap);
if (nreq != NULL) { if (nreq != NULL) {
nilfs_bmap_commit_alloc_ptr(bmap, dreq); nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
nilfs_bmap_commit_alloc_ptr(bmap, nreq); nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
/* create child node at level 1 */ /* create child node at level 1 */
lock_buffer(bh); lock_buffer(bh);
...@@ -1751,7 +1718,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, ...@@ -1751,7 +1718,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
2, 1, &keys[0], &tmpptr); 2, 1, &keys[0], &tmpptr);
} else { } else {
nilfs_bmap_commit_alloc_ptr(bmap, dreq); nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
/* create root node at level 1 */ /* create root node at level 1 */
node = nilfs_btree_get_root(btree); node = nilfs_btree_get_root(btree);
...@@ -1822,7 +1789,7 @@ static int nilfs_btree_propagate_p(struct nilfs_btree *btree, ...@@ -1822,7 +1789,7 @@ static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int level) int level, struct inode *dat)
{ {
struct nilfs_btree_node *parent; struct nilfs_btree_node *parent;
int ret; int ret;
...@@ -1832,9 +1799,8 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, ...@@ -1832,9 +1799,8 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
nilfs_btree_node_get_ptr(btree, parent, nilfs_btree_node_get_ptr(btree, parent,
path[level + 1].bp_index); path[level + 1].bp_index);
path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
ret = nilfs_bmap_prepare_update_v(&btree->bt_bmap, ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
&path[level].bp_oldreq, &path[level].bp_newreq.bpr_req);
&path[level].bp_newreq);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1846,9 +1812,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, ...@@ -1846,9 +1812,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
&NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
&path[level].bp_ctxt); &path[level].bp_ctxt);
if (ret < 0) { if (ret < 0) {
nilfs_bmap_abort_update_v(&btree->bt_bmap, nilfs_dat_abort_update(dat,
&path[level].bp_oldreq, &path[level].bp_oldreq.bpr_req,
&path[level].bp_newreq); &path[level].bp_newreq.bpr_req);
return ret; return ret;
} }
} }
...@@ -1858,13 +1824,13 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, ...@@ -1858,13 +1824,13 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
static void nilfs_btree_commit_update_v(struct nilfs_btree *btree, static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int level) int level, struct inode *dat)
{ {
struct nilfs_btree_node *parent; struct nilfs_btree_node *parent;
nilfs_bmap_commit_update_v(&btree->bt_bmap, nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
&path[level].bp_oldreq, &path[level].bp_newreq.bpr_req,
&path[level].bp_newreq); btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
if (buffer_nilfs_node(path[level].bp_bh)) { if (buffer_nilfs_node(path[level].bp_bh)) {
nilfs_btnode_commit_change_key( nilfs_btnode_commit_change_key(
...@@ -1881,11 +1847,10 @@ static void nilfs_btree_commit_update_v(struct nilfs_btree *btree, ...@@ -1881,11 +1847,10 @@ static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int level) int level, struct inode *dat)
{ {
nilfs_bmap_abort_update_v(&btree->bt_bmap, nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
&path[level].bp_oldreq, &path[level].bp_newreq.bpr_req);
&path[level].bp_newreq);
if (buffer_nilfs_node(path[level].bp_bh)) if (buffer_nilfs_node(path[level].bp_bh))
nilfs_btnode_abort_change_key( nilfs_btnode_abort_change_key(
&NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
...@@ -1894,14 +1859,14 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, ...@@ -1894,14 +1859,14 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int minlevel, int minlevel, int *maxlevelp,
int *maxlevelp) struct inode *dat)
{ {
int level, ret; int level, ret;
level = minlevel; level = minlevel;
if (!buffer_nilfs_volatile(path[level].bp_bh)) { if (!buffer_nilfs_volatile(path[level].bp_bh)) {
ret = nilfs_btree_prepare_update_v(btree, path, level); ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -1909,7 +1874,7 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, ...@@ -1909,7 +1874,7 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
!buffer_dirty(path[level].bp_bh)) { !buffer_dirty(path[level].bp_bh)) {
WARN_ON(buffer_nilfs_volatile(path[level].bp_bh)); WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
ret = nilfs_btree_prepare_update_v(btree, path, level); ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
if (ret < 0) if (ret < 0)
goto out; goto out;
} }
...@@ -1921,39 +1886,40 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, ...@@ -1921,39 +1886,40 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
/* error */ /* error */
out: out:
while (--level > minlevel) while (--level > minlevel)
nilfs_btree_abort_update_v(btree, path, level); nilfs_btree_abort_update_v(btree, path, level, dat);
if (!buffer_nilfs_volatile(path[level].bp_bh)) if (!buffer_nilfs_volatile(path[level].bp_bh))
nilfs_btree_abort_update_v(btree, path, level); nilfs_btree_abort_update_v(btree, path, level, dat);
return ret; return ret;
} }
static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree, static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int minlevel, int minlevel, int maxlevel,
int maxlevel, struct buffer_head *bh,
struct buffer_head *bh) struct inode *dat)
{ {
int level; int level;
if (!buffer_nilfs_volatile(path[minlevel].bp_bh)) if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
nilfs_btree_commit_update_v(btree, path, minlevel); nilfs_btree_commit_update_v(btree, path, minlevel, dat);
for (level = minlevel + 1; level <= maxlevel; level++) for (level = minlevel + 1; level <= maxlevel; level++)
nilfs_btree_commit_update_v(btree, path, level); nilfs_btree_commit_update_v(btree, path, level, dat);
} }
static int nilfs_btree_propagate_v(struct nilfs_btree *btree, static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
struct nilfs_btree_path *path, struct nilfs_btree_path *path,
int level, int level, struct buffer_head *bh)
struct buffer_head *bh)
{ {
int maxlevel, ret; int maxlevel, ret;
struct nilfs_btree_node *parent; struct nilfs_btree_node *parent;
struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
__u64 ptr; __u64 ptr;
get_bh(bh); get_bh(bh);
path[level].bp_bh = bh; path[level].bp_bh = bh;
ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel); ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
dat);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -1961,12 +1927,12 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree, ...@@ -1961,12 +1927,12 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
parent = nilfs_btree_get_node(btree, path, level + 1); parent = nilfs_btree_get_node(btree, path, level + 1);
ptr = nilfs_btree_node_get_ptr(btree, parent, ptr = nilfs_btree_node_get_ptr(btree, parent,
path[level + 1].bp_index); path[level + 1].bp_index);
ret = nilfs_bmap_mark_dirty(&btree->bt_bmap, ptr); ret = nilfs_dat_mark_dirty(dat, ptr);
if (ret < 0) if (ret < 0)
goto out; goto out;
} }
nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh); nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
out: out:
brelse(path[level].bp_bh); brelse(path[level].bp_bh);
...@@ -1986,15 +1952,15 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, ...@@ -1986,15 +1952,15 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
WARN_ON(!buffer_dirty(bh)); WARN_ON(!buffer_dirty(bh));
btree = (struct nilfs_btree *)bmap; btree = (struct nilfs_btree *)bmap;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
if (buffer_nilfs_node(bh)) { if (buffer_nilfs_node(bh)) {
node = (struct nilfs_btree_node *)bh->b_data; node = (struct nilfs_btree_node *)bh->b_data;
key = nilfs_btree_node_get_key(btree, node, 0); key = nilfs_btree_node_get_key(node, 0);
level = nilfs_btree_node_get_level(btree, node); level = nilfs_btree_node_get_level(node);
} else { } else {
key = nilfs_bmap_data_get_key(bmap, bh); key = nilfs_bmap_data_get_key(bmap, bh);
level = NILFS_BTREE_LEVEL_DATA; level = NILFS_BTREE_LEVEL_DATA;
...@@ -2013,8 +1979,8 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, ...@@ -2013,8 +1979,8 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
nilfs_btree_propagate_p(btree, path, level, bh); nilfs_btree_propagate_p(btree, path, level, bh);
out: out:
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
...@@ -2022,7 +1988,7 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, ...@@ -2022,7 +1988,7 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap, static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
struct buffer_head *bh) struct buffer_head *bh)
{ {
return nilfs_bmap_mark_dirty(bmap, bh->b_blocknr); return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
} }
static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
...@@ -2037,12 +2003,12 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, ...@@ -2037,12 +2003,12 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
get_bh(bh); get_bh(bh);
node = (struct nilfs_btree_node *)bh->b_data; node = (struct nilfs_btree_node *)bh->b_data;
key = nilfs_btree_node_get_key(btree, node, 0); key = nilfs_btree_node_get_key(node, 0);
level = nilfs_btree_node_get_level(btree, node); level = nilfs_btree_node_get_level(node);
list_for_each(head, &lists[level]) { list_for_each(head, &lists[level]) {
cbh = list_entry(head, struct buffer_head, b_assoc_buffers); cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
cnode = (struct nilfs_btree_node *)cbh->b_data; cnode = (struct nilfs_btree_node *)cbh->b_data;
ckey = nilfs_btree_node_get_key(btree, cnode, 0); ckey = nilfs_btree_node_get_key(cnode, 0);
if (key < ckey) if (key < ckey)
break; break;
} }
...@@ -2120,8 +2086,7 @@ static int nilfs_btree_assign_p(struct nilfs_btree *btree, ...@@ -2120,8 +2086,7 @@ static int nilfs_btree_assign_p(struct nilfs_btree *btree,
nilfs_btree_node_set_ptr(btree, parent, nilfs_btree_node_set_ptr(btree, parent,
path[level + 1].bp_index, blocknr); path[level + 1].bp_index, blocknr);
key = nilfs_btree_node_get_key(btree, parent, key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
path[level + 1].bp_index);
/* on-disk format */ /* on-disk format */
binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key); binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
binfo->bi_dat.bi_level = level; binfo->bi_dat.bi_level = level;
...@@ -2137,6 +2102,7 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, ...@@ -2137,6 +2102,7 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree,
union nilfs_binfo *binfo) union nilfs_binfo *binfo)
{ {
struct nilfs_btree_node *parent; struct nilfs_btree_node *parent;
struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
__u64 key; __u64 key;
__u64 ptr; __u64 ptr;
union nilfs_bmap_ptr_req req; union nilfs_bmap_ptr_req req;
...@@ -2146,12 +2112,12 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, ...@@ -2146,12 +2112,12 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree,
ptr = nilfs_btree_node_get_ptr(btree, parent, ptr = nilfs_btree_node_get_ptr(btree, parent,
path[level + 1].bp_index); path[level + 1].bp_index);
req.bpr_ptr = ptr; req.bpr_ptr = ptr;
ret = nilfs_bmap_start_v(&btree->bt_bmap, &req, blocknr); ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
if (unlikely(ret < 0)) if (ret < 0)
return ret; return ret;
nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
key = nilfs_btree_node_get_key(btree, parent, key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
path[level + 1].bp_index);
/* on-disk format */ /* on-disk format */
binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
...@@ -2171,15 +2137,15 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, ...@@ -2171,15 +2137,15 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap,
int level, ret; int level, ret;
btree = (struct nilfs_btree *)bmap; btree = (struct nilfs_btree *)bmap;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
if (buffer_nilfs_node(*bh)) { if (buffer_nilfs_node(*bh)) {
node = (struct nilfs_btree_node *)(*bh)->b_data; node = (struct nilfs_btree_node *)(*bh)->b_data;
key = nilfs_btree_node_get_key(btree, node, 0); key = nilfs_btree_node_get_key(node, 0);
level = nilfs_btree_node_get_level(btree, node); level = nilfs_btree_node_get_level(node);
} else { } else {
key = nilfs_bmap_data_get_key(bmap, *bh); key = nilfs_bmap_data_get_key(bmap, *bh);
level = NILFS_BTREE_LEVEL_DATA; level = NILFS_BTREE_LEVEL_DATA;
...@@ -2196,8 +2162,8 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, ...@@ -2196,8 +2162,8 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap,
nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
out: out:
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
...@@ -2207,19 +2173,18 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, ...@@ -2207,19 +2173,18 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
sector_t blocknr, sector_t blocknr,
union nilfs_binfo *binfo) union nilfs_binfo *binfo)
{ {
struct nilfs_btree *btree;
struct nilfs_btree_node *node; struct nilfs_btree_node *node;
__u64 key; __u64 key;
int ret; int ret;
btree = (struct nilfs_btree *)bmap; ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
ret = nilfs_bmap_move_v(bmap, (*bh)->b_blocknr, blocknr); blocknr);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (buffer_nilfs_node(*bh)) { if (buffer_nilfs_node(*bh)) {
node = (struct nilfs_btree_node *)(*bh)->b_data; node = (struct nilfs_btree_node *)(*bh)->b_data;
key = nilfs_btree_node_get_key(btree, node, 0); key = nilfs_btree_node_get_key(node, 0);
} else } else
key = nilfs_bmap_data_get_key(bmap, *bh); key = nilfs_bmap_data_get_key(bmap, *bh);
...@@ -2239,10 +2204,10 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) ...@@ -2239,10 +2204,10 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
int ret; int ret;
btree = (struct nilfs_btree *)bmap; btree = (struct nilfs_btree *)bmap;
path = nilfs_btree_alloc_path(btree); path = nilfs_btree_alloc_path();
if (path == NULL) if (path == NULL)
return -ENOMEM; return -ENOMEM;
nilfs_btree_init_path(btree, path); nilfs_btree_init_path(path);
ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
if (ret < 0) { if (ret < 0) {
...@@ -2262,8 +2227,8 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) ...@@ -2262,8 +2227,8 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
nilfs_bmap_set_dirty(&btree->bt_bmap); nilfs_bmap_set_dirty(&btree->bt_bmap);
out: out:
nilfs_btree_clear_path(btree, path); nilfs_btree_release_path(path);
nilfs_btree_free_path(btree, path); nilfs_btree_free_path(path);
return ret; return ret;
} }
......
...@@ -815,8 +815,10 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) ...@@ -815,8 +815,10 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno)
void *kaddr; void *kaddr;
int ret; int ret;
if (cno == 0) /* CP number is invalid if it's zero or larger than the
return -ENOENT; /* checkpoint number 0 is invalid */ largest exist one.*/
if (cno == 0 || cno >= nilfs_mdt_cno(cpfile))
return -ENOENT;
down_read(&NILFS_MDT(cpfile)->mi_sem); down_read(&NILFS_MDT(cpfile)->mi_sem);
ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh);
...@@ -824,6 +826,9 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) ...@@ -824,6 +826,9 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno)
goto out; goto out;
kaddr = kmap_atomic(bh->b_page, KM_USER0); kaddr = kmap_atomic(bh->b_page, KM_USER0);
cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
if (nilfs_checkpoint_invalid(cp))
ret = -ENOENT;
else
ret = nilfs_checkpoint_snapshot(cp); ret = nilfs_checkpoint_snapshot(cp);
kunmap_atomic(kaddr, KM_USER0); kunmap_atomic(kaddr, KM_USER0);
brelse(bh); brelse(bh);
......
...@@ -27,8 +27,6 @@ ...@@ -27,8 +27,6 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h> #include <linux/nilfs2_fs.h>
#define NILFS_CPFILE_GFP NILFS_MDT_GFP
int nilfs_cpfile_get_checkpoint(struct inode *, __u64, int, int nilfs_cpfile_get_checkpoint(struct inode *, __u64, int,
struct nilfs_checkpoint **, struct nilfs_checkpoint **,
......
...@@ -109,12 +109,6 @@ void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req) ...@@ -109,12 +109,6 @@ void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req)
nilfs_palloc_commit_free_entry(dat, req); nilfs_palloc_commit_free_entry(dat, req);
} }
void nilfs_dat_abort_free(struct inode *dat, struct nilfs_palloc_req *req)
{
nilfs_dat_abort_entry(dat, req);
nilfs_palloc_abort_free_entry(dat, req);
}
int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req) int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req)
{ {
int ret; int ret;
...@@ -140,11 +134,6 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req, ...@@ -140,11 +134,6 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
nilfs_dat_commit_entry(dat, req); nilfs_dat_commit_entry(dat, req);
} }
void nilfs_dat_abort_start(struct inode *dat, struct nilfs_palloc_req *req)
{
nilfs_dat_abort_entry(dat, req);
}
int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
{ {
struct nilfs_dat_entry *entry; struct nilfs_dat_entry *entry;
...@@ -222,6 +211,37 @@ void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req) ...@@ -222,6 +211,37 @@ void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req)
nilfs_dat_abort_entry(dat, req); nilfs_dat_abort_entry(dat, req);
} }
int nilfs_dat_prepare_update(struct inode *dat,
struct nilfs_palloc_req *oldreq,
struct nilfs_palloc_req *newreq)
{
int ret;
ret = nilfs_dat_prepare_end(dat, oldreq);
if (!ret) {
ret = nilfs_dat_prepare_alloc(dat, newreq);
if (ret < 0)
nilfs_dat_abort_end(dat, oldreq);
}
return ret;
}
void nilfs_dat_commit_update(struct inode *dat,
struct nilfs_palloc_req *oldreq,
struct nilfs_palloc_req *newreq, int dead)
{
nilfs_dat_commit_end(dat, oldreq, dead);
nilfs_dat_commit_alloc(dat, newreq);
}
void nilfs_dat_abort_update(struct inode *dat,
struct nilfs_palloc_req *oldreq,
struct nilfs_palloc_req *newreq)
{
nilfs_dat_abort_end(dat, oldreq);
nilfs_dat_abort_alloc(dat, newreq);
}
/** /**
* nilfs_dat_mark_dirty - * nilfs_dat_mark_dirty -
* @dat: DAT file inode * @dat: DAT file inode
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/fs.h> #include <linux/fs.h>
#define NILFS_DAT_GFP NILFS_MDT_GFP
struct nilfs_palloc_req; struct nilfs_palloc_req;
...@@ -39,10 +38,15 @@ void nilfs_dat_abort_alloc(struct inode *, struct nilfs_palloc_req *); ...@@ -39,10 +38,15 @@ void nilfs_dat_abort_alloc(struct inode *, struct nilfs_palloc_req *);
int nilfs_dat_prepare_start(struct inode *, struct nilfs_palloc_req *); int nilfs_dat_prepare_start(struct inode *, struct nilfs_palloc_req *);
void nilfs_dat_commit_start(struct inode *, struct nilfs_palloc_req *, void nilfs_dat_commit_start(struct inode *, struct nilfs_palloc_req *,
sector_t); sector_t);
void nilfs_dat_abort_start(struct inode *, struct nilfs_palloc_req *);
int nilfs_dat_prepare_end(struct inode *, struct nilfs_palloc_req *); int nilfs_dat_prepare_end(struct inode *, struct nilfs_palloc_req *);
void nilfs_dat_commit_end(struct inode *, struct nilfs_palloc_req *, int); void nilfs_dat_commit_end(struct inode *, struct nilfs_palloc_req *, int);
void nilfs_dat_abort_end(struct inode *, struct nilfs_palloc_req *); void nilfs_dat_abort_end(struct inode *, struct nilfs_palloc_req *);
int nilfs_dat_prepare_update(struct inode *, struct nilfs_palloc_req *,
struct nilfs_palloc_req *);
void nilfs_dat_commit_update(struct inode *, struct nilfs_palloc_req *,
struct nilfs_palloc_req *, int);
void nilfs_dat_abort_update(struct inode *, struct nilfs_palloc_req *,
struct nilfs_palloc_req *);
int nilfs_dat_mark_dirty(struct inode *, __u64); int nilfs_dat_mark_dirty(struct inode *, __u64);
int nilfs_dat_freev(struct inode *, __u64 *, size_t); int nilfs_dat_freev(struct inode *, __u64 *, size_t);
......
...@@ -125,106 +125,64 @@ static void nilfs_direct_set_target_v(struct nilfs_direct *direct, ...@@ -125,106 +125,64 @@ static void nilfs_direct_set_target_v(struct nilfs_direct *direct,
direct->d_bmap.b_last_allocated_ptr = ptr; direct->d_bmap.b_last_allocated_ptr = ptr;
} }
static int nilfs_direct_prepare_insert(struct nilfs_direct *direct,
__u64 key,
union nilfs_bmap_ptr_req *req,
struct nilfs_bmap_stats *stats)
{
int ret;
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;
stats->bs_nblocks = 1;
return 0;
}
static void nilfs_direct_commit_insert(struct nilfs_direct *direct,
union nilfs_bmap_ptr_req *req,
__u64 key, __u64 ptr)
{
struct buffer_head *bh;
/* ptr must be a pointer to a buffer head. */
bh = (struct buffer_head *)((unsigned long)ptr);
set_buffer_nilfs_volatile(bh);
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 (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) static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
{ {
struct nilfs_direct *direct; struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
union nilfs_bmap_ptr_req req; union nilfs_bmap_ptr_req req;
struct nilfs_bmap_stats stats; struct inode *dat = NULL;
struct buffer_head *bh;
int ret; int ret;
direct = (struct nilfs_direct *)bmap;
if (key > NILFS_DIRECT_KEY_MAX) if (key > NILFS_DIRECT_KEY_MAX)
return -ENOENT; return -ENOENT;
if (nilfs_direct_get_ptr(direct, key) != NILFS_BMAP_INVALID_PTR) if (nilfs_direct_get_ptr(direct, key) != NILFS_BMAP_INVALID_PTR)
return -EEXIST; return -EEXIST;
ret = nilfs_direct_prepare_insert(direct, key, &req, &stats); if (NILFS_BMAP_USE_VBN(bmap)) {
if (ret < 0) req.bpr_ptr = nilfs_direct_find_target_v(direct, key);
return ret; dat = nilfs_bmap_get_dat(bmap);
nilfs_direct_commit_insert(direct, &req, key, ptr); }
nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat);
if (!ret) {
/* ptr must be a pointer to a buffer head. */
bh = (struct buffer_head *)((unsigned long)ptr);
set_buffer_nilfs_volatile(bh);
return 0; nilfs_bmap_commit_alloc_ptr(bmap, &req, dat);
} nilfs_direct_set_ptr(direct, key, req.bpr_ptr);
static int nilfs_direct_prepare_delete(struct nilfs_direct *direct, if (!nilfs_bmap_dirty(bmap))
union nilfs_bmap_ptr_req *req, nilfs_bmap_set_dirty(bmap);
__u64 key,
struct nilfs_bmap_stats *stats)
{
int ret;
req->bpr_ptr = nilfs_direct_get_ptr(direct, key); if (NILFS_BMAP_USE_VBN(bmap))
ret = nilfs_bmap_prepare_end_ptr(&direct->d_bmap, req); nilfs_direct_set_target_v(direct, key, req.bpr_ptr);
if (!ret)
stats->bs_nblocks = 1;
return ret;
}
static void nilfs_direct_commit_delete(struct nilfs_direct *direct, nilfs_bmap_add_blocks(bmap, 1);
union nilfs_bmap_ptr_req *req, }
__u64 key) return ret;
{
nilfs_bmap_commit_end_ptr(&direct->d_bmap, req);
nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR);
} }
static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
{ {
struct nilfs_direct *direct; struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
union nilfs_bmap_ptr_req req; union nilfs_bmap_ptr_req req;
struct nilfs_bmap_stats stats; struct inode *dat;
int ret; int ret;
direct = (struct nilfs_direct *)bmap; if (key > NILFS_DIRECT_KEY_MAX ||
if ((key > NILFS_DIRECT_KEY_MAX) ||
nilfs_direct_get_ptr(direct, key) == NILFS_BMAP_INVALID_PTR) nilfs_direct_get_ptr(direct, key) == NILFS_BMAP_INVALID_PTR)
return -ENOENT; return -ENOENT;
ret = nilfs_direct_prepare_delete(direct, &req, key, &stats); dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
if (ret < 0) req.bpr_ptr = nilfs_direct_get_ptr(direct, key);
return ret;
nilfs_direct_commit_delete(direct, &req, key);
nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
return 0; ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat);
if (!ret) {
nilfs_bmap_commit_end_ptr(bmap, &req, dat);
nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR);
nilfs_bmap_sub_blocks(bmap, 1);
}
return ret;
} }
static int nilfs_direct_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) static int nilfs_direct_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
...@@ -310,59 +268,56 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, ...@@ -310,59 +268,56 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
return 0; return 0;
} }
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 buffer_head *bh)
{ {
union nilfs_bmap_ptr_req oldreq, newreq; struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
struct nilfs_palloc_req oldreq, newreq;
struct inode *dat;
__u64 key; __u64 key;
__u64 ptr; __u64 ptr;
int ret; int ret;
key = nilfs_bmap_data_get_key(&direct->d_bmap, bh); if (!NILFS_BMAP_USE_VBN(bmap))
return 0;
dat = nilfs_bmap_get_dat(bmap);
key = nilfs_bmap_data_get_key(bmap, bh);
ptr = nilfs_direct_get_ptr(direct, key); ptr = nilfs_direct_get_ptr(direct, key);
if (!buffer_nilfs_volatile(bh)) { if (!buffer_nilfs_volatile(bh)) {
oldreq.bpr_ptr = ptr; oldreq.pr_entry_nr = ptr;
newreq.bpr_ptr = ptr; newreq.pr_entry_nr = ptr;
ret = nilfs_bmap_prepare_update_v(&direct->d_bmap, &oldreq, ret = nilfs_dat_prepare_update(dat, &oldreq, &newreq);
&newreq);
if (ret < 0) if (ret < 0)
return ret; return ret;
nilfs_bmap_commit_update_v(&direct->d_bmap, &oldreq, &newreq); nilfs_dat_commit_update(dat, &oldreq, &newreq,
bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
set_buffer_nilfs_volatile(bh); set_buffer_nilfs_volatile(bh);
nilfs_direct_set_ptr(direct, key, newreq.bpr_ptr); nilfs_direct_set_ptr(direct, key, newreq.pr_entry_nr);
} else } else
ret = nilfs_bmap_mark_dirty(&direct->d_bmap, ptr); ret = nilfs_dat_mark_dirty(dat, ptr);
return ret; return ret;
} }
static int nilfs_direct_propagate(const struct nilfs_bmap *bmap,
struct buffer_head *bh)
{
struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
return NILFS_BMAP_USE_VBN(bmap) ?
nilfs_direct_propagate_v(direct, bh) : 0;
}
static int nilfs_direct_assign_v(struct nilfs_direct *direct, static int nilfs_direct_assign_v(struct nilfs_direct *direct,
__u64 key, __u64 ptr, __u64 key, __u64 ptr,
struct buffer_head **bh, struct buffer_head **bh,
sector_t blocknr, sector_t blocknr,
union nilfs_binfo *binfo) union nilfs_binfo *binfo)
{ {
struct inode *dat = nilfs_bmap_get_dat(&direct->d_bmap);
union nilfs_bmap_ptr_req req; union nilfs_bmap_ptr_req req;
int ret; int ret;
req.bpr_ptr = ptr; req.bpr_ptr = ptr;
ret = nilfs_bmap_start_v(&direct->d_bmap, &req, blocknr); ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
if (unlikely(ret < 0)) if (!ret) {
return ret; nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
}
return 0; return ret;
} }
static int nilfs_direct_assign_p(struct nilfs_direct *direct, static int nilfs_direct_assign_p(struct nilfs_direct *direct,
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "mdt.h" #include "mdt.h"
#include "alloc.h" #include "alloc.h"
#define NILFS_IFILE_GFP NILFS_MDT_GFP
static inline struct nilfs_inode * static inline struct nilfs_inode *
nilfs_ifile_map_inode(struct inode *ifile, ino_t ino, struct buffer_head *ibh) nilfs_ifile_map_inode(struct inode *ifile, ino_t ino, struct buffer_head *ibh)
......
...@@ -430,7 +430,8 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, ...@@ -430,7 +430,8 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino,
raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, bh); raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, bh);
if (nilfs_read_inode_common(inode, raw_inode)) err = nilfs_read_inode_common(inode, raw_inode);
if (err)
goto failed_unmap; goto failed_unmap;
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
......
...@@ -442,12 +442,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, ...@@ -442,12 +442,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
const char *msg; const char *msg;
int ret; int ret;
ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
if (ret < 0) {
msg = "cannot read source blocks";
goto failed;
}
ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]); ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
if (ret < 0) { if (ret < 0) {
/* /*
...@@ -548,8 +542,26 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, ...@@ -548,8 +542,26 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
} }
} }
/*
* nilfs_ioctl_move_blocks() will call nilfs_gc_iget(),
* which will operates an inode list without blocking.
* To protect the list from concurrent operations,
* nilfs_ioctl_move_blocks should be atomic operation.
*/
if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) {
ret = -EBUSY;
goto out_free;
}
ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]);
if (ret < 0)
printk(KERN_ERR "NILFS: GC failed during preparation: "
"cannot read source blocks: err=%d\n", ret);
else
ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
clear_nilfs_gc_running(nilfs);
out_free: out_free:
while (--n >= 0) while (--n >= 0)
vfree(kbufs[n]); vfree(kbufs[n]);
......
...@@ -103,15 +103,12 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block, ...@@ -103,15 +103,12 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
goto failed_unlock; goto failed_unlock;
err = -EEXIST; err = -EEXIST;
if (buffer_uptodate(bh) || buffer_mapped(bh)) if (buffer_uptodate(bh))
goto failed_bh; goto failed_bh;
#if 0
/* The uptodate flag is not protected by the page lock, but
the mapped flag is. Thus, we don't have to wait the buffer. */
wait_on_buffer(bh); wait_on_buffer(bh);
if (buffer_uptodate(bh)) if (buffer_uptodate(bh))
goto failed_bh; goto failed_bh;
#endif
bh->b_bdev = nilfs->ns_bdev; bh->b_bdev = nilfs->ns_bdev;
err = nilfs_mdt_insert_new_block(inode, block, bh, init_block); err = nilfs_mdt_insert_new_block(inode, block, bh, init_block);
...@@ -139,7 +136,7 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, ...@@ -139,7 +136,7 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff,
int mode, struct buffer_head **out_bh) int mode, struct buffer_head **out_bh)
{ {
struct buffer_head *bh; struct buffer_head *bh;
unsigned long blknum = 0; __u64 blknum = 0;
int ret = -ENOMEM; int ret = -ENOMEM;
bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0); bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0);
...@@ -162,17 +159,15 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, ...@@ -162,17 +159,15 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff,
unlock_buffer(bh); unlock_buffer(bh);
goto out; goto out;
} }
if (!buffer_mapped(bh)) { /* unused buffer */
ret = nilfs_bmap_lookup(NILFS_I(inode)->i_bmap, blkoff, ret = nilfs_bmap_lookup(NILFS_I(inode)->i_bmap, blkoff, &blknum);
&blknum);
if (unlikely(ret)) { if (unlikely(ret)) {
unlock_buffer(bh); unlock_buffer(bh);
goto failed_bh; goto failed_bh;
} }
bh->b_bdev = NILFS_MDT(inode)->mi_nilfs->ns_bdev; bh->b_bdev = NILFS_MDT(inode)->mi_nilfs->ns_bdev;
bh->b_blocknr = blknum; bh->b_blocknr = (sector_t)blknum;
set_buffer_mapped(bh); set_buffer_mapped(bh);
}
bh->b_end_io = end_buffer_read_sync; bh->b_end_io = end_buffer_read_sync;
get_bh(bh); get_bh(bh);
...@@ -402,6 +397,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) ...@@ -402,6 +397,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
struct inode *inode = container_of(page->mapping, struct inode *inode = container_of(page->mapping,
struct inode, i_data); struct inode, i_data);
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs;
struct nilfs_sb_info *writer = NULL; struct nilfs_sb_info *writer = NULL;
int err = 0; int err = 0;
...@@ -411,9 +407,10 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) ...@@ -411,9 +407,10 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
if (page->mapping->assoc_mapping) if (page->mapping->assoc_mapping)
return 0; /* Do not request flush for shadow page cache */ return 0; /* Do not request flush for shadow page cache */
if (!sb) { if (!sb) {
writer = nilfs_get_writer(NILFS_MDT(inode)->mi_nilfs); down_read(&nilfs->ns_writer_sem);
writer = nilfs->ns_writer;
if (!writer) { if (!writer) {
nilfs_put_writer(NILFS_MDT(inode)->mi_nilfs); up_read(&nilfs->ns_writer_sem);
return -EROFS; return -EROFS;
} }
sb = writer->s_super; sb = writer->s_super;
...@@ -425,7 +422,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) ...@@ -425,7 +422,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
nilfs_flush_segment(sb, inode->i_ino); nilfs_flush_segment(sb, inode->i_ino);
if (writer) if (writer)
nilfs_put_writer(NILFS_MDT(inode)->mi_nilfs); up_read(&nilfs->ns_writer_sem);
return err; return err;
} }
...@@ -516,9 +513,10 @@ nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb, ...@@ -516,9 +513,10 @@ nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb,
} }
struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb, struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb,
ino_t ino, gfp_t gfp_mask) ino_t ino)
{ {
struct inode *inode = nilfs_mdt_new_common(nilfs, sb, ino, gfp_mask); struct inode *inode = nilfs_mdt_new_common(nilfs, sb, ino,
NILFS_MDT_GFP);
if (!inode) if (!inode)
return NULL; return NULL;
......
...@@ -74,8 +74,7 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long); ...@@ -74,8 +74,7 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long);
int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long);
int nilfs_mdt_fetch_dirty(struct inode *); int nilfs_mdt_fetch_dirty(struct inode *);
struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t, struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t);
gfp_t);
struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *, struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *,
ino_t, gfp_t); ino_t, gfp_t);
void nilfs_mdt_destroy(struct inode *); void nilfs_mdt_destroy(struct inode *);
......
...@@ -552,7 +552,8 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi, ...@@ -552,7 +552,8 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi,
printk(KERN_WARNING printk(KERN_WARNING
"NILFS warning: error recovering data block " "NILFS warning: error recovering data block "
"(err=%d, ino=%lu, block-offset=%llu)\n", "(err=%d, ino=%lu, block-offset=%llu)\n",
err, rb->ino, (unsigned long long)rb->blkoff); err, (unsigned long)rb->ino,
(unsigned long long)rb->blkoff);
if (!err2) if (!err2)
err2 = err; err2 = err;
next: next:
......
...@@ -316,10 +316,10 @@ static struct bio *nilfs_alloc_seg_bio(struct super_block *sb, sector_t start, ...@@ -316,10 +316,10 @@ static struct bio *nilfs_alloc_seg_bio(struct super_block *sb, sector_t start,
{ {
struct bio *bio; struct bio *bio;
bio = bio_alloc(GFP_NOWAIT, nr_vecs); bio = bio_alloc(GFP_NOIO, nr_vecs);
if (bio == NULL) { if (bio == NULL) {
while (!bio && (nr_vecs >>= 1)) while (!bio && (nr_vecs >>= 1))
bio = bio_alloc(GFP_NOWAIT, nr_vecs); bio = bio_alloc(GFP_NOIO, nr_vecs);
} }
if (likely(bio)) { if (likely(bio)) {
bio->bi_bdev = sb->s_bdev; bio->bi_bdev = sb->s_bdev;
......
...@@ -2501,7 +2501,8 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, ...@@ -2501,7 +2501,8 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci,
if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) &&
nilfs_discontinued(nilfs)) { nilfs_discontinued(nilfs)) {
down_write(&nilfs->ns_sem); down_write(&nilfs->ns_sem);
req->sb_err = nilfs_commit_super(sbi, 0); req->sb_err = nilfs_commit_super(sbi,
nilfs_altsb_need_update(nilfs));
up_write(&nilfs->ns_sem); up_write(&nilfs->ns_sem);
} }
} }
...@@ -2689,6 +2690,7 @@ static int nilfs_segctor_thread(void *arg) ...@@ -2689,6 +2690,7 @@ static int nilfs_segctor_thread(void *arg)
} else { } else {
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
int should_sleep = 1; int should_sleep = 1;
struct the_nilfs *nilfs;
prepare_to_wait(&sci->sc_wait_daemon, &wait, prepare_to_wait(&sci->sc_wait_daemon, &wait,
TASK_INTERRUPTIBLE); TASK_INTERRUPTIBLE);
...@@ -2709,6 +2711,9 @@ static int nilfs_segctor_thread(void *arg) ...@@ -2709,6 +2711,9 @@ static int nilfs_segctor_thread(void *arg)
finish_wait(&sci->sc_wait_daemon, &wait); finish_wait(&sci->sc_wait_daemon, &wait);
timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
time_after_eq(jiffies, sci->sc_timer->expires)); time_after_eq(jiffies, sci->sc_timer->expires));
nilfs = sci->sc_sbi->s_nilfs;
if (sci->sc_super->s_dirt && nilfs_sb_need_update(nilfs))
set_nilfs_discontinued(nilfs);
} }
goto loop; goto loop;
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <linux/nilfs2_fs.h> #include <linux/nilfs2_fs.h>
#include "mdt.h" #include "mdt.h"
#define NILFS_SUFILE_GFP NILFS_MDT_GFP
static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile)
{ {
......
...@@ -50,6 +50,8 @@ ...@@ -50,6 +50,8 @@
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
#include "nilfs.h" #include "nilfs.h"
#include "mdt.h" #include "mdt.h"
#include "alloc.h" #include "alloc.h"
...@@ -65,7 +67,6 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " ...@@ -65,7 +67,6 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem "
"(NILFS)"); "(NILFS)");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static void nilfs_write_super(struct super_block *sb);
static int nilfs_remount(struct super_block *sb, int *flags, char *data); static int nilfs_remount(struct super_block *sb, int *flags, char *data);
/** /**
...@@ -311,9 +312,6 @@ static void nilfs_put_super(struct super_block *sb) ...@@ -311,9 +312,6 @@ static void nilfs_put_super(struct super_block *sb)
lock_kernel(); lock_kernel();
if (sb->s_dirt)
nilfs_write_super(sb);
nilfs_detach_segment_constructor(sbi); nilfs_detach_segment_constructor(sbi);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
...@@ -336,63 +334,21 @@ static void nilfs_put_super(struct super_block *sb) ...@@ -336,63 +334,21 @@ static void nilfs_put_super(struct super_block *sb)
unlock_kernel(); unlock_kernel();
} }
/** static int nilfs_sync_fs(struct super_block *sb, int wait)
* nilfs_write_super - write super block(s) of NILFS
* @sb: super_block
*
* nilfs_write_super() gets a fs-dependent lock, writes super block(s), and
* clears s_dirt. This function is called in the section protected by
* lock_super().
*
* The s_dirt flag is managed by each filesystem and we protect it by ns_sem
* of the struct the_nilfs. Lock order must be as follows:
*
* 1. lock_super()
* 2. down_write(&nilfs->ns_sem)
*
* Inside NILFS, locking ns_sem is enough to protect s_dirt and the buffer
* of the super block (nilfs->ns_sbp[]).
*
* In most cases, VFS functions call lock_super() before calling these
* methods. So we must be careful not to bring on deadlocks when using
* lock_super(); see generic_shutdown_super(), write_super(), and so on.
*
* Note that order of lock_kernel() and lock_super() depends on contexts
* of VFS. We should also note that lock_kernel() can be used in its
* protective section and only the outermost one has an effect.
*/
static void nilfs_write_super(struct super_block *sb)
{ {
struct nilfs_sb_info *sbi = NILFS_SB(sb); struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs; struct the_nilfs *nilfs = sbi->s_nilfs;
down_write(&nilfs->ns_sem);
if (!(sb->s_flags & MS_RDONLY)) {
struct nilfs_super_block **sbp = nilfs->ns_sbp;
u64 t = get_seconds();
int dupsb;
if (!nilfs_discontinued(nilfs) && t >= nilfs->ns_sbwtime[0] &&
t < nilfs->ns_sbwtime[0] + NILFS_SB_FREQ) {
up_write(&nilfs->ns_sem);
return;
}
dupsb = sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ;
nilfs_commit_super(sbi, dupsb);
}
sb->s_dirt = 0;
up_write(&nilfs->ns_sem);
}
static int nilfs_sync_fs(struct super_block *sb, int wait)
{
int err = 0; int err = 0;
nilfs_write_super(sb);
/* This function is called when super block should be written back */ /* This function is called when super block should be written back */
if (wait) if (wait)
err = nilfs_construct_segment(sb); err = nilfs_construct_segment(sb);
down_write(&nilfs->ns_sem);
if (sb->s_dirt)
nilfs_commit_super(sbi, 1);
up_write(&nilfs->ns_sem);
return err; return err;
} }
...@@ -407,8 +363,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) ...@@ -407,8 +363,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno)
list_add(&sbi->s_list, &nilfs->ns_supers); list_add(&sbi->s_list, &nilfs->ns_supers);
up_write(&nilfs->ns_super_sem); up_write(&nilfs->ns_super_sem);
sbi->s_ifile = nilfs_mdt_new( sbi->s_ifile = nilfs_mdt_new(nilfs, sbi->s_super, NILFS_IFILE_INO);
nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP);
if (!sbi->s_ifile) if (!sbi->s_ifile)
return -ENOMEM; return -ENOMEM;
...@@ -529,6 +484,26 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -529,6 +484,26 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
return 0; return 0;
} }
static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
{
struct super_block *sb = vfs->mnt_sb;
struct nilfs_sb_info *sbi = NILFS_SB(sb);
if (!nilfs_test_opt(sbi, BARRIER))
seq_printf(seq, ",barrier=off");
if (nilfs_test_opt(sbi, SNAPSHOT))
seq_printf(seq, ",cp=%llu",
(unsigned long long int)sbi->s_snapshot_cno);
if (nilfs_test_opt(sbi, ERRORS_RO))
seq_printf(seq, ",errors=remount-ro");
if (nilfs_test_opt(sbi, ERRORS_PANIC))
seq_printf(seq, ",errors=panic");
if (nilfs_test_opt(sbi, STRICT_ORDER))
seq_printf(seq, ",order=strict");
return 0;
}
static struct super_operations nilfs_sops = { static struct super_operations nilfs_sops = {
.alloc_inode = nilfs_alloc_inode, .alloc_inode = nilfs_alloc_inode,
.destroy_inode = nilfs_destroy_inode, .destroy_inode = nilfs_destroy_inode,
...@@ -538,7 +513,7 @@ static struct super_operations nilfs_sops = { ...@@ -538,7 +513,7 @@ static struct super_operations nilfs_sops = {
/* .drop_inode = nilfs_drop_inode, */ /* .drop_inode = nilfs_drop_inode, */
.delete_inode = nilfs_delete_inode, .delete_inode = nilfs_delete_inode,
.put_super = nilfs_put_super, .put_super = nilfs_put_super,
.write_super = nilfs_write_super, /* .write_super = nilfs_write_super, */
.sync_fs = nilfs_sync_fs, .sync_fs = nilfs_sync_fs,
/* .write_super_lockfs */ /* .write_super_lockfs */
/* .unlockfs */ /* .unlockfs */
...@@ -546,7 +521,7 @@ static struct super_operations nilfs_sops = { ...@@ -546,7 +521,7 @@ static struct super_operations nilfs_sops = {
.remount_fs = nilfs_remount, .remount_fs = nilfs_remount,
.clear_inode = nilfs_clear_inode, .clear_inode = nilfs_clear_inode,
/* .umount_begin */ /* .umount_begin */
/* .show_options */ .show_options = nilfs_show_options
}; };
static struct inode * static struct inode *
...@@ -816,10 +791,15 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, ...@@ -816,10 +791,15 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent,
if (sb->s_flags & MS_RDONLY) { if (sb->s_flags & MS_RDONLY) {
if (nilfs_test_opt(sbi, SNAPSHOT)) { if (nilfs_test_opt(sbi, SNAPSHOT)) {
down_read(&nilfs->ns_segctor_sem);
err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile,
sbi->s_snapshot_cno); sbi->s_snapshot_cno);
if (err < 0) up_read(&nilfs->ns_segctor_sem);
if (err < 0) {
if (err == -ENOENT)
err = -EINVAL;
goto failed_sbi; goto failed_sbi;
}
if (!err) { if (!err) {
printk(KERN_ERR printk(KERN_ERR
"NILFS: The specified checkpoint is " "NILFS: The specified checkpoint is "
...@@ -1127,10 +1107,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, ...@@ -1127,10 +1107,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
*/ */
sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno);
if (!sd.cno)
/* trying to get the latest checkpoint. */
sd.cno = nilfs_last_cno(nilfs);
/* /*
* Get super block instance holding the nilfs_sb_info struct. * Get super block instance holding the nilfs_sb_info struct.
* A new instance is allocated if no existing mount is present or * A new instance is allocated if no existing mount is present or
......
...@@ -68,12 +68,11 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev) ...@@ -68,12 +68,11 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev)
nilfs->ns_bdev = bdev; nilfs->ns_bdev = bdev;
atomic_set(&nilfs->ns_count, 1); atomic_set(&nilfs->ns_count, 1);
atomic_set(&nilfs->ns_writer_refcount, -1);
atomic_set(&nilfs->ns_ndirtyblks, 0); atomic_set(&nilfs->ns_ndirtyblks, 0);
init_rwsem(&nilfs->ns_sem); init_rwsem(&nilfs->ns_sem);
init_rwsem(&nilfs->ns_super_sem); init_rwsem(&nilfs->ns_super_sem);
mutex_init(&nilfs->ns_mount_mutex); mutex_init(&nilfs->ns_mount_mutex);
mutex_init(&nilfs->ns_writer_mutex); init_rwsem(&nilfs->ns_writer_sem);
INIT_LIST_HEAD(&nilfs->ns_list); INIT_LIST_HEAD(&nilfs->ns_list);
INIT_LIST_HEAD(&nilfs->ns_supers); INIT_LIST_HEAD(&nilfs->ns_supers);
spin_lock_init(&nilfs->ns_last_segment_lock); spin_lock_init(&nilfs->ns_last_segment_lock);
...@@ -188,23 +187,19 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, ...@@ -188,23 +187,19 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs,
inode_size = nilfs->ns_inode_size; inode_size = nilfs->ns_inode_size;
err = -ENOMEM; err = -ENOMEM;
nilfs->ns_dat = nilfs_mdt_new( nilfs->ns_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO);
nilfs, NULL, NILFS_DAT_INO, NILFS_DAT_GFP);
if (unlikely(!nilfs->ns_dat)) if (unlikely(!nilfs->ns_dat))
goto failed; goto failed;
nilfs->ns_gc_dat = nilfs_mdt_new( nilfs->ns_gc_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO);
nilfs, NULL, NILFS_DAT_INO, NILFS_DAT_GFP);
if (unlikely(!nilfs->ns_gc_dat)) if (unlikely(!nilfs->ns_gc_dat))
goto failed_dat; goto failed_dat;
nilfs->ns_cpfile = nilfs_mdt_new( nilfs->ns_cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO);
nilfs, NULL, NILFS_CPFILE_INO, NILFS_CPFILE_GFP);
if (unlikely(!nilfs->ns_cpfile)) if (unlikely(!nilfs->ns_cpfile))
goto failed_gc_dat; goto failed_gc_dat;
nilfs->ns_sufile = nilfs_mdt_new( nilfs->ns_sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO);
nilfs, NULL, NILFS_SUFILE_INO, NILFS_SUFILE_GFP);
if (unlikely(!nilfs->ns_sufile)) if (unlikely(!nilfs->ns_sufile))
goto failed_cpfile; goto failed_cpfile;
......
...@@ -37,6 +37,7 @@ enum { ...@@ -37,6 +37,7 @@ enum {
THE_NILFS_LOADED, /* Roll-back/roll-forward has done and THE_NILFS_LOADED, /* Roll-back/roll-forward has done and
the latest checkpoint was loaded */ the latest checkpoint was loaded */
THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */
THE_NILFS_GC_RUNNING, /* gc process is running */
}; };
/** /**
...@@ -50,8 +51,7 @@ enum { ...@@ -50,8 +51,7 @@ enum {
* @ns_sem: semaphore for shared states * @ns_sem: semaphore for shared states
* @ns_super_sem: semaphore for global operations across super block instances * @ns_super_sem: semaphore for global operations across super block instances
* @ns_mount_mutex: mutex protecting mount process of nilfs * @ns_mount_mutex: mutex protecting mount process of nilfs
* @ns_writer_mutex: mutex protecting ns_writer attach/detach * @ns_writer_sem: semaphore protecting ns_writer attach/detach
* @ns_writer_refcount: number of referrers on ns_writer
* @ns_current: back pointer to current mount * @ns_current: back pointer to current mount
* @ns_sbh: buffer heads of on-disk super blocks * @ns_sbh: buffer heads of on-disk super blocks
* @ns_sbp: pointers to super block data * @ns_sbp: pointers to super block data
...@@ -100,8 +100,7 @@ struct the_nilfs { ...@@ -100,8 +100,7 @@ struct the_nilfs {
struct rw_semaphore ns_sem; struct rw_semaphore ns_sem;
struct rw_semaphore ns_super_sem; struct rw_semaphore ns_super_sem;
struct mutex ns_mount_mutex; struct mutex ns_mount_mutex;
struct mutex ns_writer_mutex; struct rw_semaphore ns_writer_sem;
atomic_t ns_writer_refcount;
/* /*
* components protected by ns_super_sem * components protected by ns_super_sem
...@@ -197,11 +196,26 @@ static inline int nilfs_##name(struct the_nilfs *nilfs) \ ...@@ -197,11 +196,26 @@ static inline int nilfs_##name(struct the_nilfs *nilfs) \
THE_NILFS_FNS(INIT, init) THE_NILFS_FNS(INIT, init)
THE_NILFS_FNS(LOADED, loaded) THE_NILFS_FNS(LOADED, loaded)
THE_NILFS_FNS(DISCONTINUED, discontinued) THE_NILFS_FNS(DISCONTINUED, discontinued)
THE_NILFS_FNS(GC_RUNNING, gc_running)
/* Minimum interval of periodical update of superblocks (in seconds) */ /* Minimum interval of periodical update of superblocks (in seconds) */
#define NILFS_SB_FREQ 10 #define NILFS_SB_FREQ 10
#define NILFS_ALTSB_FREQ 60 /* spare superblock */ #define NILFS_ALTSB_FREQ 60 /* spare superblock */
static inline int nilfs_sb_need_update(struct the_nilfs *nilfs)
{
u64 t = get_seconds();
return t < nilfs->ns_sbwtime[0] ||
t > nilfs->ns_sbwtime[0] + NILFS_SB_FREQ;
}
static inline int nilfs_altsb_need_update(struct the_nilfs *nilfs)
{
u64 t = get_seconds();
struct nilfs_super_block **sbp = nilfs->ns_sbp;
return sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ;
}
void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
struct the_nilfs *find_or_create_nilfs(struct block_device *); struct the_nilfs *find_or_create_nilfs(struct block_device *);
void put_nilfs(struct the_nilfs *); void put_nilfs(struct the_nilfs *);
...@@ -221,34 +235,21 @@ static inline void get_nilfs(struct the_nilfs *nilfs) ...@@ -221,34 +235,21 @@ static inline void get_nilfs(struct the_nilfs *nilfs)
atomic_inc(&nilfs->ns_count); atomic_inc(&nilfs->ns_count);
} }
static inline struct nilfs_sb_info *nilfs_get_writer(struct the_nilfs *nilfs)
{
if (atomic_inc_and_test(&nilfs->ns_writer_refcount))
mutex_lock(&nilfs->ns_writer_mutex);
return nilfs->ns_writer;
}
static inline void nilfs_put_writer(struct the_nilfs *nilfs)
{
if (atomic_add_negative(-1, &nilfs->ns_writer_refcount))
mutex_unlock(&nilfs->ns_writer_mutex);
}
static inline void static inline void
nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
{ {
mutex_lock(&nilfs->ns_writer_mutex); down_write(&nilfs->ns_writer_sem);
nilfs->ns_writer = sbi; nilfs->ns_writer = sbi;
mutex_unlock(&nilfs->ns_writer_mutex); up_write(&nilfs->ns_writer_sem);
} }
static inline void static inline void
nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
{ {
mutex_lock(&nilfs->ns_writer_mutex); down_write(&nilfs->ns_writer_sem);
if (sbi == nilfs->ns_writer) if (sbi == nilfs->ns_writer)
nilfs->ns_writer = NULL; nilfs->ns_writer = NULL;
mutex_unlock(&nilfs->ns_writer_mutex); up_write(&nilfs->ns_writer_sem);
} }
static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment