diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-07 16:10:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-07 16:10:55 -0400 |
commit | a57f9a3e811cf1246b394f0cc667c6bc5a52e099 (patch) | |
tree | 488b4dd7cd061e7e0e059acb8443967e21051aab | |
parent | 09dc942c2a767e2d298f1cc9294bc19c7d7208c5 (diff) | |
parent | 89c0fd014d34d409a7b196667c2b9a4813b6c968 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2: (45 commits)
nilfs2: reject filesystem with unsupported block size
nilfs2: avoid rec_len overflow with 64KB block size
nilfs2: simplify nilfs_get_page function
nilfs2: reject incompatible filesystem
nilfs2: add feature set fields to super block
nilfs2: clarify byte offset in super block format
nilfs2: apply read-ahead for nilfs_btree_lookup_contig
nilfs2: introduce check flag to btree node buffer
nilfs2: add btree get block function with readahead option
nilfs2: add read ahead mode to nilfs_btnode_submit_block
nilfs2: fix buffer head leak in nilfs_btnode_submit_block
nilfs2: eliminate inline keywords in btree implementation
nilfs2: get maximum number of child nodes from bmap object
nilfs2: reduce repetitive calculation of max number of child nodes
nilfs2: optimize calculation of min/max number of btree node children
nilfs2: remove redundant pointer checks in bmap lookup functions
nilfs2: get rid of nilfs_bmap_union
nilfs2: unify bmap set_target_v operations
nilfs2: get rid of nilfs_btree uses
nilfs2: get rid of nilfs_direct uses
...
-rw-r--r-- | Documentation/filesystems/nilfs2.txt | 12 | ||||
-rw-r--r-- | fs/nilfs2/bmap.c | 6 | ||||
-rw-r--r-- | fs/nilfs2/bmap.h | 16 | ||||
-rw-r--r-- | fs/nilfs2/bmap_union.h | 42 | ||||
-rw-r--r-- | fs/nilfs2/btnode.c | 23 | ||||
-rw-r--r-- | fs/nilfs2/btnode.h | 4 | ||||
-rw-r--r-- | fs/nilfs2/btree.c | 914 | ||||
-rw-r--r-- | fs/nilfs2/btree.h | 12 | ||||
-rw-r--r-- | fs/nilfs2/dir.c | 33 | ||||
-rw-r--r-- | fs/nilfs2/direct.c | 96 | ||||
-rw-r--r-- | fs/nilfs2/direct.h | 11 | ||||
-rw-r--r-- | fs/nilfs2/gcinode.c | 17 | ||||
-rw-r--r-- | fs/nilfs2/mdt.c | 1 | ||||
-rw-r--r-- | fs/nilfs2/nilfs.h | 22 | ||||
-rw-r--r-- | fs/nilfs2/page.c | 5 | ||||
-rw-r--r-- | fs/nilfs2/page.h | 2 | ||||
-rw-r--r-- | fs/nilfs2/recovery.c | 348 | ||||
-rw-r--r-- | fs/nilfs2/segbuf.h | 24 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 19 | ||||
-rw-r--r-- | fs/nilfs2/segment.h | 10 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 333 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 161 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.h | 23 | ||||
-rw-r--r-- | include/linux/nilfs2_fs.h | 65 |
24 files changed, 1294 insertions, 905 deletions
diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt index d3e7673995eb..d5c0cef38a71 100644 --- a/Documentation/filesystems/nilfs2.txt +++ b/Documentation/filesystems/nilfs2.txt | |||
@@ -49,7 +49,10 @@ Mount options | |||
49 | NILFS2 supports the following mount options: | 49 | NILFS2 supports the following mount options: |
50 | (*) == default | 50 | (*) == default |
51 | 51 | ||
52 | nobarrier Disables barriers. | 52 | barrier(*) This enables/disables the use of write barriers. This |
53 | nobarrier requires an IO stack which can support barriers, and | ||
54 | if nilfs gets an error on a barrier write, it will | ||
55 | disable again with a warning. | ||
53 | errors=continue Keep going on a filesystem error. | 56 | errors=continue Keep going on a filesystem error. |
54 | errors=remount-ro(*) Remount the filesystem read-only on an error. | 57 | errors=remount-ro(*) Remount the filesystem read-only on an error. |
55 | errors=panic Panic and halt the machine if an error occurs. | 58 | errors=panic Panic and halt the machine if an error occurs. |
@@ -74,9 +77,10 @@ norecovery Disable recovery of the filesystem on mount. | |||
74 | This disables every write access on the device for | 77 | This disables every write access on the device for |
75 | read-only mounts or snapshots. This option will fail | 78 | read-only mounts or snapshots. This option will fail |
76 | for r/w mounts on an unclean volume. | 79 | for r/w mounts on an unclean volume. |
77 | discard Issue discard/TRIM commands to the underlying block | 80 | discard This enables/disables the use of discard/TRIM commands. |
78 | device when blocks are freed. This is useful for SSD | 81 | nodiscard(*) The discard/TRIM commands are sent to the underlying |
79 | devices and sparse/thinly-provisioned LUNs. | 82 | block device when blocks are freed. This is useful |
83 | for SSD devices and sparse/thinly-provisioned LUNs. | ||
80 | 84 | ||
81 | NILFS2 usage | 85 | NILFS2 usage |
82 | ============ | 86 | ============ |
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index effdbdbe6c11..3dbdc1d356bf 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "nilfs.h" | 26 | #include "nilfs.h" |
27 | #include "bmap.h" | 27 | #include "bmap.h" |
28 | #include "sb.h" | 28 | #include "sb.h" |
29 | #include "btree.h" | ||
30 | #include "direct.h" | ||
29 | #include "btnode.h" | 31 | #include "btnode.h" |
30 | #include "mdt.h" | 32 | #include "mdt.h" |
31 | #include "dat.h" | 33 | #include "dat.h" |
@@ -533,7 +535,7 @@ void nilfs_bmap_init_gc(struct nilfs_bmap *bmap) | |||
533 | 535 | ||
534 | void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | 536 | void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) |
535 | { | 537 | { |
536 | memcpy(gcbmap, bmap, sizeof(union nilfs_bmap_union)); | 538 | memcpy(gcbmap, bmap, sizeof(*bmap)); |
537 | init_rwsem(&gcbmap->b_sem); | 539 | init_rwsem(&gcbmap->b_sem); |
538 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); | 540 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); |
539 | gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; | 541 | gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; |
@@ -541,7 +543,7 @@ void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | |||
541 | 543 | ||
542 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | 544 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) |
543 | { | 545 | { |
544 | memcpy(bmap, gcbmap, sizeof(union nilfs_bmap_union)); | 546 | memcpy(bmap, gcbmap, sizeof(*bmap)); |
545 | init_rwsem(&bmap->b_sem); | 547 | init_rwsem(&bmap->b_sem); |
546 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); | 548 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); |
547 | bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; | 549 | bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; |
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index 9980d7dbab91..a20569b19929 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h | |||
@@ -32,11 +32,6 @@ | |||
32 | 32 | ||
33 | #define NILFS_BMAP_INVALID_PTR 0 | 33 | #define NILFS_BMAP_INVALID_PTR 0 |
34 | 34 | ||
35 | #define nilfs_bmap_dkey_to_key(dkey) le64_to_cpu(dkey) | ||
36 | #define nilfs_bmap_key_to_dkey(key) cpu_to_le64(key) | ||
37 | #define nilfs_bmap_dptr_to_ptr(dptr) le64_to_cpu(dptr) | ||
38 | #define nilfs_bmap_ptr_to_dptr(ptr) cpu_to_le64(ptr) | ||
39 | |||
40 | #define nilfs_bmap_keydiff_abs(diff) ((diff) < 0 ? -(diff) : (diff)) | 35 | #define nilfs_bmap_keydiff_abs(diff) ((diff) < 0 ? -(diff) : (diff)) |
41 | 36 | ||
42 | 37 | ||
@@ -71,7 +66,7 @@ struct nilfs_bmap_operations { | |||
71 | int (*bop_delete)(struct nilfs_bmap *, __u64); | 66 | int (*bop_delete)(struct nilfs_bmap *, __u64); |
72 | void (*bop_clear)(struct nilfs_bmap *); | 67 | void (*bop_clear)(struct nilfs_bmap *); |
73 | 68 | ||
74 | int (*bop_propagate)(const struct nilfs_bmap *, struct buffer_head *); | 69 | int (*bop_propagate)(struct nilfs_bmap *, struct buffer_head *); |
75 | void (*bop_lookup_dirty_buffers)(struct nilfs_bmap *, | 70 | void (*bop_lookup_dirty_buffers)(struct nilfs_bmap *, |
76 | struct list_head *); | 71 | struct list_head *); |
77 | 72 | ||
@@ -110,6 +105,7 @@ static inline int nilfs_bmap_is_new_ptr(unsigned long ptr) | |||
110 | * @b_last_allocated_ptr: last allocated ptr for data block | 105 | * @b_last_allocated_ptr: last allocated ptr for data block |
111 | * @b_ptr_type: pointer type | 106 | * @b_ptr_type: pointer type |
112 | * @b_state: state | 107 | * @b_state: state |
108 | * @b_nchildren_per_block: maximum number of child nodes for non-root nodes | ||
113 | */ | 109 | */ |
114 | struct nilfs_bmap { | 110 | struct nilfs_bmap { |
115 | union { | 111 | union { |
@@ -123,6 +119,7 @@ struct nilfs_bmap { | |||
123 | __u64 b_last_allocated_ptr; | 119 | __u64 b_last_allocated_ptr; |
124 | int b_ptr_type; | 120 | int b_ptr_type; |
125 | int b_state; | 121 | int b_state; |
122 | __u16 b_nchildren_per_block; | ||
126 | }; | 123 | }; |
127 | 124 | ||
128 | /* pointer type */ | 125 | /* pointer type */ |
@@ -224,6 +221,13 @@ static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap, | |||
224 | nilfs_dat_abort_end(dat, &req->bpr_req); | 221 | nilfs_dat_abort_end(dat, &req->bpr_req); |
225 | } | 222 | } |
226 | 223 | ||
224 | static inline void nilfs_bmap_set_target_v(struct nilfs_bmap *bmap, __u64 key, | ||
225 | __u64 ptr) | ||
226 | { | ||
227 | bmap->b_last_allocated_key = key; | ||
228 | bmap->b_last_allocated_ptr = ptr; | ||
229 | } | ||
230 | |||
227 | __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, | 231 | __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, |
228 | const struct buffer_head *); | 232 | const struct buffer_head *); |
229 | 233 | ||
diff --git a/fs/nilfs2/bmap_union.h b/fs/nilfs2/bmap_union.h deleted file mode 100644 index d41509bff47b..000000000000 --- a/fs/nilfs2/bmap_union.h +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * bmap_union.h - NILFS block mapping. | ||
3 | * | ||
4 | * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | * | ||
20 | * Written by Koji Sato <koji@osrg.net>. | ||
21 | */ | ||
22 | |||
23 | #ifndef _NILFS_BMAP_UNION_H | ||
24 | #define _NILFS_BMAP_UNION_H | ||
25 | |||
26 | #include "bmap.h" | ||
27 | #include "direct.h" | ||
28 | #include "btree.h" | ||
29 | |||
30 | /** | ||
31 | * nilfs_bmap_union - | ||
32 | * @bi_bmap: bmap structure | ||
33 | * @bi_btree: direct map structure | ||
34 | * @bi_direct: B-tree structure | ||
35 | */ | ||
36 | union nilfs_bmap_union { | ||
37 | struct nilfs_bmap bi_bmap; | ||
38 | struct nilfs_direct bi_direct; | ||
39 | struct nilfs_btree bi_btree; | ||
40 | }; | ||
41 | |||
42 | #endif /* _NILFS_BMAP_UNION_H */ | ||
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 447ce47a3306..f78ab1044d1d 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c | |||
@@ -96,10 +96,12 @@ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr) | |||
96 | } | 96 | } |
97 | 97 | ||
98 | int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | 98 | int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, |
99 | sector_t pblocknr, struct buffer_head **pbh) | 99 | sector_t pblocknr, int mode, |
100 | struct buffer_head **pbh, sector_t *submit_ptr) | ||
100 | { | 101 | { |
101 | struct buffer_head *bh; | 102 | struct buffer_head *bh; |
102 | struct inode *inode = NILFS_BTNC_I(btnc); | 103 | struct inode *inode = NILFS_BTNC_I(btnc); |
104 | struct page *page; | ||
103 | int err; | 105 | int err; |
104 | 106 | ||
105 | bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node); | 107 | bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node); |
@@ -107,6 +109,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | |||
107 | return -ENOMEM; | 109 | return -ENOMEM; |
108 | 110 | ||
109 | err = -EEXIST; /* internal code */ | 111 | err = -EEXIST; /* internal code */ |
112 | page = bh->b_page; | ||
110 | 113 | ||
111 | if (buffer_uptodate(bh) || buffer_dirty(bh)) | 114 | if (buffer_uptodate(bh) || buffer_dirty(bh)) |
112 | goto found; | 115 | goto found; |
@@ -125,7 +128,16 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | |||
125 | } | 128 | } |
126 | } | 129 | } |
127 | } | 130 | } |
128 | lock_buffer(bh); | 131 | |
132 | if (mode == READA) { | ||
133 | if (pblocknr != *submit_ptr + 1 || !trylock_buffer(bh)) { | ||
134 | err = -EBUSY; /* internal code */ | ||
135 | brelse(bh); | ||
136 | goto out_locked; | ||
137 | } | ||
138 | } else { /* mode == READ */ | ||
139 | lock_buffer(bh); | ||
140 | } | ||
129 | if (buffer_uptodate(bh)) { | 141 | if (buffer_uptodate(bh)) { |
130 | unlock_buffer(bh); | 142 | unlock_buffer(bh); |
131 | err = -EEXIST; /* internal code */ | 143 | err = -EEXIST; /* internal code */ |
@@ -136,15 +148,16 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | |||
136 | bh->b_blocknr = pblocknr; /* set block address for read */ | 148 | bh->b_blocknr = pblocknr; /* set block address for read */ |
137 | bh->b_end_io = end_buffer_read_sync; | 149 | bh->b_end_io = end_buffer_read_sync; |
138 | get_bh(bh); | 150 | get_bh(bh); |
139 | submit_bh(READ, bh); | 151 | submit_bh(mode, bh); |
140 | bh->b_blocknr = blocknr; /* set back to the given block address */ | 152 | bh->b_blocknr = blocknr; /* set back to the given block address */ |
153 | *submit_ptr = pblocknr; | ||
141 | err = 0; | 154 | err = 0; |
142 | found: | 155 | found: |
143 | *pbh = bh; | 156 | *pbh = bh; |
144 | 157 | ||
145 | out_locked: | 158 | out_locked: |
146 | unlock_page(bh->b_page); | 159 | unlock_page(page); |
147 | page_cache_release(bh->b_page); | 160 | page_cache_release(page); |
148 | return err; | 161 | return err; |
149 | } | 162 | } |
150 | 163 | ||
diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h index 07da83f07712..79037494f1e0 100644 --- a/fs/nilfs2/btnode.h +++ b/fs/nilfs2/btnode.h | |||
@@ -42,8 +42,8 @@ void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *); | |||
42 | void nilfs_btnode_cache_clear(struct address_space *); | 42 | void nilfs_btnode_cache_clear(struct address_space *); |
43 | struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, | 43 | struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, |
44 | __u64 blocknr); | 44 | __u64 blocknr); |
45 | int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t, | 45 | int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t, int, |
46 | struct buffer_head **); | 46 | struct buffer_head **, sector_t *); |
47 | void nilfs_btnode_delete(struct buffer_head *); | 47 | void nilfs_btnode_delete(struct buffer_head *); |
48 | int nilfs_btnode_prepare_change_key(struct address_space *, | 48 | int nilfs_btnode_prepare_change_key(struct address_space *, |
49 | struct nilfs_btnode_chkey_ctxt *); | 49 | struct nilfs_btnode_chkey_ctxt *); |
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index b27a342c5af6..300c2bc00c3f 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
@@ -66,30 +66,10 @@ static void nilfs_btree_free_path(struct nilfs_btree_path *path) | |||
66 | /* | 66 | /* |
67 | * B-tree node operations | 67 | * B-tree node operations |
68 | */ | 68 | */ |
69 | static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr, | 69 | static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree, |
70 | struct buffer_head **bhp) | ||
71 | { | ||
72 | struct address_space *btnc = | ||
73 | &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache; | ||
74 | int err; | ||
75 | |||
76 | err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp); | ||
77 | if (err) | ||
78 | return err == -EEXIST ? 0 : err; | ||
79 | |||
80 | wait_on_buffer(*bhp); | ||
81 | if (!buffer_uptodate(*bhp)) { | ||
82 | brelse(*bhp); | ||
83 | return -EIO; | ||
84 | } | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, | ||
89 | __u64 ptr, struct buffer_head **bhp) | 70 | __u64 ptr, struct buffer_head **bhp) |
90 | { | 71 | { |
91 | struct address_space *btnc = | 72 | struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache; |
92 | &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache; | ||
93 | struct buffer_head *bh; | 73 | struct buffer_head *bh; |
94 | 74 | ||
95 | bh = nilfs_btnode_create_block(btnc, ptr); | 75 | bh = nilfs_btnode_create_block(btnc, ptr); |
@@ -101,71 +81,55 @@ static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, | |||
101 | return 0; | 81 | return 0; |
102 | } | 82 | } |
103 | 83 | ||
104 | static inline int | 84 | static int nilfs_btree_node_get_flags(const struct nilfs_btree_node *node) |
105 | nilfs_btree_node_get_flags(const struct nilfs_btree_node *node) | ||
106 | { | 85 | { |
107 | return node->bn_flags; | 86 | return node->bn_flags; |
108 | } | 87 | } |
109 | 88 | ||
110 | static inline void | 89 | static void |
111 | nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags) | 90 | nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags) |
112 | { | 91 | { |
113 | node->bn_flags = flags; | 92 | node->bn_flags = flags; |
114 | } | 93 | } |
115 | 94 | ||
116 | static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node) | 95 | static int nilfs_btree_node_root(const struct nilfs_btree_node *node) |
117 | { | 96 | { |
118 | return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT; | 97 | return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT; |
119 | } | 98 | } |
120 | 99 | ||
121 | static inline int | 100 | static int nilfs_btree_node_get_level(const struct nilfs_btree_node *node) |
122 | nilfs_btree_node_get_level(const struct nilfs_btree_node *node) | ||
123 | { | 101 | { |
124 | return node->bn_level; | 102 | return node->bn_level; |
125 | } | 103 | } |
126 | 104 | ||
127 | static inline void | 105 | static void |
128 | nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level) | 106 | nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level) |
129 | { | 107 | { |
130 | node->bn_level = level; | 108 | node->bn_level = level; |
131 | } | 109 | } |
132 | 110 | ||
133 | static inline int | 111 | static int nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node) |
134 | nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node) | ||
135 | { | 112 | { |
136 | return le16_to_cpu(node->bn_nchildren); | 113 | return le16_to_cpu(node->bn_nchildren); |
137 | } | 114 | } |
138 | 115 | ||
139 | static inline void | 116 | static void |
140 | nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren) | 117 | nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren) |
141 | { | 118 | { |
142 | node->bn_nchildren = cpu_to_le16(nchildren); | 119 | node->bn_nchildren = cpu_to_le16(nchildren); |
143 | } | 120 | } |
144 | 121 | ||
145 | static inline int nilfs_btree_node_size(const struct nilfs_btree *btree) | 122 | static int nilfs_btree_node_size(const struct nilfs_bmap *btree) |
146 | { | 123 | { |
147 | return 1 << btree->bt_bmap.b_inode->i_blkbits; | 124 | return 1 << btree->b_inode->i_blkbits; |
148 | } | 125 | } |
149 | 126 | ||
150 | static inline int | 127 | static int nilfs_btree_nchildren_per_block(const struct nilfs_bmap *btree) |
151 | nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node, | ||
152 | const struct nilfs_btree *btree) | ||
153 | { | 128 | { |
154 | return nilfs_btree_node_root(node) ? | 129 | return btree->b_nchildren_per_block; |
155 | NILFS_BTREE_ROOT_NCHILDREN_MIN : | ||
156 | NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); | ||
157 | } | 130 | } |
158 | 131 | ||
159 | static inline int | 132 | static __le64 * |
160 | nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node, | ||
161 | const struct nilfs_btree *btree) | ||
162 | { | ||
163 | return nilfs_btree_node_root(node) ? | ||
164 | NILFS_BTREE_ROOT_NCHILDREN_MAX : | ||
165 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree)); | ||
166 | } | ||
167 | |||
168 | static inline __le64 * | ||
169 | nilfs_btree_node_dkeys(const struct nilfs_btree_node *node) | 133 | nilfs_btree_node_dkeys(const struct nilfs_btree_node *node) |
170 | { | 134 | { |
171 | return (__le64 *)((char *)(node + 1) + | 135 | return (__le64 *)((char *)(node + 1) + |
@@ -173,45 +137,40 @@ nilfs_btree_node_dkeys(const struct nilfs_btree_node *node) | |||
173 | 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); | 137 | 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); |
174 | } | 138 | } |
175 | 139 | ||
176 | static inline __le64 * | 140 | static __le64 * |
177 | nilfs_btree_node_dptrs(const struct nilfs_btree_node *node, | 141 | nilfs_btree_node_dptrs(const struct nilfs_btree_node *node, int ncmax) |
178 | const struct nilfs_btree *btree) | ||
179 | { | 142 | { |
180 | return (__le64 *)(nilfs_btree_node_dkeys(node) + | 143 | return (__le64 *)(nilfs_btree_node_dkeys(node) + ncmax); |
181 | nilfs_btree_node_nchildren_max(node, btree)); | ||
182 | } | 144 | } |
183 | 145 | ||
184 | static inline __u64 | 146 | static __u64 |
185 | nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index) | 147 | nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index) |
186 | { | 148 | { |
187 | return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index)); | 149 | return le64_to_cpu(*(nilfs_btree_node_dkeys(node) + index)); |
188 | } | 150 | } |
189 | 151 | ||
190 | static inline void | 152 | static void |
191 | nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key) | 153 | nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key) |
192 | { | 154 | { |
193 | *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key); | 155 | *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(key); |
194 | } | 156 | } |
195 | 157 | ||
196 | static inline __u64 | 158 | static __u64 |
197 | nilfs_btree_node_get_ptr(const struct nilfs_btree *btree, | 159 | nilfs_btree_node_get_ptr(const struct nilfs_btree_node *node, int index, |
198 | const struct nilfs_btree_node *node, int index) | 160 | int ncmax) |
199 | { | 161 | { |
200 | return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) + | 162 | return le64_to_cpu(*(nilfs_btree_node_dptrs(node, ncmax) + index)); |
201 | index)); | ||
202 | } | 163 | } |
203 | 164 | ||
204 | static inline void | 165 | static void |
205 | nilfs_btree_node_set_ptr(struct nilfs_btree *btree, | 166 | nilfs_btree_node_set_ptr(struct nilfs_btree_node *node, int index, __u64 ptr, |
206 | struct nilfs_btree_node *node, int index, __u64 ptr) | 167 | int ncmax) |
207 | { | 168 | { |
208 | *(nilfs_btree_node_dptrs(node, btree) + index) = | 169 | *(nilfs_btree_node_dptrs(node, ncmax) + index) = cpu_to_le64(ptr); |
209 | nilfs_bmap_ptr_to_dptr(ptr); | ||
210 | } | 170 | } |
211 | 171 | ||
212 | static void nilfs_btree_node_init(struct nilfs_btree *btree, | 172 | static void nilfs_btree_node_init(struct nilfs_btree_node *node, int flags, |
213 | struct nilfs_btree_node *node, | 173 | int level, int nchildren, int ncmax, |
214 | int flags, int level, int nchildren, | ||
215 | const __u64 *keys, const __u64 *ptrs) | 174 | const __u64 *keys, const __u64 *ptrs) |
216 | { | 175 | { |
217 | __le64 *dkeys; | 176 | __le64 *dkeys; |
@@ -223,29 +182,28 @@ static void nilfs_btree_node_init(struct nilfs_btree *btree, | |||
223 | nilfs_btree_node_set_nchildren(node, nchildren); | 182 | nilfs_btree_node_set_nchildren(node, nchildren); |
224 | 183 | ||
225 | dkeys = nilfs_btree_node_dkeys(node); | 184 | dkeys = nilfs_btree_node_dkeys(node); |
226 | dptrs = nilfs_btree_node_dptrs(node, btree); | 185 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
227 | for (i = 0; i < nchildren; i++) { | 186 | for (i = 0; i < nchildren; i++) { |
228 | dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]); | 187 | dkeys[i] = cpu_to_le64(keys[i]); |
229 | dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]); | 188 | dptrs[i] = cpu_to_le64(ptrs[i]); |
230 | } | 189 | } |
231 | } | 190 | } |
232 | 191 | ||
233 | /* Assume the buffer heads corresponding to left and right are locked. */ | 192 | /* Assume the buffer heads corresponding to left and right are locked. */ |
234 | static void nilfs_btree_node_move_left(struct nilfs_btree *btree, | 193 | static void nilfs_btree_node_move_left(struct nilfs_btree_node *left, |
235 | struct nilfs_btree_node *left, | ||
236 | struct nilfs_btree_node *right, | 194 | struct nilfs_btree_node *right, |
237 | int n) | 195 | int n, int lncmax, int rncmax) |
238 | { | 196 | { |
239 | __le64 *ldkeys, *rdkeys; | 197 | __le64 *ldkeys, *rdkeys; |
240 | __le64 *ldptrs, *rdptrs; | 198 | __le64 *ldptrs, *rdptrs; |
241 | int lnchildren, rnchildren; | 199 | int lnchildren, rnchildren; |
242 | 200 | ||
243 | ldkeys = nilfs_btree_node_dkeys(left); | 201 | ldkeys = nilfs_btree_node_dkeys(left); |
244 | ldptrs = nilfs_btree_node_dptrs(left, btree); | 202 | ldptrs = nilfs_btree_node_dptrs(left, lncmax); |
245 | lnchildren = nilfs_btree_node_get_nchildren(left); | 203 | lnchildren = nilfs_btree_node_get_nchildren(left); |
246 | 204 | ||
247 | rdkeys = nilfs_btree_node_dkeys(right); | 205 | rdkeys = nilfs_btree_node_dkeys(right); |
248 | rdptrs = nilfs_btree_node_dptrs(right, btree); | 206 | rdptrs = nilfs_btree_node_dptrs(right, rncmax); |
249 | rnchildren = nilfs_btree_node_get_nchildren(right); | 207 | rnchildren = nilfs_btree_node_get_nchildren(right); |
250 | 208 | ||
251 | memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys)); | 209 | memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys)); |
@@ -260,21 +218,20 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree, | |||
260 | } | 218 | } |
261 | 219 | ||
262 | /* Assume that the buffer heads corresponding to left and right are locked. */ | 220 | /* Assume that the buffer heads corresponding to left and right are locked. */ |
263 | static void nilfs_btree_node_move_right(struct nilfs_btree *btree, | 221 | static void nilfs_btree_node_move_right(struct nilfs_btree_node *left, |
264 | struct nilfs_btree_node *left, | ||
265 | struct nilfs_btree_node *right, | 222 | struct nilfs_btree_node *right, |
266 | int n) | 223 | int n, int lncmax, int rncmax) |
267 | { | 224 | { |
268 | __le64 *ldkeys, *rdkeys; | 225 | __le64 *ldkeys, *rdkeys; |
269 | __le64 *ldptrs, *rdptrs; | 226 | __le64 *ldptrs, *rdptrs; |
270 | int lnchildren, rnchildren; | 227 | int lnchildren, rnchildren; |
271 | 228 | ||
272 | ldkeys = nilfs_btree_node_dkeys(left); | 229 | ldkeys = nilfs_btree_node_dkeys(left); |
273 | ldptrs = nilfs_btree_node_dptrs(left, btree); | 230 | ldptrs = nilfs_btree_node_dptrs(left, lncmax); |
274 | lnchildren = nilfs_btree_node_get_nchildren(left); | 231 | lnchildren = nilfs_btree_node_get_nchildren(left); |
275 | 232 | ||
276 | rdkeys = nilfs_btree_node_dkeys(right); | 233 | rdkeys = nilfs_btree_node_dkeys(right); |
277 | rdptrs = nilfs_btree_node_dptrs(right, btree); | 234 | rdptrs = nilfs_btree_node_dptrs(right, rncmax); |
278 | rnchildren = nilfs_btree_node_get_nchildren(right); | 235 | rnchildren = nilfs_btree_node_get_nchildren(right); |
279 | 236 | ||
280 | memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys)); | 237 | memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys)); |
@@ -289,16 +246,15 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree, | |||
289 | } | 246 | } |
290 | 247 | ||
291 | /* Assume that the buffer head corresponding to node is locked. */ | 248 | /* Assume that the buffer head corresponding to node is locked. */ |
292 | static void nilfs_btree_node_insert(struct nilfs_btree *btree, | 249 | static void nilfs_btree_node_insert(struct nilfs_btree_node *node, int index, |
293 | struct nilfs_btree_node *node, | 250 | __u64 key, __u64 ptr, int ncmax) |
294 | __u64 key, __u64 ptr, int index) | ||
295 | { | 251 | { |
296 | __le64 *dkeys; | 252 | __le64 *dkeys; |
297 | __le64 *dptrs; | 253 | __le64 *dptrs; |
298 | int nchildren; | 254 | int nchildren; |
299 | 255 | ||
300 | dkeys = nilfs_btree_node_dkeys(node); | 256 | dkeys = nilfs_btree_node_dkeys(node); |
301 | dptrs = nilfs_btree_node_dptrs(node, btree); | 257 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
302 | nchildren = nilfs_btree_node_get_nchildren(node); | 258 | nchildren = nilfs_btree_node_get_nchildren(node); |
303 | if (index < nchildren) { | 259 | if (index < nchildren) { |
304 | memmove(dkeys + index + 1, dkeys + index, | 260 | memmove(dkeys + index + 1, dkeys + index, |
@@ -306,16 +262,15 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree, | |||
306 | memmove(dptrs + index + 1, dptrs + index, | 262 | memmove(dptrs + index + 1, dptrs + index, |
307 | (nchildren - index) * sizeof(*dptrs)); | 263 | (nchildren - index) * sizeof(*dptrs)); |
308 | } | 264 | } |
309 | dkeys[index] = nilfs_bmap_key_to_dkey(key); | 265 | dkeys[index] = cpu_to_le64(key); |
310 | dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr); | 266 | dptrs[index] = cpu_to_le64(ptr); |
311 | nchildren++; | 267 | nchildren++; |
312 | nilfs_btree_node_set_nchildren(node, nchildren); | 268 | nilfs_btree_node_set_nchildren(node, nchildren); |
313 | } | 269 | } |
314 | 270 | ||
315 | /* Assume that the buffer head corresponding to node is locked. */ | 271 | /* Assume that the buffer head corresponding to node is locked. */ |
316 | static void nilfs_btree_node_delete(struct nilfs_btree *btree, | 272 | static void nilfs_btree_node_delete(struct nilfs_btree_node *node, int index, |
317 | struct nilfs_btree_node *node, | 273 | __u64 *keyp, __u64 *ptrp, int ncmax) |
318 | __u64 *keyp, __u64 *ptrp, int index) | ||
319 | { | 274 | { |
320 | __u64 key; | 275 | __u64 key; |
321 | __u64 ptr; | 276 | __u64 ptr; |
@@ -324,9 +279,9 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree, | |||
324 | int nchildren; | 279 | int nchildren; |
325 | 280 | ||
326 | dkeys = nilfs_btree_node_dkeys(node); | 281 | dkeys = nilfs_btree_node_dkeys(node); |
327 | dptrs = nilfs_btree_node_dptrs(node, btree); | 282 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
328 | key = nilfs_bmap_dkey_to_key(dkeys[index]); | 283 | key = le64_to_cpu(dkeys[index]); |
329 | ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]); | 284 | ptr = le64_to_cpu(dptrs[index]); |
330 | nchildren = nilfs_btree_node_get_nchildren(node); | 285 | nchildren = nilfs_btree_node_get_nchildren(node); |
331 | if (keyp != NULL) | 286 | if (keyp != NULL) |
332 | *keyp = key; | 287 | *keyp = key; |
@@ -382,40 +337,92 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node, | |||
382 | return s == 0; | 337 | return s == 0; |
383 | } | 338 | } |
384 | 339 | ||
385 | static inline struct nilfs_btree_node * | 340 | /** |
386 | nilfs_btree_get_root(const struct nilfs_btree *btree) | 341 | * nilfs_btree_node_broken - verify consistency of btree node |
342 | * @node: btree node block to be examined | ||
343 | * @size: node size (in bytes) | ||
344 | * @blocknr: block number | ||
345 | * | ||
346 | * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned. | ||
347 | */ | ||
348 | static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, | ||
349 | size_t size, sector_t blocknr) | ||
387 | { | 350 | { |
388 | return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data; | 351 | int level, flags, nchildren; |
352 | int ret = 0; | ||
353 | |||
354 | level = nilfs_btree_node_get_level(node); | ||
355 | flags = nilfs_btree_node_get_flags(node); | ||
356 | nchildren = nilfs_btree_node_get_nchildren(node); | ||
357 | |||
358 | if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || | ||
359 | level >= NILFS_BTREE_LEVEL_MAX || | ||
360 | (flags & NILFS_BTREE_NODE_ROOT) || | ||
361 | nchildren < 0 || | ||
362 | nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) { | ||
363 | printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): " | ||
364 | "level = %d, flags = 0x%x, nchildren = %d\n", | ||
365 | (unsigned long long)blocknr, level, flags, nchildren); | ||
366 | ret = 1; | ||
367 | } | ||
368 | return ret; | ||
389 | } | 369 | } |
390 | 370 | ||
391 | static inline struct nilfs_btree_node * | 371 | int nilfs_btree_broken_node_block(struct buffer_head *bh) |
372 | { | ||
373 | int ret; | ||
374 | |||
375 | if (buffer_nilfs_checked(bh)) | ||
376 | return 0; | ||
377 | |||
378 | ret = nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data, | ||
379 | bh->b_size, bh->b_blocknr); | ||
380 | if (likely(!ret)) | ||
381 | set_buffer_nilfs_checked(bh); | ||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | static struct nilfs_btree_node * | ||
386 | nilfs_btree_get_root(const struct nilfs_bmap *btree) | ||
387 | { | ||
388 | return (struct nilfs_btree_node *)btree->b_u.u_data; | ||
389 | } | ||
390 | |||
391 | static struct nilfs_btree_node * | ||
392 | nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level) | 392 | nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level) |
393 | { | 393 | { |
394 | return (struct nilfs_btree_node *)path[level].bp_bh->b_data; | 394 | return (struct nilfs_btree_node *)path[level].bp_bh->b_data; |
395 | } | 395 | } |
396 | 396 | ||
397 | static inline struct nilfs_btree_node * | 397 | static struct nilfs_btree_node * |
398 | nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level) | 398 | nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level) |
399 | { | 399 | { |
400 | return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data; | 400 | return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data; |
401 | } | 401 | } |
402 | 402 | ||
403 | static inline int nilfs_btree_height(const struct nilfs_btree *btree) | 403 | static int nilfs_btree_height(const struct nilfs_bmap *btree) |
404 | { | 404 | { |
405 | return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1; | 405 | return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1; |
406 | } | 406 | } |
407 | 407 | ||
408 | static inline struct nilfs_btree_node * | 408 | static struct nilfs_btree_node * |
409 | nilfs_btree_get_node(const struct nilfs_btree *btree, | 409 | nilfs_btree_get_node(const struct nilfs_bmap *btree, |
410 | const struct nilfs_btree_path *path, | 410 | const struct nilfs_btree_path *path, |
411 | int level) | 411 | int level, int *ncmaxp) |
412 | { | 412 | { |
413 | return (level == nilfs_btree_height(btree) - 1) ? | 413 | struct nilfs_btree_node *node; |
414 | nilfs_btree_get_root(btree) : | 414 | |
415 | nilfs_btree_get_nonroot_node(path, level); | 415 | if (level == nilfs_btree_height(btree) - 1) { |
416 | node = nilfs_btree_get_root(btree); | ||
417 | *ncmaxp = NILFS_BTREE_ROOT_NCHILDREN_MAX; | ||
418 | } else { | ||
419 | node = nilfs_btree_get_nonroot_node(path, level); | ||
420 | *ncmaxp = nilfs_btree_nchildren_per_block(btree); | ||
421 | } | ||
422 | return node; | ||
416 | } | 423 | } |
417 | 424 | ||
418 | static inline int | 425 | static int |
419 | nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) | 426 | nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) |
420 | { | 427 | { |
421 | if (unlikely(nilfs_btree_node_get_level(node) != level)) { | 428 | if (unlikely(nilfs_btree_node_get_level(node) != level)) { |
@@ -427,13 +434,83 @@ nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) | |||
427 | return 0; | 434 | return 0; |
428 | } | 435 | } |
429 | 436 | ||
430 | static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | 437 | struct nilfs_btree_readahead_info { |
438 | struct nilfs_btree_node *node; /* parent node */ | ||
439 | int max_ra_blocks; /* max nof blocks to read ahead */ | ||
440 | int index; /* current index on the parent node */ | ||
441 | int ncmax; /* nof children in the parent node */ | ||
442 | }; | ||
443 | |||
444 | static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, | ||
445 | struct buffer_head **bhp, | ||
446 | const struct nilfs_btree_readahead_info *ra) | ||
447 | { | ||
448 | struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache; | ||
449 | struct buffer_head *bh, *ra_bh; | ||
450 | sector_t submit_ptr = 0; | ||
451 | int ret; | ||
452 | |||
453 | ret = nilfs_btnode_submit_block(btnc, ptr, 0, READ, &bh, &submit_ptr); | ||
454 | if (ret) { | ||
455 | if (ret != -EEXIST) | ||
456 | return ret; | ||
457 | goto out_check; | ||
458 | } | ||
459 | |||
460 | if (ra) { | ||
461 | int i, n; | ||
462 | __u64 ptr2; | ||
463 | |||
464 | /* read ahead sibling nodes */ | ||
465 | for (n = ra->max_ra_blocks, i = ra->index + 1; | ||
466 | n > 0 && i < ra->ncmax; n--, i++) { | ||
467 | ptr2 = nilfs_btree_node_get_ptr(ra->node, i, ra->ncmax); | ||
468 | |||
469 | ret = nilfs_btnode_submit_block(btnc, ptr2, 0, READA, | ||
470 | &ra_bh, &submit_ptr); | ||
471 | if (likely(!ret || ret == -EEXIST)) | ||
472 | brelse(ra_bh); | ||
473 | else if (ret != -EBUSY) | ||
474 | break; | ||
475 | if (!buffer_locked(bh)) | ||
476 | goto out_no_wait; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | wait_on_buffer(bh); | ||
481 | |||
482 | out_no_wait: | ||
483 | if (!buffer_uptodate(bh)) { | ||
484 | brelse(bh); | ||
485 | return -EIO; | ||
486 | } | ||
487 | |||
488 | out_check: | ||
489 | if (nilfs_btree_broken_node_block(bh)) { | ||
490 | clear_buffer_uptodate(bh); | ||
491 | brelse(bh); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | *bhp = bh; | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, | ||
500 | struct buffer_head **bhp) | ||
501 | { | ||
502 | return __nilfs_btree_get_block(btree, ptr, bhp, NULL); | ||
503 | } | ||
504 | |||
505 | static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree, | ||
431 | struct nilfs_btree_path *path, | 506 | struct nilfs_btree_path *path, |
432 | __u64 key, __u64 *ptrp, int minlevel) | 507 | __u64 key, __u64 *ptrp, int minlevel, |
508 | int readahead) | ||
433 | { | 509 | { |
434 | struct nilfs_btree_node *node; | 510 | struct nilfs_btree_node *node; |
511 | struct nilfs_btree_readahead_info p, *ra; | ||
435 | __u64 ptr; | 512 | __u64 ptr; |
436 | int level, index, found, ret; | 513 | int level, index, found, ncmax, ret; |
437 | 514 | ||
438 | node = nilfs_btree_get_root(btree); | 515 | node = nilfs_btree_get_root(btree); |
439 | level = nilfs_btree_node_get_level(node); | 516 | level = nilfs_btree_node_get_level(node); |
@@ -441,14 +518,27 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
441 | return -ENOENT; | 518 | return -ENOENT; |
442 | 519 | ||
443 | found = nilfs_btree_node_lookup(node, key, &index); | 520 | found = nilfs_btree_node_lookup(node, key, &index); |
444 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 521 | ptr = nilfs_btree_node_get_ptr(node, index, |
522 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
445 | path[level].bp_bh = NULL; | 523 | path[level].bp_bh = NULL; |
446 | path[level].bp_index = index; | 524 | path[level].bp_index = index; |
447 | 525 | ||
448 | for (level--; level >= minlevel; level--) { | 526 | ncmax = nilfs_btree_nchildren_per_block(btree); |
449 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); | 527 | |
528 | while (--level >= minlevel) { | ||
529 | ra = NULL; | ||
530 | if (level == NILFS_BTREE_LEVEL_NODE_MIN && readahead) { | ||
531 | p.node = nilfs_btree_get_node(btree, path, level + 1, | ||
532 | &p.ncmax); | ||
533 | p.index = index; | ||
534 | p.max_ra_blocks = 7; | ||
535 | ra = &p; | ||
536 | } | ||
537 | ret = __nilfs_btree_get_block(btree, ptr, &path[level].bp_bh, | ||
538 | ra); | ||
450 | if (ret < 0) | 539 | if (ret < 0) |
451 | return ret; | 540 | return ret; |
541 | |||
452 | node = nilfs_btree_get_nonroot_node(path, level); | 542 | node = nilfs_btree_get_nonroot_node(path, level); |
453 | if (nilfs_btree_bad_node(node, level)) | 543 | if (nilfs_btree_bad_node(node, level)) |
454 | return -EINVAL; | 544 | return -EINVAL; |
@@ -456,9 +546,9 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
456 | found = nilfs_btree_node_lookup(node, key, &index); | 546 | found = nilfs_btree_node_lookup(node, key, &index); |
457 | else | 547 | else |
458 | index = 0; | 548 | index = 0; |
459 | if (index < nilfs_btree_node_nchildren_max(node, btree)) | 549 | if (index < ncmax) { |
460 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 550 | ptr = nilfs_btree_node_get_ptr(node, index, ncmax); |
461 | else { | 551 | } else { |
462 | WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN); | 552 | WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN); |
463 | /* insert */ | 553 | /* insert */ |
464 | ptr = NILFS_BMAP_INVALID_PTR; | 554 | ptr = NILFS_BMAP_INVALID_PTR; |
@@ -474,22 +564,24 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
474 | return 0; | 564 | return 0; |
475 | } | 565 | } |
476 | 566 | ||
477 | static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | 567 | static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree, |
478 | struct nilfs_btree_path *path, | 568 | struct nilfs_btree_path *path, |
479 | __u64 *keyp, __u64 *ptrp) | 569 | __u64 *keyp, __u64 *ptrp) |
480 | { | 570 | { |
481 | struct nilfs_btree_node *node; | 571 | struct nilfs_btree_node *node; |
482 | __u64 ptr; | 572 | __u64 ptr; |
483 | int index, level, ret; | 573 | int index, level, ncmax, ret; |
484 | 574 | ||
485 | node = nilfs_btree_get_root(btree); | 575 | node = nilfs_btree_get_root(btree); |
486 | index = nilfs_btree_node_get_nchildren(node) - 1; | 576 | index = nilfs_btree_node_get_nchildren(node) - 1; |
487 | if (index < 0) | 577 | if (index < 0) |
488 | return -ENOENT; | 578 | return -ENOENT; |
489 | level = nilfs_btree_node_get_level(node); | 579 | level = nilfs_btree_node_get_level(node); |
490 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 580 | ptr = nilfs_btree_node_get_ptr(node, index, |
581 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
491 | path[level].bp_bh = NULL; | 582 | path[level].bp_bh = NULL; |
492 | path[level].bp_index = index; | 583 | path[level].bp_index = index; |
584 | ncmax = nilfs_btree_nchildren_per_block(btree); | ||
493 | 585 | ||
494 | for (level--; level > 0; level--) { | 586 | for (level--; level > 0; level--) { |
495 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); | 587 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); |
@@ -499,7 +591,7 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | |||
499 | if (nilfs_btree_bad_node(node, level)) | 591 | if (nilfs_btree_bad_node(node, level)) |
500 | return -EINVAL; | 592 | return -EINVAL; |
501 | index = nilfs_btree_node_get_nchildren(node) - 1; | 593 | index = nilfs_btree_node_get_nchildren(node) - 1; |
502 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 594 | ptr = nilfs_btree_node_get_ptr(node, index, ncmax); |
503 | path[level].bp_index = index; | 595 | path[level].bp_index = index; |
504 | } | 596 | } |
505 | 597 | ||
@@ -511,51 +603,45 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | |||
511 | return 0; | 603 | return 0; |
512 | } | 604 | } |
513 | 605 | ||
514 | static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, | 606 | static int nilfs_btree_lookup(const struct nilfs_bmap *btree, |
515 | __u64 key, int level, __u64 *ptrp) | 607 | __u64 key, int level, __u64 *ptrp) |
516 | { | 608 | { |
517 | struct nilfs_btree *btree; | ||
518 | struct nilfs_btree_path *path; | 609 | struct nilfs_btree_path *path; |
519 | __u64 ptr; | ||
520 | int ret; | 610 | int ret; |
521 | 611 | ||
522 | btree = (struct nilfs_btree *)bmap; | ||
523 | path = nilfs_btree_alloc_path(); | 612 | path = nilfs_btree_alloc_path(); |
524 | if (path == NULL) | 613 | if (path == NULL) |
525 | return -ENOMEM; | 614 | return -ENOMEM; |
526 | 615 | ||
527 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 616 | ret = nilfs_btree_do_lookup(btree, path, key, ptrp, level, 0); |
528 | |||
529 | if (ptrp != NULL) | ||
530 | *ptrp = ptr; | ||
531 | 617 | ||
532 | nilfs_btree_free_path(path); | 618 | nilfs_btree_free_path(path); |
533 | 619 | ||
534 | return ret; | 620 | return ret; |
535 | } | 621 | } |
536 | 622 | ||
537 | static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | 623 | static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree, |
538 | __u64 key, __u64 *ptrp, unsigned maxblocks) | 624 | __u64 key, __u64 *ptrp, unsigned maxblocks) |
539 | { | 625 | { |
540 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | ||
541 | struct nilfs_btree_path *path; | 626 | struct nilfs_btree_path *path; |
542 | struct nilfs_btree_node *node; | 627 | struct nilfs_btree_node *node; |
543 | struct inode *dat = NULL; | 628 | struct inode *dat = NULL; |
544 | __u64 ptr, ptr2; | 629 | __u64 ptr, ptr2; |
545 | sector_t blocknr; | 630 | sector_t blocknr; |
546 | int level = NILFS_BTREE_LEVEL_NODE_MIN; | 631 | int level = NILFS_BTREE_LEVEL_NODE_MIN; |
547 | int ret, cnt, index, maxlevel; | 632 | int ret, cnt, index, maxlevel, ncmax; |
633 | struct nilfs_btree_readahead_info p; | ||
548 | 634 | ||
549 | path = nilfs_btree_alloc_path(); | 635 | path = nilfs_btree_alloc_path(); |
550 | if (path == NULL) | 636 | if (path == NULL) |
551 | return -ENOMEM; | 637 | return -ENOMEM; |
552 | 638 | ||
553 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 639 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level, 1); |
554 | if (ret < 0) | 640 | if (ret < 0) |
555 | goto out; | 641 | goto out; |
556 | 642 | ||
557 | if (NILFS_BMAP_USE_VBN(bmap)) { | 643 | if (NILFS_BMAP_USE_VBN(btree)) { |
558 | dat = nilfs_bmap_get_dat(bmap); | 644 | dat = nilfs_bmap_get_dat(btree); |
559 | ret = nilfs_dat_translate(dat, ptr, &blocknr); | 645 | ret = nilfs_dat_translate(dat, ptr, &blocknr); |
560 | if (ret < 0) | 646 | if (ret < 0) |
561 | goto out; | 647 | goto out; |
@@ -566,14 +652,14 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
566 | goto end; | 652 | goto end; |
567 | 653 | ||
568 | maxlevel = nilfs_btree_height(btree) - 1; | 654 | maxlevel = nilfs_btree_height(btree) - 1; |
569 | node = nilfs_btree_get_node(btree, path, level); | 655 | node = nilfs_btree_get_node(btree, path, level, &ncmax); |
570 | index = path[level].bp_index + 1; | 656 | index = path[level].bp_index + 1; |
571 | for (;;) { | 657 | for (;;) { |
572 | while (index < nilfs_btree_node_get_nchildren(node)) { | 658 | while (index < nilfs_btree_node_get_nchildren(node)) { |
573 | if (nilfs_btree_node_get_key(node, index) != | 659 | if (nilfs_btree_node_get_key(node, index) != |
574 | key + cnt) | 660 | key + cnt) |
575 | goto end; | 661 | goto end; |
576 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | 662 | ptr2 = nilfs_btree_node_get_ptr(node, index, ncmax); |
577 | if (dat) { | 663 | if (dat) { |
578 | ret = nilfs_dat_translate(dat, ptr2, &blocknr); | 664 | ret = nilfs_dat_translate(dat, ptr2, &blocknr); |
579 | if (ret < 0) | 665 | if (ret < 0) |
@@ -589,20 +675,24 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
589 | break; | 675 | break; |
590 | 676 | ||
591 | /* look-up right sibling node */ | 677 | /* look-up right sibling node */ |
592 | node = nilfs_btree_get_node(btree, path, level + 1); | 678 | p.node = nilfs_btree_get_node(btree, path, level + 1, &p.ncmax); |
593 | index = path[level + 1].bp_index + 1; | 679 | p.index = path[level + 1].bp_index + 1; |
594 | if (index >= nilfs_btree_node_get_nchildren(node) || | 680 | p.max_ra_blocks = 7; |
595 | nilfs_btree_node_get_key(node, index) != key + cnt) | 681 | if (p.index >= nilfs_btree_node_get_nchildren(p.node) || |
682 | nilfs_btree_node_get_key(p.node, p.index) != key + cnt) | ||
596 | break; | 683 | break; |
597 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | 684 | ptr2 = nilfs_btree_node_get_ptr(p.node, p.index, p.ncmax); |
598 | path[level + 1].bp_index = index; | 685 | path[level + 1].bp_index = p.index; |
599 | 686 | ||
600 | brelse(path[level].bp_bh); | 687 | brelse(path[level].bp_bh); |
601 | path[level].bp_bh = NULL; | 688 | path[level].bp_bh = NULL; |
602 | ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh); | 689 | |
690 | ret = __nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh, | ||
691 | &p); | ||
603 | if (ret < 0) | 692 | if (ret < 0) |
604 | goto out; | 693 | goto out; |
605 | node = nilfs_btree_get_nonroot_node(path, level); | 694 | node = nilfs_btree_get_nonroot_node(path, level); |
695 | ncmax = nilfs_btree_nchildren_per_block(btree); | ||
606 | index = 0; | 696 | index = 0; |
607 | path[level].bp_index = index; | 697 | path[level].bp_index = index; |
608 | } | 698 | } |
@@ -614,7 +704,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
614 | return ret; | 704 | return ret; |
615 | } | 705 | } |
616 | 706 | ||
617 | static void nilfs_btree_promote_key(struct nilfs_btree *btree, | 707 | static void nilfs_btree_promote_key(struct nilfs_bmap *btree, |
618 | struct nilfs_btree_path *path, | 708 | struct nilfs_btree_path *path, |
619 | int level, __u64 key) | 709 | int level, __u64 key) |
620 | { | 710 | { |
@@ -636,16 +726,18 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree, | |||
636 | } | 726 | } |
637 | } | 727 | } |
638 | 728 | ||
639 | static void nilfs_btree_do_insert(struct nilfs_btree *btree, | 729 | static void nilfs_btree_do_insert(struct nilfs_bmap *btree, |
640 | struct nilfs_btree_path *path, | 730 | struct nilfs_btree_path *path, |
641 | int level, __u64 *keyp, __u64 *ptrp) | 731 | int level, __u64 *keyp, __u64 *ptrp) |
642 | { | 732 | { |
643 | struct nilfs_btree_node *node; | 733 | struct nilfs_btree_node *node; |
734 | int ncblk; | ||
644 | 735 | ||
645 | if (level < nilfs_btree_height(btree) - 1) { | 736 | if (level < nilfs_btree_height(btree) - 1) { |
646 | node = nilfs_btree_get_nonroot_node(path, level); | 737 | node = nilfs_btree_get_nonroot_node(path, level); |
647 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, | 738 | ncblk = nilfs_btree_nchildren_per_block(btree); |
648 | path[level].bp_index); | 739 | nilfs_btree_node_insert(node, path[level].bp_index, |
740 | *keyp, *ptrp, ncblk); | ||
649 | if (!buffer_dirty(path[level].bp_bh)) | 741 | if (!buffer_dirty(path[level].bp_bh)) |
650 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 742 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
651 | 743 | ||
@@ -655,22 +747,24 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree, | |||
655 | 0)); | 747 | 0)); |
656 | } else { | 748 | } else { |
657 | node = nilfs_btree_get_root(btree); | 749 | node = nilfs_btree_get_root(btree); |
658 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, | 750 | nilfs_btree_node_insert(node, path[level].bp_index, |
659 | path[level].bp_index); | 751 | *keyp, *ptrp, |
752 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
660 | } | 753 | } |
661 | } | 754 | } |
662 | 755 | ||
663 | static void nilfs_btree_carry_left(struct nilfs_btree *btree, | 756 | static void nilfs_btree_carry_left(struct nilfs_bmap *btree, |
664 | struct nilfs_btree_path *path, | 757 | struct nilfs_btree_path *path, |
665 | int level, __u64 *keyp, __u64 *ptrp) | 758 | int level, __u64 *keyp, __u64 *ptrp) |
666 | { | 759 | { |
667 | struct nilfs_btree_node *node, *left; | 760 | struct nilfs_btree_node *node, *left; |
668 | int nchildren, lnchildren, n, move; | 761 | int nchildren, lnchildren, n, move, ncblk; |
669 | 762 | ||
670 | node = nilfs_btree_get_nonroot_node(path, level); | 763 | node = nilfs_btree_get_nonroot_node(path, level); |
671 | left = nilfs_btree_get_sib_node(path, level); | 764 | left = nilfs_btree_get_sib_node(path, level); |
672 | nchildren = nilfs_btree_node_get_nchildren(node); | 765 | nchildren = nilfs_btree_node_get_nchildren(node); |
673 | lnchildren = nilfs_btree_node_get_nchildren(left); | 766 | lnchildren = nilfs_btree_node_get_nchildren(left); |
767 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
674 | move = 0; | 768 | move = 0; |
675 | 769 | ||
676 | n = (nchildren + lnchildren + 1) / 2 - lnchildren; | 770 | n = (nchildren + lnchildren + 1) / 2 - lnchildren; |
@@ -680,7 +774,7 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, | |||
680 | move = 1; | 774 | move = 1; |
681 | } | 775 | } |
682 | 776 | ||
683 | nilfs_btree_node_move_left(btree, left, node, n); | 777 | nilfs_btree_node_move_left(left, node, n, ncblk, ncblk); |
684 | 778 | ||
685 | if (!buffer_dirty(path[level].bp_bh)) | 779 | if (!buffer_dirty(path[level].bp_bh)) |
686 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 780 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -705,17 +799,18 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, | |||
705 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); | 799 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); |
706 | } | 800 | } |
707 | 801 | ||
708 | static void nilfs_btree_carry_right(struct nilfs_btree *btree, | 802 | static void nilfs_btree_carry_right(struct nilfs_bmap *btree, |
709 | struct nilfs_btree_path *path, | 803 | struct nilfs_btree_path *path, |
710 | int level, __u64 *keyp, __u64 *ptrp) | 804 | int level, __u64 *keyp, __u64 *ptrp) |
711 | { | 805 | { |
712 | struct nilfs_btree_node *node, *right; | 806 | struct nilfs_btree_node *node, *right; |
713 | int nchildren, rnchildren, n, move; | 807 | int nchildren, rnchildren, n, move, ncblk; |
714 | 808 | ||
715 | node = nilfs_btree_get_nonroot_node(path, level); | 809 | node = nilfs_btree_get_nonroot_node(path, level); |
716 | right = nilfs_btree_get_sib_node(path, level); | 810 | right = nilfs_btree_get_sib_node(path, level); |
717 | nchildren = nilfs_btree_node_get_nchildren(node); | 811 | nchildren = nilfs_btree_node_get_nchildren(node); |
718 | rnchildren = nilfs_btree_node_get_nchildren(right); | 812 | rnchildren = nilfs_btree_node_get_nchildren(right); |
813 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
719 | move = 0; | 814 | move = 0; |
720 | 815 | ||
721 | n = (nchildren + rnchildren + 1) / 2 - rnchildren; | 816 | n = (nchildren + rnchildren + 1) / 2 - rnchildren; |
@@ -725,7 +820,7 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, | |||
725 | move = 1; | 820 | move = 1; |
726 | } | 821 | } |
727 | 822 | ||
728 | nilfs_btree_node_move_right(btree, node, right, n); | 823 | nilfs_btree_node_move_right(node, right, n, ncblk, ncblk); |
729 | 824 | ||
730 | if (!buffer_dirty(path[level].bp_bh)) | 825 | if (!buffer_dirty(path[level].bp_bh)) |
731 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 826 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -751,18 +846,19 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, | |||
751 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); | 846 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); |
752 | } | 847 | } |
753 | 848 | ||
754 | static void nilfs_btree_split(struct nilfs_btree *btree, | 849 | static void nilfs_btree_split(struct nilfs_bmap *btree, |
755 | struct nilfs_btree_path *path, | 850 | struct nilfs_btree_path *path, |
756 | int level, __u64 *keyp, __u64 *ptrp) | 851 | int level, __u64 *keyp, __u64 *ptrp) |
757 | { | 852 | { |
758 | struct nilfs_btree_node *node, *right; | 853 | struct nilfs_btree_node *node, *right; |
759 | __u64 newkey; | 854 | __u64 newkey; |
760 | __u64 newptr; | 855 | __u64 newptr; |
761 | int nchildren, n, move; | 856 | int nchildren, n, move, ncblk; |
762 | 857 | ||
763 | node = nilfs_btree_get_nonroot_node(path, level); | 858 | node = nilfs_btree_get_nonroot_node(path, level); |
764 | right = nilfs_btree_get_sib_node(path, level); | 859 | right = nilfs_btree_get_sib_node(path, level); |
765 | nchildren = nilfs_btree_node_get_nchildren(node); | 860 | nchildren = nilfs_btree_node_get_nchildren(node); |
861 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
766 | move = 0; | 862 | move = 0; |
767 | 863 | ||
768 | n = (nchildren + 1) / 2; | 864 | n = (nchildren + 1) / 2; |
@@ -771,7 +867,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
771 | move = 1; | 867 | move = 1; |
772 | } | 868 | } |
773 | 869 | ||
774 | nilfs_btree_node_move_right(btree, node, right, n); | 870 | nilfs_btree_node_move_right(node, right, n, ncblk, ncblk); |
775 | 871 | ||
776 | if (!buffer_dirty(path[level].bp_bh)) | 872 | if (!buffer_dirty(path[level].bp_bh)) |
777 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 873 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -783,8 +879,8 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
783 | 879 | ||
784 | if (move) { | 880 | if (move) { |
785 | path[level].bp_index -= nilfs_btree_node_get_nchildren(node); | 881 | path[level].bp_index -= nilfs_btree_node_get_nchildren(node); |
786 | nilfs_btree_node_insert(btree, right, *keyp, *ptrp, | 882 | nilfs_btree_node_insert(right, path[level].bp_index, |
787 | path[level].bp_index); | 883 | *keyp, *ptrp, ncblk); |
788 | 884 | ||
789 | *keyp = nilfs_btree_node_get_key(right, 0); | 885 | *keyp = nilfs_btree_node_get_key(right, 0); |
790 | *ptrp = path[level].bp_newreq.bpr_ptr; | 886 | *ptrp = path[level].bp_newreq.bpr_ptr; |
@@ -805,19 +901,21 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
805 | path[level + 1].bp_index++; | 901 | path[level + 1].bp_index++; |
806 | } | 902 | } |
807 | 903 | ||
808 | static void nilfs_btree_grow(struct nilfs_btree *btree, | 904 | static void nilfs_btree_grow(struct nilfs_bmap *btree, |
809 | struct nilfs_btree_path *path, | 905 | struct nilfs_btree_path *path, |
810 | int level, __u64 *keyp, __u64 *ptrp) | 906 | int level, __u64 *keyp, __u64 *ptrp) |
811 | { | 907 | { |
812 | struct nilfs_btree_node *root, *child; | 908 | struct nilfs_btree_node *root, *child; |
813 | int n; | 909 | int n, ncblk; |
814 | 910 | ||
815 | root = nilfs_btree_get_root(btree); | 911 | root = nilfs_btree_get_root(btree); |
816 | child = nilfs_btree_get_sib_node(path, level); | 912 | child = nilfs_btree_get_sib_node(path, level); |
913 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
817 | 914 | ||
818 | n = nilfs_btree_node_get_nchildren(root); | 915 | n = nilfs_btree_node_get_nchildren(root); |
819 | 916 | ||
820 | nilfs_btree_node_move_right(btree, root, child, n); | 917 | nilfs_btree_node_move_right(root, child, n, |
918 | NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk); | ||
821 | nilfs_btree_node_set_level(root, level + 1); | 919 | nilfs_btree_node_set_level(root, level + 1); |
822 | 920 | ||
823 | if (!buffer_dirty(path[level].bp_sib_bh)) | 921 | if (!buffer_dirty(path[level].bp_sib_bh)) |
@@ -832,11 +930,11 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, | |||
832 | *ptrp = path[level].bp_newreq.bpr_ptr; | 930 | *ptrp = path[level].bp_newreq.bpr_ptr; |
833 | } | 931 | } |
834 | 932 | ||
835 | static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree, | 933 | static __u64 nilfs_btree_find_near(const struct nilfs_bmap *btree, |
836 | const struct nilfs_btree_path *path) | 934 | const struct nilfs_btree_path *path) |
837 | { | 935 | { |
838 | struct nilfs_btree_node *node; | 936 | struct nilfs_btree_node *node; |
839 | int level; | 937 | int level, ncmax; |
840 | 938 | ||
841 | if (path == NULL) | 939 | if (path == NULL) |
842 | return NILFS_BMAP_INVALID_PTR; | 940 | return NILFS_BMAP_INVALID_PTR; |
@@ -844,29 +942,30 @@ static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree, | |||
844 | /* left sibling */ | 942 | /* left sibling */ |
845 | level = NILFS_BTREE_LEVEL_NODE_MIN; | 943 | level = NILFS_BTREE_LEVEL_NODE_MIN; |
846 | if (path[level].bp_index > 0) { | 944 | if (path[level].bp_index > 0) { |
847 | node = nilfs_btree_get_node(btree, path, level); | 945 | node = nilfs_btree_get_node(btree, path, level, &ncmax); |
848 | return nilfs_btree_node_get_ptr(btree, node, | 946 | return nilfs_btree_node_get_ptr(node, |
849 | path[level].bp_index - 1); | 947 | path[level].bp_index - 1, |
948 | ncmax); | ||
850 | } | 949 | } |
851 | 950 | ||
852 | /* parent */ | 951 | /* parent */ |
853 | level = NILFS_BTREE_LEVEL_NODE_MIN + 1; | 952 | level = NILFS_BTREE_LEVEL_NODE_MIN + 1; |
854 | if (level <= nilfs_btree_height(btree) - 1) { | 953 | if (level <= nilfs_btree_height(btree) - 1) { |
855 | node = nilfs_btree_get_node(btree, path, level); | 954 | node = nilfs_btree_get_node(btree, path, level, &ncmax); |
856 | return nilfs_btree_node_get_ptr(btree, node, | 955 | return nilfs_btree_node_get_ptr(node, path[level].bp_index, |
857 | path[level].bp_index); | 956 | ncmax); |
858 | } | 957 | } |
859 | 958 | ||
860 | return NILFS_BMAP_INVALID_PTR; | 959 | return NILFS_BMAP_INVALID_PTR; |
861 | } | 960 | } |
862 | 961 | ||
863 | static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree, | 962 | static __u64 nilfs_btree_find_target_v(const struct nilfs_bmap *btree, |
864 | const struct nilfs_btree_path *path, | 963 | const struct nilfs_btree_path *path, |
865 | __u64 key) | 964 | __u64 key) |
866 | { | 965 | { |
867 | __u64 ptr; | 966 | __u64 ptr; |
868 | 967 | ||
869 | ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key); | 968 | ptr = nilfs_bmap_find_target_seq(btree, key); |
870 | if (ptr != NILFS_BMAP_INVALID_PTR) | 969 | if (ptr != NILFS_BMAP_INVALID_PTR) |
871 | /* sequential access */ | 970 | /* sequential access */ |
872 | return ptr; | 971 | return ptr; |
@@ -877,17 +976,10 @@ static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree, | |||
877 | return ptr; | 976 | return ptr; |
878 | } | 977 | } |
879 | /* block group */ | 978 | /* block group */ |
880 | return nilfs_bmap_find_target_in_group(&btree->bt_bmap); | 979 | return nilfs_bmap_find_target_in_group(btree); |
881 | } | ||
882 | |||
883 | static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key, | ||
884 | __u64 ptr) | ||
885 | { | ||
886 | btree->bt_bmap.b_last_allocated_key = key; | ||
887 | btree->bt_bmap.b_last_allocated_ptr = ptr; | ||
888 | } | 980 | } |
889 | 981 | ||
890 | static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | 982 | static int nilfs_btree_prepare_insert(struct nilfs_bmap *btree, |
891 | struct nilfs_btree_path *path, | 983 | struct nilfs_btree_path *path, |
892 | int *levelp, __u64 key, __u64 ptr, | 984 | int *levelp, __u64 key, __u64 ptr, |
893 | struct nilfs_bmap_stats *stats) | 985 | struct nilfs_bmap_stats *stats) |
@@ -895,79 +987,78 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
895 | struct buffer_head *bh; | 987 | struct buffer_head *bh; |
896 | struct nilfs_btree_node *node, *parent, *sib; | 988 | struct nilfs_btree_node *node, *parent, *sib; |
897 | __u64 sibptr; | 989 | __u64 sibptr; |
898 | int pindex, level, ret; | 990 | int pindex, level, ncmax, ncblk, ret; |
899 | struct inode *dat = NULL; | 991 | struct inode *dat = NULL; |
900 | 992 | ||
901 | stats->bs_nblocks = 0; | 993 | stats->bs_nblocks = 0; |
902 | level = NILFS_BTREE_LEVEL_DATA; | 994 | level = NILFS_BTREE_LEVEL_DATA; |
903 | 995 | ||
904 | /* allocate a new ptr for data block */ | 996 | /* allocate a new ptr for data block */ |
905 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) { | 997 | if (NILFS_BMAP_USE_VBN(btree)) { |
906 | path[level].bp_newreq.bpr_ptr = | 998 | path[level].bp_newreq.bpr_ptr = |
907 | nilfs_btree_find_target_v(btree, path, key); | 999 | nilfs_btree_find_target_v(btree, path, key); |
908 | dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 1000 | dat = nilfs_bmap_get_dat(btree); |
909 | } | 1001 | } |
910 | 1002 | ||
911 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1003 | ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat); |
912 | &path[level].bp_newreq, dat); | ||
913 | if (ret < 0) | 1004 | if (ret < 0) |
914 | goto err_out_data; | 1005 | goto err_out_data; |
915 | 1006 | ||
1007 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1008 | |||
916 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; | 1009 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; |
917 | level < nilfs_btree_height(btree) - 1; | 1010 | level < nilfs_btree_height(btree) - 1; |
918 | level++) { | 1011 | level++) { |
919 | node = nilfs_btree_get_nonroot_node(path, level); | 1012 | node = nilfs_btree_get_nonroot_node(path, level); |
920 | if (nilfs_btree_node_get_nchildren(node) < | 1013 | if (nilfs_btree_node_get_nchildren(node) < ncblk) { |
921 | nilfs_btree_node_nchildren_max(node, btree)) { | ||
922 | path[level].bp_op = nilfs_btree_do_insert; | 1014 | path[level].bp_op = nilfs_btree_do_insert; |
923 | stats->bs_nblocks++; | 1015 | stats->bs_nblocks++; |
924 | goto out; | 1016 | goto out; |
925 | } | 1017 | } |
926 | 1018 | ||
927 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1019 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
928 | pindex = path[level + 1].bp_index; | 1020 | pindex = path[level + 1].bp_index; |
929 | 1021 | ||
930 | /* left sibling */ | 1022 | /* left sibling */ |
931 | if (pindex > 0) { | 1023 | if (pindex > 0) { |
932 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1024 | sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1, |
933 | pindex - 1); | 1025 | ncmax); |
934 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1026 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
935 | if (ret < 0) | 1027 | if (ret < 0) |
936 | goto err_out_child_node; | 1028 | goto err_out_child_node; |
937 | sib = (struct nilfs_btree_node *)bh->b_data; | 1029 | sib = (struct nilfs_btree_node *)bh->b_data; |
938 | if (nilfs_btree_node_get_nchildren(sib) < | 1030 | if (nilfs_btree_node_get_nchildren(sib) < ncblk) { |
939 | nilfs_btree_node_nchildren_max(sib, btree)) { | ||
940 | path[level].bp_sib_bh = bh; | 1031 | path[level].bp_sib_bh = bh; |
941 | path[level].bp_op = nilfs_btree_carry_left; | 1032 | path[level].bp_op = nilfs_btree_carry_left; |
942 | stats->bs_nblocks++; | 1033 | stats->bs_nblocks++; |
943 | goto out; | 1034 | goto out; |
944 | } else | 1035 | } else { |
945 | brelse(bh); | 1036 | brelse(bh); |
1037 | } | ||
946 | } | 1038 | } |
947 | 1039 | ||
948 | /* right sibling */ | 1040 | /* right sibling */ |
949 | if (pindex < | 1041 | if (pindex < nilfs_btree_node_get_nchildren(parent) - 1) { |
950 | nilfs_btree_node_get_nchildren(parent) - 1) { | 1042 | sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1, |
951 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1043 | ncmax); |
952 | pindex + 1); | ||
953 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1044 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
954 | if (ret < 0) | 1045 | if (ret < 0) |
955 | goto err_out_child_node; | 1046 | goto err_out_child_node; |
956 | sib = (struct nilfs_btree_node *)bh->b_data; | 1047 | sib = (struct nilfs_btree_node *)bh->b_data; |
957 | if (nilfs_btree_node_get_nchildren(sib) < | 1048 | if (nilfs_btree_node_get_nchildren(sib) < ncblk) { |
958 | nilfs_btree_node_nchildren_max(sib, btree)) { | ||
959 | path[level].bp_sib_bh = bh; | 1049 | path[level].bp_sib_bh = bh; |
960 | path[level].bp_op = nilfs_btree_carry_right; | 1050 | path[level].bp_op = nilfs_btree_carry_right; |
961 | stats->bs_nblocks++; | 1051 | stats->bs_nblocks++; |
962 | goto out; | 1052 | goto out; |
963 | } else | 1053 | } else { |
964 | brelse(bh); | 1054 | brelse(bh); |
1055 | } | ||
965 | } | 1056 | } |
966 | 1057 | ||
967 | /* split */ | 1058 | /* split */ |
968 | path[level].bp_newreq.bpr_ptr = | 1059 | path[level].bp_newreq.bpr_ptr = |
969 | path[level - 1].bp_newreq.bpr_ptr + 1; | 1060 | path[level - 1].bp_newreq.bpr_ptr + 1; |
970 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1061 | ret = nilfs_bmap_prepare_alloc_ptr(btree, |
971 | &path[level].bp_newreq, dat); | 1062 | &path[level].bp_newreq, dat); |
972 | if (ret < 0) | 1063 | if (ret < 0) |
973 | goto err_out_child_node; | 1064 | goto err_out_child_node; |
@@ -979,9 +1070,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
979 | 1070 | ||
980 | stats->bs_nblocks++; | 1071 | stats->bs_nblocks++; |
981 | 1072 | ||
982 | nilfs_btree_node_init(btree, | 1073 | sib = (struct nilfs_btree_node *)bh->b_data; |
983 | (struct nilfs_btree_node *)bh->b_data, | 1074 | nilfs_btree_node_init(sib, 0, level, 0, ncblk, NULL, NULL); |
984 | 0, level, 0, NULL, NULL); | ||
985 | path[level].bp_sib_bh = bh; | 1075 | path[level].bp_sib_bh = bh; |
986 | path[level].bp_op = nilfs_btree_split; | 1076 | path[level].bp_op = nilfs_btree_split; |
987 | } | 1077 | } |
@@ -989,7 +1079,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
989 | /* root */ | 1079 | /* root */ |
990 | node = nilfs_btree_get_root(btree); | 1080 | node = nilfs_btree_get_root(btree); |
991 | if (nilfs_btree_node_get_nchildren(node) < | 1081 | if (nilfs_btree_node_get_nchildren(node) < |
992 | nilfs_btree_node_nchildren_max(node, btree)) { | 1082 | NILFS_BTREE_ROOT_NCHILDREN_MAX) { |
993 | path[level].bp_op = nilfs_btree_do_insert; | 1083 | path[level].bp_op = nilfs_btree_do_insert; |
994 | stats->bs_nblocks++; | 1084 | stats->bs_nblocks++; |
995 | goto out; | 1085 | goto out; |
@@ -997,8 +1087,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
997 | 1087 | ||
998 | /* grow */ | 1088 | /* grow */ |
999 | path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; | 1089 | path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; |
1000 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1090 | ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1001 | &path[level].bp_newreq, dat); | ||
1002 | if (ret < 0) | 1091 | if (ret < 0) |
1003 | goto err_out_child_node; | 1092 | goto err_out_child_node; |
1004 | ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr, | 1093 | ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr, |
@@ -1006,8 +1095,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
1006 | if (ret < 0) | 1095 | if (ret < 0) |
1007 | goto err_out_curr_node; | 1096 | goto err_out_curr_node; |
1008 | 1097 | ||
1009 | nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data, | 1098 | nilfs_btree_node_init((struct nilfs_btree_node *)bh->b_data, |
1010 | 0, level, 0, NULL, NULL); | 1099 | 0, level, 0, ncblk, NULL, NULL); |
1011 | path[level].bp_sib_bh = bh; | 1100 | path[level].bp_sib_bh = bh; |
1012 | path[level].bp_op = nilfs_btree_grow; | 1101 | path[level].bp_op = nilfs_btree_grow; |
1013 | 1102 | ||
@@ -1024,25 +1113,22 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
1024 | 1113 | ||
1025 | /* error */ | 1114 | /* error */ |
1026 | err_out_curr_node: | 1115 | err_out_curr_node: |
1027 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq, | 1116 | nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1028 | dat); | ||
1029 | err_out_child_node: | 1117 | err_out_child_node: |
1030 | for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { | 1118 | for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { |
1031 | nilfs_btnode_delete(path[level].bp_sib_bh); | 1119 | nilfs_btnode_delete(path[level].bp_sib_bh); |
1032 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, | 1120 | nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1033 | &path[level].bp_newreq, dat); | ||
1034 | 1121 | ||
1035 | } | 1122 | } |
1036 | 1123 | ||
1037 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq, | 1124 | nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1038 | dat); | ||
1039 | err_out_data: | 1125 | err_out_data: |
1040 | *levelp = level; | 1126 | *levelp = level; |
1041 | stats->bs_nblocks = 0; | 1127 | stats->bs_nblocks = 0; |
1042 | return ret; | 1128 | return ret; |
1043 | } | 1129 | } |
1044 | 1130 | ||
1045 | static void nilfs_btree_commit_insert(struct nilfs_btree *btree, | 1131 | static void nilfs_btree_commit_insert(struct nilfs_bmap *btree, |
1046 | struct nilfs_btree_path *path, | 1132 | struct nilfs_btree_path *path, |
1047 | int maxlevel, __u64 key, __u64 ptr) | 1133 | int maxlevel, __u64 key, __u64 ptr) |
1048 | { | 1134 | { |
@@ -1051,35 +1137,33 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree, | |||
1051 | 1137 | ||
1052 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); | 1138 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); |
1053 | ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; | 1139 | ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; |
1054 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) { | 1140 | if (NILFS_BMAP_USE_VBN(btree)) { |
1055 | nilfs_btree_set_target_v(btree, key, ptr); | 1141 | nilfs_bmap_set_target_v(btree, key, ptr); |
1056 | dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 1142 | dat = nilfs_bmap_get_dat(btree); |
1057 | } | 1143 | } |
1058 | 1144 | ||
1059 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { | 1145 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { |
1060 | nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap, | 1146 | nilfs_bmap_commit_alloc_ptr(btree, |
1061 | &path[level - 1].bp_newreq, dat); | 1147 | &path[level - 1].bp_newreq, dat); |
1062 | path[level].bp_op(btree, path, level, &key, &ptr); | 1148 | path[level].bp_op(btree, path, level, &key, &ptr); |
1063 | } | 1149 | } |
1064 | 1150 | ||
1065 | if (!nilfs_bmap_dirty(&btree->bt_bmap)) | 1151 | if (!nilfs_bmap_dirty(btree)) |
1066 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 1152 | nilfs_bmap_set_dirty(btree); |
1067 | } | 1153 | } |
1068 | 1154 | ||
1069 | static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | 1155 | static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr) |
1070 | { | 1156 | { |
1071 | struct nilfs_btree *btree; | ||
1072 | struct nilfs_btree_path *path; | 1157 | struct nilfs_btree_path *path; |
1073 | struct nilfs_bmap_stats stats; | 1158 | struct nilfs_bmap_stats stats; |
1074 | int level, ret; | 1159 | int level, ret; |
1075 | 1160 | ||
1076 | btree = (struct nilfs_btree *)bmap; | ||
1077 | path = nilfs_btree_alloc_path(); | 1161 | path = nilfs_btree_alloc_path(); |
1078 | if (path == NULL) | 1162 | if (path == NULL) |
1079 | return -ENOMEM; | 1163 | return -ENOMEM; |
1080 | 1164 | ||
1081 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1165 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
1082 | NILFS_BTREE_LEVEL_NODE_MIN); | 1166 | NILFS_BTREE_LEVEL_NODE_MIN, 0); |
1083 | if (ret != -ENOENT) { | 1167 | if (ret != -ENOENT) { |
1084 | if (ret == 0) | 1168 | if (ret == 0) |
1085 | ret = -EEXIST; | 1169 | ret = -EEXIST; |
@@ -1090,23 +1174,25 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
1090 | if (ret < 0) | 1174 | if (ret < 0) |
1091 | goto out; | 1175 | goto out; |
1092 | nilfs_btree_commit_insert(btree, path, level, key, ptr); | 1176 | nilfs_btree_commit_insert(btree, path, level, key, ptr); |
1093 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); | 1177 | nilfs_bmap_add_blocks(btree, stats.bs_nblocks); |
1094 | 1178 | ||
1095 | out: | 1179 | out: |
1096 | nilfs_btree_free_path(path); | 1180 | nilfs_btree_free_path(path); |
1097 | return ret; | 1181 | return ret; |
1098 | } | 1182 | } |
1099 | 1183 | ||
1100 | static void nilfs_btree_do_delete(struct nilfs_btree *btree, | 1184 | static void nilfs_btree_do_delete(struct nilfs_bmap *btree, |
1101 | struct nilfs_btree_path *path, | 1185 | struct nilfs_btree_path *path, |
1102 | int level, __u64 *keyp, __u64 *ptrp) | 1186 | int level, __u64 *keyp, __u64 *ptrp) |
1103 | { | 1187 | { |
1104 | struct nilfs_btree_node *node; | 1188 | struct nilfs_btree_node *node; |
1189 | int ncblk; | ||
1105 | 1190 | ||
1106 | if (level < nilfs_btree_height(btree) - 1) { | 1191 | if (level < nilfs_btree_height(btree) - 1) { |
1107 | node = nilfs_btree_get_nonroot_node(path, level); | 1192 | node = nilfs_btree_get_nonroot_node(path, level); |
1108 | nilfs_btree_node_delete(btree, node, keyp, ptrp, | 1193 | ncblk = nilfs_btree_nchildren_per_block(btree); |
1109 | path[level].bp_index); | 1194 | nilfs_btree_node_delete(node, path[level].bp_index, |
1195 | keyp, ptrp, ncblk); | ||
1110 | if (!buffer_dirty(path[level].bp_bh)) | 1196 | if (!buffer_dirty(path[level].bp_bh)) |
1111 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1197 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
1112 | if (path[level].bp_index == 0) | 1198 | if (path[level].bp_index == 0) |
@@ -1114,17 +1200,18 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree, | |||
1114 | nilfs_btree_node_get_key(node, 0)); | 1200 | nilfs_btree_node_get_key(node, 0)); |
1115 | } else { | 1201 | } else { |
1116 | node = nilfs_btree_get_root(btree); | 1202 | node = nilfs_btree_get_root(btree); |
1117 | nilfs_btree_node_delete(btree, node, keyp, ptrp, | 1203 | nilfs_btree_node_delete(node, path[level].bp_index, |
1118 | path[level].bp_index); | 1204 | keyp, ptrp, |
1205 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1119 | } | 1206 | } |
1120 | } | 1207 | } |
1121 | 1208 | ||
1122 | static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | 1209 | static void nilfs_btree_borrow_left(struct nilfs_bmap *btree, |
1123 | struct nilfs_btree_path *path, | 1210 | struct nilfs_btree_path *path, |
1124 | int level, __u64 *keyp, __u64 *ptrp) | 1211 | int level, __u64 *keyp, __u64 *ptrp) |
1125 | { | 1212 | { |
1126 | struct nilfs_btree_node *node, *left; | 1213 | struct nilfs_btree_node *node, *left; |
1127 | int nchildren, lnchildren, n; | 1214 | int nchildren, lnchildren, n, ncblk; |
1128 | 1215 | ||
1129 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1216 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1130 | 1217 | ||
@@ -1132,10 +1219,11 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | |||
1132 | left = nilfs_btree_get_sib_node(path, level); | 1219 | left = nilfs_btree_get_sib_node(path, level); |
1133 | nchildren = nilfs_btree_node_get_nchildren(node); | 1220 | nchildren = nilfs_btree_node_get_nchildren(node); |
1134 | lnchildren = nilfs_btree_node_get_nchildren(left); | 1221 | lnchildren = nilfs_btree_node_get_nchildren(left); |
1222 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1135 | 1223 | ||
1136 | n = (nchildren + lnchildren) / 2 - nchildren; | 1224 | n = (nchildren + lnchildren) / 2 - nchildren; |
1137 | 1225 | ||
1138 | nilfs_btree_node_move_right(btree, left, node, n); | 1226 | nilfs_btree_node_move_right(left, node, n, ncblk, ncblk); |
1139 | 1227 | ||
1140 | if (!buffer_dirty(path[level].bp_bh)) | 1228 | if (!buffer_dirty(path[level].bp_bh)) |
1141 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1229 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -1150,12 +1238,12 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | |||
1150 | path[level].bp_index += n; | 1238 | path[level].bp_index += n; |
1151 | } | 1239 | } |
1152 | 1240 | ||
1153 | static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | 1241 | static void nilfs_btree_borrow_right(struct nilfs_bmap *btree, |
1154 | struct nilfs_btree_path *path, | 1242 | struct nilfs_btree_path *path, |
1155 | int level, __u64 *keyp, __u64 *ptrp) | 1243 | int level, __u64 *keyp, __u64 *ptrp) |
1156 | { | 1244 | { |
1157 | struct nilfs_btree_node *node, *right; | 1245 | struct nilfs_btree_node *node, *right; |
1158 | int nchildren, rnchildren, n; | 1246 | int nchildren, rnchildren, n, ncblk; |
1159 | 1247 | ||
1160 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1248 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1161 | 1249 | ||
@@ -1163,10 +1251,11 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | |||
1163 | right = nilfs_btree_get_sib_node(path, level); | 1251 | right = nilfs_btree_get_sib_node(path, level); |
1164 | nchildren = nilfs_btree_node_get_nchildren(node); | 1252 | nchildren = nilfs_btree_node_get_nchildren(node); |
1165 | rnchildren = nilfs_btree_node_get_nchildren(right); | 1253 | rnchildren = nilfs_btree_node_get_nchildren(right); |
1254 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1166 | 1255 | ||
1167 | n = (nchildren + rnchildren) / 2 - nchildren; | 1256 | n = (nchildren + rnchildren) / 2 - nchildren; |
1168 | 1257 | ||
1169 | nilfs_btree_node_move_left(btree, node, right, n); | 1258 | nilfs_btree_node_move_left(node, right, n, ncblk, ncblk); |
1170 | 1259 | ||
1171 | if (!buffer_dirty(path[level].bp_bh)) | 1260 | if (!buffer_dirty(path[level].bp_bh)) |
1172 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1261 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -1182,21 +1271,22 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | |||
1182 | path[level].bp_sib_bh = NULL; | 1271 | path[level].bp_sib_bh = NULL; |
1183 | } | 1272 | } |
1184 | 1273 | ||
1185 | static void nilfs_btree_concat_left(struct nilfs_btree *btree, | 1274 | static void nilfs_btree_concat_left(struct nilfs_bmap *btree, |
1186 | struct nilfs_btree_path *path, | 1275 | struct nilfs_btree_path *path, |
1187 | int level, __u64 *keyp, __u64 *ptrp) | 1276 | int level, __u64 *keyp, __u64 *ptrp) |
1188 | { | 1277 | { |
1189 | struct nilfs_btree_node *node, *left; | 1278 | struct nilfs_btree_node *node, *left; |
1190 | int n; | 1279 | int n, ncblk; |
1191 | 1280 | ||
1192 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1281 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1193 | 1282 | ||
1194 | node = nilfs_btree_get_nonroot_node(path, level); | 1283 | node = nilfs_btree_get_nonroot_node(path, level); |
1195 | left = nilfs_btree_get_sib_node(path, level); | 1284 | left = nilfs_btree_get_sib_node(path, level); |
1285 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1196 | 1286 | ||
1197 | n = nilfs_btree_node_get_nchildren(node); | 1287 | n = nilfs_btree_node_get_nchildren(node); |
1198 | 1288 | ||
1199 | nilfs_btree_node_move_left(btree, left, node, n); | 1289 | nilfs_btree_node_move_left(left, node, n, ncblk, ncblk); |
1200 | 1290 | ||
1201 | if (!buffer_dirty(path[level].bp_sib_bh)) | 1291 | if (!buffer_dirty(path[level].bp_sib_bh)) |
1202 | nilfs_btnode_mark_dirty(path[level].bp_sib_bh); | 1292 | nilfs_btnode_mark_dirty(path[level].bp_sib_bh); |
@@ -1207,21 +1297,22 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, | |||
1207 | path[level].bp_index += nilfs_btree_node_get_nchildren(left); | 1297 | path[level].bp_index += nilfs_btree_node_get_nchildren(left); |
1208 | } | 1298 | } |
1209 | 1299 | ||
1210 | static void nilfs_btree_concat_right(struct nilfs_btree *btree, | 1300 | static void nilfs_btree_concat_right(struct nilfs_bmap *btree, |
1211 | struct nilfs_btree_path *path, | 1301 | struct nilfs_btree_path *path, |
1212 | int level, __u64 *keyp, __u64 *ptrp) | 1302 | int level, __u64 *keyp, __u64 *ptrp) |
1213 | { | 1303 | { |
1214 | struct nilfs_btree_node *node, *right; | 1304 | struct nilfs_btree_node *node, *right; |
1215 | int n; | 1305 | int n, ncblk; |
1216 | 1306 | ||
1217 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1307 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1218 | 1308 | ||
1219 | node = nilfs_btree_get_nonroot_node(path, level); | 1309 | node = nilfs_btree_get_nonroot_node(path, level); |
1220 | right = nilfs_btree_get_sib_node(path, level); | 1310 | right = nilfs_btree_get_sib_node(path, level); |
1311 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1221 | 1312 | ||
1222 | n = nilfs_btree_node_get_nchildren(right); | 1313 | n = nilfs_btree_node_get_nchildren(right); |
1223 | 1314 | ||
1224 | nilfs_btree_node_move_left(btree, node, right, n); | 1315 | nilfs_btree_node_move_left(node, right, n, ncblk, ncblk); |
1225 | 1316 | ||
1226 | if (!buffer_dirty(path[level].bp_bh)) | 1317 | if (!buffer_dirty(path[level].bp_bh)) |
1227 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1318 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -1231,29 +1322,32 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree, | |||
1231 | path[level + 1].bp_index++; | 1322 | path[level + 1].bp_index++; |
1232 | } | 1323 | } |
1233 | 1324 | ||
1234 | static void nilfs_btree_shrink(struct nilfs_btree *btree, | 1325 | static void nilfs_btree_shrink(struct nilfs_bmap *btree, |
1235 | struct nilfs_btree_path *path, | 1326 | struct nilfs_btree_path *path, |
1236 | int level, __u64 *keyp, __u64 *ptrp) | 1327 | int level, __u64 *keyp, __u64 *ptrp) |
1237 | { | 1328 | { |
1238 | struct nilfs_btree_node *root, *child; | 1329 | struct nilfs_btree_node *root, *child; |
1239 | int n; | 1330 | int n, ncblk; |
1240 | 1331 | ||
1241 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1332 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1242 | 1333 | ||
1243 | root = nilfs_btree_get_root(btree); | 1334 | root = nilfs_btree_get_root(btree); |
1244 | child = nilfs_btree_get_nonroot_node(path, level); | 1335 | child = nilfs_btree_get_nonroot_node(path, level); |
1336 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1245 | 1337 | ||
1246 | nilfs_btree_node_delete(btree, root, NULL, NULL, 0); | 1338 | nilfs_btree_node_delete(root, 0, NULL, NULL, |
1339 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1247 | nilfs_btree_node_set_level(root, level); | 1340 | nilfs_btree_node_set_level(root, level); |
1248 | n = nilfs_btree_node_get_nchildren(child); | 1341 | n = nilfs_btree_node_get_nchildren(child); |
1249 | nilfs_btree_node_move_left(btree, root, child, n); | 1342 | nilfs_btree_node_move_left(root, child, n, |
1343 | NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk); | ||
1250 | 1344 | ||
1251 | nilfs_btnode_delete(path[level].bp_bh); | 1345 | nilfs_btnode_delete(path[level].bp_bh); |
1252 | path[level].bp_bh = NULL; | 1346 | path[level].bp_bh = NULL; |
1253 | } | 1347 | } |
1254 | 1348 | ||
1255 | 1349 | ||
1256 | static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | 1350 | static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, |
1257 | struct nilfs_btree_path *path, | 1351 | struct nilfs_btree_path *path, |
1258 | int *levelp, | 1352 | int *levelp, |
1259 | struct nilfs_bmap_stats *stats, | 1353 | struct nilfs_bmap_stats *stats, |
@@ -1262,42 +1356,43 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1262 | struct buffer_head *bh; | 1356 | struct buffer_head *bh; |
1263 | struct nilfs_btree_node *node, *parent, *sib; | 1357 | struct nilfs_btree_node *node, *parent, *sib; |
1264 | __u64 sibptr; | 1358 | __u64 sibptr; |
1265 | int pindex, level, ret; | 1359 | int pindex, level, ncmin, ncmax, ncblk, ret; |
1266 | 1360 | ||
1267 | ret = 0; | 1361 | ret = 0; |
1268 | stats->bs_nblocks = 0; | 1362 | stats->bs_nblocks = 0; |
1363 | ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); | ||
1364 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1365 | |||
1269 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; | 1366 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; |
1270 | level < nilfs_btree_height(btree) - 1; | 1367 | level < nilfs_btree_height(btree) - 1; |
1271 | level++) { | 1368 | level++) { |
1272 | node = nilfs_btree_get_nonroot_node(path, level); | 1369 | node = nilfs_btree_get_nonroot_node(path, level); |
1273 | path[level].bp_oldreq.bpr_ptr = | 1370 | path[level].bp_oldreq.bpr_ptr = |
1274 | nilfs_btree_node_get_ptr(btree, node, | 1371 | nilfs_btree_node_get_ptr(node, path[level].bp_index, |
1275 | path[level].bp_index); | 1372 | ncblk); |
1276 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, | 1373 | ret = nilfs_bmap_prepare_end_ptr(btree, |
1277 | &path[level].bp_oldreq, dat); | 1374 | &path[level].bp_oldreq, dat); |
1278 | if (ret < 0) | 1375 | if (ret < 0) |
1279 | goto err_out_child_node; | 1376 | goto err_out_child_node; |
1280 | 1377 | ||
1281 | if (nilfs_btree_node_get_nchildren(node) > | 1378 | if (nilfs_btree_node_get_nchildren(node) > ncmin) { |
1282 | nilfs_btree_node_nchildren_min(node, btree)) { | ||
1283 | path[level].bp_op = nilfs_btree_do_delete; | 1379 | path[level].bp_op = nilfs_btree_do_delete; |
1284 | stats->bs_nblocks++; | 1380 | stats->bs_nblocks++; |
1285 | goto out; | 1381 | goto out; |
1286 | } | 1382 | } |
1287 | 1383 | ||
1288 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1384 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1289 | pindex = path[level + 1].bp_index; | 1385 | pindex = path[level + 1].bp_index; |
1290 | 1386 | ||
1291 | if (pindex > 0) { | 1387 | if (pindex > 0) { |
1292 | /* left sibling */ | 1388 | /* left sibling */ |
1293 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1389 | sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1, |
1294 | pindex - 1); | 1390 | ncmax); |
1295 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1391 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
1296 | if (ret < 0) | 1392 | if (ret < 0) |
1297 | goto err_out_curr_node; | 1393 | goto err_out_curr_node; |
1298 | sib = (struct nilfs_btree_node *)bh->b_data; | 1394 | sib = (struct nilfs_btree_node *)bh->b_data; |
1299 | if (nilfs_btree_node_get_nchildren(sib) > | 1395 | if (nilfs_btree_node_get_nchildren(sib) > ncmin) { |
1300 | nilfs_btree_node_nchildren_min(sib, btree)) { | ||
1301 | path[level].bp_sib_bh = bh; | 1396 | path[level].bp_sib_bh = bh; |
1302 | path[level].bp_op = nilfs_btree_borrow_left; | 1397 | path[level].bp_op = nilfs_btree_borrow_left; |
1303 | stats->bs_nblocks++; | 1398 | stats->bs_nblocks++; |
@@ -1311,14 +1406,13 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1311 | } else if (pindex < | 1406 | } else if (pindex < |
1312 | nilfs_btree_node_get_nchildren(parent) - 1) { | 1407 | nilfs_btree_node_get_nchildren(parent) - 1) { |
1313 | /* right sibling */ | 1408 | /* right sibling */ |
1314 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1409 | sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1, |
1315 | pindex + 1); | 1410 | ncmax); |
1316 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1411 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
1317 | if (ret < 0) | 1412 | if (ret < 0) |
1318 | goto err_out_curr_node; | 1413 | goto err_out_curr_node; |
1319 | sib = (struct nilfs_btree_node *)bh->b_data; | 1414 | sib = (struct nilfs_btree_node *)bh->b_data; |
1320 | if (nilfs_btree_node_get_nchildren(sib) > | 1415 | if (nilfs_btree_node_get_nchildren(sib) > ncmin) { |
1321 | nilfs_btree_node_nchildren_min(sib, btree)) { | ||
1322 | path[level].bp_sib_bh = bh; | 1416 | path[level].bp_sib_bh = bh; |
1323 | path[level].bp_op = nilfs_btree_borrow_right; | 1417 | path[level].bp_op = nilfs_btree_borrow_right; |
1324 | stats->bs_nblocks++; | 1418 | stats->bs_nblocks++; |
@@ -1349,10 +1443,10 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1349 | 1443 | ||
1350 | node = nilfs_btree_get_root(btree); | 1444 | node = nilfs_btree_get_root(btree); |
1351 | path[level].bp_oldreq.bpr_ptr = | 1445 | path[level].bp_oldreq.bpr_ptr = |
1352 | nilfs_btree_node_get_ptr(btree, node, path[level].bp_index); | 1446 | nilfs_btree_node_get_ptr(node, path[level].bp_index, |
1447 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1353 | 1448 | ||
1354 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, | 1449 | ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); |
1355 | &path[level].bp_oldreq, dat); | ||
1356 | if (ret < 0) | 1450 | if (ret < 0) |
1357 | goto err_out_child_node; | 1451 | goto err_out_child_node; |
1358 | 1452 | ||
@@ -1367,75 +1461,68 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1367 | 1461 | ||
1368 | /* error */ | 1462 | /* error */ |
1369 | err_out_curr_node: | 1463 | err_out_curr_node: |
1370 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat); | 1464 | nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat); |
1371 | err_out_child_node: | 1465 | err_out_child_node: |
1372 | for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { | 1466 | for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { |
1373 | brelse(path[level].bp_sib_bh); | 1467 | brelse(path[level].bp_sib_bh); |
1374 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, | 1468 | nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat); |
1375 | &path[level].bp_oldreq, dat); | ||
1376 | } | 1469 | } |
1377 | *levelp = level; | 1470 | *levelp = level; |
1378 | stats->bs_nblocks = 0; | 1471 | stats->bs_nblocks = 0; |
1379 | return ret; | 1472 | return ret; |
1380 | } | 1473 | } |
1381 | 1474 | ||
1382 | static void nilfs_btree_commit_delete(struct nilfs_btree *btree, | 1475 | static void nilfs_btree_commit_delete(struct nilfs_bmap *btree, |
1383 | struct nilfs_btree_path *path, | 1476 | struct nilfs_btree_path *path, |
1384 | int maxlevel, struct inode *dat) | 1477 | int maxlevel, struct inode *dat) |
1385 | { | 1478 | { |
1386 | int level; | 1479 | int level; |
1387 | 1480 | ||
1388 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { | 1481 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { |
1389 | nilfs_bmap_commit_end_ptr(&btree->bt_bmap, | 1482 | nilfs_bmap_commit_end_ptr(btree, &path[level].bp_oldreq, dat); |
1390 | &path[level].bp_oldreq, dat); | ||
1391 | path[level].bp_op(btree, path, level, NULL, NULL); | 1483 | path[level].bp_op(btree, path, level, NULL, NULL); |
1392 | } | 1484 | } |
1393 | 1485 | ||
1394 | if (!nilfs_bmap_dirty(&btree->bt_bmap)) | 1486 | if (!nilfs_bmap_dirty(btree)) |
1395 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 1487 | nilfs_bmap_set_dirty(btree); |
1396 | } | 1488 | } |
1397 | 1489 | ||
1398 | static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) | 1490 | static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key) |
1399 | 1491 | ||
1400 | { | 1492 | { |
1401 | struct nilfs_btree *btree; | ||
1402 | struct nilfs_btree_path *path; | 1493 | struct nilfs_btree_path *path; |
1403 | struct nilfs_bmap_stats stats; | 1494 | struct nilfs_bmap_stats stats; |
1404 | struct inode *dat; | 1495 | struct inode *dat; |
1405 | int level, ret; | 1496 | int level, ret; |
1406 | 1497 | ||
1407 | btree = (struct nilfs_btree *)bmap; | ||
1408 | path = nilfs_btree_alloc_path(); | 1498 | path = nilfs_btree_alloc_path(); |
1409 | if (path == NULL) | 1499 | if (path == NULL) |
1410 | return -ENOMEM; | 1500 | return -ENOMEM; |
1411 | 1501 | ||
1412 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1502 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
1413 | NILFS_BTREE_LEVEL_NODE_MIN); | 1503 | NILFS_BTREE_LEVEL_NODE_MIN, 0); |
1414 | if (ret < 0) | 1504 | if (ret < 0) |
1415 | goto out; | 1505 | goto out; |
1416 | 1506 | ||
1417 | 1507 | ||
1418 | dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ? | 1508 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; |
1419 | nilfs_bmap_get_dat(&btree->bt_bmap) : NULL; | ||
1420 | 1509 | ||
1421 | ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat); | 1510 | ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat); |
1422 | if (ret < 0) | 1511 | if (ret < 0) |
1423 | goto out; | 1512 | goto out; |
1424 | nilfs_btree_commit_delete(btree, path, level, dat); | 1513 | nilfs_btree_commit_delete(btree, path, level, dat); |
1425 | nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); | 1514 | nilfs_bmap_sub_blocks(btree, stats.bs_nblocks); |
1426 | 1515 | ||
1427 | out: | 1516 | out: |
1428 | nilfs_btree_free_path(path); | 1517 | nilfs_btree_free_path(path); |
1429 | return ret; | 1518 | return ret; |
1430 | } | 1519 | } |
1431 | 1520 | ||
1432 | static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | 1521 | static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) |
1433 | { | 1522 | { |
1434 | struct nilfs_btree *btree; | ||
1435 | struct nilfs_btree_path *path; | 1523 | struct nilfs_btree_path *path; |
1436 | int ret; | 1524 | int ret; |
1437 | 1525 | ||
1438 | btree = (struct nilfs_btree *)bmap; | ||
1439 | path = nilfs_btree_alloc_path(); | 1526 | path = nilfs_btree_alloc_path(); |
1440 | if (path == NULL) | 1527 | if (path == NULL) |
1441 | return -ENOMEM; | 1528 | return -ENOMEM; |
@@ -1447,16 +1534,14 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | |||
1447 | return ret; | 1534 | return ret; |
1448 | } | 1535 | } |
1449 | 1536 | ||
1450 | static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | 1537 | static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) |
1451 | { | 1538 | { |
1452 | struct buffer_head *bh; | 1539 | struct buffer_head *bh; |
1453 | struct nilfs_btree *btree; | ||
1454 | struct nilfs_btree_node *root, *node; | 1540 | struct nilfs_btree_node *root, *node; |
1455 | __u64 maxkey, nextmaxkey; | 1541 | __u64 maxkey, nextmaxkey; |
1456 | __u64 ptr; | 1542 | __u64 ptr; |
1457 | int nchildren, ret; | 1543 | int nchildren, ret; |
1458 | 1544 | ||
1459 | btree = (struct nilfs_btree *)bmap; | ||
1460 | root = nilfs_btree_get_root(btree); | 1545 | root = nilfs_btree_get_root(btree); |
1461 | switch (nilfs_btree_height(btree)) { | 1546 | switch (nilfs_btree_height(btree)) { |
1462 | case 2: | 1547 | case 2: |
@@ -1467,7 +1552,8 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | |||
1467 | nchildren = nilfs_btree_node_get_nchildren(root); | 1552 | nchildren = nilfs_btree_node_get_nchildren(root); |
1468 | if (nchildren > 1) | 1553 | if (nchildren > 1) |
1469 | return 0; | 1554 | return 0; |
1470 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); | 1555 | ptr = nilfs_btree_node_get_ptr(root, nchildren - 1, |
1556 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1471 | ret = nilfs_btree_get_block(btree, ptr, &bh); | 1557 | ret = nilfs_btree_get_block(btree, ptr, &bh); |
1472 | if (ret < 0) | 1558 | if (ret < 0) |
1473 | return ret; | 1559 | return ret; |
@@ -1487,32 +1573,33 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | |||
1487 | return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW); | 1573 | return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW); |
1488 | } | 1574 | } |
1489 | 1575 | ||
1490 | static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | 1576 | static int nilfs_btree_gather_data(struct nilfs_bmap *btree, |
1491 | __u64 *keys, __u64 *ptrs, int nitems) | 1577 | __u64 *keys, __u64 *ptrs, int nitems) |
1492 | { | 1578 | { |
1493 | struct buffer_head *bh; | 1579 | struct buffer_head *bh; |
1494 | struct nilfs_btree *btree; | ||
1495 | struct nilfs_btree_node *node, *root; | 1580 | struct nilfs_btree_node *node, *root; |
1496 | __le64 *dkeys; | 1581 | __le64 *dkeys; |
1497 | __le64 *dptrs; | 1582 | __le64 *dptrs; |
1498 | __u64 ptr; | 1583 | __u64 ptr; |
1499 | int nchildren, i, ret; | 1584 | int nchildren, ncmax, i, ret; |
1500 | 1585 | ||
1501 | btree = (struct nilfs_btree *)bmap; | ||
1502 | root = nilfs_btree_get_root(btree); | 1586 | root = nilfs_btree_get_root(btree); |
1503 | switch (nilfs_btree_height(btree)) { | 1587 | switch (nilfs_btree_height(btree)) { |
1504 | case 2: | 1588 | case 2: |
1505 | bh = NULL; | 1589 | bh = NULL; |
1506 | node = root; | 1590 | node = root; |
1591 | ncmax = NILFS_BTREE_ROOT_NCHILDREN_MAX; | ||
1507 | break; | 1592 | break; |
1508 | case 3: | 1593 | case 3: |
1509 | nchildren = nilfs_btree_node_get_nchildren(root); | 1594 | nchildren = nilfs_btree_node_get_nchildren(root); |
1510 | WARN_ON(nchildren > 1); | 1595 | WARN_ON(nchildren > 1); |
1511 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); | 1596 | ptr = nilfs_btree_node_get_ptr(root, nchildren - 1, |
1597 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1512 | ret = nilfs_btree_get_block(btree, ptr, &bh); | 1598 | ret = nilfs_btree_get_block(btree, ptr, &bh); |
1513 | if (ret < 0) | 1599 | if (ret < 0) |
1514 | return ret; | 1600 | return ret; |
1515 | node = (struct nilfs_btree_node *)bh->b_data; | 1601 | node = (struct nilfs_btree_node *)bh->b_data; |
1602 | ncmax = nilfs_btree_nchildren_per_block(btree); | ||
1516 | break; | 1603 | break; |
1517 | default: | 1604 | default: |
1518 | node = NULL; | 1605 | node = NULL; |
@@ -1523,10 +1610,10 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | |||
1523 | if (nchildren < nitems) | 1610 | if (nchildren < nitems) |
1524 | nitems = nchildren; | 1611 | nitems = nchildren; |
1525 | dkeys = nilfs_btree_node_dkeys(node); | 1612 | dkeys = nilfs_btree_node_dkeys(node); |
1526 | dptrs = nilfs_btree_node_dptrs(node, btree); | 1613 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
1527 | for (i = 0; i < nitems; i++) { | 1614 | for (i = 0; i < nitems; i++) { |
1528 | keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]); | 1615 | keys[i] = le64_to_cpu(dkeys[i]); |
1529 | ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]); | 1616 | ptrs[i] = le64_to_cpu(dptrs[i]); |
1530 | } | 1617 | } |
1531 | 1618 | ||
1532 | if (bh != NULL) | 1619 | if (bh != NULL) |
@@ -1536,14 +1623,13 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | |||
1536 | } | 1623 | } |
1537 | 1624 | ||
1538 | static int | 1625 | static int |
1539 | nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | 1626 | nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *btree, __u64 key, |
1540 | union nilfs_bmap_ptr_req *dreq, | 1627 | union nilfs_bmap_ptr_req *dreq, |
1541 | union nilfs_bmap_ptr_req *nreq, | 1628 | union nilfs_bmap_ptr_req *nreq, |
1542 | struct buffer_head **bhp, | 1629 | struct buffer_head **bhp, |
1543 | struct nilfs_bmap_stats *stats) | 1630 | struct nilfs_bmap_stats *stats) |
1544 | { | 1631 | { |
1545 | struct buffer_head *bh; | 1632 | struct buffer_head *bh; |
1546 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | ||
1547 | struct inode *dat = NULL; | 1633 | struct inode *dat = NULL; |
1548 | int ret; | 1634 | int ret; |
1549 | 1635 | ||
@@ -1551,12 +1637,12 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
1551 | 1637 | ||
1552 | /* for data */ | 1638 | /* for data */ |
1553 | /* cannot find near ptr */ | 1639 | /* cannot find near ptr */ |
1554 | if (NILFS_BMAP_USE_VBN(bmap)) { | 1640 | if (NILFS_BMAP_USE_VBN(btree)) { |
1555 | dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key); | 1641 | dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key); |
1556 | dat = nilfs_bmap_get_dat(bmap); | 1642 | dat = nilfs_bmap_get_dat(btree); |
1557 | } | 1643 | } |
1558 | 1644 | ||
1559 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat); | 1645 | ret = nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat); |
1560 | if (ret < 0) | 1646 | if (ret < 0) |
1561 | return ret; | 1647 | return ret; |
1562 | 1648 | ||
@@ -1564,7 +1650,7 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
1564 | stats->bs_nblocks++; | 1650 | stats->bs_nblocks++; |
1565 | if (nreq != NULL) { | 1651 | if (nreq != NULL) { |
1566 | nreq->bpr_ptr = dreq->bpr_ptr + 1; | 1652 | nreq->bpr_ptr = dreq->bpr_ptr + 1; |
1567 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat); | 1653 | ret = nilfs_bmap_prepare_alloc_ptr(btree, nreq, dat); |
1568 | if (ret < 0) | 1654 | if (ret < 0) |
1569 | goto err_out_dreq; | 1655 | goto err_out_dreq; |
1570 | 1656 | ||
@@ -1581,16 +1667,16 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
1581 | 1667 | ||
1582 | /* error */ | 1668 | /* error */ |
1583 | err_out_nreq: | 1669 | err_out_nreq: |
1584 | nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat); | 1670 | nilfs_bmap_abort_alloc_ptr(btree, nreq, dat); |
1585 | err_out_dreq: | 1671 | err_out_dreq: |
1586 | nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat); | 1672 | nilfs_bmap_abort_alloc_ptr(btree, dreq, dat); |
1587 | stats->bs_nblocks = 0; | 1673 | stats->bs_nblocks = 0; |
1588 | return ret; | 1674 | return ret; |
1589 | 1675 | ||
1590 | } | 1676 | } |
1591 | 1677 | ||
1592 | static void | 1678 | static void |
1593 | nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | 1679 | nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree, |
1594 | __u64 key, __u64 ptr, | 1680 | __u64 key, __u64 ptr, |
1595 | const __u64 *keys, const __u64 *ptrs, | 1681 | const __u64 *keys, const __u64 *ptrs, |
1596 | int n, | 1682 | int n, |
@@ -1598,57 +1684,59 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | |||
1598 | union nilfs_bmap_ptr_req *nreq, | 1684 | union nilfs_bmap_ptr_req *nreq, |
1599 | struct buffer_head *bh) | 1685 | struct buffer_head *bh) |
1600 | { | 1686 | { |
1601 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | ||
1602 | struct nilfs_btree_node *node; | 1687 | struct nilfs_btree_node *node; |
1603 | struct inode *dat; | 1688 | struct inode *dat; |
1604 | __u64 tmpptr; | 1689 | __u64 tmpptr; |
1690 | int ncblk; | ||
1605 | 1691 | ||
1606 | /* free resources */ | 1692 | /* free resources */ |
1607 | if (bmap->b_ops->bop_clear != NULL) | 1693 | if (btree->b_ops->bop_clear != NULL) |
1608 | bmap->b_ops->bop_clear(bmap); | 1694 | btree->b_ops->bop_clear(btree); |
1609 | 1695 | ||
1610 | /* ptr must be a pointer to a buffer head. */ | 1696 | /* ptr must be a pointer to a buffer head. */ |
1611 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); | 1697 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); |
1612 | 1698 | ||
1613 | /* convert and insert */ | 1699 | /* convert and insert */ |
1614 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; | 1700 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; |
1615 | nilfs_btree_init(bmap); | 1701 | nilfs_btree_init(btree); |
1616 | if (nreq != NULL) { | 1702 | if (nreq != NULL) { |
1617 | nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat); | 1703 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); |
1618 | nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat); | 1704 | nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); |
1619 | 1705 | ||
1620 | /* create child node at level 1 */ | 1706 | /* create child node at level 1 */ |
1621 | node = (struct nilfs_btree_node *)bh->b_data; | 1707 | node = (struct nilfs_btree_node *)bh->b_data; |
1622 | nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs); | 1708 | ncblk = nilfs_btree_nchildren_per_block(btree); |
1623 | nilfs_btree_node_insert(btree, node, | 1709 | nilfs_btree_node_init(node, 0, 1, n, ncblk, keys, ptrs); |
1624 | key, dreq->bpr_ptr, n); | 1710 | nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr, ncblk); |
1625 | if (!buffer_dirty(bh)) | 1711 | if (!buffer_dirty(bh)) |
1626 | nilfs_btnode_mark_dirty(bh); | 1712 | nilfs_btnode_mark_dirty(bh); |
1627 | if (!nilfs_bmap_dirty(bmap)) | 1713 | if (!nilfs_bmap_dirty(btree)) |
1628 | nilfs_bmap_set_dirty(bmap); | 1714 | nilfs_bmap_set_dirty(btree); |
1629 | 1715 | ||
1630 | brelse(bh); | 1716 | brelse(bh); |
1631 | 1717 | ||
1632 | /* create root node at level 2 */ | 1718 | /* create root node at level 2 */ |
1633 | node = nilfs_btree_get_root(btree); | 1719 | node = nilfs_btree_get_root(btree); |
1634 | tmpptr = nreq->bpr_ptr; | 1720 | tmpptr = nreq->bpr_ptr; |
1635 | nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, | 1721 | nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 2, 1, |
1636 | 2, 1, &keys[0], &tmpptr); | 1722 | NILFS_BTREE_ROOT_NCHILDREN_MAX, |
1723 | &keys[0], &tmpptr); | ||
1637 | } else { | 1724 | } else { |
1638 | nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat); | 1725 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); |
1639 | 1726 | ||
1640 | /* create root node at level 1 */ | 1727 | /* create root node at level 1 */ |
1641 | node = nilfs_btree_get_root(btree); | 1728 | node = nilfs_btree_get_root(btree); |
1642 | nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, | 1729 | nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 1, n, |
1643 | 1, n, keys, ptrs); | 1730 | NILFS_BTREE_ROOT_NCHILDREN_MAX, |
1644 | nilfs_btree_node_insert(btree, node, | 1731 | keys, ptrs); |
1645 | key, dreq->bpr_ptr, n); | 1732 | nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr, |
1646 | if (!nilfs_bmap_dirty(bmap)) | 1733 | NILFS_BTREE_ROOT_NCHILDREN_MAX); |
1647 | nilfs_bmap_set_dirty(bmap); | 1734 | if (!nilfs_bmap_dirty(btree)) |
1735 | nilfs_bmap_set_dirty(btree); | ||
1648 | } | 1736 | } |
1649 | 1737 | ||
1650 | if (NILFS_BMAP_USE_VBN(bmap)) | 1738 | if (NILFS_BMAP_USE_VBN(btree)) |
1651 | nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr); | 1739 | nilfs_bmap_set_target_v(btree, key, dreq->bpr_ptr); |
1652 | } | 1740 | } |
1653 | 1741 | ||
1654 | /** | 1742 | /** |
@@ -1660,7 +1748,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | |||
1660 | * @ptrs: | 1748 | * @ptrs: |
1661 | * @n: | 1749 | * @n: |
1662 | */ | 1750 | */ |
1663 | int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap, | 1751 | int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree, |
1664 | __u64 key, __u64 ptr, | 1752 | __u64 key, __u64 ptr, |
1665 | const __u64 *keys, const __u64 *ptrs, int n) | 1753 | const __u64 *keys, const __u64 *ptrs, int n) |
1666 | { | 1754 | { |
@@ -1673,7 +1761,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap, | |||
1673 | di = &dreq; | 1761 | di = &dreq; |
1674 | ni = NULL; | 1762 | ni = NULL; |
1675 | } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX( | 1763 | } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX( |
1676 | 1 << bmap->b_inode->i_blkbits)) { | 1764 | 1 << btree->b_inode->i_blkbits)) { |
1677 | di = &dreq; | 1765 | di = &dreq; |
1678 | ni = &nreq; | 1766 | ni = &nreq; |
1679 | } else { | 1767 | } else { |
@@ -1682,17 +1770,17 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap, | |||
1682 | BUG(); | 1770 | BUG(); |
1683 | } | 1771 | } |
1684 | 1772 | ||
1685 | ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh, | 1773 | ret = nilfs_btree_prepare_convert_and_insert(btree, key, di, ni, &bh, |
1686 | &stats); | 1774 | &stats); |
1687 | if (ret < 0) | 1775 | if (ret < 0) |
1688 | return ret; | 1776 | return ret; |
1689 | nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n, | 1777 | nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n, |
1690 | di, ni, bh); | 1778 | di, ni, bh); |
1691 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); | 1779 | nilfs_bmap_add_blocks(btree, stats.bs_nblocks); |
1692 | return 0; | 1780 | return 0; |
1693 | } | 1781 | } |
1694 | 1782 | ||
1695 | static int nilfs_btree_propagate_p(struct nilfs_btree *btree, | 1783 | static int nilfs_btree_propagate_p(struct nilfs_bmap *btree, |
1696 | struct nilfs_btree_path *path, | 1784 | struct nilfs_btree_path *path, |
1697 | int level, | 1785 | int level, |
1698 | struct buffer_head *bh) | 1786 | struct buffer_head *bh) |
@@ -1704,17 +1792,17 @@ static int nilfs_btree_propagate_p(struct nilfs_btree *btree, | |||
1704 | return 0; | 1792 | return 0; |
1705 | } | 1793 | } |
1706 | 1794 | ||
1707 | static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | 1795 | static int nilfs_btree_prepare_update_v(struct nilfs_bmap *btree, |
1708 | struct nilfs_btree_path *path, | 1796 | struct nilfs_btree_path *path, |
1709 | int level, struct inode *dat) | 1797 | int level, struct inode *dat) |
1710 | { | 1798 | { |
1711 | struct nilfs_btree_node *parent; | 1799 | struct nilfs_btree_node *parent; |
1712 | int ret; | 1800 | int ncmax, ret; |
1713 | 1801 | ||
1714 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1802 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1715 | path[level].bp_oldreq.bpr_ptr = | 1803 | path[level].bp_oldreq.bpr_ptr = |
1716 | nilfs_btree_node_get_ptr(btree, parent, | 1804 | nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index, |
1717 | path[level + 1].bp_index); | 1805 | ncmax); |
1718 | path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; | 1806 | path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; |
1719 | ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req, | 1807 | ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req, |
1720 | &path[level].bp_newreq.bpr_req); | 1808 | &path[level].bp_newreq.bpr_req); |
@@ -1726,7 +1814,7 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | |||
1726 | path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr; | 1814 | path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr; |
1727 | path[level].bp_ctxt.bh = path[level].bp_bh; | 1815 | path[level].bp_ctxt.bh = path[level].bp_bh; |
1728 | ret = nilfs_btnode_prepare_change_key( | 1816 | ret = nilfs_btnode_prepare_change_key( |
1729 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1817 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1730 | &path[level].bp_ctxt); | 1818 | &path[level].bp_ctxt); |
1731 | if (ret < 0) { | 1819 | if (ret < 0) { |
1732 | nilfs_dat_abort_update(dat, | 1820 | nilfs_dat_abort_update(dat, |
@@ -1739,30 +1827,31 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | |||
1739 | return 0; | 1827 | return 0; |
1740 | } | 1828 | } |
1741 | 1829 | ||
1742 | static void nilfs_btree_commit_update_v(struct nilfs_btree *btree, | 1830 | static void nilfs_btree_commit_update_v(struct nilfs_bmap *btree, |
1743 | struct nilfs_btree_path *path, | 1831 | struct nilfs_btree_path *path, |
1744 | int level, struct inode *dat) | 1832 | int level, struct inode *dat) |
1745 | { | 1833 | { |
1746 | struct nilfs_btree_node *parent; | 1834 | struct nilfs_btree_node *parent; |
1835 | int ncmax; | ||
1747 | 1836 | ||
1748 | nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req, | 1837 | nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req, |
1749 | &path[level].bp_newreq.bpr_req, | 1838 | &path[level].bp_newreq.bpr_req, |
1750 | btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS); | 1839 | btree->b_ptr_type == NILFS_BMAP_PTR_VS); |
1751 | 1840 | ||
1752 | if (buffer_nilfs_node(path[level].bp_bh)) { | 1841 | if (buffer_nilfs_node(path[level].bp_bh)) { |
1753 | nilfs_btnode_commit_change_key( | 1842 | nilfs_btnode_commit_change_key( |
1754 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1843 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1755 | &path[level].bp_ctxt); | 1844 | &path[level].bp_ctxt); |
1756 | path[level].bp_bh = path[level].bp_ctxt.bh; | 1845 | path[level].bp_bh = path[level].bp_ctxt.bh; |
1757 | } | 1846 | } |
1758 | set_buffer_nilfs_volatile(path[level].bp_bh); | 1847 | set_buffer_nilfs_volatile(path[level].bp_bh); |
1759 | 1848 | ||
1760 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1849 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1761 | nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index, | 1850 | nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index, |
1762 | path[level].bp_newreq.bpr_ptr); | 1851 | path[level].bp_newreq.bpr_ptr, ncmax); |
1763 | } | 1852 | } |
1764 | 1853 | ||
1765 | static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, | 1854 | static void nilfs_btree_abort_update_v(struct nilfs_bmap *btree, |
1766 | struct nilfs_btree_path *path, | 1855 | struct nilfs_btree_path *path, |
1767 | int level, struct inode *dat) | 1856 | int level, struct inode *dat) |
1768 | { | 1857 | { |
@@ -1770,11 +1859,11 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, | |||
1770 | &path[level].bp_newreq.bpr_req); | 1859 | &path[level].bp_newreq.bpr_req); |
1771 | if (buffer_nilfs_node(path[level].bp_bh)) | 1860 | if (buffer_nilfs_node(path[level].bp_bh)) |
1772 | nilfs_btnode_abort_change_key( | 1861 | nilfs_btnode_abort_change_key( |
1773 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1862 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1774 | &path[level].bp_ctxt); | 1863 | &path[level].bp_ctxt); |
1775 | } | 1864 | } |
1776 | 1865 | ||
1777 | static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, | 1866 | static int nilfs_btree_prepare_propagate_v(struct nilfs_bmap *btree, |
1778 | struct nilfs_btree_path *path, | 1867 | struct nilfs_btree_path *path, |
1779 | int minlevel, int *maxlevelp, | 1868 | int minlevel, int *maxlevelp, |
1780 | struct inode *dat) | 1869 | struct inode *dat) |
@@ -1809,7 +1898,7 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, | |||
1809 | return ret; | 1898 | return ret; |
1810 | } | 1899 | } |
1811 | 1900 | ||
1812 | static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree, | 1901 | static void nilfs_btree_commit_propagate_v(struct nilfs_bmap *btree, |
1813 | struct nilfs_btree_path *path, | 1902 | struct nilfs_btree_path *path, |
1814 | int minlevel, int maxlevel, | 1903 | int minlevel, int maxlevel, |
1815 | struct buffer_head *bh, | 1904 | struct buffer_head *bh, |
@@ -1824,14 +1913,15 @@ static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree, | |||
1824 | nilfs_btree_commit_update_v(btree, path, level, dat); | 1913 | nilfs_btree_commit_update_v(btree, path, level, dat); |
1825 | } | 1914 | } |
1826 | 1915 | ||
1827 | static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | 1916 | static int nilfs_btree_propagate_v(struct nilfs_bmap *btree, |
1828 | struct nilfs_btree_path *path, | 1917 | struct nilfs_btree_path *path, |
1829 | int level, struct buffer_head *bh) | 1918 | int level, struct buffer_head *bh) |
1830 | { | 1919 | { |
1831 | int maxlevel = 0, ret; | 1920 | int maxlevel = 0, ret; |
1832 | struct nilfs_btree_node *parent; | 1921 | struct nilfs_btree_node *parent; |
1833 | struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 1922 | struct inode *dat = nilfs_bmap_get_dat(btree); |
1834 | __u64 ptr; | 1923 | __u64 ptr; |
1924 | int ncmax; | ||
1835 | 1925 | ||
1836 | get_bh(bh); | 1926 | get_bh(bh); |
1837 | path[level].bp_bh = bh; | 1927 | path[level].bp_bh = bh; |
@@ -1841,9 +1931,10 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | |||
1841 | goto out; | 1931 | goto out; |
1842 | 1932 | ||
1843 | if (buffer_nilfs_volatile(path[level].bp_bh)) { | 1933 | if (buffer_nilfs_volatile(path[level].bp_bh)) { |
1844 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1934 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1845 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 1935 | ptr = nilfs_btree_node_get_ptr(parent, |
1846 | path[level + 1].bp_index); | 1936 | path[level + 1].bp_index, |
1937 | ncmax); | ||
1847 | ret = nilfs_dat_mark_dirty(dat, ptr); | 1938 | ret = nilfs_dat_mark_dirty(dat, ptr); |
1848 | if (ret < 0) | 1939 | if (ret < 0) |
1849 | goto out; | 1940 | goto out; |
@@ -1857,10 +1948,9 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | |||
1857 | return ret; | 1948 | return ret; |
1858 | } | 1949 | } |
1859 | 1950 | ||
1860 | static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | 1951 | static int nilfs_btree_propagate(struct nilfs_bmap *btree, |
1861 | struct buffer_head *bh) | 1952 | struct buffer_head *bh) |
1862 | { | 1953 | { |
1863 | struct nilfs_btree *btree; | ||
1864 | struct nilfs_btree_path *path; | 1954 | struct nilfs_btree_path *path; |
1865 | struct nilfs_btree_node *node; | 1955 | struct nilfs_btree_node *node; |
1866 | __u64 key; | 1956 | __u64 key; |
@@ -1868,7 +1958,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1868 | 1958 | ||
1869 | WARN_ON(!buffer_dirty(bh)); | 1959 | WARN_ON(!buffer_dirty(bh)); |
1870 | 1960 | ||
1871 | btree = (struct nilfs_btree *)bmap; | ||
1872 | path = nilfs_btree_alloc_path(); | 1961 | path = nilfs_btree_alloc_path(); |
1873 | if (path == NULL) | 1962 | if (path == NULL) |
1874 | return -ENOMEM; | 1963 | return -ENOMEM; |
@@ -1878,11 +1967,11 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1878 | key = nilfs_btree_node_get_key(node, 0); | 1967 | key = nilfs_btree_node_get_key(node, 0); |
1879 | level = nilfs_btree_node_get_level(node); | 1968 | level = nilfs_btree_node_get_level(node); |
1880 | } else { | 1969 | } else { |
1881 | key = nilfs_bmap_data_get_key(bmap, bh); | 1970 | key = nilfs_bmap_data_get_key(btree, bh); |
1882 | level = NILFS_BTREE_LEVEL_DATA; | 1971 | level = NILFS_BTREE_LEVEL_DATA; |
1883 | } | 1972 | } |
1884 | 1973 | ||
1885 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1); | 1974 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0); |
1886 | if (ret < 0) { | 1975 | if (ret < 0) { |
1887 | if (unlikely(ret == -ENOENT)) | 1976 | if (unlikely(ret == -ENOENT)) |
1888 | printk(KERN_CRIT "%s: key = %llu, level == %d\n", | 1977 | printk(KERN_CRIT "%s: key = %llu, level == %d\n", |
@@ -1890,7 +1979,7 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1890 | goto out; | 1979 | goto out; |
1891 | } | 1980 | } |
1892 | 1981 | ||
1893 | ret = NILFS_BMAP_USE_VBN(bmap) ? | 1982 | ret = NILFS_BMAP_USE_VBN(btree) ? |
1894 | nilfs_btree_propagate_v(btree, path, level, bh) : | 1983 | nilfs_btree_propagate_v(btree, path, level, bh) : |
1895 | nilfs_btree_propagate_p(btree, path, level, bh); | 1984 | nilfs_btree_propagate_p(btree, path, level, bh); |
1896 | 1985 | ||
@@ -1900,13 +1989,13 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1900 | return ret; | 1989 | return ret; |
1901 | } | 1990 | } |
1902 | 1991 | ||
1903 | static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap, | 1992 | static int nilfs_btree_propagate_gc(struct nilfs_bmap *btree, |
1904 | struct buffer_head *bh) | 1993 | struct buffer_head *bh) |
1905 | { | 1994 | { |
1906 | return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr); | 1995 | return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(btree), bh->b_blocknr); |
1907 | } | 1996 | } |
1908 | 1997 | ||
1909 | static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | 1998 | static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree, |
1910 | struct list_head *lists, | 1999 | struct list_head *lists, |
1911 | struct buffer_head *bh) | 2000 | struct buffer_head *bh) |
1912 | { | 2001 | { |
@@ -1920,6 +2009,18 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | |||
1920 | node = (struct nilfs_btree_node *)bh->b_data; | 2009 | node = (struct nilfs_btree_node *)bh->b_data; |
1921 | key = nilfs_btree_node_get_key(node, 0); | 2010 | key = nilfs_btree_node_get_key(node, 0); |
1922 | level = nilfs_btree_node_get_level(node); | 2011 | level = nilfs_btree_node_get_level(node); |
2012 | if (level < NILFS_BTREE_LEVEL_NODE_MIN || | ||
2013 | level >= NILFS_BTREE_LEVEL_MAX) { | ||
2014 | dump_stack(); | ||
2015 | printk(KERN_WARNING | ||
2016 | "%s: invalid btree level: %d (key=%llu, ino=%lu, " | ||
2017 | "blocknr=%llu)\n", | ||
2018 | __func__, level, (unsigned long long)key, | ||
2019 | NILFS_BMAP_I(btree)->vfs_inode.i_ino, | ||
2020 | (unsigned long long)bh->b_blocknr); | ||
2021 | return; | ||
2022 | } | ||
2023 | |||
1923 | list_for_each(head, &lists[level]) { | 2024 | list_for_each(head, &lists[level]) { |
1924 | cbh = list_entry(head, struct buffer_head, b_assoc_buffers); | 2025 | cbh = list_entry(head, struct buffer_head, b_assoc_buffers); |
1925 | cnode = (struct nilfs_btree_node *)cbh->b_data; | 2026 | cnode = (struct nilfs_btree_node *)cbh->b_data; |
@@ -1930,11 +2031,10 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | |||
1930 | list_add_tail(&bh->b_assoc_buffers, head); | 2031 | list_add_tail(&bh->b_assoc_buffers, head); |
1931 | } | 2032 | } |
1932 | 2033 | ||
1933 | static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap, | 2034 | static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree, |
1934 | struct list_head *listp) | 2035 | struct list_head *listp) |
1935 | { | 2036 | { |
1936 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | 2037 | struct address_space *btcache = &NILFS_BMAP_I(btree)->i_btnode_cache; |
1937 | struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache; | ||
1938 | struct list_head lists[NILFS_BTREE_LEVEL_MAX]; | 2038 | struct list_head lists[NILFS_BTREE_LEVEL_MAX]; |
1939 | struct pagevec pvec; | 2039 | struct pagevec pvec; |
1940 | struct buffer_head *bh, *head; | 2040 | struct buffer_head *bh, *head; |
@@ -1968,7 +2068,7 @@ static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap, | |||
1968 | list_splice_tail(&lists[level], listp); | 2068 | list_splice_tail(&lists[level], listp); |
1969 | } | 2069 | } |
1970 | 2070 | ||
1971 | static int nilfs_btree_assign_p(struct nilfs_btree *btree, | 2071 | static int nilfs_btree_assign_p(struct nilfs_bmap *btree, |
1972 | struct nilfs_btree_path *path, | 2072 | struct nilfs_btree_path *path, |
1973 | int level, | 2073 | int level, |
1974 | struct buffer_head **bh, | 2074 | struct buffer_head **bh, |
@@ -1978,38 +2078,38 @@ static int nilfs_btree_assign_p(struct nilfs_btree *btree, | |||
1978 | struct nilfs_btree_node *parent; | 2078 | struct nilfs_btree_node *parent; |
1979 | __u64 key; | 2079 | __u64 key; |
1980 | __u64 ptr; | 2080 | __u64 ptr; |
1981 | int ret; | 2081 | int ncmax, ret; |
1982 | 2082 | ||
1983 | parent = nilfs_btree_get_node(btree, path, level + 1); | 2083 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1984 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 2084 | ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index, |
1985 | path[level + 1].bp_index); | 2085 | ncmax); |
1986 | if (buffer_nilfs_node(*bh)) { | 2086 | if (buffer_nilfs_node(*bh)) { |
1987 | path[level].bp_ctxt.oldkey = ptr; | 2087 | path[level].bp_ctxt.oldkey = ptr; |
1988 | path[level].bp_ctxt.newkey = blocknr; | 2088 | path[level].bp_ctxt.newkey = blocknr; |
1989 | path[level].bp_ctxt.bh = *bh; | 2089 | path[level].bp_ctxt.bh = *bh; |
1990 | ret = nilfs_btnode_prepare_change_key( | 2090 | ret = nilfs_btnode_prepare_change_key( |
1991 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 2091 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1992 | &path[level].bp_ctxt); | 2092 | &path[level].bp_ctxt); |
1993 | if (ret < 0) | 2093 | if (ret < 0) |
1994 | return ret; | 2094 | return ret; |
1995 | nilfs_btnode_commit_change_key( | 2095 | nilfs_btnode_commit_change_key( |
1996 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 2096 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1997 | &path[level].bp_ctxt); | 2097 | &path[level].bp_ctxt); |
1998 | *bh = path[level].bp_ctxt.bh; | 2098 | *bh = path[level].bp_ctxt.bh; |
1999 | } | 2099 | } |
2000 | 2100 | ||
2001 | nilfs_btree_node_set_ptr(btree, parent, | 2101 | nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index, blocknr, |
2002 | path[level + 1].bp_index, blocknr); | 2102 | ncmax); |
2003 | 2103 | ||
2004 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); | 2104 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); |
2005 | /* on-disk format */ | 2105 | /* on-disk format */ |
2006 | binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2106 | binfo->bi_dat.bi_blkoff = cpu_to_le64(key); |
2007 | binfo->bi_dat.bi_level = level; | 2107 | binfo->bi_dat.bi_level = level; |
2008 | 2108 | ||
2009 | return 0; | 2109 | return 0; |
2010 | } | 2110 | } |
2011 | 2111 | ||
2012 | static int nilfs_btree_assign_v(struct nilfs_btree *btree, | 2112 | static int nilfs_btree_assign_v(struct nilfs_bmap *btree, |
2013 | struct nilfs_btree_path *path, | 2113 | struct nilfs_btree_path *path, |
2014 | int level, | 2114 | int level, |
2015 | struct buffer_head **bh, | 2115 | struct buffer_head **bh, |
@@ -2017,15 +2117,15 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, | |||
2017 | union nilfs_binfo *binfo) | 2117 | union nilfs_binfo *binfo) |
2018 | { | 2118 | { |
2019 | struct nilfs_btree_node *parent; | 2119 | struct nilfs_btree_node *parent; |
2020 | struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 2120 | struct inode *dat = nilfs_bmap_get_dat(btree); |
2021 | __u64 key; | 2121 | __u64 key; |
2022 | __u64 ptr; | 2122 | __u64 ptr; |
2023 | union nilfs_bmap_ptr_req req; | 2123 | union nilfs_bmap_ptr_req req; |
2024 | int ret; | 2124 | int ncmax, ret; |
2025 | 2125 | ||
2026 | parent = nilfs_btree_get_node(btree, path, level + 1); | 2126 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
2027 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 2127 | ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index, |
2028 | path[level + 1].bp_index); | 2128 | ncmax); |
2029 | req.bpr_ptr = ptr; | 2129 | req.bpr_ptr = ptr; |
2030 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); | 2130 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); |
2031 | if (ret < 0) | 2131 | if (ret < 0) |
@@ -2034,24 +2134,22 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, | |||
2034 | 2134 | ||
2035 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); | 2135 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); |
2036 | /* on-disk format */ | 2136 | /* on-disk format */ |
2037 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); | 2137 | binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr); |
2038 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2138 | binfo->bi_v.bi_blkoff = cpu_to_le64(key); |
2039 | 2139 | ||
2040 | return 0; | 2140 | return 0; |
2041 | } | 2141 | } |
2042 | 2142 | ||
2043 | static int nilfs_btree_assign(struct nilfs_bmap *bmap, | 2143 | static int nilfs_btree_assign(struct nilfs_bmap *btree, |
2044 | struct buffer_head **bh, | 2144 | struct buffer_head **bh, |
2045 | sector_t blocknr, | 2145 | sector_t blocknr, |
2046 | union nilfs_binfo *binfo) | 2146 | union nilfs_binfo *binfo) |
2047 | { | 2147 | { |
2048 | struct nilfs_btree *btree; | ||
2049 | struct nilfs_btree_path *path; | 2148 | struct nilfs_btree_path *path; |
2050 | struct nilfs_btree_node *node; | 2149 | struct nilfs_btree_node *node; |
2051 | __u64 key; | 2150 | __u64 key; |
2052 | int level, ret; | 2151 | int level, ret; |
2053 | 2152 | ||
2054 | btree = (struct nilfs_btree *)bmap; | ||
2055 | path = nilfs_btree_alloc_path(); | 2153 | path = nilfs_btree_alloc_path(); |
2056 | if (path == NULL) | 2154 | if (path == NULL) |
2057 | return -ENOMEM; | 2155 | return -ENOMEM; |
@@ -2061,17 +2159,17 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
2061 | key = nilfs_btree_node_get_key(node, 0); | 2159 | key = nilfs_btree_node_get_key(node, 0); |
2062 | level = nilfs_btree_node_get_level(node); | 2160 | level = nilfs_btree_node_get_level(node); |
2063 | } else { | 2161 | } else { |
2064 | key = nilfs_bmap_data_get_key(bmap, *bh); | 2162 | key = nilfs_bmap_data_get_key(btree, *bh); |
2065 | level = NILFS_BTREE_LEVEL_DATA; | 2163 | level = NILFS_BTREE_LEVEL_DATA; |
2066 | } | 2164 | } |
2067 | 2165 | ||
2068 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1); | 2166 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0); |
2069 | if (ret < 0) { | 2167 | if (ret < 0) { |
2070 | WARN_ON(ret == -ENOENT); | 2168 | WARN_ON(ret == -ENOENT); |
2071 | goto out; | 2169 | goto out; |
2072 | } | 2170 | } |
2073 | 2171 | ||
2074 | ret = NILFS_BMAP_USE_VBN(bmap) ? | 2172 | ret = NILFS_BMAP_USE_VBN(btree) ? |
2075 | nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) : | 2173 | nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) : |
2076 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); | 2174 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); |
2077 | 2175 | ||
@@ -2081,7 +2179,7 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
2081 | return ret; | 2179 | return ret; |
2082 | } | 2180 | } |
2083 | 2181 | ||
2084 | static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, | 2182 | static int nilfs_btree_assign_gc(struct nilfs_bmap *btree, |
2085 | struct buffer_head **bh, | 2183 | struct buffer_head **bh, |
2086 | sector_t blocknr, | 2184 | sector_t blocknr, |
2087 | union nilfs_binfo *binfo) | 2185 | union nilfs_binfo *binfo) |
@@ -2090,7 +2188,7 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, | |||
2090 | __u64 key; | 2188 | __u64 key; |
2091 | int ret; | 2189 | int ret; |
2092 | 2190 | ||
2093 | ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr, | 2191 | ret = nilfs_dat_move(nilfs_bmap_get_dat(btree), (*bh)->b_blocknr, |
2094 | blocknr); | 2192 | blocknr); |
2095 | if (ret < 0) | 2193 | if (ret < 0) |
2096 | return ret; | 2194 | return ret; |
@@ -2099,29 +2197,27 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, | |||
2099 | node = (struct nilfs_btree_node *)(*bh)->b_data; | 2197 | node = (struct nilfs_btree_node *)(*bh)->b_data; |
2100 | key = nilfs_btree_node_get_key(node, 0); | 2198 | key = nilfs_btree_node_get_key(node, 0); |
2101 | } else | 2199 | } else |
2102 | key = nilfs_bmap_data_get_key(bmap, *bh); | 2200 | key = nilfs_bmap_data_get_key(btree, *bh); |
2103 | 2201 | ||
2104 | /* on-disk format */ | 2202 | /* on-disk format */ |
2105 | binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr); | 2203 | binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr); |
2106 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2204 | binfo->bi_v.bi_blkoff = cpu_to_le64(key); |
2107 | 2205 | ||
2108 | return 0; | 2206 | return 0; |
2109 | } | 2207 | } |
2110 | 2208 | ||
2111 | static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | 2209 | static int nilfs_btree_mark(struct nilfs_bmap *btree, __u64 key, int level) |
2112 | { | 2210 | { |
2113 | struct buffer_head *bh; | 2211 | struct buffer_head *bh; |
2114 | struct nilfs_btree *btree; | ||
2115 | struct nilfs_btree_path *path; | 2212 | struct nilfs_btree_path *path; |
2116 | __u64 ptr; | 2213 | __u64 ptr; |
2117 | int ret; | 2214 | int ret; |
2118 | 2215 | ||
2119 | btree = (struct nilfs_btree *)bmap; | ||
2120 | path = nilfs_btree_alloc_path(); | 2216 | path = nilfs_btree_alloc_path(); |
2121 | if (path == NULL) | 2217 | if (path == NULL) |
2122 | return -ENOMEM; | 2218 | return -ENOMEM; |
2123 | 2219 | ||
2124 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); | 2220 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1, 0); |
2125 | if (ret < 0) { | 2221 | if (ret < 0) { |
2126 | WARN_ON(ret == -ENOENT); | 2222 | WARN_ON(ret == -ENOENT); |
2127 | goto out; | 2223 | goto out; |
@@ -2135,8 +2231,8 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
2135 | if (!buffer_dirty(bh)) | 2231 | if (!buffer_dirty(bh)) |
2136 | nilfs_btnode_mark_dirty(bh); | 2232 | nilfs_btnode_mark_dirty(bh); |
2137 | brelse(bh); | 2233 | brelse(bh); |
2138 | if (!nilfs_bmap_dirty(&btree->bt_bmap)) | 2234 | if (!nilfs_bmap_dirty(btree)) |
2139 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 2235 | nilfs_bmap_set_dirty(btree); |
2140 | 2236 | ||
2141 | out: | 2237 | out: |
2142 | nilfs_btree_free_path(path); | 2238 | nilfs_btree_free_path(path); |
@@ -2186,10 +2282,14 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { | |||
2186 | int nilfs_btree_init(struct nilfs_bmap *bmap) | 2282 | int nilfs_btree_init(struct nilfs_bmap *bmap) |
2187 | { | 2283 | { |
2188 | bmap->b_ops = &nilfs_btree_ops; | 2284 | bmap->b_ops = &nilfs_btree_ops; |
2285 | bmap->b_nchildren_per_block = | ||
2286 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); | ||
2189 | return 0; | 2287 | return 0; |
2190 | } | 2288 | } |
2191 | 2289 | ||
2192 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) | 2290 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) |
2193 | { | 2291 | { |
2194 | bmap->b_ops = &nilfs_btree_ops_gc; | 2292 | bmap->b_ops = &nilfs_btree_ops_gc; |
2293 | bmap->b_nchildren_per_block = | ||
2294 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); | ||
2195 | } | 2295 | } |
diff --git a/fs/nilfs2/btree.h b/fs/nilfs2/btree.h index 43c8c5b541fd..22c02e35b6ef 100644 --- a/fs/nilfs2/btree.h +++ b/fs/nilfs2/btree.h | |||
@@ -31,14 +31,6 @@ | |||
31 | #include "bmap.h" | 31 | #include "bmap.h" |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * struct nilfs_btree - B-tree structure | ||
35 | * @bt_bmap: bmap base structure | ||
36 | */ | ||
37 | struct nilfs_btree { | ||
38 | struct nilfs_bmap bt_bmap; | ||
39 | }; | ||
40 | |||
41 | /** | ||
42 | * struct nilfs_btree_path - A path on which B-tree operations are executed | 34 | * struct nilfs_btree_path - A path on which B-tree operations are executed |
43 | * @bp_bh: buffer head of node block | 35 | * @bp_bh: buffer head of node block |
44 | * @bp_sib_bh: buffer head of sibling node block | 36 | * @bp_sib_bh: buffer head of sibling node block |
@@ -54,7 +46,7 @@ struct nilfs_btree_path { | |||
54 | union nilfs_bmap_ptr_req bp_oldreq; | 46 | union nilfs_bmap_ptr_req bp_oldreq; |
55 | union nilfs_bmap_ptr_req bp_newreq; | 47 | union nilfs_bmap_ptr_req bp_newreq; |
56 | struct nilfs_btnode_chkey_ctxt bp_ctxt; | 48 | struct nilfs_btnode_chkey_ctxt bp_ctxt; |
57 | void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *, | 49 | void (*bp_op)(struct nilfs_bmap *, struct nilfs_btree_path *, |
58 | int, __u64 *, __u64 *); | 50 | int, __u64 *, __u64 *); |
59 | }; | 51 | }; |
60 | 52 | ||
@@ -80,4 +72,6 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64, | |||
80 | const __u64 *, const __u64 *, int); | 72 | const __u64 *, const __u64 *, int); |
81 | void nilfs_btree_init_gc(struct nilfs_bmap *); | 73 | void nilfs_btree_init_gc(struct nilfs_bmap *); |
82 | 74 | ||
75 | int nilfs_btree_broken_node_block(struct buffer_head *bh); | ||
76 | |||
83 | #endif /* _NILFS_BTREE_H */ | 77 | #endif /* _NILFS_BTREE_H */ |
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 85c89dfc71f0..b60277b44468 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c | |||
@@ -141,7 +141,7 @@ static void nilfs_check_page(struct page *page) | |||
141 | } | 141 | } |
142 | for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) { | 142 | for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) { |
143 | p = (struct nilfs_dir_entry *)(kaddr + offs); | 143 | p = (struct nilfs_dir_entry *)(kaddr + offs); |
144 | rec_len = le16_to_cpu(p->rec_len); | 144 | rec_len = nilfs_rec_len_from_disk(p->rec_len); |
145 | 145 | ||
146 | if (rec_len < NILFS_DIR_REC_LEN(1)) | 146 | if (rec_len < NILFS_DIR_REC_LEN(1)) |
147 | goto Eshort; | 147 | goto Eshort; |
@@ -199,13 +199,10 @@ fail: | |||
199 | static struct page *nilfs_get_page(struct inode *dir, unsigned long n) | 199 | static struct page *nilfs_get_page(struct inode *dir, unsigned long n) |
200 | { | 200 | { |
201 | struct address_space *mapping = dir->i_mapping; | 201 | struct address_space *mapping = dir->i_mapping; |
202 | struct page *page = read_cache_page(mapping, n, | 202 | struct page *page = read_mapping_page(mapping, n, NULL); |
203 | (filler_t *)mapping->a_ops->readpage, NULL); | 203 | |
204 | if (!IS_ERR(page)) { | 204 | if (!IS_ERR(page)) { |
205 | wait_on_page_locked(page); | ||
206 | kmap(page); | 205 | kmap(page); |
207 | if (!PageUptodate(page)) | ||
208 | goto fail; | ||
209 | if (!PageChecked(page)) | 206 | if (!PageChecked(page)) |
210 | nilfs_check_page(page); | 207 | nilfs_check_page(page); |
211 | if (PageError(page)) | 208 | if (PageError(page)) |
@@ -238,7 +235,8 @@ nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de) | |||
238 | */ | 235 | */ |
239 | static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p) | 236 | static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p) |
240 | { | 237 | { |
241 | return (struct nilfs_dir_entry *)((char *)p + le16_to_cpu(p->rec_len)); | 238 | return (struct nilfs_dir_entry *)((char *)p + |
239 | nilfs_rec_len_from_disk(p->rec_len)); | ||
242 | } | 240 | } |
243 | 241 | ||
244 | static unsigned char | 242 | static unsigned char |
@@ -329,7 +327,7 @@ static int nilfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
329 | goto success; | 327 | goto success; |
330 | } | 328 | } |
331 | } | 329 | } |
332 | filp->f_pos += le16_to_cpu(de->rec_len); | 330 | filp->f_pos += nilfs_rec_len_from_disk(de->rec_len); |
333 | } | 331 | } |
334 | nilfs_put_page(page); | 332 | nilfs_put_page(page); |
335 | } | 333 | } |
@@ -444,7 +442,7 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, | |||
444 | struct page *page, struct inode *inode) | 442 | struct page *page, struct inode *inode) |
445 | { | 443 | { |
446 | unsigned from = (char *) de - (char *) page_address(page); | 444 | unsigned from = (char *) de - (char *) page_address(page); |
447 | unsigned to = from + le16_to_cpu(de->rec_len); | 445 | unsigned to = from + nilfs_rec_len_from_disk(de->rec_len); |
448 | struct address_space *mapping = page->mapping; | 446 | struct address_space *mapping = page->mapping; |
449 | int err; | 447 | int err; |
450 | 448 | ||
@@ -500,7 +498,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) | |||
500 | /* We hit i_size */ | 498 | /* We hit i_size */ |
501 | name_len = 0; | 499 | name_len = 0; |
502 | rec_len = chunk_size; | 500 | rec_len = chunk_size; |
503 | de->rec_len = cpu_to_le16(chunk_size); | 501 | de->rec_len = nilfs_rec_len_to_disk(chunk_size); |
504 | de->inode = 0; | 502 | de->inode = 0; |
505 | goto got_it; | 503 | goto got_it; |
506 | } | 504 | } |
@@ -514,7 +512,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) | |||
514 | if (nilfs_match(namelen, name, de)) | 512 | if (nilfs_match(namelen, name, de)) |
515 | goto out_unlock; | 513 | goto out_unlock; |
516 | name_len = NILFS_DIR_REC_LEN(de->name_len); | 514 | name_len = NILFS_DIR_REC_LEN(de->name_len); |
517 | rec_len = le16_to_cpu(de->rec_len); | 515 | rec_len = nilfs_rec_len_from_disk(de->rec_len); |
518 | if (!de->inode && rec_len >= reclen) | 516 | if (!de->inode && rec_len >= reclen) |
519 | goto got_it; | 517 | goto got_it; |
520 | if (rec_len >= name_len + reclen) | 518 | if (rec_len >= name_len + reclen) |
@@ -537,8 +535,8 @@ got_it: | |||
537 | struct nilfs_dir_entry *de1; | 535 | struct nilfs_dir_entry *de1; |
538 | 536 | ||
539 | de1 = (struct nilfs_dir_entry *)((char *)de + name_len); | 537 | de1 = (struct nilfs_dir_entry *)((char *)de + name_len); |
540 | de1->rec_len = cpu_to_le16(rec_len - name_len); | 538 | de1->rec_len = nilfs_rec_len_to_disk(rec_len - name_len); |
541 | de->rec_len = cpu_to_le16(name_len); | 539 | de->rec_len = nilfs_rec_len_to_disk(name_len); |
542 | de = de1; | 540 | de = de1; |
543 | } | 541 | } |
544 | de->name_len = namelen; | 542 | de->name_len = namelen; |
@@ -569,7 +567,8 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) | |||
569 | struct inode *inode = mapping->host; | 567 | struct inode *inode = mapping->host; |
570 | char *kaddr = page_address(page); | 568 | char *kaddr = page_address(page); |
571 | unsigned from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1); | 569 | unsigned from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1); |
572 | unsigned to = ((char *)dir - kaddr) + le16_to_cpu(dir->rec_len); | 570 | unsigned to = ((char *)dir - kaddr) + |
571 | nilfs_rec_len_from_disk(dir->rec_len); | ||
573 | struct nilfs_dir_entry *pde = NULL; | 572 | struct nilfs_dir_entry *pde = NULL; |
574 | struct nilfs_dir_entry *de = (struct nilfs_dir_entry *)(kaddr + from); | 573 | struct nilfs_dir_entry *de = (struct nilfs_dir_entry *)(kaddr + from); |
575 | int err; | 574 | int err; |
@@ -590,7 +589,7 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) | |||
590 | err = nilfs_prepare_chunk(page, mapping, from, to); | 589 | err = nilfs_prepare_chunk(page, mapping, from, to); |
591 | BUG_ON(err); | 590 | BUG_ON(err); |
592 | if (pde) | 591 | if (pde) |
593 | pde->rec_len = cpu_to_le16(to - from); | 592 | pde->rec_len = nilfs_rec_len_to_disk(to - from); |
594 | dir->inode = 0; | 593 | dir->inode = 0; |
595 | nilfs_commit_chunk(page, mapping, from, to); | 594 | nilfs_commit_chunk(page, mapping, from, to); |
596 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | 595 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; |
@@ -624,14 +623,14 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent) | |||
624 | memset(kaddr, 0, chunk_size); | 623 | memset(kaddr, 0, chunk_size); |
625 | de = (struct nilfs_dir_entry *)kaddr; | 624 | de = (struct nilfs_dir_entry *)kaddr; |
626 | de->name_len = 1; | 625 | de->name_len = 1; |
627 | de->rec_len = cpu_to_le16(NILFS_DIR_REC_LEN(1)); | 626 | de->rec_len = nilfs_rec_len_to_disk(NILFS_DIR_REC_LEN(1)); |
628 | memcpy(de->name, ".\0\0", 4); | 627 | memcpy(de->name, ".\0\0", 4); |
629 | de->inode = cpu_to_le64(inode->i_ino); | 628 | de->inode = cpu_to_le64(inode->i_ino); |
630 | nilfs_set_de_type(de, inode); | 629 | nilfs_set_de_type(de, inode); |
631 | 630 | ||
632 | de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1)); | 631 | de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1)); |
633 | de->name_len = 2; | 632 | de->name_len = 2; |
634 | de->rec_len = cpu_to_le16(chunk_size - NILFS_DIR_REC_LEN(1)); | 633 | de->rec_len = nilfs_rec_len_to_disk(chunk_size - NILFS_DIR_REC_LEN(1)); |
635 | de->inode = cpu_to_le64(parent->i_ino); | 634 | de->inode = cpu_to_le64(parent->i_ino); |
636 | memcpy(de->name, "..\0", 4); | 635 | memcpy(de->name, "..\0", 4); |
637 | nilfs_set_de_type(de, inode); | 636 | nilfs_set_de_type(de, inode); |
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 236753df5cdf..324d80c57518 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c | |||
@@ -27,47 +27,43 @@ | |||
27 | #include "alloc.h" | 27 | #include "alloc.h" |
28 | #include "dat.h" | 28 | #include "dat.h" |
29 | 29 | ||
30 | static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct) | 30 | static inline __le64 *nilfs_direct_dptrs(const struct nilfs_bmap *direct) |
31 | { | 31 | { |
32 | return (__le64 *) | 32 | return (__le64 *) |
33 | ((struct nilfs_direct_node *)direct->d_bmap.b_u.u_data + 1); | 33 | ((struct nilfs_direct_node *)direct->b_u.u_data + 1); |
34 | } | 34 | } |
35 | 35 | ||
36 | static inline __u64 | 36 | static inline __u64 |
37 | nilfs_direct_get_ptr(const struct nilfs_direct *direct, __u64 key) | 37 | nilfs_direct_get_ptr(const struct nilfs_bmap *direct, __u64 key) |
38 | { | 38 | { |
39 | return nilfs_bmap_dptr_to_ptr(*(nilfs_direct_dptrs(direct) + key)); | 39 | return le64_to_cpu(*(nilfs_direct_dptrs(direct) + key)); |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline void nilfs_direct_set_ptr(struct nilfs_direct *direct, | 42 | static inline void nilfs_direct_set_ptr(struct nilfs_bmap *direct, |
43 | __u64 key, __u64 ptr) | 43 | __u64 key, __u64 ptr) |
44 | { | 44 | { |
45 | *(nilfs_direct_dptrs(direct) + key) = nilfs_bmap_ptr_to_dptr(ptr); | 45 | *(nilfs_direct_dptrs(direct) + key) = cpu_to_le64(ptr); |
46 | } | 46 | } |
47 | 47 | ||
48 | static int nilfs_direct_lookup(const struct nilfs_bmap *bmap, | 48 | static int nilfs_direct_lookup(const struct nilfs_bmap *direct, |
49 | __u64 key, int level, __u64 *ptrp) | 49 | __u64 key, int level, __u64 *ptrp) |
50 | { | 50 | { |
51 | struct nilfs_direct *direct; | ||
52 | __u64 ptr; | 51 | __u64 ptr; |
53 | 52 | ||
54 | direct = (struct nilfs_direct *)bmap; /* XXX: use macro for level 1 */ | ||
55 | if (key > NILFS_DIRECT_KEY_MAX || level != 1) | 53 | if (key > NILFS_DIRECT_KEY_MAX || level != 1) |
56 | return -ENOENT; | 54 | return -ENOENT; |
57 | ptr = nilfs_direct_get_ptr(direct, key); | 55 | ptr = nilfs_direct_get_ptr(direct, key); |
58 | if (ptr == NILFS_BMAP_INVALID_PTR) | 56 | if (ptr == NILFS_BMAP_INVALID_PTR) |
59 | return -ENOENT; | 57 | return -ENOENT; |
60 | 58 | ||
61 | if (ptrp != NULL) | 59 | *ptrp = ptr; |
62 | *ptrp = ptr; | ||
63 | return 0; | 60 | return 0; |
64 | } | 61 | } |
65 | 62 | ||
66 | static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap, | 63 | static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct, |
67 | __u64 key, __u64 *ptrp, | 64 | __u64 key, __u64 *ptrp, |
68 | unsigned maxblocks) | 65 | unsigned maxblocks) |
69 | { | 66 | { |
70 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
71 | struct inode *dat = NULL; | 67 | struct inode *dat = NULL; |
72 | __u64 ptr, ptr2; | 68 | __u64 ptr, ptr2; |
73 | sector_t blocknr; | 69 | sector_t blocknr; |
@@ -79,8 +75,8 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap, | |||
79 | if (ptr == NILFS_BMAP_INVALID_PTR) | 75 | if (ptr == NILFS_BMAP_INVALID_PTR) |
80 | return -ENOENT; | 76 | return -ENOENT; |
81 | 77 | ||
82 | if (NILFS_BMAP_USE_VBN(bmap)) { | 78 | if (NILFS_BMAP_USE_VBN(direct)) { |
83 | dat = nilfs_bmap_get_dat(bmap); | 79 | dat = nilfs_bmap_get_dat(direct); |
84 | ret = nilfs_dat_translate(dat, ptr, &blocknr); | 80 | ret = nilfs_dat_translate(dat, ptr, &blocknr); |
85 | if (ret < 0) | 81 | if (ret < 0) |
86 | return ret; | 82 | return ret; |
@@ -106,29 +102,21 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap, | |||
106 | } | 102 | } |
107 | 103 | ||
108 | static __u64 | 104 | static __u64 |
109 | nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key) | 105 | nilfs_direct_find_target_v(const struct nilfs_bmap *direct, __u64 key) |
110 | { | 106 | { |
111 | __u64 ptr; | 107 | __u64 ptr; |
112 | 108 | ||
113 | ptr = nilfs_bmap_find_target_seq(&direct->d_bmap, key); | 109 | ptr = nilfs_bmap_find_target_seq(direct, key); |
114 | if (ptr != NILFS_BMAP_INVALID_PTR) | 110 | if (ptr != NILFS_BMAP_INVALID_PTR) |
115 | /* sequential access */ | 111 | /* sequential access */ |
116 | return ptr; | 112 | return ptr; |
117 | else | 113 | else |
118 | /* block group */ | 114 | /* block group */ |
119 | return nilfs_bmap_find_target_in_group(&direct->d_bmap); | 115 | return nilfs_bmap_find_target_in_group(direct); |
120 | } | ||
121 | |||
122 | static void nilfs_direct_set_target_v(struct nilfs_direct *direct, | ||
123 | __u64 key, __u64 ptr) | ||
124 | { | ||
125 | direct->d_bmap.b_last_allocated_key = key; | ||
126 | direct->d_bmap.b_last_allocated_ptr = ptr; | ||
127 | } | 116 | } |
128 | 117 | ||
129 | static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | 118 | static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) |
130 | { | 119 | { |
131 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
132 | union nilfs_bmap_ptr_req req; | 120 | union nilfs_bmap_ptr_req req; |
133 | struct inode *dat = NULL; | 121 | struct inode *dat = NULL; |
134 | struct buffer_head *bh; | 122 | struct buffer_head *bh; |
@@ -136,11 +124,11 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
136 | 124 | ||
137 | if (key > NILFS_DIRECT_KEY_MAX) | 125 | if (key > NILFS_DIRECT_KEY_MAX) |
138 | return -ENOENT; | 126 | return -ENOENT; |
139 | if (nilfs_direct_get_ptr(direct, key) != NILFS_BMAP_INVALID_PTR) | 127 | if (nilfs_direct_get_ptr(bmap, key) != NILFS_BMAP_INVALID_PTR) |
140 | return -EEXIST; | 128 | return -EEXIST; |
141 | 129 | ||
142 | if (NILFS_BMAP_USE_VBN(bmap)) { | 130 | if (NILFS_BMAP_USE_VBN(bmap)) { |
143 | req.bpr_ptr = nilfs_direct_find_target_v(direct, key); | 131 | req.bpr_ptr = nilfs_direct_find_target_v(bmap, key); |
144 | dat = nilfs_bmap_get_dat(bmap); | 132 | dat = nilfs_bmap_get_dat(bmap); |
145 | } | 133 | } |
146 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat); | 134 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat); |
@@ -150,13 +138,13 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
150 | set_buffer_nilfs_volatile(bh); | 138 | set_buffer_nilfs_volatile(bh); |
151 | 139 | ||
152 | nilfs_bmap_commit_alloc_ptr(bmap, &req, dat); | 140 | nilfs_bmap_commit_alloc_ptr(bmap, &req, dat); |
153 | nilfs_direct_set_ptr(direct, key, req.bpr_ptr); | 141 | nilfs_direct_set_ptr(bmap, key, req.bpr_ptr); |
154 | 142 | ||
155 | if (!nilfs_bmap_dirty(bmap)) | 143 | if (!nilfs_bmap_dirty(bmap)) |
156 | nilfs_bmap_set_dirty(bmap); | 144 | nilfs_bmap_set_dirty(bmap); |
157 | 145 | ||
158 | if (NILFS_BMAP_USE_VBN(bmap)) | 146 | if (NILFS_BMAP_USE_VBN(bmap)) |
159 | nilfs_direct_set_target_v(direct, key, req.bpr_ptr); | 147 | nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr); |
160 | 148 | ||
161 | nilfs_bmap_add_blocks(bmap, 1); | 149 | nilfs_bmap_add_blocks(bmap, 1); |
162 | } | 150 | } |
@@ -165,33 +153,30 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
165 | 153 | ||
166 | static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) | 154 | static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) |
167 | { | 155 | { |
168 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
169 | union nilfs_bmap_ptr_req req; | 156 | union nilfs_bmap_ptr_req req; |
170 | struct inode *dat; | 157 | struct inode *dat; |
171 | int ret; | 158 | int ret; |
172 | 159 | ||
173 | if (key > NILFS_DIRECT_KEY_MAX || | 160 | if (key > NILFS_DIRECT_KEY_MAX || |
174 | nilfs_direct_get_ptr(direct, key) == NILFS_BMAP_INVALID_PTR) | 161 | nilfs_direct_get_ptr(bmap, key) == NILFS_BMAP_INVALID_PTR) |
175 | return -ENOENT; | 162 | return -ENOENT; |
176 | 163 | ||
177 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; | 164 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; |
178 | req.bpr_ptr = nilfs_direct_get_ptr(direct, key); | 165 | req.bpr_ptr = nilfs_direct_get_ptr(bmap, key); |
179 | 166 | ||
180 | ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat); | 167 | ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat); |
181 | if (!ret) { | 168 | if (!ret) { |
182 | nilfs_bmap_commit_end_ptr(bmap, &req, dat); | 169 | nilfs_bmap_commit_end_ptr(bmap, &req, dat); |
183 | nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR); | 170 | nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR); |
184 | nilfs_bmap_sub_blocks(bmap, 1); | 171 | nilfs_bmap_sub_blocks(bmap, 1); |
185 | } | 172 | } |
186 | return ret; | 173 | return ret; |
187 | } | 174 | } |
188 | 175 | ||
189 | static int nilfs_direct_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | 176 | static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) |
190 | { | 177 | { |
191 | struct nilfs_direct *direct; | ||
192 | __u64 key, lastkey; | 178 | __u64 key, lastkey; |
193 | 179 | ||
194 | direct = (struct nilfs_direct *)bmap; | ||
195 | lastkey = NILFS_DIRECT_KEY_MAX + 1; | 180 | lastkey = NILFS_DIRECT_KEY_MAX + 1; |
196 | for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++) | 181 | for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++) |
197 | if (nilfs_direct_get_ptr(direct, key) != | 182 | if (nilfs_direct_get_ptr(direct, key) != |
@@ -211,15 +196,13 @@ static int nilfs_direct_check_insert(const struct nilfs_bmap *bmap, __u64 key) | |||
211 | return key > NILFS_DIRECT_KEY_MAX; | 196 | return key > NILFS_DIRECT_KEY_MAX; |
212 | } | 197 | } |
213 | 198 | ||
214 | static int nilfs_direct_gather_data(struct nilfs_bmap *bmap, | 199 | static int nilfs_direct_gather_data(struct nilfs_bmap *direct, |
215 | __u64 *keys, __u64 *ptrs, int nitems) | 200 | __u64 *keys, __u64 *ptrs, int nitems) |
216 | { | 201 | { |
217 | struct nilfs_direct *direct; | ||
218 | __u64 key; | 202 | __u64 key; |
219 | __u64 ptr; | 203 | __u64 ptr; |
220 | int n; | 204 | int n; |
221 | 205 | ||
222 | direct = (struct nilfs_direct *)bmap; | ||
223 | if (nitems > NILFS_DIRECT_NBLOCKS) | 206 | if (nitems > NILFS_DIRECT_NBLOCKS) |
224 | nitems = NILFS_DIRECT_NBLOCKS; | 207 | nitems = NILFS_DIRECT_NBLOCKS; |
225 | n = 0; | 208 | n = 0; |
@@ -237,7 +220,6 @@ static int nilfs_direct_gather_data(struct nilfs_bmap *bmap, | |||
237 | int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, | 220 | int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, |
238 | __u64 key, __u64 *keys, __u64 *ptrs, int n) | 221 | __u64 key, __u64 *keys, __u64 *ptrs, int n) |
239 | { | 222 | { |
240 | struct nilfs_direct *direct; | ||
241 | __le64 *dptrs; | 223 | __le64 *dptrs; |
242 | int ret, i, j; | 224 | int ret, i, j; |
243 | 225 | ||
@@ -253,12 +235,11 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, | |||
253 | bmap->b_ops->bop_clear(bmap); | 235 | bmap->b_ops->bop_clear(bmap); |
254 | 236 | ||
255 | /* convert */ | 237 | /* convert */ |
256 | direct = (struct nilfs_direct *)bmap; | 238 | dptrs = nilfs_direct_dptrs(bmap); |
257 | dptrs = nilfs_direct_dptrs(direct); | ||
258 | for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) { | 239 | for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) { |
259 | if ((j < n) && (i == keys[j])) { | 240 | if ((j < n) && (i == keys[j])) { |
260 | dptrs[i] = (i != key) ? | 241 | dptrs[i] = (i != key) ? |
261 | nilfs_bmap_ptr_to_dptr(ptrs[j]) : | 242 | cpu_to_le64(ptrs[j]) : |
262 | NILFS_BMAP_INVALID_PTR; | 243 | NILFS_BMAP_INVALID_PTR; |
263 | j++; | 244 | j++; |
264 | } else | 245 | } else |
@@ -269,10 +250,9 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, | |||
269 | return 0; | 250 | return 0; |
270 | } | 251 | } |
271 | 252 | ||
272 | static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, | 253 | static int nilfs_direct_propagate(struct nilfs_bmap *bmap, |
273 | struct buffer_head *bh) | 254 | struct buffer_head *bh) |
274 | { | 255 | { |
275 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
276 | struct nilfs_palloc_req oldreq, newreq; | 256 | struct nilfs_palloc_req oldreq, newreq; |
277 | struct inode *dat; | 257 | struct inode *dat; |
278 | __u64 key; | 258 | __u64 key; |
@@ -284,7 +264,7 @@ static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, | |||
284 | 264 | ||
285 | dat = nilfs_bmap_get_dat(bmap); | 265 | dat = nilfs_bmap_get_dat(bmap); |
286 | key = nilfs_bmap_data_get_key(bmap, bh); | 266 | key = nilfs_bmap_data_get_key(bmap, bh); |
287 | ptr = nilfs_direct_get_ptr(direct, key); | 267 | ptr = nilfs_direct_get_ptr(bmap, key); |
288 | if (!buffer_nilfs_volatile(bh)) { | 268 | if (!buffer_nilfs_volatile(bh)) { |
289 | oldreq.pr_entry_nr = ptr; | 269 | oldreq.pr_entry_nr = ptr; |
290 | newreq.pr_entry_nr = ptr; | 270 | newreq.pr_entry_nr = ptr; |
@@ -294,20 +274,20 @@ static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, | |||
294 | nilfs_dat_commit_update(dat, &oldreq, &newreq, | 274 | nilfs_dat_commit_update(dat, &oldreq, &newreq, |
295 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); | 275 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); |
296 | set_buffer_nilfs_volatile(bh); | 276 | set_buffer_nilfs_volatile(bh); |
297 | nilfs_direct_set_ptr(direct, key, newreq.pr_entry_nr); | 277 | nilfs_direct_set_ptr(bmap, key, newreq.pr_entry_nr); |
298 | } else | 278 | } else |
299 | ret = nilfs_dat_mark_dirty(dat, ptr); | 279 | ret = nilfs_dat_mark_dirty(dat, ptr); |
300 | 280 | ||
301 | return ret; | 281 | return ret; |
302 | } | 282 | } |
303 | 283 | ||
304 | static int nilfs_direct_assign_v(struct nilfs_direct *direct, | 284 | static int nilfs_direct_assign_v(struct nilfs_bmap *direct, |
305 | __u64 key, __u64 ptr, | 285 | __u64 key, __u64 ptr, |
306 | struct buffer_head **bh, | 286 | struct buffer_head **bh, |
307 | sector_t blocknr, | 287 | sector_t blocknr, |
308 | union nilfs_binfo *binfo) | 288 | union nilfs_binfo *binfo) |
309 | { | 289 | { |
310 | struct inode *dat = nilfs_bmap_get_dat(&direct->d_bmap); | 290 | struct inode *dat = nilfs_bmap_get_dat(direct); |
311 | union nilfs_bmap_ptr_req req; | 291 | union nilfs_bmap_ptr_req req; |
312 | int ret; | 292 | int ret; |
313 | 293 | ||
@@ -315,13 +295,13 @@ static int nilfs_direct_assign_v(struct nilfs_direct *direct, | |||
315 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); | 295 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); |
316 | if (!ret) { | 296 | if (!ret) { |
317 | nilfs_dat_commit_start(dat, &req.bpr_req, blocknr); | 297 | nilfs_dat_commit_start(dat, &req.bpr_req, blocknr); |
318 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); | 298 | binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr); |
319 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 299 | binfo->bi_v.bi_blkoff = cpu_to_le64(key); |
320 | } | 300 | } |
321 | return ret; | 301 | return ret; |
322 | } | 302 | } |
323 | 303 | ||
324 | static int nilfs_direct_assign_p(struct nilfs_direct *direct, | 304 | static int nilfs_direct_assign_p(struct nilfs_bmap *direct, |
325 | __u64 key, __u64 ptr, | 305 | __u64 key, __u64 ptr, |
326 | struct buffer_head **bh, | 306 | struct buffer_head **bh, |
327 | sector_t blocknr, | 307 | sector_t blocknr, |
@@ -329,7 +309,7 @@ static int nilfs_direct_assign_p(struct nilfs_direct *direct, | |||
329 | { | 309 | { |
330 | nilfs_direct_set_ptr(direct, key, blocknr); | 310 | nilfs_direct_set_ptr(direct, key, blocknr); |
331 | 311 | ||
332 | binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 312 | binfo->bi_dat.bi_blkoff = cpu_to_le64(key); |
333 | binfo->bi_dat.bi_level = 0; | 313 | binfo->bi_dat.bi_level = 0; |
334 | 314 | ||
335 | return 0; | 315 | return 0; |
@@ -340,18 +320,16 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap, | |||
340 | sector_t blocknr, | 320 | sector_t blocknr, |
341 | union nilfs_binfo *binfo) | 321 | union nilfs_binfo *binfo) |
342 | { | 322 | { |
343 | struct nilfs_direct *direct; | ||
344 | __u64 key; | 323 | __u64 key; |
345 | __u64 ptr; | 324 | __u64 ptr; |
346 | 325 | ||
347 | direct = (struct nilfs_direct *)bmap; | ||
348 | key = nilfs_bmap_data_get_key(bmap, *bh); | 326 | key = nilfs_bmap_data_get_key(bmap, *bh); |
349 | if (unlikely(key > NILFS_DIRECT_KEY_MAX)) { | 327 | if (unlikely(key > NILFS_DIRECT_KEY_MAX)) { |
350 | printk(KERN_CRIT "%s: invalid key: %llu\n", __func__, | 328 | printk(KERN_CRIT "%s: invalid key: %llu\n", __func__, |
351 | (unsigned long long)key); | 329 | (unsigned long long)key); |
352 | return -EINVAL; | 330 | return -EINVAL; |
353 | } | 331 | } |
354 | ptr = nilfs_direct_get_ptr(direct, key); | 332 | ptr = nilfs_direct_get_ptr(bmap, key); |
355 | if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) { | 333 | if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) { |
356 | printk(KERN_CRIT "%s: invalid pointer: %llu\n", __func__, | 334 | printk(KERN_CRIT "%s: invalid pointer: %llu\n", __func__, |
357 | (unsigned long long)ptr); | 335 | (unsigned long long)ptr); |
@@ -359,8 +337,8 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap, | |||
359 | } | 337 | } |
360 | 338 | ||
361 | return NILFS_BMAP_USE_VBN(bmap) ? | 339 | return NILFS_BMAP_USE_VBN(bmap) ? |
362 | nilfs_direct_assign_v(direct, key, ptr, bh, blocknr, binfo) : | 340 | nilfs_direct_assign_v(bmap, key, ptr, bh, blocknr, binfo) : |
363 | nilfs_direct_assign_p(direct, key, ptr, bh, blocknr, binfo); | 341 | nilfs_direct_assign_p(bmap, key, ptr, bh, blocknr, binfo); |
364 | } | 342 | } |
365 | 343 | ||
366 | static const struct nilfs_bmap_operations nilfs_direct_ops = { | 344 | static const struct nilfs_bmap_operations nilfs_direct_ops = { |
diff --git a/fs/nilfs2/direct.h b/fs/nilfs2/direct.h index a5ffd66e25d0..dc643de20a25 100644 --- a/fs/nilfs2/direct.h +++ b/fs/nilfs2/direct.h | |||
@@ -28,8 +28,6 @@ | |||
28 | #include "bmap.h" | 28 | #include "bmap.h" |
29 | 29 | ||
30 | 30 | ||
31 | struct nilfs_direct; | ||
32 | |||
33 | /** | 31 | /** |
34 | * struct nilfs_direct_node - direct node | 32 | * struct nilfs_direct_node - direct node |
35 | * @dn_flags: flags | 33 | * @dn_flags: flags |
@@ -40,15 +38,6 @@ struct nilfs_direct_node { | |||
40 | __u8 pad[7]; | 38 | __u8 pad[7]; |
41 | }; | 39 | }; |
42 | 40 | ||
43 | /** | ||
44 | * struct nilfs_direct - direct mapping | ||
45 | * @d_bmap: bmap structure | ||
46 | */ | ||
47 | struct nilfs_direct { | ||
48 | struct nilfs_bmap d_bmap; | ||
49 | }; | ||
50 | |||
51 | |||
52 | #define NILFS_DIRECT_NBLOCKS (NILFS_BMAP_SIZE / sizeof(__le64) - 1) | 41 | #define NILFS_DIRECT_NBLOCKS (NILFS_BMAP_SIZE / sizeof(__le64) - 1) |
53 | #define NILFS_DIRECT_KEY_MIN 0 | 42 | #define NILFS_DIRECT_KEY_MIN 0 |
54 | #define NILFS_DIRECT_KEY_MAX (NILFS_DIRECT_NBLOCKS - 1) | 43 | #define NILFS_DIRECT_KEY_MAX (NILFS_DIRECT_NBLOCKS - 1) |
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index 145f03cd7d3e..bed3a783129b 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #include <linux/slab.h> | 48 | #include <linux/slab.h> |
49 | #include <linux/swap.h> | 49 | #include <linux/swap.h> |
50 | #include "nilfs.h" | 50 | #include "nilfs.h" |
51 | #include "btree.h" | ||
52 | #include "btnode.h" | ||
51 | #include "page.h" | 53 | #include "page.h" |
52 | #include "mdt.h" | 54 | #include "mdt.h" |
53 | #include "dat.h" | 55 | #include "dat.h" |
@@ -149,8 +151,10 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff, | |||
149 | int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, | 151 | int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, |
150 | __u64 vbn, struct buffer_head **out_bh) | 152 | __u64 vbn, struct buffer_head **out_bh) |
151 | { | 153 | { |
152 | int ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, | 154 | int ret; |
153 | vbn ? : pbn, pbn, out_bh); | 155 | |
156 | ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, | ||
157 | vbn ? : pbn, pbn, READ, out_bh, &pbn); | ||
154 | if (ret == -EEXIST) /* internal code (cache hit) */ | 158 | if (ret == -EEXIST) /* internal code (cache hit) */ |
155 | ret = 0; | 159 | ret = 0; |
156 | return ret; | 160 | return ret; |
@@ -164,10 +168,15 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh) | |||
164 | if (buffer_dirty(bh)) | 168 | if (buffer_dirty(bh)) |
165 | return -EEXIST; | 169 | return -EEXIST; |
166 | 170 | ||
167 | if (buffer_nilfs_node(bh)) | 171 | if (buffer_nilfs_node(bh)) { |
172 | if (nilfs_btree_broken_node_block(bh)) { | ||
173 | clear_buffer_uptodate(bh); | ||
174 | return -EIO; | ||
175 | } | ||
168 | nilfs_btnode_mark_dirty(bh); | 176 | nilfs_btnode_mark_dirty(bh); |
169 | else | 177 | } else { |
170 | nilfs_mdt_mark_buffer_dirty(bh); | 178 | nilfs_mdt_mark_buffer_dirty(bh); |
179 | } | ||
171 | return 0; | 180 | return 0; |
172 | } | 181 | } |
173 | 182 | ||
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 024be8c35bb6..d01aff4957d9 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/swap.h> | 28 | #include <linux/swap.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include "nilfs.h" | 30 | #include "nilfs.h" |
31 | #include "btnode.h" | ||
31 | #include "segment.h" | 32 | #include "segment.h" |
32 | #include "page.h" | 33 | #include "page.h" |
33 | #include "mdt.h" | 34 | #include "mdt.h" |
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 47d6d7928122..0842d775b3e0 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "the_nilfs.h" | 32 | #include "the_nilfs.h" |
33 | #include "sb.h" | 33 | #include "sb.h" |
34 | #include "bmap.h" | 34 | #include "bmap.h" |
35 | #include "bmap_union.h" | ||
36 | 35 | ||
37 | /* | 36 | /* |
38 | * nilfs inode data in memory | 37 | * nilfs inode data in memory |
@@ -41,7 +40,7 @@ struct nilfs_inode_info { | |||
41 | __u32 i_flags; | 40 | __u32 i_flags; |
42 | unsigned long i_state; /* Dynamic state flags */ | 41 | unsigned long i_state; /* Dynamic state flags */ |
43 | struct nilfs_bmap *i_bmap; | 42 | struct nilfs_bmap *i_bmap; |
44 | union nilfs_bmap_union i_bmap_union; | 43 | struct nilfs_bmap i_bmap_data; |
45 | __u64 i_xattr; /* sector_t ??? */ | 44 | __u64 i_xattr; /* sector_t ??? */ |
46 | __u32 i_dir_start_lookup; | 45 | __u32 i_dir_start_lookup; |
47 | __u64 i_cno; /* check point number for GC inode */ | 46 | __u64 i_cno; /* check point number for GC inode */ |
@@ -71,9 +70,7 @@ static inline struct nilfs_inode_info *NILFS_I(const struct inode *inode) | |||
71 | static inline struct nilfs_inode_info * | 70 | static inline struct nilfs_inode_info * |
72 | NILFS_BMAP_I(const struct nilfs_bmap *bmap) | 71 | NILFS_BMAP_I(const struct nilfs_bmap *bmap) |
73 | { | 72 | { |
74 | return container_of((union nilfs_bmap_union *)bmap, | 73 | return container_of(bmap, struct nilfs_inode_info, i_bmap_data); |
75 | struct nilfs_inode_info, | ||
76 | i_bmap_union); | ||
77 | } | 74 | } |
78 | 75 | ||
79 | static inline struct inode *NILFS_BTNC_I(struct address_space *btnc) | 76 | static inline struct inode *NILFS_BTNC_I(struct address_space *btnc) |
@@ -107,6 +104,14 @@ enum { | |||
107 | }; | 104 | }; |
108 | 105 | ||
109 | /* | 106 | /* |
107 | * commit flags for nilfs_commit_super and nilfs_sync_super | ||
108 | */ | ||
109 | enum { | ||
110 | NILFS_SB_COMMIT = 0, /* Commit a super block alternately */ | ||
111 | NILFS_SB_COMMIT_ALL /* Commit both super blocks */ | ||
112 | }; | ||
113 | |||
114 | /* | ||
110 | * Macros to check inode numbers | 115 | * Macros to check inode numbers |
111 | */ | 116 | */ |
112 | #define NILFS_MDT_INO_BITS \ | 117 | #define NILFS_MDT_INO_BITS \ |
@@ -270,7 +275,14 @@ extern struct nilfs_super_block * | |||
270 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); | 275 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); |
271 | extern int nilfs_store_magic_and_option(struct super_block *, | 276 | extern int nilfs_store_magic_and_option(struct super_block *, |
272 | struct nilfs_super_block *, char *); | 277 | struct nilfs_super_block *, char *); |
278 | extern int nilfs_check_feature_compatibility(struct super_block *, | ||
279 | struct nilfs_super_block *); | ||
280 | extern void nilfs_set_log_cursor(struct nilfs_super_block *, | ||
281 | struct the_nilfs *); | ||
282 | extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, | ||
283 | int flip); | ||
273 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); | 284 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); |
285 | extern int nilfs_cleanup_super(struct nilfs_sb_info *); | ||
274 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); | 286 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); |
275 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); | 287 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); |
276 | 288 | ||
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 8de3e1e48130..aab11db2cb08 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c | |||
@@ -37,7 +37,8 @@ | |||
37 | 37 | ||
38 | #define NILFS_BUFFER_INHERENT_BITS \ | 38 | #define NILFS_BUFFER_INHERENT_BITS \ |
39 | ((1UL << BH_Uptodate) | (1UL << BH_Mapped) | (1UL << BH_NILFS_Node) | \ | 39 | ((1UL << BH_Uptodate) | (1UL << BH_Mapped) | (1UL << BH_NILFS_Node) | \ |
40 | (1UL << BH_NILFS_Volatile) | (1UL << BH_NILFS_Allocated)) | 40 | (1UL << BH_NILFS_Volatile) | (1UL << BH_NILFS_Allocated) | \ |
41 | (1UL << BH_NILFS_Checked)) | ||
41 | 42 | ||
42 | static struct buffer_head * | 43 | static struct buffer_head * |
43 | __nilfs_get_page_block(struct page *page, unsigned long block, pgoff_t index, | 44 | __nilfs_get_page_block(struct page *page, unsigned long block, pgoff_t index, |
@@ -129,6 +130,7 @@ void nilfs_forget_buffer(struct buffer_head *bh) | |||
129 | 130 | ||
130 | lock_buffer(bh); | 131 | lock_buffer(bh); |
131 | clear_buffer_nilfs_volatile(bh); | 132 | clear_buffer_nilfs_volatile(bh); |
133 | clear_buffer_nilfs_checked(bh); | ||
132 | clear_buffer_dirty(bh); | 134 | clear_buffer_dirty(bh); |
133 | if (nilfs_page_buffers_clean(page)) | 135 | if (nilfs_page_buffers_clean(page)) |
134 | __nilfs_clear_page_dirty(page); | 136 | __nilfs_clear_page_dirty(page); |
@@ -480,6 +482,7 @@ void nilfs_clear_dirty_pages(struct address_space *mapping) | |||
480 | lock_buffer(bh); | 482 | lock_buffer(bh); |
481 | clear_buffer_dirty(bh); | 483 | clear_buffer_dirty(bh); |
482 | clear_buffer_nilfs_volatile(bh); | 484 | clear_buffer_nilfs_volatile(bh); |
485 | clear_buffer_nilfs_checked(bh); | ||
483 | clear_buffer_uptodate(bh); | 486 | clear_buffer_uptodate(bh); |
484 | clear_buffer_mapped(bh); | 487 | clear_buffer_mapped(bh); |
485 | unlock_buffer(bh); | 488 | unlock_buffer(bh); |
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h index 8abca4d1c1f8..f53d8da41ed7 100644 --- a/fs/nilfs2/page.h +++ b/fs/nilfs2/page.h | |||
@@ -34,11 +34,13 @@ enum { | |||
34 | BH_NILFS_Allocated = BH_PrivateStart, | 34 | BH_NILFS_Allocated = BH_PrivateStart, |
35 | BH_NILFS_Node, | 35 | BH_NILFS_Node, |
36 | BH_NILFS_Volatile, | 36 | BH_NILFS_Volatile, |
37 | BH_NILFS_Checked, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ | 40 | BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ |
40 | BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ | 41 | BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ |
41 | BUFFER_FNS(NILFS_Volatile, nilfs_volatile) | 42 | BUFFER_FNS(NILFS_Volatile, nilfs_volatile) |
43 | BUFFER_FNS(NILFS_Checked, nilfs_checked) /* buffer is verified */ | ||
42 | 44 | ||
43 | 45 | ||
44 | void nilfs_mark_buffer_dirty(struct buffer_head *bh); | 46 | void nilfs_mark_buffer_dirty(struct buffer_head *bh); |
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index bae2a516b4ee..83e3d8c61a01 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c | |||
@@ -91,27 +91,9 @@ static int nilfs_warn_segment_error(int err) | |||
91 | return -EINVAL; | 91 | return -EINVAL; |
92 | } | 92 | } |
93 | 93 | ||
94 | static void store_segsum_info(struct nilfs_segsum_info *ssi, | ||
95 | struct nilfs_segment_summary *sum, | ||
96 | unsigned int blocksize) | ||
97 | { | ||
98 | ssi->flags = le16_to_cpu(sum->ss_flags); | ||
99 | ssi->seg_seq = le64_to_cpu(sum->ss_seq); | ||
100 | ssi->ctime = le64_to_cpu(sum->ss_create); | ||
101 | ssi->next = le64_to_cpu(sum->ss_next); | ||
102 | ssi->nblocks = le32_to_cpu(sum->ss_nblocks); | ||
103 | ssi->nfinfo = le32_to_cpu(sum->ss_nfinfo); | ||
104 | ssi->sumbytes = le32_to_cpu(sum->ss_sumbytes); | ||
105 | |||
106 | ssi->nsumblk = DIV_ROUND_UP(ssi->sumbytes, blocksize); | ||
107 | ssi->nfileblk = ssi->nblocks - ssi->nsumblk - !!NILFS_SEG_HAS_SR(ssi); | ||
108 | |||
109 | /* need to verify ->ss_bytes field if read ->ss_cno */ | ||
110 | } | ||
111 | |||
112 | /** | 94 | /** |
113 | * calc_crc_cont - check CRC of blocks continuously | 95 | * nilfs_compute_checksum - compute checksum of blocks continuously |
114 | * @sbi: nilfs_sb_info | 96 | * @nilfs: nilfs object |
115 | * @bhs: buffer head of start block | 97 | * @bhs: buffer head of start block |
116 | * @sum: place to store result | 98 | * @sum: place to store result |
117 | * @offset: offset bytes in the first block | 99 | * @offset: offset bytes in the first block |
@@ -119,23 +101,25 @@ static void store_segsum_info(struct nilfs_segsum_info *ssi, | |||
119 | * @start: DBN of start block | 101 | * @start: DBN of start block |
120 | * @nblock: number of blocks to be checked | 102 | * @nblock: number of blocks to be checked |
121 | */ | 103 | */ |
122 | static int calc_crc_cont(struct nilfs_sb_info *sbi, struct buffer_head *bhs, | 104 | static int nilfs_compute_checksum(struct the_nilfs *nilfs, |
123 | u32 *sum, unsigned long offset, u64 check_bytes, | 105 | struct buffer_head *bhs, u32 *sum, |
124 | sector_t start, unsigned long nblock) | 106 | unsigned long offset, u64 check_bytes, |
107 | sector_t start, unsigned long nblock) | ||
125 | { | 108 | { |
126 | unsigned long blocksize = sbi->s_super->s_blocksize; | 109 | unsigned int blocksize = nilfs->ns_blocksize; |
127 | unsigned long size; | 110 | unsigned long size; |
128 | u32 crc; | 111 | u32 crc; |
129 | 112 | ||
130 | BUG_ON(offset >= blocksize); | 113 | BUG_ON(offset >= blocksize); |
131 | check_bytes -= offset; | 114 | check_bytes -= offset; |
132 | size = min_t(u64, check_bytes, blocksize - offset); | 115 | size = min_t(u64, check_bytes, blocksize - offset); |
133 | crc = crc32_le(sbi->s_nilfs->ns_crc_seed, | 116 | crc = crc32_le(nilfs->ns_crc_seed, |
134 | (unsigned char *)bhs->b_data + offset, size); | 117 | (unsigned char *)bhs->b_data + offset, size); |
135 | if (--nblock > 0) { | 118 | if (--nblock > 0) { |
136 | do { | 119 | do { |
137 | struct buffer_head *bh | 120 | struct buffer_head *bh; |
138 | = sb_bread(sbi->s_super, ++start); | 121 | |
122 | bh = __bread(nilfs->ns_bdev, ++start, blocksize); | ||
139 | if (!bh) | 123 | if (!bh) |
140 | return -EIO; | 124 | return -EIO; |
141 | check_bytes -= size; | 125 | check_bytes -= size; |
@@ -150,12 +134,12 @@ static int calc_crc_cont(struct nilfs_sb_info *sbi, struct buffer_head *bhs, | |||
150 | 134 | ||
151 | /** | 135 | /** |
152 | * nilfs_read_super_root_block - read super root block | 136 | * nilfs_read_super_root_block - read super root block |
153 | * @sb: super_block | 137 | * @nilfs: nilfs object |
154 | * @sr_block: disk block number of the super root block | 138 | * @sr_block: disk block number of the super root block |
155 | * @pbh: address of a buffer_head pointer to return super root buffer | 139 | * @pbh: address of a buffer_head pointer to return super root buffer |
156 | * @check: CRC check flag | 140 | * @check: CRC check flag |
157 | */ | 141 | */ |
158 | int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | 142 | int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block, |
159 | struct buffer_head **pbh, int check) | 143 | struct buffer_head **pbh, int check) |
160 | { | 144 | { |
161 | struct buffer_head *bh_sr; | 145 | struct buffer_head *bh_sr; |
@@ -164,7 +148,7 @@ int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | |||
164 | int ret; | 148 | int ret; |
165 | 149 | ||
166 | *pbh = NULL; | 150 | *pbh = NULL; |
167 | bh_sr = sb_bread(sb, sr_block); | 151 | bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize); |
168 | if (unlikely(!bh_sr)) { | 152 | if (unlikely(!bh_sr)) { |
169 | ret = NILFS_SEG_FAIL_IO; | 153 | ret = NILFS_SEG_FAIL_IO; |
170 | goto failed; | 154 | goto failed; |
@@ -174,12 +158,13 @@ int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | |||
174 | if (check) { | 158 | if (check) { |
175 | unsigned bytes = le16_to_cpu(sr->sr_bytes); | 159 | unsigned bytes = le16_to_cpu(sr->sr_bytes); |
176 | 160 | ||
177 | if (bytes == 0 || bytes > sb->s_blocksize) { | 161 | if (bytes == 0 || bytes > nilfs->ns_blocksize) { |
178 | ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; | 162 | ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; |
179 | goto failed_bh; | 163 | goto failed_bh; |
180 | } | 164 | } |
181 | if (calc_crc_cont(NILFS_SB(sb), bh_sr, &crc, | 165 | if (nilfs_compute_checksum( |
182 | sizeof(sr->sr_sum), bytes, sr_block, 1)) { | 166 | nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes, |
167 | sr_block, 1)) { | ||
183 | ret = NILFS_SEG_FAIL_IO; | 168 | ret = NILFS_SEG_FAIL_IO; |
184 | goto failed_bh; | 169 | goto failed_bh; |
185 | } | 170 | } |
@@ -199,64 +184,76 @@ int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | |||
199 | } | 184 | } |
200 | 185 | ||
201 | /** | 186 | /** |
202 | * load_segment_summary - read segment summary of the specified partial segment | 187 | * nilfs_read_log_header - read summary header of the specified log |
203 | * @sbi: nilfs_sb_info | 188 | * @nilfs: nilfs object |
204 | * @pseg_start: start disk block number of partial segment | 189 | * @start_blocknr: start block number of the log |
205 | * @seg_seq: sequence number requested | 190 | * @sum: pointer to return segment summary structure |
206 | * @ssi: pointer to nilfs_segsum_info struct to store information | ||
207 | */ | 191 | */ |
208 | static int | 192 | static struct buffer_head * |
209 | load_segment_summary(struct nilfs_sb_info *sbi, sector_t pseg_start, | 193 | nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr, |
210 | u64 seg_seq, struct nilfs_segsum_info *ssi) | 194 | struct nilfs_segment_summary **sum) |
211 | { | 195 | { |
212 | struct buffer_head *bh_sum; | 196 | struct buffer_head *bh_sum; |
213 | struct nilfs_segment_summary *sum; | 197 | |
198 | bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); | ||
199 | if (bh_sum) | ||
200 | *sum = (struct nilfs_segment_summary *)bh_sum->b_data; | ||
201 | return bh_sum; | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * nilfs_validate_log - verify consistency of log | ||
206 | * @nilfs: nilfs object | ||
207 | * @seg_seq: sequence number of segment | ||
208 | * @bh_sum: buffer head of summary block | ||
209 | * @sum: segment summary struct | ||
210 | */ | ||
211 | static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq, | ||
212 | struct buffer_head *bh_sum, | ||
213 | struct nilfs_segment_summary *sum) | ||
214 | { | ||
214 | unsigned long nblock; | 215 | unsigned long nblock; |
215 | u32 crc; | 216 | u32 crc; |
216 | int ret = NILFS_SEG_FAIL_IO; | 217 | int ret; |
217 | 218 | ||
218 | bh_sum = sb_bread(sbi->s_super, pseg_start); | 219 | ret = NILFS_SEG_FAIL_MAGIC; |
219 | if (!bh_sum) | 220 | if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) |
220 | goto out; | 221 | goto out; |
221 | 222 | ||
222 | sum = (struct nilfs_segment_summary *)bh_sum->b_data; | 223 | ret = NILFS_SEG_FAIL_SEQ; |
223 | 224 | if (le64_to_cpu(sum->ss_seq) != seg_seq) | |
224 | /* Check consistency of segment summary */ | 225 | goto out; |
225 | if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) { | ||
226 | ret = NILFS_SEG_FAIL_MAGIC; | ||
227 | goto failed; | ||
228 | } | ||
229 | store_segsum_info(ssi, sum, sbi->s_super->s_blocksize); | ||
230 | if (seg_seq != ssi->seg_seq) { | ||
231 | ret = NILFS_SEG_FAIL_SEQ; | ||
232 | goto failed; | ||
233 | } | ||
234 | 226 | ||
235 | nblock = ssi->nblocks; | 227 | nblock = le32_to_cpu(sum->ss_nblocks); |
236 | if (unlikely(nblock == 0 || | 228 | ret = NILFS_SEG_FAIL_CONSISTENCY; |
237 | nblock > sbi->s_nilfs->ns_blocks_per_segment)) { | 229 | if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment)) |
238 | /* This limits the number of blocks read in the CRC check */ | 230 | /* This limits the number of blocks read in the CRC check */ |
239 | ret = NILFS_SEG_FAIL_CONSISTENCY; | 231 | goto out; |
240 | goto failed; | 232 | |
241 | } | 233 | ret = NILFS_SEG_FAIL_IO; |
242 | if (calc_crc_cont(sbi, bh_sum, &crc, sizeof(sum->ss_datasum), | 234 | if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum), |
243 | ((u64)nblock << sbi->s_super->s_blocksize_bits), | 235 | ((u64)nblock << nilfs->ns_blocksize_bits), |
244 | pseg_start, nblock)) { | 236 | bh_sum->b_blocknr, nblock)) |
245 | ret = NILFS_SEG_FAIL_IO; | 237 | goto out; |
246 | goto failed; | 238 | |
247 | } | 239 | ret = NILFS_SEG_FAIL_CHECKSUM_FULL; |
248 | if (crc == le32_to_cpu(sum->ss_datasum)) | 240 | if (crc != le32_to_cpu(sum->ss_datasum)) |
249 | ret = 0; | 241 | goto out; |
250 | else | 242 | ret = 0; |
251 | ret = NILFS_SEG_FAIL_CHECKSUM_FULL; | 243 | out: |
252 | failed: | ||
253 | brelse(bh_sum); | ||
254 | out: | ||
255 | return ret; | 244 | return ret; |
256 | } | 245 | } |
257 | 246 | ||
258 | static void *segsum_get(struct super_block *sb, struct buffer_head **pbh, | 247 | /** |
259 | unsigned int *offset, unsigned int bytes) | 248 | * nilfs_read_summary_info - read an item on summary blocks of a log |
249 | * @nilfs: nilfs object | ||
250 | * @pbh: the current buffer head on summary blocks [in, out] | ||
251 | * @offset: the current byte offset on summary blocks [in, out] | ||
252 | * @bytes: byte size of the item to be read | ||
253 | */ | ||
254 | static void *nilfs_read_summary_info(struct the_nilfs *nilfs, | ||
255 | struct buffer_head **pbh, | ||
256 | unsigned int *offset, unsigned int bytes) | ||
260 | { | 257 | { |
261 | void *ptr; | 258 | void *ptr; |
262 | sector_t blocknr; | 259 | sector_t blocknr; |
@@ -265,7 +262,8 @@ static void *segsum_get(struct super_block *sb, struct buffer_head **pbh, | |||
265 | if (bytes > (*pbh)->b_size - *offset) { | 262 | if (bytes > (*pbh)->b_size - *offset) { |
266 | blocknr = (*pbh)->b_blocknr; | 263 | blocknr = (*pbh)->b_blocknr; |
267 | brelse(*pbh); | 264 | brelse(*pbh); |
268 | *pbh = sb_bread(sb, blocknr + 1); | 265 | *pbh = __bread(nilfs->ns_bdev, blocknr + 1, |
266 | nilfs->ns_blocksize); | ||
269 | if (unlikely(!*pbh)) | 267 | if (unlikely(!*pbh)) |
270 | return NULL; | 268 | return NULL; |
271 | *offset = 0; | 269 | *offset = 0; |
@@ -275,9 +273,18 @@ static void *segsum_get(struct super_block *sb, struct buffer_head **pbh, | |||
275 | return ptr; | 273 | return ptr; |
276 | } | 274 | } |
277 | 275 | ||
278 | static void segsum_skip(struct super_block *sb, struct buffer_head **pbh, | 276 | /** |
279 | unsigned int *offset, unsigned int bytes, | 277 | * nilfs_skip_summary_info - skip items on summary blocks of a log |
280 | unsigned long count) | 278 | * @nilfs: nilfs object |
279 | * @pbh: the current buffer head on summary blocks [in, out] | ||
280 | * @offset: the current byte offset on summary blocks [in, out] | ||
281 | * @bytes: byte size of the item to be skipped | ||
282 | * @count: number of items to be skipped | ||
283 | */ | ||
284 | static void nilfs_skip_summary_info(struct the_nilfs *nilfs, | ||
285 | struct buffer_head **pbh, | ||
286 | unsigned int *offset, unsigned int bytes, | ||
287 | unsigned long count) | ||
281 | { | 288 | { |
282 | unsigned int rest_item_in_current_block | 289 | unsigned int rest_item_in_current_block |
283 | = ((*pbh)->b_size - *offset) / bytes; | 290 | = ((*pbh)->b_size - *offset) / bytes; |
@@ -294,36 +301,46 @@ static void segsum_skip(struct super_block *sb, struct buffer_head **pbh, | |||
294 | *offset = bytes * (count - (bcnt - 1) * nitem_per_block); | 301 | *offset = bytes * (count - (bcnt - 1) * nitem_per_block); |
295 | 302 | ||
296 | brelse(*pbh); | 303 | brelse(*pbh); |
297 | *pbh = sb_bread(sb, blocknr + bcnt); | 304 | *pbh = __bread(nilfs->ns_bdev, blocknr + bcnt, |
305 | nilfs->ns_blocksize); | ||
298 | } | 306 | } |
299 | } | 307 | } |
300 | 308 | ||
301 | static int | 309 | /** |
302 | collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr, | 310 | * nilfs_scan_dsync_log - get block information of a log written for data sync |
303 | struct nilfs_segsum_info *ssi, | 311 | * @nilfs: nilfs object |
304 | struct list_head *head) | 312 | * @start_blocknr: start block number of the log |
313 | * @sum: log summary information | ||
314 | * @head: list head to add nilfs_recovery_block struct | ||
315 | */ | ||
316 | static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr, | ||
317 | struct nilfs_segment_summary *sum, | ||
318 | struct list_head *head) | ||
305 | { | 319 | { |
306 | struct buffer_head *bh; | 320 | struct buffer_head *bh; |
307 | unsigned int offset; | 321 | unsigned int offset; |
308 | unsigned long nfinfo = ssi->nfinfo; | 322 | u32 nfinfo, sumbytes; |
309 | sector_t blocknr = sum_blocknr + ssi->nsumblk; | 323 | sector_t blocknr; |
310 | ino_t ino; | 324 | ino_t ino; |
311 | int err = -EIO; | 325 | int err = -EIO; |
312 | 326 | ||
327 | nfinfo = le32_to_cpu(sum->ss_nfinfo); | ||
313 | if (!nfinfo) | 328 | if (!nfinfo) |
314 | return 0; | 329 | return 0; |
315 | 330 | ||
316 | bh = sb_bread(sbi->s_super, sum_blocknr); | 331 | sumbytes = le32_to_cpu(sum->ss_sumbytes); |
332 | blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize); | ||
333 | bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); | ||
317 | if (unlikely(!bh)) | 334 | if (unlikely(!bh)) |
318 | goto out; | 335 | goto out; |
319 | 336 | ||
320 | offset = le16_to_cpu( | 337 | offset = le16_to_cpu(sum->ss_bytes); |
321 | ((struct nilfs_segment_summary *)bh->b_data)->ss_bytes); | ||
322 | for (;;) { | 338 | for (;;) { |
323 | unsigned long nblocks, ndatablk, nnodeblk; | 339 | unsigned long nblocks, ndatablk, nnodeblk; |
324 | struct nilfs_finfo *finfo; | 340 | struct nilfs_finfo *finfo; |
325 | 341 | ||
326 | finfo = segsum_get(sbi->s_super, &bh, &offset, sizeof(*finfo)); | 342 | finfo = nilfs_read_summary_info(nilfs, &bh, &offset, |
343 | sizeof(*finfo)); | ||
327 | if (unlikely(!finfo)) | 344 | if (unlikely(!finfo)) |
328 | goto out; | 345 | goto out; |
329 | 346 | ||
@@ -336,8 +353,8 @@ collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr, | |||
336 | struct nilfs_recovery_block *rb; | 353 | struct nilfs_recovery_block *rb; |
337 | struct nilfs_binfo_v *binfo; | 354 | struct nilfs_binfo_v *binfo; |
338 | 355 | ||
339 | binfo = segsum_get(sbi->s_super, &bh, &offset, | 356 | binfo = nilfs_read_summary_info(nilfs, &bh, &offset, |
340 | sizeof(*binfo)); | 357 | sizeof(*binfo)); |
341 | if (unlikely(!binfo)) | 358 | if (unlikely(!binfo)) |
342 | goto out; | 359 | goto out; |
343 | 360 | ||
@@ -355,9 +372,9 @@ collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr, | |||
355 | } | 372 | } |
356 | if (--nfinfo == 0) | 373 | if (--nfinfo == 0) |
357 | break; | 374 | break; |
358 | blocknr += nnodeblk; /* always 0 for the data sync segments */ | 375 | blocknr += nnodeblk; /* always 0 for data sync logs */ |
359 | segsum_skip(sbi->s_super, &bh, &offset, sizeof(__le64), | 376 | nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64), |
360 | nnodeblk); | 377 | nnodeblk); |
361 | if (unlikely(!bh)) | 378 | if (unlikely(!bh)) |
362 | goto out; | 379 | goto out; |
363 | } | 380 | } |
@@ -467,14 +484,14 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, | |||
467 | return err; | 484 | return err; |
468 | } | 485 | } |
469 | 486 | ||
470 | static int nilfs_recovery_copy_block(struct nilfs_sb_info *sbi, | 487 | static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, |
471 | struct nilfs_recovery_block *rb, | 488 | struct nilfs_recovery_block *rb, |
472 | struct page *page) | 489 | struct page *page) |
473 | { | 490 | { |
474 | struct buffer_head *bh_org; | 491 | struct buffer_head *bh_org; |
475 | void *kaddr; | 492 | void *kaddr; |
476 | 493 | ||
477 | bh_org = sb_bread(sbi->s_super, rb->blocknr); | 494 | bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize); |
478 | if (unlikely(!bh_org)) | 495 | if (unlikely(!bh_org)) |
479 | return -EIO; | 496 | return -EIO; |
480 | 497 | ||
@@ -485,13 +502,14 @@ static int nilfs_recovery_copy_block(struct nilfs_sb_info *sbi, | |||
485 | return 0; | 502 | return 0; |
486 | } | 503 | } |
487 | 504 | ||
488 | static int recover_dsync_blocks(struct nilfs_sb_info *sbi, | 505 | static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, |
489 | struct list_head *head, | 506 | struct nilfs_sb_info *sbi, |
490 | unsigned long *nr_salvaged_blocks) | 507 | struct list_head *head, |
508 | unsigned long *nr_salvaged_blocks) | ||
491 | { | 509 | { |
492 | struct inode *inode; | 510 | struct inode *inode; |
493 | struct nilfs_recovery_block *rb, *n; | 511 | struct nilfs_recovery_block *rb, *n; |
494 | unsigned blocksize = sbi->s_super->s_blocksize; | 512 | unsigned blocksize = nilfs->ns_blocksize; |
495 | struct page *page; | 513 | struct page *page; |
496 | loff_t pos; | 514 | loff_t pos; |
497 | int err = 0, err2 = 0; | 515 | int err = 0, err2 = 0; |
@@ -511,7 +529,7 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi, | |||
511 | if (unlikely(err)) | 529 | if (unlikely(err)) |
512 | goto failed_inode; | 530 | goto failed_inode; |
513 | 531 | ||
514 | err = nilfs_recovery_copy_block(sbi, rb, page); | 532 | err = nilfs_recovery_copy_block(nilfs, rb, page); |
515 | if (unlikely(err)) | 533 | if (unlikely(err)) |
516 | goto failed_page; | 534 | goto failed_page; |
517 | 535 | ||
@@ -551,18 +569,20 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi, | |||
551 | /** | 569 | /** |
552 | * nilfs_do_roll_forward - salvage logical segments newer than the latest | 570 | * nilfs_do_roll_forward - salvage logical segments newer than the latest |
553 | * checkpoint | 571 | * checkpoint |
572 | * @nilfs: nilfs object | ||
554 | * @sbi: nilfs_sb_info | 573 | * @sbi: nilfs_sb_info |
555 | * @nilfs: the_nilfs | ||
556 | * @ri: pointer to a nilfs_recovery_info | 574 | * @ri: pointer to a nilfs_recovery_info |
557 | */ | 575 | */ |
558 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | 576 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, |
559 | struct nilfs_sb_info *sbi, | 577 | struct nilfs_sb_info *sbi, |
560 | struct nilfs_recovery_info *ri) | 578 | struct nilfs_recovery_info *ri) |
561 | { | 579 | { |
562 | struct nilfs_segsum_info ssi; | 580 | struct buffer_head *bh_sum = NULL; |
581 | struct nilfs_segment_summary *sum; | ||
563 | sector_t pseg_start; | 582 | sector_t pseg_start; |
564 | sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ | 583 | sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ |
565 | unsigned long nsalvaged_blocks = 0; | 584 | unsigned long nsalvaged_blocks = 0; |
585 | unsigned int flags; | ||
566 | u64 seg_seq; | 586 | u64 seg_seq; |
567 | __u64 segnum, nextnum = 0; | 587 | __u64 segnum, nextnum = 0; |
568 | int empty_seg = 0; | 588 | int empty_seg = 0; |
@@ -581,8 +601,14 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
581 | nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); | 601 | nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); |
582 | 602 | ||
583 | while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { | 603 | while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { |
604 | brelse(bh_sum); | ||
605 | bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); | ||
606 | if (!bh_sum) { | ||
607 | err = -EIO; | ||
608 | goto failed; | ||
609 | } | ||
584 | 610 | ||
585 | ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi); | 611 | ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); |
586 | if (ret) { | 612 | if (ret) { |
587 | if (ret == NILFS_SEG_FAIL_IO) { | 613 | if (ret == NILFS_SEG_FAIL_IO) { |
588 | err = -EIO; | 614 | err = -EIO; |
@@ -590,33 +616,38 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
590 | } | 616 | } |
591 | goto strayed; | 617 | goto strayed; |
592 | } | 618 | } |
593 | if (unlikely(NILFS_SEG_HAS_SR(&ssi))) | 619 | |
620 | flags = le16_to_cpu(sum->ss_flags); | ||
621 | if (flags & NILFS_SS_SR) | ||
594 | goto confused; | 622 | goto confused; |
595 | 623 | ||
596 | /* Found a valid partial segment; do recovery actions */ | 624 | /* Found a valid partial segment; do recovery actions */ |
597 | nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next); | 625 | nextnum = nilfs_get_segnum_of_block(nilfs, |
626 | le64_to_cpu(sum->ss_next)); | ||
598 | empty_seg = 0; | 627 | empty_seg = 0; |
599 | nilfs->ns_ctime = ssi.ctime; | 628 | nilfs->ns_ctime = le64_to_cpu(sum->ss_create); |
600 | if (!(ssi.flags & NILFS_SS_GC)) | 629 | if (!(flags & NILFS_SS_GC)) |
601 | nilfs->ns_nongc_ctime = ssi.ctime; | 630 | nilfs->ns_nongc_ctime = nilfs->ns_ctime; |
602 | 631 | ||
603 | switch (state) { | 632 | switch (state) { |
604 | case RF_INIT_ST: | 633 | case RF_INIT_ST: |
605 | if (!NILFS_SEG_LOGBGN(&ssi) || !NILFS_SEG_DSYNC(&ssi)) | 634 | if (!(flags & NILFS_SS_LOGBGN) || |
635 | !(flags & NILFS_SS_SYNDT)) | ||
606 | goto try_next_pseg; | 636 | goto try_next_pseg; |
607 | state = RF_DSYNC_ST; | 637 | state = RF_DSYNC_ST; |
608 | /* Fall through */ | 638 | /* Fall through */ |
609 | case RF_DSYNC_ST: | 639 | case RF_DSYNC_ST: |
610 | if (!NILFS_SEG_DSYNC(&ssi)) | 640 | if (!(flags & NILFS_SS_SYNDT)) |
611 | goto confused; | 641 | goto confused; |
612 | 642 | ||
613 | err = collect_blocks_from_segsum( | 643 | err = nilfs_scan_dsync_log(nilfs, pseg_start, sum, |
614 | sbi, pseg_start, &ssi, &dsync_blocks); | 644 | &dsync_blocks); |
615 | if (unlikely(err)) | 645 | if (unlikely(err)) |
616 | goto failed; | 646 | goto failed; |
617 | if (NILFS_SEG_LOGEND(&ssi)) { | 647 | if (flags & NILFS_SS_LOGEND) { |
618 | err = recover_dsync_blocks( | 648 | err = nilfs_recover_dsync_blocks( |
619 | sbi, &dsync_blocks, &nsalvaged_blocks); | 649 | nilfs, sbi, &dsync_blocks, |
650 | &nsalvaged_blocks); | ||
620 | if (unlikely(err)) | 651 | if (unlikely(err)) |
621 | goto failed; | 652 | goto failed; |
622 | state = RF_INIT_ST; | 653 | state = RF_INIT_ST; |
@@ -627,7 +658,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
627 | try_next_pseg: | 658 | try_next_pseg: |
628 | if (pseg_start == ri->ri_lsegs_end) | 659 | if (pseg_start == ri->ri_lsegs_end) |
629 | break; | 660 | break; |
630 | pseg_start += ssi.nblocks; | 661 | pseg_start += le32_to_cpu(sum->ss_nblocks); |
631 | if (pseg_start < seg_end) | 662 | if (pseg_start < seg_end) |
632 | continue; | 663 | continue; |
633 | goto feed_segment; | 664 | goto feed_segment; |
@@ -652,8 +683,9 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
652 | ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; | 683 | ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; |
653 | } | 684 | } |
654 | out: | 685 | out: |
686 | brelse(bh_sum); | ||
655 | dispose_recovery_list(&dsync_blocks); | 687 | dispose_recovery_list(&dsync_blocks); |
656 | nilfs_detach_writer(sbi->s_nilfs, sbi); | 688 | nilfs_detach_writer(nilfs, sbi); |
657 | return err; | 689 | return err; |
658 | 690 | ||
659 | confused: | 691 | confused: |
@@ -667,7 +699,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
667 | } | 699 | } |
668 | 700 | ||
669 | static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | 701 | static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, |
670 | struct nilfs_sb_info *sbi, | ||
671 | struct nilfs_recovery_info *ri) | 702 | struct nilfs_recovery_info *ri) |
672 | { | 703 | { |
673 | struct buffer_head *bh; | 704 | struct buffer_head *bh; |
@@ -677,7 +708,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | |||
677 | nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) | 708 | nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) |
678 | return; | 709 | return; |
679 | 710 | ||
680 | bh = sb_getblk(sbi->s_super, ri->ri_lsegs_start); | 711 | bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize); |
681 | BUG_ON(!bh); | 712 | BUG_ON(!bh); |
682 | memset(bh->b_data, 0, bh->b_size); | 713 | memset(bh->b_data, 0, bh->b_size); |
683 | set_buffer_dirty(bh); | 714 | set_buffer_dirty(bh); |
@@ -690,9 +721,8 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | |||
690 | } | 721 | } |
691 | 722 | ||
692 | /** | 723 | /** |
693 | * nilfs_recover_logical_segments - salvage logical segments written after | 724 | * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint |
694 | * the latest super root | 725 | * @nilfs: nilfs object |
695 | * @nilfs: the_nilfs | ||
696 | * @sbi: nilfs_sb_info | 726 | * @sbi: nilfs_sb_info |
697 | * @ri: pointer to a nilfs_recovery_info struct to store search results. | 727 | * @ri: pointer to a nilfs_recovery_info struct to store search results. |
698 | * | 728 | * |
@@ -709,9 +739,9 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | |||
709 | * | 739 | * |
710 | * %-ENOMEM - Insufficient memory available. | 740 | * %-ENOMEM - Insufficient memory available. |
711 | */ | 741 | */ |
712 | int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | 742 | int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, |
713 | struct nilfs_sb_info *sbi, | 743 | struct nilfs_sb_info *sbi, |
714 | struct nilfs_recovery_info *ri) | 744 | struct nilfs_recovery_info *ri) |
715 | { | 745 | { |
716 | int err; | 746 | int err; |
717 | 747 | ||
@@ -751,7 +781,7 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | |||
751 | goto failed; | 781 | goto failed; |
752 | } | 782 | } |
753 | 783 | ||
754 | nilfs_finish_roll_forward(nilfs, sbi, ri); | 784 | nilfs_finish_roll_forward(nilfs, ri); |
755 | } | 785 | } |
756 | 786 | ||
757 | failed: | 787 | failed: |
@@ -762,7 +792,6 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | |||
762 | /** | 792 | /** |
763 | * nilfs_search_super_root - search the latest valid super root | 793 | * nilfs_search_super_root - search the latest valid super root |
764 | * @nilfs: the_nilfs | 794 | * @nilfs: the_nilfs |
765 | * @sbi: nilfs_sb_info | ||
766 | * @ri: pointer to a nilfs_recovery_info struct to store search results. | 795 | * @ri: pointer to a nilfs_recovery_info struct to store search results. |
767 | * | 796 | * |
768 | * nilfs_search_super_root() looks for the latest super-root from a partial | 797 | * nilfs_search_super_root() looks for the latest super-root from a partial |
@@ -775,14 +804,19 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | |||
775 | * %-EINVAL - No valid segment found | 804 | * %-EINVAL - No valid segment found |
776 | * | 805 | * |
777 | * %-EIO - I/O error | 806 | * %-EIO - I/O error |
807 | * | ||
808 | * %-ENOMEM - Insufficient memory available. | ||
778 | */ | 809 | */ |
779 | int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | 810 | int nilfs_search_super_root(struct the_nilfs *nilfs, |
780 | struct nilfs_recovery_info *ri) | 811 | struct nilfs_recovery_info *ri) |
781 | { | 812 | { |
782 | struct nilfs_segsum_info ssi; | 813 | struct buffer_head *bh_sum = NULL; |
814 | struct nilfs_segment_summary *sum; | ||
783 | sector_t pseg_start, pseg_end, sr_pseg_start = 0; | 815 | sector_t pseg_start, pseg_end, sr_pseg_start = 0; |
784 | sector_t seg_start, seg_end; /* range of full segment (block number) */ | 816 | sector_t seg_start, seg_end; /* range of full segment (block number) */ |
785 | sector_t b, end; | 817 | sector_t b, end; |
818 | unsigned long nblocks; | ||
819 | unsigned int flags; | ||
786 | u64 seg_seq; | 820 | u64 seg_seq; |
787 | __u64 segnum, nextnum = 0; | 821 | __u64 segnum, nextnum = 0; |
788 | __u64 cno; | 822 | __u64 cno; |
@@ -801,17 +835,24 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
801 | /* Read ahead segment */ | 835 | /* Read ahead segment */ |
802 | b = seg_start; | 836 | b = seg_start; |
803 | while (b <= seg_end) | 837 | while (b <= seg_end) |
804 | sb_breadahead(sbi->s_super, b++); | 838 | __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize); |
805 | 839 | ||
806 | for (;;) { | 840 | for (;;) { |
807 | /* Load segment summary */ | 841 | brelse(bh_sum); |
808 | ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi); | 842 | ret = NILFS_SEG_FAIL_IO; |
843 | bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); | ||
844 | if (!bh_sum) | ||
845 | goto failed; | ||
846 | |||
847 | ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); | ||
809 | if (ret) { | 848 | if (ret) { |
810 | if (ret == NILFS_SEG_FAIL_IO) | 849 | if (ret == NILFS_SEG_FAIL_IO) |
811 | goto failed; | 850 | goto failed; |
812 | goto strayed; | 851 | goto strayed; |
813 | } | 852 | } |
814 | pseg_end = pseg_start + ssi.nblocks - 1; | 853 | |
854 | nblocks = le32_to_cpu(sum->ss_nblocks); | ||
855 | pseg_end = pseg_start + nblocks - 1; | ||
815 | if (unlikely(pseg_end > seg_end)) { | 856 | if (unlikely(pseg_end > seg_end)) { |
816 | ret = NILFS_SEG_FAIL_CONSISTENCY; | 857 | ret = NILFS_SEG_FAIL_CONSISTENCY; |
817 | goto strayed; | 858 | goto strayed; |
@@ -821,11 +862,13 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
821 | ri->ri_pseg_start = pseg_start; | 862 | ri->ri_pseg_start = pseg_start; |
822 | ri->ri_seq = seg_seq; | 863 | ri->ri_seq = seg_seq; |
823 | ri->ri_segnum = segnum; | 864 | ri->ri_segnum = segnum; |
824 | nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next); | 865 | nextnum = nilfs_get_segnum_of_block(nilfs, |
866 | le64_to_cpu(sum->ss_next)); | ||
825 | ri->ri_nextnum = nextnum; | 867 | ri->ri_nextnum = nextnum; |
826 | empty_seg = 0; | 868 | empty_seg = 0; |
827 | 869 | ||
828 | if (!NILFS_SEG_HAS_SR(&ssi) && !scan_newer) { | 870 | flags = le16_to_cpu(sum->ss_flags); |
871 | if (!(flags & NILFS_SS_SR) && !scan_newer) { | ||
829 | /* This will never happen because a superblock | 872 | /* This will never happen because a superblock |
830 | (last_segment) always points to a pseg | 873 | (last_segment) always points to a pseg |
831 | having a super root. */ | 874 | having a super root. */ |
@@ -836,14 +879,15 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
836 | if (pseg_start == seg_start) { | 879 | if (pseg_start == seg_start) { |
837 | nilfs_get_segment_range(nilfs, nextnum, &b, &end); | 880 | nilfs_get_segment_range(nilfs, nextnum, &b, &end); |
838 | while (b <= end) | 881 | while (b <= end) |
839 | sb_breadahead(sbi->s_super, b++); | 882 | __breadahead(nilfs->ns_bdev, b++, |
883 | nilfs->ns_blocksize); | ||
840 | } | 884 | } |
841 | if (!NILFS_SEG_HAS_SR(&ssi)) { | 885 | if (!(flags & NILFS_SS_SR)) { |
842 | if (!ri->ri_lsegs_start && NILFS_SEG_LOGBGN(&ssi)) { | 886 | if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) { |
843 | ri->ri_lsegs_start = pseg_start; | 887 | ri->ri_lsegs_start = pseg_start; |
844 | ri->ri_lsegs_start_seq = seg_seq; | 888 | ri->ri_lsegs_start_seq = seg_seq; |
845 | } | 889 | } |
846 | if (NILFS_SEG_LOGEND(&ssi)) | 890 | if (flags & NILFS_SS_LOGEND) |
847 | ri->ri_lsegs_end = pseg_start; | 891 | ri->ri_lsegs_end = pseg_start; |
848 | goto try_next_pseg; | 892 | goto try_next_pseg; |
849 | } | 893 | } |
@@ -854,12 +898,12 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
854 | ri->ri_lsegs_start = ri->ri_lsegs_end = 0; | 898 | ri->ri_lsegs_start = ri->ri_lsegs_end = 0; |
855 | 899 | ||
856 | nilfs_dispose_segment_list(&segments); | 900 | nilfs_dispose_segment_list(&segments); |
857 | nilfs->ns_pseg_offset = (sr_pseg_start = pseg_start) | 901 | sr_pseg_start = pseg_start; |
858 | + ssi.nblocks - seg_start; | 902 | nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start; |
859 | nilfs->ns_seg_seq = seg_seq; | 903 | nilfs->ns_seg_seq = seg_seq; |
860 | nilfs->ns_segnum = segnum; | 904 | nilfs->ns_segnum = segnum; |
861 | nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ | 905 | nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ |
862 | nilfs->ns_ctime = ssi.ctime; | 906 | nilfs->ns_ctime = le64_to_cpu(sum->ss_create); |
863 | nilfs->ns_nextnum = nextnum; | 907 | nilfs->ns_nextnum = nextnum; |
864 | 908 | ||
865 | if (scan_newer) | 909 | if (scan_newer) |
@@ -870,15 +914,9 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
870 | scan_newer = 1; | 914 | scan_newer = 1; |
871 | } | 915 | } |
872 | 916 | ||
873 | /* reset region for roll-forward */ | ||
874 | pseg_start += ssi.nblocks; | ||
875 | if (pseg_start < seg_end) | ||
876 | continue; | ||
877 | goto feed_segment; | ||
878 | |||
879 | try_next_pseg: | 917 | try_next_pseg: |
880 | /* Standing on a course, or met an inconsistent state */ | 918 | /* Standing on a course, or met an inconsistent state */ |
881 | pseg_start += ssi.nblocks; | 919 | pseg_start += nblocks; |
882 | if (pseg_start < seg_end) | 920 | if (pseg_start < seg_end) |
883 | continue; | 921 | continue; |
884 | goto feed_segment; | 922 | goto feed_segment; |
@@ -909,6 +947,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
909 | 947 | ||
910 | super_root_found: | 948 | super_root_found: |
911 | /* Updating pointers relating to the latest checkpoint */ | 949 | /* Updating pointers relating to the latest checkpoint */ |
950 | brelse(bh_sum); | ||
912 | list_splice_tail(&segments, &ri->ri_used_segments); | 951 | list_splice_tail(&segments, &ri->ri_used_segments); |
913 | nilfs->ns_last_pseg = sr_pseg_start; | 952 | nilfs->ns_last_pseg = sr_pseg_start; |
914 | nilfs->ns_last_seq = nilfs->ns_seg_seq; | 953 | nilfs->ns_last_seq = nilfs->ns_seg_seq; |
@@ -916,6 +955,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
916 | return 0; | 955 | return 0; |
917 | 956 | ||
918 | failed: | 957 | failed: |
958 | brelse(bh_sum); | ||
919 | nilfs_dispose_segment_list(&segments); | 959 | nilfs_dispose_segment_list(&segments); |
920 | return (ret < 0) ? ret : nilfs_warn_segment_error(ret); | 960 | return (ret < 0) ? ret : nilfs_warn_segment_error(ret); |
921 | } | 961 | } |
diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index 85fbb66455e2..b04f08cc2397 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h | |||
@@ -54,17 +54,6 @@ struct nilfs_segsum_info { | |||
54 | sector_t next; | 54 | sector_t next; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | /* macro for the flags */ | ||
58 | #define NILFS_SEG_HAS_SR(sum) ((sum)->flags & NILFS_SS_SR) | ||
59 | #define NILFS_SEG_LOGBGN(sum) ((sum)->flags & NILFS_SS_LOGBGN) | ||
60 | #define NILFS_SEG_LOGEND(sum) ((sum)->flags & NILFS_SS_LOGEND) | ||
61 | #define NILFS_SEG_DSYNC(sum) ((sum)->flags & NILFS_SS_SYNDT) | ||
62 | #define NILFS_SEG_SIMPLEX(sum) \ | ||
63 | (((sum)->flags & (NILFS_SS_LOGBGN | NILFS_SS_LOGEND)) == \ | ||
64 | (NILFS_SS_LOGBGN | NILFS_SS_LOGEND)) | ||
65 | |||
66 | #define NILFS_SEG_EMPTY(sum) ((sum)->nblocks == (sum)->nsumblk) | ||
67 | |||
68 | /** | 57 | /** |
69 | * struct nilfs_segment_buffer - Segment buffer | 58 | * struct nilfs_segment_buffer - Segment buffer |
70 | * @sb_super: back pointer to a superblock struct | 59 | * @sb_super: back pointer to a superblock struct |
@@ -141,6 +130,19 @@ int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *, | |||
141 | struct buffer_head **); | 130 | struct buffer_head **); |
142 | void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *); | 131 | void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *); |
143 | 132 | ||
133 | static inline int nilfs_segbuf_simplex(struct nilfs_segment_buffer *segbuf) | ||
134 | { | ||
135 | unsigned int flags = segbuf->sb_sum.flags; | ||
136 | |||
137 | return (flags & (NILFS_SS_LOGBGN | NILFS_SS_LOGEND)) == | ||
138 | (NILFS_SS_LOGBGN | NILFS_SS_LOGEND); | ||
139 | } | ||
140 | |||
141 | static inline int nilfs_segbuf_empty(struct nilfs_segment_buffer *segbuf) | ||
142 | { | ||
143 | return segbuf->sb_sum.nblocks == segbuf->sb_sum.nsumblk; | ||
144 | } | ||
145 | |||
144 | static inline void | 146 | static inline void |
145 | nilfs_segbuf_add_segsum_buffer(struct nilfs_segment_buffer *segbuf, | 147 | nilfs_segbuf_add_segsum_buffer(struct nilfs_segment_buffer *segbuf, |
146 | struct buffer_head *bh) | 148 | struct buffer_head *bh) |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index c9201649cc49..9fd051a33c4f 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -1914,12 +1914,12 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1914 | } | 1914 | } |
1915 | } | 1915 | } |
1916 | 1916 | ||
1917 | if (!NILFS_SEG_SIMPLEX(&segbuf->sb_sum)) { | 1917 | if (!nilfs_segbuf_simplex(segbuf)) { |
1918 | if (NILFS_SEG_LOGBGN(&segbuf->sb_sum)) { | 1918 | if (segbuf->sb_sum.flags & NILFS_SS_LOGBGN) { |
1919 | set_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); | 1919 | set_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); |
1920 | sci->sc_lseg_stime = jiffies; | 1920 | sci->sc_lseg_stime = jiffies; |
1921 | } | 1921 | } |
1922 | if (NILFS_SEG_LOGEND(&segbuf->sb_sum)) | 1922 | if (segbuf->sb_sum.flags & NILFS_SS_LOGEND) |
1923 | clear_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); | 1923 | clear_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); |
1924 | } | 1924 | } |
1925 | } | 1925 | } |
@@ -1951,7 +1951,6 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1951 | if (update_sr) { | 1951 | if (update_sr) { |
1952 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, | 1952 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, |
1953 | segbuf->sb_sum.seg_seq, nilfs->ns_cno++); | 1953 | segbuf->sb_sum.seg_seq, nilfs->ns_cno++); |
1954 | set_nilfs_sb_dirty(nilfs); | ||
1955 | 1954 | ||
1956 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); | 1955 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); |
1957 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); | 1956 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); |
@@ -2082,7 +2081,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2082 | 2081 | ||
2083 | /* Avoid empty segment */ | 2082 | /* Avoid empty segment */ |
2084 | if (sci->sc_stage.scnt == NILFS_ST_DONE && | 2083 | if (sci->sc_stage.scnt == NILFS_ST_DONE && |
2085 | NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { | 2084 | nilfs_segbuf_empty(sci->sc_curseg)) { |
2086 | nilfs_segctor_abort_construction(sci, nilfs, 1); | 2085 | nilfs_segctor_abort_construction(sci, nilfs, 1); |
2087 | goto out; | 2086 | goto out; |
2088 | } | 2087 | } |
@@ -2408,6 +2407,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) | |||
2408 | { | 2407 | { |
2409 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 2408 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
2410 | struct the_nilfs *nilfs = sbi->s_nilfs; | 2409 | struct the_nilfs *nilfs = sbi->s_nilfs; |
2410 | struct nilfs_super_block **sbp; | ||
2411 | int err = 0; | 2411 | int err = 0; |
2412 | 2412 | ||
2413 | nilfs_segctor_accept(sci); | 2413 | nilfs_segctor_accept(sci); |
@@ -2423,8 +2423,13 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) | |||
2423 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && | 2423 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && |
2424 | nilfs_discontinued(nilfs)) { | 2424 | nilfs_discontinued(nilfs)) { |
2425 | down_write(&nilfs->ns_sem); | 2425 | down_write(&nilfs->ns_sem); |
2426 | err = nilfs_commit_super( | 2426 | err = -EIO; |
2427 | sbi, nilfs_altsb_need_update(nilfs)); | 2427 | sbp = nilfs_prepare_super(sbi, |
2428 | nilfs_sb_will_flip(nilfs)); | ||
2429 | if (likely(sbp)) { | ||
2430 | nilfs_set_log_cursor(sbp[0], nilfs); | ||
2431 | err = nilfs_commit_super(sbi, NILFS_SB_COMMIT); | ||
2432 | } | ||
2428 | up_write(&nilfs->ns_sem); | 2433 | up_write(&nilfs->ns_sem); |
2429 | } | 2434 | } |
2430 | } | 2435 | } |
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 01e20dbb217d..17c487bd8152 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h | |||
@@ -234,13 +234,13 @@ extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *); | |||
234 | extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); | 234 | extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); |
235 | 235 | ||
236 | /* recovery.c */ | 236 | /* recovery.c */ |
237 | extern int nilfs_read_super_root_block(struct super_block *, sector_t, | 237 | extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t, |
238 | struct buffer_head **, int); | 238 | struct buffer_head **, int); |
239 | extern int nilfs_search_super_root(struct the_nilfs *, struct nilfs_sb_info *, | 239 | extern int nilfs_search_super_root(struct the_nilfs *, |
240 | struct nilfs_recovery_info *); | 240 | struct nilfs_recovery_info *); |
241 | extern int nilfs_recover_logical_segments(struct the_nilfs *, | 241 | extern int nilfs_salvage_orphan_logs(struct the_nilfs *, |
242 | struct nilfs_sb_info *, | 242 | struct nilfs_sb_info *, |
243 | struct nilfs_recovery_info *); | 243 | struct nilfs_recovery_info *); |
244 | extern void nilfs_dispose_segment_list(struct list_head *); | 244 | extern void nilfs_dispose_segment_list(struct list_head *); |
245 | 245 | ||
246 | #endif /* _NILFS_SEGMENT_H */ | 246 | #endif /* _NILFS_SEGMENT_H */ |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 414ef68931cf..26078b3407c9 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -55,6 +55,8 @@ | |||
55 | #include "nilfs.h" | 55 | #include "nilfs.h" |
56 | #include "mdt.h" | 56 | #include "mdt.h" |
57 | #include "alloc.h" | 57 | #include "alloc.h" |
58 | #include "btree.h" | ||
59 | #include "btnode.h" | ||
58 | #include "page.h" | 60 | #include "page.h" |
59 | #include "cpfile.h" | 61 | #include "cpfile.h" |
60 | #include "ifile.h" | 62 | #include "ifile.h" |
@@ -74,6 +76,25 @@ struct kmem_cache *nilfs_btree_path_cache; | |||
74 | 76 | ||
75 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 77 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
76 | 78 | ||
79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) | ||
80 | { | ||
81 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
82 | struct nilfs_super_block **sbp; | ||
83 | |||
84 | down_write(&nilfs->ns_sem); | ||
85 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { | ||
86 | nilfs->ns_mount_state |= NILFS_ERROR_FS; | ||
87 | sbp = nilfs_prepare_super(sbi, 0); | ||
88 | if (likely(sbp)) { | ||
89 | sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); | ||
90 | if (sbp[1]) | ||
91 | sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS); | ||
92 | nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | ||
93 | } | ||
94 | } | ||
95 | up_write(&nilfs->ns_sem); | ||
96 | } | ||
97 | |||
77 | /** | 98 | /** |
78 | * nilfs_error() - report failure condition on a filesystem | 99 | * nilfs_error() - report failure condition on a filesystem |
79 | * | 100 | * |
@@ -99,16 +120,7 @@ void nilfs_error(struct super_block *sb, const char *function, | |||
99 | va_end(args); | 120 | va_end(args); |
100 | 121 | ||
101 | if (!(sb->s_flags & MS_RDONLY)) { | 122 | if (!(sb->s_flags & MS_RDONLY)) { |
102 | struct the_nilfs *nilfs = sbi->s_nilfs; | 123 | nilfs_set_error(sbi); |
103 | |||
104 | down_write(&nilfs->ns_sem); | ||
105 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { | ||
106 | nilfs->ns_mount_state |= NILFS_ERROR_FS; | ||
107 | nilfs->ns_sbp[0]->s_state |= | ||
108 | cpu_to_le16(NILFS_ERROR_FS); | ||
109 | nilfs_commit_super(sbi, 1); | ||
110 | } | ||
111 | up_write(&nilfs->ns_sem); | ||
112 | 124 | ||
113 | if (nilfs_test_opt(sbi, ERRORS_RO)) { | 125 | if (nilfs_test_opt(sbi, ERRORS_RO)) { |
114 | printk(KERN_CRIT "Remounting filesystem read-only\n"); | 126 | printk(KERN_CRIT "Remounting filesystem read-only\n"); |
@@ -176,7 +188,7 @@ static void nilfs_clear_inode(struct inode *inode) | |||
176 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); | 188 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); |
177 | } | 189 | } |
178 | 190 | ||
179 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb) | 191 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) |
180 | { | 192 | { |
181 | struct the_nilfs *nilfs = sbi->s_nilfs; | 193 | struct the_nilfs *nilfs = sbi->s_nilfs; |
182 | int err; | 194 | int err; |
@@ -202,12 +214,20 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb) | |||
202 | printk(KERN_ERR | 214 | printk(KERN_ERR |
203 | "NILFS: unable to write superblock (err=%d)\n", err); | 215 | "NILFS: unable to write superblock (err=%d)\n", err); |
204 | if (err == -EIO && nilfs->ns_sbh[1]) { | 216 | if (err == -EIO && nilfs->ns_sbh[1]) { |
217 | /* | ||
218 | * sbp[0] points to newer log than sbp[1], | ||
219 | * so copy sbp[0] to sbp[1] to take over sbp[0]. | ||
220 | */ | ||
221 | memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0], | ||
222 | nilfs->ns_sbsize); | ||
205 | nilfs_fall_back_super_block(nilfs); | 223 | nilfs_fall_back_super_block(nilfs); |
206 | goto retry; | 224 | goto retry; |
207 | } | 225 | } |
208 | } else { | 226 | } else { |
209 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; | 227 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; |
210 | 228 | ||
229 | nilfs->ns_sbwcount++; | ||
230 | |||
211 | /* | 231 | /* |
212 | * The latest segment becomes trailable from the position | 232 | * The latest segment becomes trailable from the position |
213 | * written in superblock. | 233 | * written in superblock. |
@@ -216,66 +236,122 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb) | |||
216 | 236 | ||
217 | /* update GC protection for recent segments */ | 237 | /* update GC protection for recent segments */ |
218 | if (nilfs->ns_sbh[1]) { | 238 | if (nilfs->ns_sbh[1]) { |
219 | sbp = NULL; | 239 | if (flag == NILFS_SB_COMMIT_ALL) { |
220 | if (dupsb) { | ||
221 | set_buffer_dirty(nilfs->ns_sbh[1]); | 240 | set_buffer_dirty(nilfs->ns_sbh[1]); |
222 | if (!sync_dirty_buffer(nilfs->ns_sbh[1])) | 241 | if (sync_dirty_buffer(nilfs->ns_sbh[1]) < 0) |
223 | sbp = nilfs->ns_sbp[1]; | 242 | goto out; |
224 | } | 243 | } |
244 | if (le64_to_cpu(nilfs->ns_sbp[1]->s_last_cno) < | ||
245 | le64_to_cpu(nilfs->ns_sbp[0]->s_last_cno)) | ||
246 | sbp = nilfs->ns_sbp[1]; | ||
225 | } | 247 | } |
226 | if (sbp) { | ||
227 | spin_lock(&nilfs->ns_last_segment_lock); | ||
228 | nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq); | ||
229 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
230 | } | ||
231 | } | ||
232 | 248 | ||
249 | spin_lock(&nilfs->ns_last_segment_lock); | ||
250 | nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq); | ||
251 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
252 | } | ||
253 | out: | ||
233 | return err; | 254 | return err; |
234 | } | 255 | } |
235 | 256 | ||
236 | int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb) | 257 | void nilfs_set_log_cursor(struct nilfs_super_block *sbp, |
258 | struct the_nilfs *nilfs) | ||
259 | { | ||
260 | sector_t nfreeblocks; | ||
261 | |||
262 | /* nilfs->ns_sem must be locked by the caller. */ | ||
263 | nilfs_count_free_blocks(nilfs, &nfreeblocks); | ||
264 | sbp->s_free_blocks_count = cpu_to_le64(nfreeblocks); | ||
265 | |||
266 | spin_lock(&nilfs->ns_last_segment_lock); | ||
267 | sbp->s_last_seq = cpu_to_le64(nilfs->ns_last_seq); | ||
268 | sbp->s_last_pseg = cpu_to_le64(nilfs->ns_last_pseg); | ||
269 | sbp->s_last_cno = cpu_to_le64(nilfs->ns_last_cno); | ||
270 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
271 | } | ||
272 | |||
273 | struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, | ||
274 | int flip) | ||
237 | { | 275 | { |
238 | struct the_nilfs *nilfs = sbi->s_nilfs; | 276 | struct the_nilfs *nilfs = sbi->s_nilfs; |
239 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 277 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
240 | sector_t nfreeblocks; | ||
241 | time_t t; | ||
242 | int err; | ||
243 | 278 | ||
244 | /* nilfs->sem must be locked by the caller. */ | 279 | /* nilfs->ns_sem must be locked by the caller. */ |
245 | if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { | 280 | if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { |
246 | if (sbp[1] && sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) | 281 | if (sbp[1] && |
247 | nilfs_swap_super_block(nilfs); | 282 | sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) { |
248 | else { | 283 | memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); |
284 | } else { | ||
249 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", | 285 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", |
250 | sbi->s_super->s_id); | 286 | sbi->s_super->s_id); |
251 | return -EIO; | 287 | return NULL; |
252 | } | 288 | } |
289 | } else if (sbp[1] && | ||
290 | sbp[1]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { | ||
291 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | ||
253 | } | 292 | } |
254 | err = nilfs_count_free_blocks(nilfs, &nfreeblocks); | ||
255 | if (unlikely(err)) { | ||
256 | printk(KERN_ERR "NILFS: failed to count free blocks\n"); | ||
257 | return err; | ||
258 | } | ||
259 | spin_lock(&nilfs->ns_last_segment_lock); | ||
260 | sbp[0]->s_last_seq = cpu_to_le64(nilfs->ns_last_seq); | ||
261 | sbp[0]->s_last_pseg = cpu_to_le64(nilfs->ns_last_pseg); | ||
262 | sbp[0]->s_last_cno = cpu_to_le64(nilfs->ns_last_cno); | ||
263 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
264 | 293 | ||
294 | if (flip && sbp[1]) | ||
295 | nilfs_swap_super_block(nilfs); | ||
296 | |||
297 | return sbp; | ||
298 | } | ||
299 | |||
300 | int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) | ||
301 | { | ||
302 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
303 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
304 | time_t t; | ||
305 | |||
306 | /* nilfs->ns_sem must be locked by the caller. */ | ||
265 | t = get_seconds(); | 307 | t = get_seconds(); |
266 | nilfs->ns_sbwtime[0] = t; | 308 | nilfs->ns_sbwtime = t; |
267 | sbp[0]->s_free_blocks_count = cpu_to_le64(nfreeblocks); | ||
268 | sbp[0]->s_wtime = cpu_to_le64(t); | 309 | sbp[0]->s_wtime = cpu_to_le64(t); |
269 | sbp[0]->s_sum = 0; | 310 | sbp[0]->s_sum = 0; |
270 | sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, | 311 | sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, |
271 | (unsigned char *)sbp[0], | 312 | (unsigned char *)sbp[0], |
272 | nilfs->ns_sbsize)); | 313 | nilfs->ns_sbsize)); |
273 | if (dupsb && sbp[1]) { | 314 | if (flag == NILFS_SB_COMMIT_ALL && sbp[1]) { |
274 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | 315 | sbp[1]->s_wtime = sbp[0]->s_wtime; |
275 | nilfs->ns_sbwtime[1] = t; | 316 | sbp[1]->s_sum = 0; |
317 | sbp[1]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, | ||
318 | (unsigned char *)sbp[1], | ||
319 | nilfs->ns_sbsize)); | ||
276 | } | 320 | } |
277 | clear_nilfs_sb_dirty(nilfs); | 321 | clear_nilfs_sb_dirty(nilfs); |
278 | return nilfs_sync_super(sbi, dupsb); | 322 | return nilfs_sync_super(sbi, flag); |
323 | } | ||
324 | |||
325 | /** | ||
326 | * nilfs_cleanup_super() - write filesystem state for cleanup | ||
327 | * @sbi: nilfs_sb_info to be unmounted or degraded to read-only | ||
328 | * | ||
329 | * This function restores state flags in the on-disk super block. | ||
330 | * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the | ||
331 | * filesystem was not clean previously. | ||
332 | */ | ||
333 | int nilfs_cleanup_super(struct nilfs_sb_info *sbi) | ||
334 | { | ||
335 | struct nilfs_super_block **sbp; | ||
336 | int flag = NILFS_SB_COMMIT; | ||
337 | int ret = -EIO; | ||
338 | |||
339 | sbp = nilfs_prepare_super(sbi, 0); | ||
340 | if (sbp) { | ||
341 | sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state); | ||
342 | nilfs_set_log_cursor(sbp[0], sbi->s_nilfs); | ||
343 | if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) { | ||
344 | /* | ||
345 | * make the "clean" flag also to the opposite | ||
346 | * super block if both super blocks point to | ||
347 | * the same checkpoint. | ||
348 | */ | ||
349 | sbp[1]->s_state = sbp[0]->s_state; | ||
350 | flag = NILFS_SB_COMMIT_ALL; | ||
351 | } | ||
352 | ret = nilfs_commit_super(sbi, flag); | ||
353 | } | ||
354 | return ret; | ||
279 | } | 355 | } |
280 | 356 | ||
281 | static void nilfs_put_super(struct super_block *sb) | 357 | static void nilfs_put_super(struct super_block *sb) |
@@ -289,8 +365,7 @@ static void nilfs_put_super(struct super_block *sb) | |||
289 | 365 | ||
290 | if (!(sb->s_flags & MS_RDONLY)) { | 366 | if (!(sb->s_flags & MS_RDONLY)) { |
291 | down_write(&nilfs->ns_sem); | 367 | down_write(&nilfs->ns_sem); |
292 | nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); | 368 | nilfs_cleanup_super(sbi); |
293 | nilfs_commit_super(sbi, 1); | ||
294 | up_write(&nilfs->ns_sem); | 369 | up_write(&nilfs->ns_sem); |
295 | } | 370 | } |
296 | down_write(&nilfs->ns_super_sem); | 371 | down_write(&nilfs->ns_super_sem); |
@@ -311,6 +386,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
311 | { | 386 | { |
312 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 387 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
313 | struct the_nilfs *nilfs = sbi->s_nilfs; | 388 | struct the_nilfs *nilfs = sbi->s_nilfs; |
389 | struct nilfs_super_block **sbp; | ||
314 | int err = 0; | 390 | int err = 0; |
315 | 391 | ||
316 | /* This function is called when super block should be written back */ | 392 | /* This function is called when super block should be written back */ |
@@ -318,8 +394,13 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
318 | err = nilfs_construct_segment(sb); | 394 | err = nilfs_construct_segment(sb); |
319 | 395 | ||
320 | down_write(&nilfs->ns_sem); | 396 | down_write(&nilfs->ns_sem); |
321 | if (nilfs_sb_dirty(nilfs)) | 397 | if (nilfs_sb_dirty(nilfs)) { |
322 | nilfs_commit_super(sbi, 1); | 398 | sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs)); |
399 | if (likely(sbp)) { | ||
400 | nilfs_set_log_cursor(sbp[0], nilfs); | ||
401 | nilfs_commit_super(sbi, NILFS_SB_COMMIT); | ||
402 | } | ||
403 | } | ||
323 | up_write(&nilfs->ns_sem); | 404 | up_write(&nilfs->ns_sem); |
324 | 405 | ||
325 | return err; | 406 | return err; |
@@ -442,20 +523,20 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
442 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 523 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
443 | 524 | ||
444 | if (!nilfs_test_opt(sbi, BARRIER)) | 525 | if (!nilfs_test_opt(sbi, BARRIER)) |
445 | seq_printf(seq, ",nobarrier"); | 526 | seq_puts(seq, ",nobarrier"); |
446 | if (nilfs_test_opt(sbi, SNAPSHOT)) | 527 | if (nilfs_test_opt(sbi, SNAPSHOT)) |
447 | seq_printf(seq, ",cp=%llu", | 528 | seq_printf(seq, ",cp=%llu", |
448 | (unsigned long long int)sbi->s_snapshot_cno); | 529 | (unsigned long long int)sbi->s_snapshot_cno); |
449 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | 530 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) |
450 | seq_printf(seq, ",errors=panic"); | 531 | seq_puts(seq, ",errors=panic"); |
451 | if (nilfs_test_opt(sbi, ERRORS_CONT)) | 532 | if (nilfs_test_opt(sbi, ERRORS_CONT)) |
452 | seq_printf(seq, ",errors=continue"); | 533 | seq_puts(seq, ",errors=continue"); |
453 | if (nilfs_test_opt(sbi, STRICT_ORDER)) | 534 | if (nilfs_test_opt(sbi, STRICT_ORDER)) |
454 | seq_printf(seq, ",order=strict"); | 535 | seq_puts(seq, ",order=strict"); |
455 | if (nilfs_test_opt(sbi, NORECOVERY)) | 536 | if (nilfs_test_opt(sbi, NORECOVERY)) |
456 | seq_printf(seq, ",norecovery"); | 537 | seq_puts(seq, ",norecovery"); |
457 | if (nilfs_test_opt(sbi, DISCARD)) | 538 | if (nilfs_test_opt(sbi, DISCARD)) |
458 | seq_printf(seq, ",discard"); | 539 | seq_puts(seq, ",discard"); |
459 | 540 | ||
460 | return 0; | 541 | return 0; |
461 | } | 542 | } |
@@ -524,23 +605,25 @@ static const struct export_operations nilfs_export_ops = { | |||
524 | 605 | ||
525 | enum { | 606 | enum { |
526 | Opt_err_cont, Opt_err_panic, Opt_err_ro, | 607 | Opt_err_cont, Opt_err_panic, Opt_err_ro, |
527 | Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, | 608 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, |
528 | Opt_discard, Opt_err, | 609 | Opt_discard, Opt_nodiscard, Opt_err, |
529 | }; | 610 | }; |
530 | 611 | ||
531 | static match_table_t tokens = { | 612 | static match_table_t tokens = { |
532 | {Opt_err_cont, "errors=continue"}, | 613 | {Opt_err_cont, "errors=continue"}, |
533 | {Opt_err_panic, "errors=panic"}, | 614 | {Opt_err_panic, "errors=panic"}, |
534 | {Opt_err_ro, "errors=remount-ro"}, | 615 | {Opt_err_ro, "errors=remount-ro"}, |
616 | {Opt_barrier, "barrier"}, | ||
535 | {Opt_nobarrier, "nobarrier"}, | 617 | {Opt_nobarrier, "nobarrier"}, |
536 | {Opt_snapshot, "cp=%u"}, | 618 | {Opt_snapshot, "cp=%u"}, |
537 | {Opt_order, "order=%s"}, | 619 | {Opt_order, "order=%s"}, |
538 | {Opt_norecovery, "norecovery"}, | 620 | {Opt_norecovery, "norecovery"}, |
539 | {Opt_discard, "discard"}, | 621 | {Opt_discard, "discard"}, |
622 | {Opt_nodiscard, "nodiscard"}, | ||
540 | {Opt_err, NULL} | 623 | {Opt_err, NULL} |
541 | }; | 624 | }; |
542 | 625 | ||
543 | static int parse_options(char *options, struct super_block *sb) | 626 | static int parse_options(char *options, struct super_block *sb, int is_remount) |
544 | { | 627 | { |
545 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 628 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
546 | char *p; | 629 | char *p; |
@@ -557,6 +640,9 @@ static int parse_options(char *options, struct super_block *sb) | |||
557 | 640 | ||
558 | token = match_token(p, tokens, args); | 641 | token = match_token(p, tokens, args); |
559 | switch (token) { | 642 | switch (token) { |
643 | case Opt_barrier: | ||
644 | nilfs_set_opt(sbi, BARRIER); | ||
645 | break; | ||
560 | case Opt_nobarrier: | 646 | case Opt_nobarrier: |
561 | nilfs_clear_opt(sbi, BARRIER); | 647 | nilfs_clear_opt(sbi, BARRIER); |
562 | break; | 648 | break; |
@@ -582,8 +668,26 @@ static int parse_options(char *options, struct super_block *sb) | |||
582 | case Opt_snapshot: | 668 | case Opt_snapshot: |
583 | if (match_int(&args[0], &option) || option <= 0) | 669 | if (match_int(&args[0], &option) || option <= 0) |
584 | return 0; | 670 | return 0; |
585 | if (!(sb->s_flags & MS_RDONLY)) | 671 | if (is_remount) { |
672 | if (!nilfs_test_opt(sbi, SNAPSHOT)) { | ||
673 | printk(KERN_ERR | ||
674 | "NILFS: cannot change regular " | ||
675 | "mount to snapshot.\n"); | ||
676 | return 0; | ||
677 | } else if (option != sbi->s_snapshot_cno) { | ||
678 | printk(KERN_ERR | ||
679 | "NILFS: cannot remount to a " | ||
680 | "different snapshot.\n"); | ||
681 | return 0; | ||
682 | } | ||
683 | break; | ||
684 | } | ||
685 | if (!(sb->s_flags & MS_RDONLY)) { | ||
686 | printk(KERN_ERR "NILFS: cannot mount snapshot " | ||
687 | "read/write. A read-only option is " | ||
688 | "required.\n"); | ||
586 | return 0; | 689 | return 0; |
690 | } | ||
587 | sbi->s_snapshot_cno = option; | 691 | sbi->s_snapshot_cno = option; |
588 | nilfs_set_opt(sbi, SNAPSHOT); | 692 | nilfs_set_opt(sbi, SNAPSHOT); |
589 | break; | 693 | break; |
@@ -593,6 +697,9 @@ static int parse_options(char *options, struct super_block *sb) | |||
593 | case Opt_discard: | 697 | case Opt_discard: |
594 | nilfs_set_opt(sbi, DISCARD); | 698 | nilfs_set_opt(sbi, DISCARD); |
595 | break; | 699 | break; |
700 | case Opt_nodiscard: | ||
701 | nilfs_clear_opt(sbi, DISCARD); | ||
702 | break; | ||
596 | default: | 703 | default: |
597 | printk(KERN_ERR | 704 | printk(KERN_ERR |
598 | "NILFS: Unrecognized mount option \"%s\"\n", p); | 705 | "NILFS: Unrecognized mount option \"%s\"\n", p); |
@@ -613,11 +720,18 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, | |||
613 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) | 720 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) |
614 | { | 721 | { |
615 | struct the_nilfs *nilfs = sbi->s_nilfs; | 722 | struct the_nilfs *nilfs = sbi->s_nilfs; |
616 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; | 723 | struct nilfs_super_block **sbp; |
617 | int max_mnt_count = le16_to_cpu(sbp->s_max_mnt_count); | 724 | int max_mnt_count; |
618 | int mnt_count = le16_to_cpu(sbp->s_mnt_count); | 725 | int mnt_count; |
726 | |||
727 | /* nilfs->ns_sem must be locked by the caller. */ | ||
728 | sbp = nilfs_prepare_super(sbi, 0); | ||
729 | if (!sbp) | ||
730 | return -EIO; | ||
731 | |||
732 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); | ||
733 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); | ||
619 | 734 | ||
620 | /* nilfs->sem must be locked by the caller. */ | ||
621 | if (nilfs->ns_mount_state & NILFS_ERROR_FS) { | 735 | if (nilfs->ns_mount_state & NILFS_ERROR_FS) { |
622 | printk(KERN_WARNING | 736 | printk(KERN_WARNING |
623 | "NILFS warning: mounting fs with errors\n"); | 737 | "NILFS warning: mounting fs with errors\n"); |
@@ -628,12 +742,15 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
628 | #endif | 742 | #endif |
629 | } | 743 | } |
630 | if (!max_mnt_count) | 744 | if (!max_mnt_count) |
631 | sbp->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); | 745 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); |
632 | 746 | ||
633 | sbp->s_mnt_count = cpu_to_le16(mnt_count + 1); | 747 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); |
634 | sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS); | 748 | sbp[0]->s_state = |
635 | sbp->s_mtime = cpu_to_le64(get_seconds()); | 749 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); |
636 | return nilfs_commit_super(sbi, 1); | 750 | sbp[0]->s_mtime = cpu_to_le64(get_seconds()); |
751 | /* synchronize sbp[1] with sbp[0] */ | ||
752 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | ||
753 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | ||
637 | } | 754 | } |
638 | 755 | ||
639 | struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, | 756 | struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, |
@@ -670,7 +787,31 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
670 | sbi->s_interval = le32_to_cpu(sbp->s_c_interval); | 787 | sbi->s_interval = le32_to_cpu(sbp->s_c_interval); |
671 | sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); | 788 | sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); |
672 | 789 | ||
673 | return !parse_options(data, sb) ? -EINVAL : 0 ; | 790 | return !parse_options(data, sb, 0) ? -EINVAL : 0 ; |
791 | } | ||
792 | |||
793 | int nilfs_check_feature_compatibility(struct super_block *sb, | ||
794 | struct nilfs_super_block *sbp) | ||
795 | { | ||
796 | __u64 features; | ||
797 | |||
798 | features = le64_to_cpu(sbp->s_feature_incompat) & | ||
799 | ~NILFS_FEATURE_INCOMPAT_SUPP; | ||
800 | if (features) { | ||
801 | printk(KERN_ERR "NILFS: couldn't mount because of unsupported " | ||
802 | "optional features (%llx)\n", | ||
803 | (unsigned long long)features); | ||
804 | return -EINVAL; | ||
805 | } | ||
806 | features = le64_to_cpu(sbp->s_feature_compat_ro) & | ||
807 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
808 | if (!(sb->s_flags & MS_RDONLY) && features) { | ||
809 | printk(KERN_ERR "NILFS: couldn't mount RDWR because of " | ||
810 | "unsupported optional features (%llx)\n", | ||
811 | (unsigned long long)features); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | return 0; | ||
674 | } | 815 | } |
675 | 816 | ||
676 | /** | 817 | /** |
@@ -819,7 +960,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
819 | static int nilfs_remount(struct super_block *sb, int *flags, char *data) | 960 | static int nilfs_remount(struct super_block *sb, int *flags, char *data) |
820 | { | 961 | { |
821 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 962 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
822 | struct nilfs_super_block *sbp; | ||
823 | struct the_nilfs *nilfs = sbi->s_nilfs; | 963 | struct the_nilfs *nilfs = sbi->s_nilfs; |
824 | unsigned long old_sb_flags; | 964 | unsigned long old_sb_flags; |
825 | struct nilfs_mount_options old_opts; | 965 | struct nilfs_mount_options old_opts; |
@@ -833,32 +973,17 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
833 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | 973 | old_opts.snapshot_cno = sbi->s_snapshot_cno; |
834 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); | 974 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); |
835 | 975 | ||
836 | if (!parse_options(data, sb)) { | 976 | if (!parse_options(data, sb, 1)) { |
837 | err = -EINVAL; | 977 | err = -EINVAL; |
838 | goto restore_opts; | 978 | goto restore_opts; |
839 | } | 979 | } |
840 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); | 980 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); |
841 | 981 | ||
842 | err = -EINVAL; | 982 | err = -EINVAL; |
843 | if (was_snapshot) { | 983 | if (was_snapshot && !(*flags & MS_RDONLY)) { |
844 | if (!(*flags & MS_RDONLY)) { | 984 | printk(KERN_ERR "NILFS (device %s): cannot remount snapshot " |
845 | printk(KERN_ERR "NILFS (device %s): cannot remount " | 985 | "read/write.\n", sb->s_id); |
846 | "snapshot read/write.\n", | 986 | goto restore_opts; |
847 | sb->s_id); | ||
848 | goto restore_opts; | ||
849 | } else if (sbi->s_snapshot_cno != old_opts.snapshot_cno) { | ||
850 | printk(KERN_ERR "NILFS (device %s): cannot " | ||
851 | "remount to a different snapshot.\n", | ||
852 | sb->s_id); | ||
853 | goto restore_opts; | ||
854 | } | ||
855 | } else { | ||
856 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | ||
857 | printk(KERN_ERR "NILFS (device %s): cannot change " | ||
858 | "a regular mount to a snapshot.\n", | ||
859 | sb->s_id); | ||
860 | goto restore_opts; | ||
861 | } | ||
862 | } | 987 | } |
863 | 988 | ||
864 | if (!nilfs_valid_fs(nilfs)) { | 989 | if (!nilfs_valid_fs(nilfs)) { |
@@ -880,19 +1005,29 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
880 | * the RDONLY flag and then mark the partition as valid again. | 1005 | * the RDONLY flag and then mark the partition as valid again. |
881 | */ | 1006 | */ |
882 | down_write(&nilfs->ns_sem); | 1007 | down_write(&nilfs->ns_sem); |
883 | sbp = nilfs->ns_sbp[0]; | 1008 | nilfs_cleanup_super(sbi); |
884 | if (!(sbp->s_state & le16_to_cpu(NILFS_VALID_FS)) && | ||
885 | (nilfs->ns_mount_state & NILFS_VALID_FS)) | ||
886 | sbp->s_state = cpu_to_le16(nilfs->ns_mount_state); | ||
887 | sbp->s_mtime = cpu_to_le64(get_seconds()); | ||
888 | nilfs_commit_super(sbi, 1); | ||
889 | up_write(&nilfs->ns_sem); | 1009 | up_write(&nilfs->ns_sem); |
890 | } else { | 1010 | } else { |
1011 | __u64 features; | ||
1012 | |||
891 | /* | 1013 | /* |
892 | * Mounting a RDONLY partition read-write, so reread and | 1014 | * Mounting a RDONLY partition read-write, so reread and |
893 | * store the current valid flag. (It may have been changed | 1015 | * store the current valid flag. (It may have been changed |
894 | * by fsck since we originally mounted the partition.) | 1016 | * by fsck since we originally mounted the partition.) |
895 | */ | 1017 | */ |
1018 | down_read(&nilfs->ns_sem); | ||
1019 | features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & | ||
1020 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
1021 | up_read(&nilfs->ns_sem); | ||
1022 | if (features) { | ||
1023 | printk(KERN_WARNING "NILFS (device %s): couldn't " | ||
1024 | "remount RDWR because of unsupported optional " | ||
1025 | "features (%llx)\n", | ||
1026 | sb->s_id, (unsigned long long)features); | ||
1027 | err = -EROFS; | ||
1028 | goto restore_opts; | ||
1029 | } | ||
1030 | |||
896 | sb->s_flags &= ~MS_RDONLY; | 1031 | sb->s_flags &= ~MS_RDONLY; |
897 | 1032 | ||
898 | err = nilfs_attach_segment_constructor(sbi); | 1033 | err = nilfs_attach_segment_constructor(sbi); |
@@ -1119,7 +1254,7 @@ static void nilfs_inode_init_once(void *obj) | |||
1119 | init_rwsem(&ii->xattr_sem); | 1254 | init_rwsem(&ii->xattr_sem); |
1120 | #endif | 1255 | #endif |
1121 | nilfs_btnode_cache_init_once(&ii->i_btnode_cache); | 1256 | nilfs_btnode_cache_init_once(&ii->i_btnode_cache); |
1122 | ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; | 1257 | ii->i_bmap = &ii->i_bmap_data; |
1123 | inode_init_once(&ii->vfs_inode); | 1258 | inode_init_once(&ii->vfs_inode); |
1124 | } | 1259 | } |
1125 | 1260 | ||
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 8c1097327abc..37de1f062d81 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -38,6 +38,8 @@ | |||
38 | static LIST_HEAD(nilfs_objects); | 38 | static LIST_HEAD(nilfs_objects); |
39 | static DEFINE_SPINLOCK(nilfs_lock); | 39 | static DEFINE_SPINLOCK(nilfs_lock); |
40 | 40 | ||
41 | static int nilfs_valid_sb(struct nilfs_super_block *sbp); | ||
42 | |||
41 | void nilfs_set_last_segment(struct the_nilfs *nilfs, | 43 | void nilfs_set_last_segment(struct the_nilfs *nilfs, |
42 | sector_t start_blocknr, u64 seq, __u64 cno) | 44 | sector_t start_blocknr, u64 seq, __u64 cno) |
43 | { | 45 | { |
@@ -45,6 +47,16 @@ void nilfs_set_last_segment(struct the_nilfs *nilfs, | |||
45 | nilfs->ns_last_pseg = start_blocknr; | 47 | nilfs->ns_last_pseg = start_blocknr; |
46 | nilfs->ns_last_seq = seq; | 48 | nilfs->ns_last_seq = seq; |
47 | nilfs->ns_last_cno = cno; | 49 | nilfs->ns_last_cno = cno; |
50 | |||
51 | if (!nilfs_sb_dirty(nilfs)) { | ||
52 | if (nilfs->ns_prev_seq == nilfs->ns_last_seq) | ||
53 | goto stay_cursor; | ||
54 | |||
55 | set_nilfs_sb_dirty(nilfs); | ||
56 | } | ||
57 | nilfs->ns_prev_seq = nilfs->ns_last_seq; | ||
58 | |||
59 | stay_cursor: | ||
48 | spin_unlock(&nilfs->ns_last_segment_lock); | 60 | spin_unlock(&nilfs->ns_last_segment_lock); |
49 | } | 61 | } |
50 | 62 | ||
@@ -159,8 +171,7 @@ void put_nilfs(struct the_nilfs *nilfs) | |||
159 | kfree(nilfs); | 171 | kfree(nilfs); |
160 | } | 172 | } |
161 | 173 | ||
162 | static int nilfs_load_super_root(struct the_nilfs *nilfs, | 174 | static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block) |
163 | struct nilfs_sb_info *sbi, sector_t sr_block) | ||
164 | { | 175 | { |
165 | struct buffer_head *bh_sr; | 176 | struct buffer_head *bh_sr; |
166 | struct nilfs_super_root *raw_sr; | 177 | struct nilfs_super_root *raw_sr; |
@@ -169,7 +180,7 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, | |||
169 | unsigned inode_size; | 180 | unsigned inode_size; |
170 | int err; | 181 | int err; |
171 | 182 | ||
172 | err = nilfs_read_super_root_block(sbi->s_super, sr_block, &bh_sr, 1); | 183 | err = nilfs_read_super_root_block(nilfs, sr_block, &bh_sr, 1); |
173 | if (unlikely(err)) | 184 | if (unlikely(err)) |
174 | return err; | 185 | return err; |
175 | 186 | ||
@@ -248,6 +259,37 @@ static void nilfs_clear_recovery_info(struct nilfs_recovery_info *ri) | |||
248 | } | 259 | } |
249 | 260 | ||
250 | /** | 261 | /** |
262 | * nilfs_store_log_cursor - load log cursor from a super block | ||
263 | * @nilfs: nilfs object | ||
264 | * @sbp: buffer storing super block to be read | ||
265 | * | ||
266 | * nilfs_store_log_cursor() reads the last position of the log | ||
267 | * containing a super root from a given super block, and initializes | ||
268 | * relevant information on the nilfs object preparatory for log | ||
269 | * scanning and recovery. | ||
270 | */ | ||
271 | static int nilfs_store_log_cursor(struct the_nilfs *nilfs, | ||
272 | struct nilfs_super_block *sbp) | ||
273 | { | ||
274 | int ret = 0; | ||
275 | |||
276 | nilfs->ns_last_pseg = le64_to_cpu(sbp->s_last_pseg); | ||
277 | nilfs->ns_last_cno = le64_to_cpu(sbp->s_last_cno); | ||
278 | nilfs->ns_last_seq = le64_to_cpu(sbp->s_last_seq); | ||
279 | |||
280 | nilfs->ns_prev_seq = nilfs->ns_last_seq; | ||
281 | nilfs->ns_seg_seq = nilfs->ns_last_seq; | ||
282 | nilfs->ns_segnum = | ||
283 | nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg); | ||
284 | nilfs->ns_cno = nilfs->ns_last_cno + 1; | ||
285 | if (nilfs->ns_segnum >= nilfs->ns_nsegments) { | ||
286 | printk(KERN_ERR "NILFS invalid last segment number.\n"); | ||
287 | ret = -EINVAL; | ||
288 | } | ||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | /** | ||
251 | * load_nilfs - load and recover the nilfs | 293 | * load_nilfs - load and recover the nilfs |
252 | * @nilfs: the_nilfs structure to be released | 294 | * @nilfs: the_nilfs structure to be released |
253 | * @sbi: nilfs_sb_info used to recover past segment | 295 | * @sbi: nilfs_sb_info used to recover past segment |
@@ -285,13 +327,55 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
285 | 327 | ||
286 | nilfs_init_recovery_info(&ri); | 328 | nilfs_init_recovery_info(&ri); |
287 | 329 | ||
288 | err = nilfs_search_super_root(nilfs, sbi, &ri); | 330 | err = nilfs_search_super_root(nilfs, &ri); |
289 | if (unlikely(err)) { | 331 | if (unlikely(err)) { |
290 | printk(KERN_ERR "NILFS: error searching super root.\n"); | 332 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
291 | goto failed; | 333 | int blocksize; |
334 | |||
335 | if (err != -EINVAL) | ||
336 | goto scan_error; | ||
337 | |||
338 | if (!nilfs_valid_sb(sbp[1])) { | ||
339 | printk(KERN_WARNING | ||
340 | "NILFS warning: unable to fall back to spare" | ||
341 | "super block\n"); | ||
342 | goto scan_error; | ||
343 | } | ||
344 | printk(KERN_INFO | ||
345 | "NILFS: try rollback from an earlier position\n"); | ||
346 | |||
347 | /* | ||
348 | * restore super block with its spare and reconfigure | ||
349 | * relevant states of the nilfs object. | ||
350 | */ | ||
351 | memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); | ||
352 | nilfs->ns_crc_seed = le32_to_cpu(sbp[0]->s_crc_seed); | ||
353 | nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); | ||
354 | |||
355 | /* verify consistency between two super blocks */ | ||
356 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); | ||
357 | if (blocksize != nilfs->ns_blocksize) { | ||
358 | printk(KERN_WARNING | ||
359 | "NILFS warning: blocksize differs between " | ||
360 | "two super blocks (%d != %d)\n", | ||
361 | blocksize, nilfs->ns_blocksize); | ||
362 | goto scan_error; | ||
363 | } | ||
364 | |||
365 | err = nilfs_store_log_cursor(nilfs, sbp[0]); | ||
366 | if (err) | ||
367 | goto scan_error; | ||
368 | |||
369 | /* drop clean flag to allow roll-forward and recovery */ | ||
370 | nilfs->ns_mount_state &= ~NILFS_VALID_FS; | ||
371 | valid_fs = 0; | ||
372 | |||
373 | err = nilfs_search_super_root(nilfs, &ri); | ||
374 | if (err) | ||
375 | goto scan_error; | ||
292 | } | 376 | } |
293 | 377 | ||
294 | err = nilfs_load_super_root(nilfs, sbi, ri.ri_super_root); | 378 | err = nilfs_load_super_root(nilfs, ri.ri_super_root); |
295 | if (unlikely(err)) { | 379 | if (unlikely(err)) { |
296 | printk(KERN_ERR "NILFS: error loading super root.\n"); | 380 | printk(KERN_ERR "NILFS: error loading super root.\n"); |
297 | goto failed; | 381 | goto failed; |
@@ -301,11 +385,23 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
301 | goto skip_recovery; | 385 | goto skip_recovery; |
302 | 386 | ||
303 | if (s_flags & MS_RDONLY) { | 387 | if (s_flags & MS_RDONLY) { |
388 | __u64 features; | ||
389 | |||
304 | if (nilfs_test_opt(sbi, NORECOVERY)) { | 390 | if (nilfs_test_opt(sbi, NORECOVERY)) { |
305 | printk(KERN_INFO "NILFS: norecovery option specified. " | 391 | printk(KERN_INFO "NILFS: norecovery option specified. " |
306 | "skipping roll-forward recovery\n"); | 392 | "skipping roll-forward recovery\n"); |
307 | goto skip_recovery; | 393 | goto skip_recovery; |
308 | } | 394 | } |
395 | features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & | ||
396 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
397 | if (features) { | ||
398 | printk(KERN_ERR "NILFS: couldn't proceed with " | ||
399 | "recovery because of unsupported optional " | ||
400 | "features (%llx)\n", | ||
401 | (unsigned long long)features); | ||
402 | err = -EROFS; | ||
403 | goto failed_unload; | ||
404 | } | ||
309 | if (really_read_only) { | 405 | if (really_read_only) { |
310 | printk(KERN_ERR "NILFS: write access " | 406 | printk(KERN_ERR "NILFS: write access " |
311 | "unavailable, cannot proceed.\n"); | 407 | "unavailable, cannot proceed.\n"); |
@@ -320,14 +416,13 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
320 | goto failed_unload; | 416 | goto failed_unload; |
321 | } | 417 | } |
322 | 418 | ||
323 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); | 419 | err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri); |
324 | if (err) | 420 | if (err) |
325 | goto failed_unload; | 421 | goto failed_unload; |
326 | 422 | ||
327 | down_write(&nilfs->ns_sem); | 423 | down_write(&nilfs->ns_sem); |
328 | nilfs->ns_mount_state |= NILFS_VALID_FS; | 424 | nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */ |
329 | nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); | 425 | err = nilfs_cleanup_super(sbi); |
330 | err = nilfs_commit_super(sbi, 1); | ||
331 | up_write(&nilfs->ns_sem); | 426 | up_write(&nilfs->ns_sem); |
332 | 427 | ||
333 | if (err) { | 428 | if (err) { |
@@ -343,6 +438,10 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
343 | sbi->s_super->s_flags = s_flags; | 438 | sbi->s_super->s_flags = s_flags; |
344 | return 0; | 439 | return 0; |
345 | 440 | ||
441 | scan_error: | ||
442 | printk(KERN_ERR "NILFS: error searching super root.\n"); | ||
443 | goto failed; | ||
444 | |||
346 | failed_unload: | 445 | failed_unload: |
347 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 446 | nilfs_mdt_destroy(nilfs->ns_cpfile); |
348 | nilfs_mdt_destroy(nilfs->ns_sufile); | 447 | nilfs_mdt_destroy(nilfs->ns_sufile); |
@@ -515,8 +614,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, | |||
515 | nilfs_swap_super_block(nilfs); | 614 | nilfs_swap_super_block(nilfs); |
516 | } | 615 | } |
517 | 616 | ||
518 | nilfs->ns_sbwtime[0] = le64_to_cpu(sbp[0]->s_wtime); | 617 | nilfs->ns_sbwcount = 0; |
519 | nilfs->ns_sbwtime[1] = valid[!swp] ? le64_to_cpu(sbp[1]->s_wtime) : 0; | 618 | nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); |
520 | nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq); | 619 | nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq); |
521 | *sbpp = sbp[0]; | 620 | *sbpp = sbp[0]; |
522 | return 0; | 621 | return 0; |
@@ -557,6 +656,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
557 | if (err) | 656 | if (err) |
558 | goto out; | 657 | goto out; |
559 | 658 | ||
659 | err = nilfs_check_feature_compatibility(sb, sbp); | ||
660 | if (err) | ||
661 | goto out; | ||
662 | |||
560 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); | 663 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
561 | if (sb->s_blocksize != blocksize && | 664 | if (sb->s_blocksize != blocksize && |
562 | !sb_set_blocksize(sb, blocksize)) { | 665 | !sb_set_blocksize(sb, blocksize)) { |
@@ -568,7 +671,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
568 | goto out; | 671 | goto out; |
569 | } | 672 | } |
570 | 673 | ||
571 | blocksize = sb_min_blocksize(sb, BLOCK_SIZE); | 674 | blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); |
572 | if (!blocksize) { | 675 | if (!blocksize) { |
573 | printk(KERN_ERR "NILFS: unable to set blocksize\n"); | 676 | printk(KERN_ERR "NILFS: unable to set blocksize\n"); |
574 | err = -EINVAL; | 677 | err = -EINVAL; |
@@ -582,7 +685,18 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
582 | if (err) | 685 | if (err) |
583 | goto failed_sbh; | 686 | goto failed_sbh; |
584 | 687 | ||
688 | err = nilfs_check_feature_compatibility(sb, sbp); | ||
689 | if (err) | ||
690 | goto failed_sbh; | ||
691 | |||
585 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); | 692 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
693 | if (blocksize < NILFS_MIN_BLOCK_SIZE || | ||
694 | blocksize > NILFS_MAX_BLOCK_SIZE) { | ||
695 | printk(KERN_ERR "NILFS: couldn't mount because of unsupported " | ||
696 | "filesystem blocksize %d\n", blocksize); | ||
697 | err = -EINVAL; | ||
698 | goto failed_sbh; | ||
699 | } | ||
586 | if (sb->s_blocksize != blocksize) { | 700 | if (sb->s_blocksize != blocksize) { |
587 | int hw_blocksize = bdev_logical_block_size(sb->s_bdev); | 701 | int hw_blocksize = bdev_logical_block_size(sb->s_bdev); |
588 | 702 | ||
@@ -604,6 +718,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
604 | when reloading fails. */ | 718 | when reloading fails. */ |
605 | } | 719 | } |
606 | nilfs->ns_blocksize_bits = sb->s_blocksize_bits; | 720 | nilfs->ns_blocksize_bits = sb->s_blocksize_bits; |
721 | nilfs->ns_blocksize = blocksize; | ||
607 | 722 | ||
608 | err = nilfs_store_disk_layout(nilfs, sbp); | 723 | err = nilfs_store_disk_layout(nilfs, sbp); |
609 | if (err) | 724 | if (err) |
@@ -616,23 +731,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
616 | bdi = nilfs->ns_bdev->bd_inode->i_mapping->backing_dev_info; | 731 | bdi = nilfs->ns_bdev->bd_inode->i_mapping->backing_dev_info; |
617 | nilfs->ns_bdi = bdi ? : &default_backing_dev_info; | 732 | nilfs->ns_bdi = bdi ? : &default_backing_dev_info; |
618 | 733 | ||
619 | /* Finding last segment */ | 734 | err = nilfs_store_log_cursor(nilfs, sbp); |
620 | nilfs->ns_last_pseg = le64_to_cpu(sbp->s_last_pseg); | 735 | if (err) |
621 | nilfs->ns_last_cno = le64_to_cpu(sbp->s_last_cno); | ||
622 | nilfs->ns_last_seq = le64_to_cpu(sbp->s_last_seq); | ||
623 | |||
624 | nilfs->ns_seg_seq = nilfs->ns_last_seq; | ||
625 | nilfs->ns_segnum = | ||
626 | nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg); | ||
627 | nilfs->ns_cno = nilfs->ns_last_cno + 1; | ||
628 | if (nilfs->ns_segnum >= nilfs->ns_nsegments) { | ||
629 | printk(KERN_ERR "NILFS invalid last segment number.\n"); | ||
630 | err = -EINVAL; | ||
631 | goto failed_sbh; | 736 | goto failed_sbh; |
632 | } | ||
633 | /* Dummy values */ | ||
634 | nilfs->ns_free_segments_count = | ||
635 | nilfs->ns_nsegments - (nilfs->ns_segnum + 1); | ||
636 | 737 | ||
637 | /* Initialize gcinode cache */ | 738 | /* Initialize gcinode cache */ |
638 | err = nilfs_init_gccache(nilfs); | 739 | err = nilfs_init_gccache(nilfs); |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 1ab974533697..f785a7b0ab99 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -57,7 +57,8 @@ enum { | |||
57 | * @ns_current: back pointer to current mount | 57 | * @ns_current: back pointer to current mount |
58 | * @ns_sbh: buffer heads of on-disk super blocks | 58 | * @ns_sbh: buffer heads of on-disk super blocks |
59 | * @ns_sbp: pointers to super block data | 59 | * @ns_sbp: pointers to super block data |
60 | * @ns_sbwtime: previous write time of super blocks | 60 | * @ns_sbwtime: previous write time of super block |
61 | * @ns_sbwcount: write count of super block | ||
61 | * @ns_sbsize: size of valid data in super block | 62 | * @ns_sbsize: size of valid data in super block |
62 | * @ns_supers: list of nilfs super block structs | 63 | * @ns_supers: list of nilfs super block structs |
63 | * @ns_seg_seq: segment sequence counter | 64 | * @ns_seg_seq: segment sequence counter |
@@ -73,7 +74,7 @@ enum { | |||
73 | * @ns_last_seq: sequence value of the latest segment | 74 | * @ns_last_seq: sequence value of the latest segment |
74 | * @ns_last_cno: checkpoint number of the latest segment | 75 | * @ns_last_cno: checkpoint number of the latest segment |
75 | * @ns_prot_seq: least sequence number of segments which must not be reclaimed | 76 | * @ns_prot_seq: least sequence number of segments which must not be reclaimed |
76 | * @ns_free_segments_count: counter of free segments | 77 | * @ns_prev_seq: base sequence number used to decide if advance log cursor |
77 | * @ns_segctor_sem: segment constructor semaphore | 78 | * @ns_segctor_sem: segment constructor semaphore |
78 | * @ns_dat: DAT file inode | 79 | * @ns_dat: DAT file inode |
79 | * @ns_cpfile: checkpoint file inode | 80 | * @ns_cpfile: checkpoint file inode |
@@ -82,6 +83,7 @@ enum { | |||
82 | * @ns_gc_inodes: dummy inodes to keep live blocks | 83 | * @ns_gc_inodes: dummy inodes to keep live blocks |
83 | * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks | 84 | * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks |
84 | * @ns_blocksize_bits: bit length of block size | 85 | * @ns_blocksize_bits: bit length of block size |
86 | * @ns_blocksize: block size | ||
85 | * @ns_nsegments: number of segments in filesystem | 87 | * @ns_nsegments: number of segments in filesystem |
86 | * @ns_blocks_per_segment: number of blocks per segment | 88 | * @ns_blocks_per_segment: number of blocks per segment |
87 | * @ns_r_segments_percentage: reserved segments percentage | 89 | * @ns_r_segments_percentage: reserved segments percentage |
@@ -119,7 +121,8 @@ struct the_nilfs { | |||
119 | */ | 121 | */ |
120 | struct buffer_head *ns_sbh[2]; | 122 | struct buffer_head *ns_sbh[2]; |
121 | struct nilfs_super_block *ns_sbp[2]; | 123 | struct nilfs_super_block *ns_sbp[2]; |
122 | time_t ns_sbwtime[2]; | 124 | time_t ns_sbwtime; |
125 | unsigned ns_sbwcount; | ||
123 | unsigned ns_sbsize; | 126 | unsigned ns_sbsize; |
124 | unsigned ns_mount_state; | 127 | unsigned ns_mount_state; |
125 | 128 | ||
@@ -149,7 +152,7 @@ struct the_nilfs { | |||
149 | u64 ns_last_seq; | 152 | u64 ns_last_seq; |
150 | __u64 ns_last_cno; | 153 | __u64 ns_last_cno; |
151 | u64 ns_prot_seq; | 154 | u64 ns_prot_seq; |
152 | unsigned long ns_free_segments_count; | 155 | u64 ns_prev_seq; |
153 | 156 | ||
154 | struct rw_semaphore ns_segctor_sem; | 157 | struct rw_semaphore ns_segctor_sem; |
155 | 158 | ||
@@ -168,6 +171,7 @@ struct the_nilfs { | |||
168 | 171 | ||
169 | /* Disk layout information (static) */ | 172 | /* Disk layout information (static) */ |
170 | unsigned int ns_blocksize_bits; | 173 | unsigned int ns_blocksize_bits; |
174 | unsigned int ns_blocksize; | ||
171 | unsigned long ns_nsegments; | 175 | unsigned long ns_nsegments; |
172 | unsigned long ns_blocks_per_segment; | 176 | unsigned long ns_blocks_per_segment; |
173 | unsigned long ns_r_segments_percentage; | 177 | unsigned long ns_r_segments_percentage; |
@@ -203,20 +207,17 @@ THE_NILFS_FNS(SB_DIRTY, sb_dirty) | |||
203 | 207 | ||
204 | /* Minimum interval of periodical update of superblocks (in seconds) */ | 208 | /* Minimum interval of periodical update of superblocks (in seconds) */ |
205 | #define NILFS_SB_FREQ 10 | 209 | #define NILFS_SB_FREQ 10 |
206 | #define NILFS_ALTSB_FREQ 60 /* spare superblock */ | ||
207 | 210 | ||
208 | static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) | 211 | static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) |
209 | { | 212 | { |
210 | u64 t = get_seconds(); | 213 | u64 t = get_seconds(); |
211 | return t < nilfs->ns_sbwtime[0] || | 214 | return t < nilfs->ns_sbwtime || t > nilfs->ns_sbwtime + NILFS_SB_FREQ; |
212 | t > nilfs->ns_sbwtime[0] + NILFS_SB_FREQ; | ||
213 | } | 215 | } |
214 | 216 | ||
215 | static inline int nilfs_altsb_need_update(struct the_nilfs *nilfs) | 217 | static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) |
216 | { | 218 | { |
217 | u64 t = get_seconds(); | 219 | int flip_bits = nilfs->ns_sbwcount & 0x0FL; |
218 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 220 | return (flip_bits != 0x08 && flip_bits != 0x0F); |
219 | return sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ; | ||
220 | } | 221 | } |
221 | 222 | ||
222 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); | 223 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); |
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 8c2c6116e788..f5487b6f91ed 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h | |||
@@ -160,7 +160,7 @@ struct nilfs_super_root { | |||
160 | * struct nilfs_super_block - structure of super block on disk | 160 | * struct nilfs_super_block - structure of super block on disk |
161 | */ | 161 | */ |
162 | struct nilfs_super_block { | 162 | struct nilfs_super_block { |
163 | __le32 s_rev_level; /* Revision level */ | 163 | /*00*/ __le32 s_rev_level; /* Revision level */ |
164 | __le16 s_minor_rev_level; /* minor revision level */ | 164 | __le16 s_minor_rev_level; /* minor revision level */ |
165 | __le16 s_magic; /* Magic signature */ | 165 | __le16 s_magic; /* Magic signature */ |
166 | 166 | ||
@@ -169,50 +169,53 @@ struct nilfs_super_block { | |||
169 | is excluded. */ | 169 | is excluded. */ |
170 | __le16 s_flags; /* flags */ | 170 | __le16 s_flags; /* flags */ |
171 | __le32 s_crc_seed; /* Seed value of CRC calculation */ | 171 | __le32 s_crc_seed; /* Seed value of CRC calculation */ |
172 | __le32 s_sum; /* Check sum of super block */ | 172 | /*10*/ __le32 s_sum; /* Check sum of super block */ |
173 | 173 | ||
174 | __le32 s_log_block_size; /* Block size represented as follows | 174 | __le32 s_log_block_size; /* Block size represented as follows |
175 | blocksize = | 175 | blocksize = |
176 | 1 << (s_log_block_size + 10) */ | 176 | 1 << (s_log_block_size + 10) */ |
177 | __le64 s_nsegments; /* Number of segments in filesystem */ | 177 | __le64 s_nsegments; /* Number of segments in filesystem */ |
178 | __le64 s_dev_size; /* block device size in bytes */ | 178 | /*20*/ __le64 s_dev_size; /* block device size in bytes */ |
179 | __le64 s_first_data_block; /* 1st seg disk block number */ | 179 | __le64 s_first_data_block; /* 1st seg disk block number */ |
180 | __le32 s_blocks_per_segment; /* number of blocks per full segment */ | 180 | /*30*/ __le32 s_blocks_per_segment; /* number of blocks per full segment */ |
181 | __le32 s_r_segments_percentage; /* Reserved segments percentage */ | 181 | __le32 s_r_segments_percentage; /* Reserved segments percentage */ |
182 | 182 | ||
183 | __le64 s_last_cno; /* Last checkpoint number */ | 183 | __le64 s_last_cno; /* Last checkpoint number */ |
184 | __le64 s_last_pseg; /* disk block addr pseg written last */ | 184 | /*40*/ __le64 s_last_pseg; /* disk block addr pseg written last */ |
185 | __le64 s_last_seq; /* seq. number of seg written last */ | 185 | __le64 s_last_seq; /* seq. number of seg written last */ |
186 | __le64 s_free_blocks_count; /* Free blocks count */ | 186 | /*50*/ __le64 s_free_blocks_count; /* Free blocks count */ |
187 | 187 | ||
188 | __le64 s_ctime; /* Creation time (execution time of | 188 | __le64 s_ctime; /* Creation time (execution time of |
189 | newfs) */ | 189 | newfs) */ |
190 | __le64 s_mtime; /* Mount time */ | 190 | /*60*/ __le64 s_mtime; /* Mount time */ |
191 | __le64 s_wtime; /* Write time */ | 191 | __le64 s_wtime; /* Write time */ |
192 | __le16 s_mnt_count; /* Mount count */ | 192 | /*70*/ __le16 s_mnt_count; /* Mount count */ |
193 | __le16 s_max_mnt_count; /* Maximal mount count */ | 193 | __le16 s_max_mnt_count; /* Maximal mount count */ |
194 | __le16 s_state; /* File system state */ | 194 | __le16 s_state; /* File system state */ |
195 | __le16 s_errors; /* Behaviour when detecting errors */ | 195 | __le16 s_errors; /* Behaviour when detecting errors */ |
196 | __le64 s_lastcheck; /* time of last check */ | 196 | __le64 s_lastcheck; /* time of last check */ |
197 | 197 | ||
198 | __le32 s_checkinterval; /* max. time between checks */ | 198 | /*80*/ __le32 s_checkinterval; /* max. time between checks */ |
199 | __le32 s_creator_os; /* OS */ | 199 | __le32 s_creator_os; /* OS */ |
200 | __le16 s_def_resuid; /* Default uid for reserved blocks */ | 200 | __le16 s_def_resuid; /* Default uid for reserved blocks */ |
201 | __le16 s_def_resgid; /* Default gid for reserved blocks */ | 201 | __le16 s_def_resgid; /* Default gid for reserved blocks */ |
202 | __le32 s_first_ino; /* First non-reserved inode */ | 202 | __le32 s_first_ino; /* First non-reserved inode */ |
203 | 203 | ||
204 | __le16 s_inode_size; /* Size of an inode */ | 204 | /*90*/ __le16 s_inode_size; /* Size of an inode */ |
205 | __le16 s_dat_entry_size; /* Size of a dat entry */ | 205 | __le16 s_dat_entry_size; /* Size of a dat entry */ |
206 | __le16 s_checkpoint_size; /* Size of a checkpoint */ | 206 | __le16 s_checkpoint_size; /* Size of a checkpoint */ |
207 | __le16 s_segment_usage_size; /* Size of a segment usage */ | 207 | __le16 s_segment_usage_size; /* Size of a segment usage */ |
208 | 208 | ||
209 | __u8 s_uuid[16]; /* 128-bit uuid for volume */ | 209 | /*98*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */ |
210 | char s_volume_name[80]; /* volume name */ | 210 | /*A8*/ char s_volume_name[80]; /* volume name */ |
211 | 211 | ||
212 | __le32 s_c_interval; /* Commit interval of segment */ | 212 | /*F8*/ __le32 s_c_interval; /* Commit interval of segment */ |
213 | __le32 s_c_block_max; /* Threshold of data amount for | 213 | __le32 s_c_block_max; /* Threshold of data amount for |
214 | the segment construction */ | 214 | the segment construction */ |
215 | __u32 s_reserved[192]; /* padding to the end of the block */ | 215 | /*100*/ __le64 s_feature_compat; /* Compatible feature set */ |
216 | __le64 s_feature_compat_ro; /* Read-only compatible feature set */ | ||
217 | __le64 s_feature_incompat; /* Incompatible feature set */ | ||
218 | __u32 s_reserved[186]; /* padding to the end of the block */ | ||
216 | }; | 219 | }; |
217 | 220 | ||
218 | /* | 221 | /* |
@@ -228,6 +231,16 @@ struct nilfs_super_block { | |||
228 | #define NILFS_MINOR_REV 0 /* minor revision */ | 231 | #define NILFS_MINOR_REV 0 /* minor revision */ |
229 | 232 | ||
230 | /* | 233 | /* |
234 | * Feature set definitions | ||
235 | * | ||
236 | * If there is a bit set in the incompatible feature set that the kernel | ||
237 | * doesn't know about, it should refuse to mount the filesystem. | ||
238 | */ | ||
239 | #define NILFS_FEATURE_COMPAT_SUPP 0ULL | ||
240 | #define NILFS_FEATURE_COMPAT_RO_SUPP 0ULL | ||
241 | #define NILFS_FEATURE_INCOMPAT_SUPP 0ULL | ||
242 | |||
243 | /* | ||
231 | * Bytes count of super_block for CRC-calculation | 244 | * Bytes count of super_block for CRC-calculation |
232 | */ | 245 | */ |
233 | #define NILFS_SB_BYTES \ | 246 | #define NILFS_SB_BYTES \ |
@@ -274,6 +287,12 @@ struct nilfs_super_block { | |||
274 | #define NILFS_NAME_LEN 255 | 287 | #define NILFS_NAME_LEN 255 |
275 | 288 | ||
276 | /* | 289 | /* |
290 | * Block size limitations | ||
291 | */ | ||
292 | #define NILFS_MIN_BLOCK_SIZE 1024 | ||
293 | #define NILFS_MAX_BLOCK_SIZE 65536 | ||
294 | |||
295 | /* | ||
277 | * The new version of the directory entry. Since V0 structures are | 296 | * The new version of the directory entry. Since V0 structures are |
278 | * stored in intel byte order, and the name_len field could never be | 297 | * stored in intel byte order, and the name_len field could never be |
279 | * bigger than 255 chars, it's safe to reclaim the extra byte for the | 298 | * bigger than 255 chars, it's safe to reclaim the extra byte for the |
@@ -313,7 +332,25 @@ enum { | |||
313 | #define NILFS_DIR_ROUND (NILFS_DIR_PAD - 1) | 332 | #define NILFS_DIR_ROUND (NILFS_DIR_PAD - 1) |
314 | #define NILFS_DIR_REC_LEN(name_len) (((name_len) + 12 + NILFS_DIR_ROUND) & \ | 333 | #define NILFS_DIR_REC_LEN(name_len) (((name_len) + 12 + NILFS_DIR_ROUND) & \ |
315 | ~NILFS_DIR_ROUND) | 334 | ~NILFS_DIR_ROUND) |
335 | #define NILFS_MAX_REC_LEN ((1<<16)-1) | ||
316 | 336 | ||
337 | static inline unsigned nilfs_rec_len_from_disk(__le16 dlen) | ||
338 | { | ||
339 | unsigned len = le16_to_cpu(dlen); | ||
340 | |||
341 | if (len == NILFS_MAX_REC_LEN) | ||
342 | return 1 << 16; | ||
343 | return len; | ||
344 | } | ||
345 | |||
346 | static inline __le16 nilfs_rec_len_to_disk(unsigned len) | ||
347 | { | ||
348 | if (len == (1 << 16)) | ||
349 | return cpu_to_le16(NILFS_MAX_REC_LEN); | ||
350 | else if (len > (1 << 16)) | ||
351 | BUG(); | ||
352 | return cpu_to_le16(len); | ||
353 | } | ||
317 | 354 | ||
318 | /** | 355 | /** |
319 | * struct nilfs_finfo - file information | 356 | * struct nilfs_finfo - file information |