Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 15 Jun 2009 16:27:37 +0000 (09:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 15 Jun 2009 16:27:37 +0000 (09:27 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6:
  regulator/max1586: fix V3 gain calculation integer overflow
  regulator/max1586: support increased V3 voltage range
  regulator: lp3971 - fix driver link error when built-in.
  LP3971 PMIC regulator driver (updated and combined version)
  regulator: remove driver_data direct access of struct device
  regulator: Set MODULE_ALIAS for regulator drivers
  regulator: Support list_voltage for fixed voltage regulator
  regulator: Move regulator drivers to subsys_initcall()
  regulator: build fix for powerpc - renamed show_state
  regulator: add userspace-consumer driver
  Maxim 1586 regulator driver

28 files changed:
Documentation/filesystems/nilfs2.txt
fs/nilfs2/bmap.c
fs/nilfs2/bmap.h
fs/nilfs2/btnode.c
fs/nilfs2/btnode.h
fs/nilfs2/btree.c
fs/nilfs2/btree.h
fs/nilfs2/cpfile.c
fs/nilfs2/cpfile.h
fs/nilfs2/dat.c
fs/nilfs2/dat.h
fs/nilfs2/direct.c
fs/nilfs2/direct.h
fs/nilfs2/gcinode.c
fs/nilfs2/inode.c
fs/nilfs2/ioctl.c
fs/nilfs2/mdt.c
fs/nilfs2/nilfs.h
fs/nilfs2/recovery.c
fs/nilfs2/segbuf.c
fs/nilfs2/seglist.h [deleted file]
fs/nilfs2/segment.c
fs/nilfs2/segment.h
fs/nilfs2/sufile.c
fs/nilfs2/sufile.h
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.c
fs/ramfs/inode.c

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