diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 10:47:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 10:47:00 -0400 |
commit | d7dbf4ffee1c7a17e2e5b5f01efe76fbd1671db6 (patch) | |
tree | 2f4eda25c0c9eb6de1e573dba92b4d23fc383db5 /fs/nilfs2 | |
parent | 677abe49ad017679627af9d3bbd9a7ecb3d94c42 (diff) | |
parent | d240e06713007bba309b074a386b7072b73c31a6 (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: (23 commits)
nilfs2: disallow remount of snapshot from/to a regular mount
nilfs2: use huge_encode_dev/huge_decode_dev
nilfs2: update comment on deactivate_super at nilfs_get_sb
nilfs2: replace MS_VERBOSE with MS_SILENT
nilfs2: add missing initialization of s_mode
nilfs2: fix misuse of open_bdev_exclusive/close_bdev_exclusive
nilfs2: enlarge s_volume_name member in nilfs_super_block
nilfs2: use checkpoint number instead of timestamp to select super block
nilfs2: add missing endian conversion on super block magic number
nilfs2: make nilfs_sc_*_ops static
nilfs2: add kernel doc comments to persistent object allocator functions
nilfs2: change sc_timer from a pointer to an embedded one in struct nilfs_sc_info
nilfs2: remove nilfs_segctor_init() in segment.c
nilfs2: insert checkpoint number in segment summary header
nilfs2: add a print message after loading nilfs2
nilfs2: cleanup multi kmem_cache_{create,destroy} code
nilfs2: move out checksum routines to segment buffer code
nilfs2: move pointer to super root block into logs
nilfs2: change default of 'errors' mount option to 'remount-ro' mode
nilfs2: Combine nilfs_btree_release_path() and nilfs_btree_free_path()
...
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/alloc.c | 154 | ||||
-rw-r--r-- | fs/nilfs2/alloc.h | 7 | ||||
-rw-r--r-- | fs/nilfs2/btree.c | 91 | ||||
-rw-r--r-- | fs/nilfs2/btree.h | 23 | ||||
-rw-r--r-- | fs/nilfs2/inode.c | 4 | ||||
-rw-r--r-- | fs/nilfs2/recovery.c | 2 | ||||
-rw-r--r-- | fs/nilfs2/segbuf.c | 70 | ||||
-rw-r--r-- | fs/nilfs2/segbuf.h | 10 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 157 | ||||
-rw-r--r-- | fs/nilfs2/segment.h | 6 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 218 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 10 |
12 files changed, 412 insertions, 340 deletions
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index 7cfb87e692da..d7fd696e595c 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c | |||
@@ -31,6 +31,11 @@ | |||
31 | #include "alloc.h" | 31 | #include "alloc.h" |
32 | 32 | ||
33 | 33 | ||
34 | /** | ||
35 | * nilfs_palloc_groups_per_desc_block - get the number of groups that a group | ||
36 | * descriptor block can maintain | ||
37 | * @inode: inode of metadata file using this allocator | ||
38 | */ | ||
34 | static inline unsigned long | 39 | static inline unsigned long |
35 | nilfs_palloc_groups_per_desc_block(const struct inode *inode) | 40 | nilfs_palloc_groups_per_desc_block(const struct inode *inode) |
36 | { | 41 | { |
@@ -38,12 +43,21 @@ nilfs_palloc_groups_per_desc_block(const struct inode *inode) | |||
38 | sizeof(struct nilfs_palloc_group_desc); | 43 | sizeof(struct nilfs_palloc_group_desc); |
39 | } | 44 | } |
40 | 45 | ||
46 | /** | ||
47 | * nilfs_palloc_groups_count - get maximum number of groups | ||
48 | * @inode: inode of metadata file using this allocator | ||
49 | */ | ||
41 | static inline unsigned long | 50 | static inline unsigned long |
42 | nilfs_palloc_groups_count(const struct inode *inode) | 51 | nilfs_palloc_groups_count(const struct inode *inode) |
43 | { | 52 | { |
44 | return 1UL << (BITS_PER_LONG - (inode->i_blkbits + 3 /* log2(8) */)); | 53 | return 1UL << (BITS_PER_LONG - (inode->i_blkbits + 3 /* log2(8) */)); |
45 | } | 54 | } |
46 | 55 | ||
56 | /** | ||
57 | * nilfs_palloc_init_blockgroup - initialize private variables for allocator | ||
58 | * @inode: inode of metadata file using this allocator | ||
59 | * @entry_size: size of the persistent object | ||
60 | */ | ||
47 | int nilfs_palloc_init_blockgroup(struct inode *inode, unsigned entry_size) | 61 | int nilfs_palloc_init_blockgroup(struct inode *inode, unsigned entry_size) |
48 | { | 62 | { |
49 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); | 63 | struct nilfs_mdt_info *mi = NILFS_MDT(inode); |
@@ -69,6 +83,12 @@ int nilfs_palloc_init_blockgroup(struct inode *inode, unsigned entry_size) | |||
69 | return 0; | 83 | return 0; |
70 | } | 84 | } |
71 | 85 | ||
86 | /** | ||
87 | * nilfs_palloc_group - get group number and offset from an entry number | ||
88 | * @inode: inode of metadata file using this allocator | ||
89 | * @nr: serial number of the entry (e.g. inode number) | ||
90 | * @offset: pointer to store offset number in the group | ||
91 | */ | ||
72 | static unsigned long nilfs_palloc_group(const struct inode *inode, __u64 nr, | 92 | static unsigned long nilfs_palloc_group(const struct inode *inode, __u64 nr, |
73 | unsigned long *offset) | 93 | unsigned long *offset) |
74 | { | 94 | { |
@@ -78,6 +98,14 @@ static unsigned long nilfs_palloc_group(const struct inode *inode, __u64 nr, | |||
78 | return group; | 98 | return group; |
79 | } | 99 | } |
80 | 100 | ||
101 | /** | ||
102 | * nilfs_palloc_desc_blkoff - get block offset of a group descriptor block | ||
103 | * @inode: inode of metadata file using this allocator | ||
104 | * @group: group number | ||
105 | * | ||
106 | * nilfs_palloc_desc_blkoff() returns block offset of the descriptor | ||
107 | * block which contains a descriptor of the specified group. | ||
108 | */ | ||
81 | static unsigned long | 109 | static unsigned long |
82 | nilfs_palloc_desc_blkoff(const struct inode *inode, unsigned long group) | 110 | nilfs_palloc_desc_blkoff(const struct inode *inode, unsigned long group) |
83 | { | 111 | { |
@@ -86,6 +114,14 @@ nilfs_palloc_desc_blkoff(const struct inode *inode, unsigned long group) | |||
86 | return desc_block * NILFS_MDT(inode)->mi_blocks_per_desc_block; | 114 | return desc_block * NILFS_MDT(inode)->mi_blocks_per_desc_block; |
87 | } | 115 | } |
88 | 116 | ||
117 | /** | ||
118 | * nilfs_palloc_bitmap_blkoff - get block offset of a bitmap block | ||
119 | * @inode: inode of metadata file using this allocator | ||
120 | * @group: group number | ||
121 | * | ||
122 | * nilfs_palloc_bitmap_blkoff() returns block offset of the bitmap | ||
123 | * block used to allocate/deallocate entries in the specified group. | ||
124 | */ | ||
89 | static unsigned long | 125 | static unsigned long |
90 | nilfs_palloc_bitmap_blkoff(const struct inode *inode, unsigned long group) | 126 | nilfs_palloc_bitmap_blkoff(const struct inode *inode, unsigned long group) |
91 | { | 127 | { |
@@ -95,6 +131,12 @@ nilfs_palloc_bitmap_blkoff(const struct inode *inode, unsigned long group) | |||
95 | desc_offset * NILFS_MDT(inode)->mi_blocks_per_group; | 131 | desc_offset * NILFS_MDT(inode)->mi_blocks_per_group; |
96 | } | 132 | } |
97 | 133 | ||
134 | /** | ||
135 | * nilfs_palloc_group_desc_nfrees - get the number of free entries in a group | ||
136 | * @inode: inode of metadata file using this allocator | ||
137 | * @group: group number | ||
138 | * @desc: pointer to descriptor structure for the group | ||
139 | */ | ||
98 | static unsigned long | 140 | static unsigned long |
99 | nilfs_palloc_group_desc_nfrees(struct inode *inode, unsigned long group, | 141 | nilfs_palloc_group_desc_nfrees(struct inode *inode, unsigned long group, |
100 | const struct nilfs_palloc_group_desc *desc) | 142 | const struct nilfs_palloc_group_desc *desc) |
@@ -107,6 +149,13 @@ nilfs_palloc_group_desc_nfrees(struct inode *inode, unsigned long group, | |||
107 | return nfree; | 149 | return nfree; |
108 | } | 150 | } |
109 | 151 | ||
152 | /** | ||
153 | * nilfs_palloc_group_desc_add_entries - adjust count of free entries | ||
154 | * @inode: inode of metadata file using this allocator | ||
155 | * @group: group number | ||
156 | * @desc: pointer to descriptor structure for the group | ||
157 | * @n: delta to be added | ||
158 | */ | ||
110 | static void | 159 | static void |
111 | nilfs_palloc_group_desc_add_entries(struct inode *inode, | 160 | nilfs_palloc_group_desc_add_entries(struct inode *inode, |
112 | unsigned long group, | 161 | unsigned long group, |
@@ -118,6 +167,11 @@ nilfs_palloc_group_desc_add_entries(struct inode *inode, | |||
118 | spin_unlock(nilfs_mdt_bgl_lock(inode, group)); | 167 | spin_unlock(nilfs_mdt_bgl_lock(inode, group)); |
119 | } | 168 | } |
120 | 169 | ||
170 | /** | ||
171 | * nilfs_palloc_entry_blkoff - get block offset of an entry block | ||
172 | * @inode: inode of metadata file using this allocator | ||
173 | * @nr: serial number of the entry (e.g. inode number) | ||
174 | */ | ||
121 | static unsigned long | 175 | static unsigned long |
122 | nilfs_palloc_entry_blkoff(const struct inode *inode, __u64 nr) | 176 | nilfs_palloc_entry_blkoff(const struct inode *inode, __u64 nr) |
123 | { | 177 | { |
@@ -129,6 +183,12 @@ nilfs_palloc_entry_blkoff(const struct inode *inode, __u64 nr) | |||
129 | group_offset / NILFS_MDT(inode)->mi_entries_per_block; | 183 | group_offset / NILFS_MDT(inode)->mi_entries_per_block; |
130 | } | 184 | } |
131 | 185 | ||
186 | /** | ||
187 | * nilfs_palloc_desc_block_init - initialize buffer of a group descriptor block | ||
188 | * @inode: inode of metadata file | ||
189 | * @bh: buffer head of the buffer to be initialized | ||
190 | * @kaddr: kernel address mapped for the page including the buffer | ||
191 | */ | ||
132 | static void nilfs_palloc_desc_block_init(struct inode *inode, | 192 | static void nilfs_palloc_desc_block_init(struct inode *inode, |
133 | struct buffer_head *bh, void *kaddr) | 193 | struct buffer_head *bh, void *kaddr) |
134 | { | 194 | { |
@@ -179,6 +239,13 @@ static int nilfs_palloc_get_block(struct inode *inode, unsigned long blkoff, | |||
179 | return ret; | 239 | return ret; |
180 | } | 240 | } |
181 | 241 | ||
242 | /** | ||
243 | * nilfs_palloc_get_desc_block - get buffer head of a group descriptor block | ||
244 | * @inode: inode of metadata file using this allocator | ||
245 | * @group: group number | ||
246 | * @create: create flag | ||
247 | * @bhp: pointer to store the resultant buffer head | ||
248 | */ | ||
182 | static int nilfs_palloc_get_desc_block(struct inode *inode, | 249 | static int nilfs_palloc_get_desc_block(struct inode *inode, |
183 | unsigned long group, | 250 | unsigned long group, |
184 | int create, struct buffer_head **bhp) | 251 | int create, struct buffer_head **bhp) |
@@ -191,6 +258,13 @@ static int nilfs_palloc_get_desc_block(struct inode *inode, | |||
191 | bhp, &cache->prev_desc, &cache->lock); | 258 | bhp, &cache->prev_desc, &cache->lock); |
192 | } | 259 | } |
193 | 260 | ||
261 | /** | ||
262 | * nilfs_palloc_get_bitmap_block - get buffer head of a bitmap block | ||
263 | * @inode: inode of metadata file using this allocator | ||
264 | * @group: group number | ||
265 | * @create: create flag | ||
266 | * @bhp: pointer to store the resultant buffer head | ||
267 | */ | ||
194 | static int nilfs_palloc_get_bitmap_block(struct inode *inode, | 268 | static int nilfs_palloc_get_bitmap_block(struct inode *inode, |
195 | unsigned long group, | 269 | unsigned long group, |
196 | int create, struct buffer_head **bhp) | 270 | int create, struct buffer_head **bhp) |
@@ -203,6 +277,13 @@ static int nilfs_palloc_get_bitmap_block(struct inode *inode, | |||
203 | &cache->prev_bitmap, &cache->lock); | 277 | &cache->prev_bitmap, &cache->lock); |
204 | } | 278 | } |
205 | 279 | ||
280 | /** | ||
281 | * nilfs_palloc_get_entry_block - get buffer head of an entry block | ||
282 | * @inode: inode of metadata file using this allocator | ||
283 | * @nr: serial number of the entry (e.g. inode number) | ||
284 | * @create: create flag | ||
285 | * @bhp: pointer to store the resultant buffer head | ||
286 | */ | ||
206 | int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, | 287 | int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, |
207 | int create, struct buffer_head **bhp) | 288 | int create, struct buffer_head **bhp) |
208 | { | 289 | { |
@@ -214,6 +295,13 @@ int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, | |||
214 | &cache->prev_entry, &cache->lock); | 295 | &cache->prev_entry, &cache->lock); |
215 | } | 296 | } |
216 | 297 | ||
298 | /** | ||
299 | * nilfs_palloc_block_get_group_desc - get kernel address of a group descriptor | ||
300 | * @inode: inode of metadata file using this allocator | ||
301 | * @group: group number | ||
302 | * @bh: buffer head of the buffer storing the group descriptor block | ||
303 | * @kaddr: kernel address mapped for the page including the buffer | ||
304 | */ | ||
217 | static struct nilfs_palloc_group_desc * | 305 | static struct nilfs_palloc_group_desc * |
218 | nilfs_palloc_block_get_group_desc(const struct inode *inode, | 306 | nilfs_palloc_block_get_group_desc(const struct inode *inode, |
219 | unsigned long group, | 307 | unsigned long group, |
@@ -223,6 +311,13 @@ nilfs_palloc_block_get_group_desc(const struct inode *inode, | |||
223 | group % nilfs_palloc_groups_per_desc_block(inode); | 311 | group % nilfs_palloc_groups_per_desc_block(inode); |
224 | } | 312 | } |
225 | 313 | ||
314 | /** | ||
315 | * nilfs_palloc_block_get_entry - get kernel address of an entry | ||
316 | * @inode: inode of metadata file using this allocator | ||
317 | * @nr: serial number of the entry (e.g. inode number) | ||
318 | * @bh: buffer head of the buffer storing the entry block | ||
319 | * @kaddr: kernel address mapped for the page including the buffer | ||
320 | */ | ||
226 | void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, | 321 | void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, |
227 | const struct buffer_head *bh, void *kaddr) | 322 | const struct buffer_head *bh, void *kaddr) |
228 | { | 323 | { |
@@ -235,11 +330,19 @@ void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, | |||
235 | entry_offset * NILFS_MDT(inode)->mi_entry_size; | 330 | entry_offset * NILFS_MDT(inode)->mi_entry_size; |
236 | } | 331 | } |
237 | 332 | ||
333 | /** | ||
334 | * nilfs_palloc_find_available_slot - find available slot in a group | ||
335 | * @inode: inode of metadata file using this allocator | ||
336 | * @group: group number | ||
337 | * @target: offset number of an entry in the group (start point) | ||
338 | * @bitmap: bitmap of the group | ||
339 | * @bsize: size in bits | ||
340 | */ | ||
238 | static int nilfs_palloc_find_available_slot(struct inode *inode, | 341 | static int nilfs_palloc_find_available_slot(struct inode *inode, |
239 | unsigned long group, | 342 | unsigned long group, |
240 | unsigned long target, | 343 | unsigned long target, |
241 | unsigned char *bitmap, | 344 | unsigned char *bitmap, |
242 | int bsize) /* size in bits */ | 345 | int bsize) |
243 | { | 346 | { |
244 | int curr, pos, end, i; | 347 | int curr, pos, end, i; |
245 | 348 | ||
@@ -277,6 +380,13 @@ static int nilfs_palloc_find_available_slot(struct inode *inode, | |||
277 | return -ENOSPC; | 380 | return -ENOSPC; |
278 | } | 381 | } |
279 | 382 | ||
383 | /** | ||
384 | * nilfs_palloc_rest_groups_in_desc_block - get the remaining number of groups | ||
385 | * in a group descriptor block | ||
386 | * @inode: inode of metadata file using this allocator | ||
387 | * @curr: current group number | ||
388 | * @max: maximum number of groups | ||
389 | */ | ||
280 | static unsigned long | 390 | static unsigned long |
281 | nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode, | 391 | nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode, |
282 | unsigned long curr, unsigned long max) | 392 | unsigned long curr, unsigned long max) |
@@ -287,6 +397,11 @@ nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode, | |||
287 | max - curr + 1); | 397 | max - curr + 1); |
288 | } | 398 | } |
289 | 399 | ||
400 | /** | ||
401 | * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object | ||
402 | * @inode: inode of metadata file using this allocator | ||
403 | * @req: nilfs_palloc_req structure exchanged for the allocation | ||
404 | */ | ||
290 | int nilfs_palloc_prepare_alloc_entry(struct inode *inode, | 405 | int nilfs_palloc_prepare_alloc_entry(struct inode *inode, |
291 | struct nilfs_palloc_req *req) | 406 | struct nilfs_palloc_req *req) |
292 | { | 407 | { |
@@ -366,6 +481,11 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode, | |||
366 | return ret; | 481 | return ret; |
367 | } | 482 | } |
368 | 483 | ||
484 | /** | ||
485 | * nilfs_palloc_commit_alloc_entry - finish allocation of a persistent object | ||
486 | * @inode: inode of metadata file using this allocator | ||
487 | * @req: nilfs_palloc_req structure exchanged for the allocation | ||
488 | */ | ||
369 | void nilfs_palloc_commit_alloc_entry(struct inode *inode, | 489 | void nilfs_palloc_commit_alloc_entry(struct inode *inode, |
370 | struct nilfs_palloc_req *req) | 490 | struct nilfs_palloc_req *req) |
371 | { | 491 | { |
@@ -377,6 +497,11 @@ void nilfs_palloc_commit_alloc_entry(struct inode *inode, | |||
377 | brelse(req->pr_desc_bh); | 497 | brelse(req->pr_desc_bh); |
378 | } | 498 | } |
379 | 499 | ||
500 | /** | ||
501 | * nilfs_palloc_commit_free_entry - finish deallocating a persistent object | ||
502 | * @inode: inode of metadata file using this allocator | ||
503 | * @req: nilfs_palloc_req structure exchanged for the removal | ||
504 | */ | ||
380 | void nilfs_palloc_commit_free_entry(struct inode *inode, | 505 | void nilfs_palloc_commit_free_entry(struct inode *inode, |
381 | struct nilfs_palloc_req *req) | 506 | struct nilfs_palloc_req *req) |
382 | { | 507 | { |
@@ -410,6 +535,11 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, | |||
410 | brelse(req->pr_desc_bh); | 535 | brelse(req->pr_desc_bh); |
411 | } | 536 | } |
412 | 537 | ||
538 | /** | ||
539 | * nilfs_palloc_abort_alloc_entry - cancel allocation of a persistent object | ||
540 | * @inode: inode of metadata file using this allocator | ||
541 | * @req: nilfs_palloc_req structure exchanged for the allocation | ||
542 | */ | ||
413 | void nilfs_palloc_abort_alloc_entry(struct inode *inode, | 543 | void nilfs_palloc_abort_alloc_entry(struct inode *inode, |
414 | struct nilfs_palloc_req *req) | 544 | struct nilfs_palloc_req *req) |
415 | { | 545 | { |
@@ -442,6 +572,11 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, | |||
442 | req->pr_desc_bh = NULL; | 572 | req->pr_desc_bh = NULL; |
443 | } | 573 | } |
444 | 574 | ||
575 | /** | ||
576 | * nilfs_palloc_prepare_free_entry - prepare to deallocate a persistent object | ||
577 | * @inode: inode of metadata file using this allocator | ||
578 | * @req: nilfs_palloc_req structure exchanged for the removal | ||
579 | */ | ||
445 | int nilfs_palloc_prepare_free_entry(struct inode *inode, | 580 | int nilfs_palloc_prepare_free_entry(struct inode *inode, |
446 | struct nilfs_palloc_req *req) | 581 | struct nilfs_palloc_req *req) |
447 | { | 582 | { |
@@ -464,6 +599,11 @@ int nilfs_palloc_prepare_free_entry(struct inode *inode, | |||
464 | return 0; | 599 | return 0; |
465 | } | 600 | } |
466 | 601 | ||
602 | /** | ||
603 | * nilfs_palloc_abort_free_entry - cancel deallocating a persistent object | ||
604 | * @inode: inode of metadata file using this allocator | ||
605 | * @req: nilfs_palloc_req structure exchanged for the removal | ||
606 | */ | ||
467 | void nilfs_palloc_abort_free_entry(struct inode *inode, | 607 | void nilfs_palloc_abort_free_entry(struct inode *inode, |
468 | struct nilfs_palloc_req *req) | 608 | struct nilfs_palloc_req *req) |
469 | { | 609 | { |
@@ -475,6 +615,12 @@ void nilfs_palloc_abort_free_entry(struct inode *inode, | |||
475 | req->pr_desc_bh = NULL; | 615 | req->pr_desc_bh = NULL; |
476 | } | 616 | } |
477 | 617 | ||
618 | /** | ||
619 | * nilfs_palloc_group_is_in - judge if an entry is in a group | ||
620 | * @inode: inode of metadata file using this allocator | ||
621 | * @group: group number | ||
622 | * @nr: serial number of the entry (e.g. inode number) | ||
623 | */ | ||
478 | static int | 624 | static int |
479 | nilfs_palloc_group_is_in(struct inode *inode, unsigned long group, __u64 nr) | 625 | nilfs_palloc_group_is_in(struct inode *inode, unsigned long group, __u64 nr) |
480 | { | 626 | { |
@@ -485,6 +631,12 @@ nilfs_palloc_group_is_in(struct inode *inode, unsigned long group, __u64 nr) | |||
485 | return (nr >= first) && (nr <= last); | 631 | return (nr >= first) && (nr <= last); |
486 | } | 632 | } |
487 | 633 | ||
634 | /** | ||
635 | * nilfs_palloc_freev - deallocate a set of persistent objects | ||
636 | * @inode: inode of metadata file using this allocator | ||
637 | * @entry_nrs: array of entry numbers to be deallocated | ||
638 | * @nitems: number of entries stored in @entry_nrs | ||
639 | */ | ||
488 | int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) | 640 | int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) |
489 | { | 641 | { |
490 | struct buffer_head *desc_bh, *bitmap_bh; | 642 | struct buffer_head *desc_bh, *bitmap_bh; |
diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h index 5cccf874d692..9af34a7e6e13 100644 --- a/fs/nilfs2/alloc.h +++ b/fs/nilfs2/alloc.h | |||
@@ -29,6 +29,13 @@ | |||
29 | #include <linux/buffer_head.h> | 29 | #include <linux/buffer_head.h> |
30 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
31 | 31 | ||
32 | /** | ||
33 | * nilfs_palloc_entries_per_group - get the number of entries per group | ||
34 | * @inode: inode of metadata file using this allocator | ||
35 | * | ||
36 | * The number of entries per group is defined by the number of bits | ||
37 | * that a bitmap block can maintain. | ||
38 | */ | ||
32 | static inline unsigned long | 39 | static inline unsigned long |
33 | nilfs_palloc_entries_per_group(const struct inode *inode) | 40 | nilfs_palloc_entries_per_group(const struct inode *inode) |
34 | { | 41 | { |
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 76c38e3e19d2..b27a342c5af6 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
@@ -31,63 +31,16 @@ | |||
31 | #include "alloc.h" | 31 | #include "alloc.h" |
32 | #include "dat.h" | 32 | #include "dat.h" |
33 | 33 | ||
34 | /** | 34 | static struct nilfs_btree_path *nilfs_btree_alloc_path(void) |
35 | * struct nilfs_btree_path - A path on which B-tree operations are executed | ||
36 | * @bp_bh: buffer head of node block | ||
37 | * @bp_sib_bh: buffer head of sibling node block | ||
38 | * @bp_index: index of child node | ||
39 | * @bp_oldreq: ptr end request for old ptr | ||
40 | * @bp_newreq: ptr alloc request for new ptr | ||
41 | * @bp_op: rebalance operation | ||
42 | */ | ||
43 | struct nilfs_btree_path { | ||
44 | struct buffer_head *bp_bh; | ||
45 | struct buffer_head *bp_sib_bh; | ||
46 | int bp_index; | ||
47 | union nilfs_bmap_ptr_req bp_oldreq; | ||
48 | union nilfs_bmap_ptr_req bp_newreq; | ||
49 | struct nilfs_btnode_chkey_ctxt bp_ctxt; | ||
50 | void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *, | ||
51 | int, __u64 *, __u64 *); | ||
52 | }; | ||
53 | |||
54 | /* | ||
55 | * B-tree path operations | ||
56 | */ | ||
57 | |||
58 | static struct kmem_cache *nilfs_btree_path_cache; | ||
59 | |||
60 | int __init nilfs_btree_path_cache_init(void) | ||
61 | { | ||
62 | nilfs_btree_path_cache = | ||
63 | kmem_cache_create("nilfs2_btree_path_cache", | ||
64 | sizeof(struct nilfs_btree_path) * | ||
65 | NILFS_BTREE_LEVEL_MAX, 0, 0, NULL); | ||
66 | return (nilfs_btree_path_cache != NULL) ? 0 : -ENOMEM; | ||
67 | } | ||
68 | |||
69 | void nilfs_btree_path_cache_destroy(void) | ||
70 | { | ||
71 | kmem_cache_destroy(nilfs_btree_path_cache); | ||
72 | } | ||
73 | |||
74 | static inline struct nilfs_btree_path *nilfs_btree_alloc_path(void) | ||
75 | { | ||
76 | return kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS); | ||
77 | } | ||
78 | |||
79 | static inline void nilfs_btree_free_path(struct nilfs_btree_path *path) | ||
80 | { | 35 | { |
81 | kmem_cache_free(nilfs_btree_path_cache, path); | 36 | struct nilfs_btree_path *path; |
82 | } | 37 | int level = NILFS_BTREE_LEVEL_DATA; |
83 | 38 | ||
84 | static void nilfs_btree_init_path(struct nilfs_btree_path *path) | 39 | path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS); |
85 | { | 40 | if (path == NULL) |
86 | int level; | 41 | goto out; |
87 | 42 | ||
88 | for (level = NILFS_BTREE_LEVEL_DATA; | 43 | for (; level < NILFS_BTREE_LEVEL_MAX; level++) { |
89 | level < NILFS_BTREE_LEVEL_MAX; | ||
90 | level++) { | ||
91 | path[level].bp_bh = NULL; | 44 | path[level].bp_bh = NULL; |
92 | path[level].bp_sib_bh = NULL; | 45 | path[level].bp_sib_bh = NULL; |
93 | path[level].bp_index = 0; | 46 | path[level].bp_index = 0; |
@@ -95,15 +48,19 @@ static void nilfs_btree_init_path(struct nilfs_btree_path *path) | |||
95 | path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR; | 48 | path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR; |
96 | path[level].bp_op = NULL; | 49 | path[level].bp_op = NULL; |
97 | } | 50 | } |
51 | |||
52 | out: | ||
53 | return path; | ||
98 | } | 54 | } |
99 | 55 | ||
100 | static void nilfs_btree_release_path(struct nilfs_btree_path *path) | 56 | static void nilfs_btree_free_path(struct nilfs_btree_path *path) |
101 | { | 57 | { |
102 | int level; | 58 | int level = NILFS_BTREE_LEVEL_DATA; |
103 | 59 | ||
104 | for (level = NILFS_BTREE_LEVEL_DATA; level < NILFS_BTREE_LEVEL_MAX; | 60 | for (; level < NILFS_BTREE_LEVEL_MAX; level++) |
105 | level++) | ||
106 | brelse(path[level].bp_bh); | 61 | brelse(path[level].bp_bh); |
62 | |||
63 | kmem_cache_free(nilfs_btree_path_cache, path); | ||
107 | } | 64 | } |
108 | 65 | ||
109 | /* | 66 | /* |
@@ -566,14 +523,12 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, | |||
566 | path = nilfs_btree_alloc_path(); | 523 | path = nilfs_btree_alloc_path(); |
567 | if (path == NULL) | 524 | if (path == NULL) |
568 | return -ENOMEM; | 525 | return -ENOMEM; |
569 | nilfs_btree_init_path(path); | ||
570 | 526 | ||
571 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 527 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); |
572 | 528 | ||
573 | if (ptrp != NULL) | 529 | if (ptrp != NULL) |
574 | *ptrp = ptr; | 530 | *ptrp = ptr; |
575 | 531 | ||
576 | nilfs_btree_release_path(path); | ||
577 | nilfs_btree_free_path(path); | 532 | nilfs_btree_free_path(path); |
578 | 533 | ||
579 | return ret; | 534 | return ret; |
@@ -594,7 +549,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
594 | path = nilfs_btree_alloc_path(); | 549 | path = nilfs_btree_alloc_path(); |
595 | if (path == NULL) | 550 | if (path == NULL) |
596 | return -ENOMEM; | 551 | return -ENOMEM; |
597 | nilfs_btree_init_path(path); | 552 | |
598 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 553 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); |
599 | if (ret < 0) | 554 | if (ret < 0) |
600 | goto out; | 555 | goto out; |
@@ -655,7 +610,6 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
655 | *ptrp = ptr; | 610 | *ptrp = ptr; |
656 | ret = cnt; | 611 | ret = cnt; |
657 | out: | 612 | out: |
658 | nilfs_btree_release_path(path); | ||
659 | nilfs_btree_free_path(path); | 613 | nilfs_btree_free_path(path); |
660 | return ret; | 614 | return ret; |
661 | } | 615 | } |
@@ -1123,7 +1077,6 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
1123 | path = nilfs_btree_alloc_path(); | 1077 | path = nilfs_btree_alloc_path(); |
1124 | if (path == NULL) | 1078 | if (path == NULL) |
1125 | return -ENOMEM; | 1079 | return -ENOMEM; |
1126 | nilfs_btree_init_path(path); | ||
1127 | 1080 | ||
1128 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1081 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
1129 | NILFS_BTREE_LEVEL_NODE_MIN); | 1082 | NILFS_BTREE_LEVEL_NODE_MIN); |
@@ -1140,7 +1093,6 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
1140 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); | 1093 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); |
1141 | 1094 | ||
1142 | out: | 1095 | out: |
1143 | nilfs_btree_release_path(path); | ||
1144 | nilfs_btree_free_path(path); | 1096 | nilfs_btree_free_path(path); |
1145 | return ret; | 1097 | return ret; |
1146 | } | 1098 | } |
@@ -1456,7 +1408,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) | |||
1456 | path = nilfs_btree_alloc_path(); | 1408 | path = nilfs_btree_alloc_path(); |
1457 | if (path == NULL) | 1409 | if (path == NULL) |
1458 | return -ENOMEM; | 1410 | return -ENOMEM; |
1459 | nilfs_btree_init_path(path); | 1411 | |
1460 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1412 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
1461 | NILFS_BTREE_LEVEL_NODE_MIN); | 1413 | NILFS_BTREE_LEVEL_NODE_MIN); |
1462 | if (ret < 0) | 1414 | if (ret < 0) |
@@ -1473,7 +1425,6 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) | |||
1473 | nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); | 1425 | nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); |
1474 | 1426 | ||
1475 | out: | 1427 | out: |
1476 | nilfs_btree_release_path(path); | ||
1477 | nilfs_btree_free_path(path); | 1428 | nilfs_btree_free_path(path); |
1478 | return ret; | 1429 | return ret; |
1479 | } | 1430 | } |
@@ -1488,11 +1439,9 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | |||
1488 | path = nilfs_btree_alloc_path(); | 1439 | path = nilfs_btree_alloc_path(); |
1489 | if (path == NULL) | 1440 | if (path == NULL) |
1490 | return -ENOMEM; | 1441 | return -ENOMEM; |
1491 | nilfs_btree_init_path(path); | ||
1492 | 1442 | ||
1493 | ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL); | 1443 | ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL); |
1494 | 1444 | ||
1495 | nilfs_btree_release_path(path); | ||
1496 | nilfs_btree_free_path(path); | 1445 | nilfs_btree_free_path(path); |
1497 | 1446 | ||
1498 | return ret; | 1447 | return ret; |
@@ -1923,7 +1872,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1923 | path = nilfs_btree_alloc_path(); | 1872 | path = nilfs_btree_alloc_path(); |
1924 | if (path == NULL) | 1873 | if (path == NULL) |
1925 | return -ENOMEM; | 1874 | return -ENOMEM; |
1926 | nilfs_btree_init_path(path); | ||
1927 | 1875 | ||
1928 | if (buffer_nilfs_node(bh)) { | 1876 | if (buffer_nilfs_node(bh)) { |
1929 | node = (struct nilfs_btree_node *)bh->b_data; | 1877 | node = (struct nilfs_btree_node *)bh->b_data; |
@@ -1947,7 +1895,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1947 | nilfs_btree_propagate_p(btree, path, level, bh); | 1895 | nilfs_btree_propagate_p(btree, path, level, bh); |
1948 | 1896 | ||
1949 | out: | 1897 | out: |
1950 | nilfs_btree_release_path(path); | ||
1951 | nilfs_btree_free_path(path); | 1898 | nilfs_btree_free_path(path); |
1952 | 1899 | ||
1953 | return ret; | 1900 | return ret; |
@@ -2108,7 +2055,6 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
2108 | path = nilfs_btree_alloc_path(); | 2055 | path = nilfs_btree_alloc_path(); |
2109 | if (path == NULL) | 2056 | if (path == NULL) |
2110 | return -ENOMEM; | 2057 | return -ENOMEM; |
2111 | nilfs_btree_init_path(path); | ||
2112 | 2058 | ||
2113 | if (buffer_nilfs_node(*bh)) { | 2059 | if (buffer_nilfs_node(*bh)) { |
2114 | node = (struct nilfs_btree_node *)(*bh)->b_data; | 2060 | node = (struct nilfs_btree_node *)(*bh)->b_data; |
@@ -2130,7 +2076,6 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
2130 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); | 2076 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); |
2131 | 2077 | ||
2132 | out: | 2078 | out: |
2133 | nilfs_btree_release_path(path); | ||
2134 | nilfs_btree_free_path(path); | 2079 | nilfs_btree_free_path(path); |
2135 | 2080 | ||
2136 | return ret; | 2081 | return ret; |
@@ -2175,7 +2120,6 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
2175 | path = nilfs_btree_alloc_path(); | 2120 | path = nilfs_btree_alloc_path(); |
2176 | if (path == NULL) | 2121 | if (path == NULL) |
2177 | return -ENOMEM; | 2122 | return -ENOMEM; |
2178 | nilfs_btree_init_path(path); | ||
2179 | 2123 | ||
2180 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); | 2124 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); |
2181 | if (ret < 0) { | 2125 | if (ret < 0) { |
@@ -2195,7 +2139,6 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
2195 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 2139 | nilfs_bmap_set_dirty(&btree->bt_bmap); |
2196 | 2140 | ||
2197 | out: | 2141 | out: |
2198 | nilfs_btree_release_path(path); | ||
2199 | nilfs_btree_free_path(path); | 2142 | nilfs_btree_free_path(path); |
2200 | return ret; | 2143 | return ret; |
2201 | } | 2144 | } |
diff --git a/fs/nilfs2/btree.h b/fs/nilfs2/btree.h index 4b82d84ade75..af638d59e3bf 100644 --- a/fs/nilfs2/btree.h +++ b/fs/nilfs2/btree.h | |||
@@ -30,9 +30,6 @@ | |||
30 | #include "btnode.h" | 30 | #include "btnode.h" |
31 | #include "bmap.h" | 31 | #include "bmap.h" |
32 | 32 | ||
33 | struct nilfs_btree; | ||
34 | struct nilfs_btree_path; | ||
35 | |||
36 | /** | 33 | /** |
37 | * struct nilfs_btree - B-tree structure | 34 | * struct nilfs_btree - B-tree structure |
38 | * @bt_bmap: bmap base structure | 35 | * @bt_bmap: bmap base structure |
@@ -41,6 +38,25 @@ struct nilfs_btree { | |||
41 | struct nilfs_bmap bt_bmap; | 38 | struct nilfs_bmap bt_bmap; |
42 | }; | 39 | }; |
43 | 40 | ||
41 | /** | ||
42 | * struct nilfs_btree_path - A path on which B-tree operations are executed | ||
43 | * @bp_bh: buffer head of node block | ||
44 | * @bp_sib_bh: buffer head of sibling node block | ||
45 | * @bp_index: index of child node | ||
46 | * @bp_oldreq: ptr end request for old ptr | ||
47 | * @bp_newreq: ptr alloc request for new ptr | ||
48 | * @bp_op: rebalance operation | ||
49 | */ | ||
50 | struct nilfs_btree_path { | ||
51 | struct buffer_head *bp_bh; | ||
52 | struct buffer_head *bp_sib_bh; | ||
53 | int bp_index; | ||
54 | union nilfs_bmap_ptr_req bp_oldreq; | ||
55 | union nilfs_bmap_ptr_req bp_newreq; | ||
56 | struct nilfs_btnode_chkey_ctxt bp_ctxt; | ||
57 | void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *, | ||
58 | int, __u64 *, __u64 *); | ||
59 | }; | ||
44 | 60 | ||
45 | #define NILFS_BTREE_ROOT_SIZE NILFS_BMAP_SIZE | 61 | #define NILFS_BTREE_ROOT_SIZE NILFS_BMAP_SIZE |
46 | #define NILFS_BTREE_ROOT_NCHILDREN_MAX \ | 62 | #define NILFS_BTREE_ROOT_NCHILDREN_MAX \ |
@@ -57,6 +73,7 @@ struct nilfs_btree { | |||
57 | #define NILFS_BTREE_KEY_MIN ((__u64)0) | 73 | #define NILFS_BTREE_KEY_MIN ((__u64)0) |
58 | #define NILFS_BTREE_KEY_MAX (~(__u64)0) | 74 | #define NILFS_BTREE_KEY_MAX (~(__u64)0) |
59 | 75 | ||
76 | extern struct kmem_cache *nilfs_btree_path_cache; | ||
60 | 77 | ||
61 | int nilfs_btree_path_cache_init(void); | 78 | int nilfs_btree_path_cache_init(void); |
62 | void nilfs_btree_path_cache_destroy(void); | 79 | void nilfs_btree_path_cache_destroy(void); |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 0957b58f909d..5e226d4b41d3 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -451,7 +451,7 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, | |||
451 | inode->i_op = &nilfs_special_inode_operations; | 451 | inode->i_op = &nilfs_special_inode_operations; |
452 | init_special_inode( | 452 | init_special_inode( |
453 | inode, inode->i_mode, | 453 | inode, inode->i_mode, |
454 | new_decode_dev(le64_to_cpu(raw_inode->i_device_code))); | 454 | huge_decode_dev(le64_to_cpu(raw_inode->i_device_code))); |
455 | } | 455 | } |
456 | nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh); | 456 | nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh); |
457 | brelse(bh); | 457 | brelse(bh); |
@@ -511,7 +511,7 @@ void nilfs_write_inode_common(struct inode *inode, | |||
511 | nilfs_bmap_write(ii->i_bmap, raw_inode); | 511 | nilfs_bmap_write(ii->i_bmap, raw_inode); |
512 | else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) | 512 | else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) |
513 | raw_inode->i_device_code = | 513 | raw_inode->i_device_code = |
514 | cpu_to_le64(new_encode_dev(inode->i_rdev)); | 514 | cpu_to_le64(huge_encode_dev(inode->i_rdev)); |
515 | /* When extending inode, nilfs->ns_inode_size should be checked | 515 | /* When extending inode, nilfs->ns_inode_size should be checked |
516 | for substitutions of appended fields */ | 516 | for substitutions of appended fields */ |
517 | } | 517 | } |
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index ba43146f3c30..bae2a516b4ee 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c | |||
@@ -105,6 +105,8 @@ static void store_segsum_info(struct nilfs_segsum_info *ssi, | |||
105 | 105 | ||
106 | ssi->nsumblk = DIV_ROUND_UP(ssi->sumbytes, blocksize); | 106 | ssi->nsumblk = DIV_ROUND_UP(ssi->sumbytes, blocksize); |
107 | ssi->nfileblk = ssi->nblocks - ssi->nsumblk - !!NILFS_SEG_HAS_SR(ssi); | 107 | ssi->nfileblk = ssi->nblocks - ssi->nsumblk - !!NILFS_SEG_HAS_SR(ssi); |
108 | |||
109 | /* need to verify ->ss_bytes field if read ->ss_cno */ | ||
108 | } | 110 | } |
109 | 111 | ||
110 | /** | 112 | /** |
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 17851f77f739..2e6a2723b8fa 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c | |||
@@ -40,35 +40,10 @@ struct nilfs_write_info { | |||
40 | sector_t blocknr; | 40 | sector_t blocknr; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | |||
44 | static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, | 43 | static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, |
45 | struct the_nilfs *nilfs); | 44 | struct the_nilfs *nilfs); |
46 | static int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf); | 45 | static int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf); |
47 | 46 | ||
48 | |||
49 | static struct kmem_cache *nilfs_segbuf_cachep; | ||
50 | |||
51 | static void nilfs_segbuf_init_once(void *obj) | ||
52 | { | ||
53 | memset(obj, 0, sizeof(struct nilfs_segment_buffer)); | ||
54 | } | ||
55 | |||
56 | int __init nilfs_init_segbuf_cache(void) | ||
57 | { | ||
58 | nilfs_segbuf_cachep = | ||
59 | kmem_cache_create("nilfs2_segbuf_cache", | ||
60 | sizeof(struct nilfs_segment_buffer), | ||
61 | 0, SLAB_RECLAIM_ACCOUNT, | ||
62 | nilfs_segbuf_init_once); | ||
63 | |||
64 | return (nilfs_segbuf_cachep == NULL) ? -ENOMEM : 0; | ||
65 | } | ||
66 | |||
67 | void nilfs_destroy_segbuf_cache(void) | ||
68 | { | ||
69 | kmem_cache_destroy(nilfs_segbuf_cachep); | ||
70 | } | ||
71 | |||
72 | struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) | 47 | struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) |
73 | { | 48 | { |
74 | struct nilfs_segment_buffer *segbuf; | 49 | struct nilfs_segment_buffer *segbuf; |
@@ -81,6 +56,7 @@ struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *sb) | |||
81 | INIT_LIST_HEAD(&segbuf->sb_list); | 56 | INIT_LIST_HEAD(&segbuf->sb_list); |
82 | INIT_LIST_HEAD(&segbuf->sb_segsum_buffers); | 57 | INIT_LIST_HEAD(&segbuf->sb_segsum_buffers); |
83 | INIT_LIST_HEAD(&segbuf->sb_payload_buffers); | 58 | INIT_LIST_HEAD(&segbuf->sb_payload_buffers); |
59 | segbuf->sb_super_root = NULL; | ||
84 | 60 | ||
85 | init_completion(&segbuf->sb_bio_event); | 61 | init_completion(&segbuf->sb_bio_event); |
86 | atomic_set(&segbuf->sb_err, 0); | 62 | atomic_set(&segbuf->sb_err, 0); |
@@ -158,7 +134,7 @@ int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *segbuf, | |||
158 | } | 134 | } |
159 | 135 | ||
160 | int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, | 136 | int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, |
161 | time_t ctime) | 137 | time_t ctime, __u64 cno) |
162 | { | 138 | { |
163 | int err; | 139 | int err; |
164 | 140 | ||
@@ -171,6 +147,7 @@ int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned flags, | |||
171 | segbuf->sb_sum.sumbytes = sizeof(struct nilfs_segment_summary); | 147 | segbuf->sb_sum.sumbytes = sizeof(struct nilfs_segment_summary); |
172 | segbuf->sb_sum.nfinfo = segbuf->sb_sum.nfileblk = 0; | 148 | segbuf->sb_sum.nfinfo = segbuf->sb_sum.nfileblk = 0; |
173 | segbuf->sb_sum.ctime = ctime; | 149 | segbuf->sb_sum.ctime = ctime; |
150 | segbuf->sb_sum.cno = cno; | ||
174 | return 0; | 151 | return 0; |
175 | } | 152 | } |
176 | 153 | ||
@@ -196,13 +173,14 @@ void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *segbuf) | |||
196 | raw_sum->ss_nfinfo = cpu_to_le32(segbuf->sb_sum.nfinfo); | 173 | raw_sum->ss_nfinfo = cpu_to_le32(segbuf->sb_sum.nfinfo); |
197 | raw_sum->ss_sumbytes = cpu_to_le32(segbuf->sb_sum.sumbytes); | 174 | raw_sum->ss_sumbytes = cpu_to_le32(segbuf->sb_sum.sumbytes); |
198 | raw_sum->ss_pad = 0; | 175 | raw_sum->ss_pad = 0; |
176 | raw_sum->ss_cno = cpu_to_le64(segbuf->sb_sum.cno); | ||
199 | } | 177 | } |
200 | 178 | ||
201 | /* | 179 | /* |
202 | * CRC calculation routines | 180 | * CRC calculation routines |
203 | */ | 181 | */ |
204 | void nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *segbuf, | 182 | static void |
205 | u32 seed) | 183 | nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *segbuf, u32 seed) |
206 | { | 184 | { |
207 | struct buffer_head *bh; | 185 | struct buffer_head *bh; |
208 | struct nilfs_segment_summary *raw_sum; | 186 | struct nilfs_segment_summary *raw_sum; |
@@ -229,8 +207,8 @@ void nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *segbuf, | |||
229 | raw_sum->ss_sumsum = cpu_to_le32(crc); | 207 | raw_sum->ss_sumsum = cpu_to_le32(crc); |
230 | } | 208 | } |
231 | 209 | ||
232 | void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, | 210 | static void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, |
233 | u32 seed) | 211 | u32 seed) |
234 | { | 212 | { |
235 | struct buffer_head *bh; | 213 | struct buffer_head *bh; |
236 | struct nilfs_segment_summary *raw_sum; | 214 | struct nilfs_segment_summary *raw_sum; |
@@ -256,6 +234,20 @@ void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf, | |||
256 | raw_sum->ss_datasum = cpu_to_le32(crc); | 234 | raw_sum->ss_datasum = cpu_to_le32(crc); |
257 | } | 235 | } |
258 | 236 | ||
237 | static void | ||
238 | nilfs_segbuf_fill_in_super_root_crc(struct nilfs_segment_buffer *segbuf, | ||
239 | u32 seed) | ||
240 | { | ||
241 | struct nilfs_super_root *raw_sr; | ||
242 | u32 crc; | ||
243 | |||
244 | raw_sr = (struct nilfs_super_root *)segbuf->sb_super_root->b_data; | ||
245 | crc = crc32_le(seed, | ||
246 | (unsigned char *)raw_sr + sizeof(raw_sr->sr_sum), | ||
247 | NILFS_SR_BYTES - sizeof(raw_sr->sr_sum)); | ||
248 | raw_sr->sr_sum = cpu_to_le32(crc); | ||
249 | } | ||
250 | |||
259 | static void nilfs_release_buffers(struct list_head *list) | 251 | static void nilfs_release_buffers(struct list_head *list) |
260 | { | 252 | { |
261 | struct buffer_head *bh, *n; | 253 | struct buffer_head *bh, *n; |
@@ -282,6 +274,7 @@ static void nilfs_segbuf_clear(struct nilfs_segment_buffer *segbuf) | |||
282 | { | 274 | { |
283 | nilfs_release_buffers(&segbuf->sb_segsum_buffers); | 275 | nilfs_release_buffers(&segbuf->sb_segsum_buffers); |
284 | nilfs_release_buffers(&segbuf->sb_payload_buffers); | 276 | nilfs_release_buffers(&segbuf->sb_payload_buffers); |
277 | segbuf->sb_super_root = NULL; | ||
285 | } | 278 | } |
286 | 279 | ||
287 | /* | 280 | /* |
@@ -334,6 +327,23 @@ int nilfs_wait_on_logs(struct list_head *logs) | |||
334 | return ret; | 327 | return ret; |
335 | } | 328 | } |
336 | 329 | ||
330 | /** | ||
331 | * nilfs_add_checksums_on_logs - add checksums on the logs | ||
332 | * @logs: list of segment buffers storing target logs | ||
333 | * @seed: checksum seed value | ||
334 | */ | ||
335 | void nilfs_add_checksums_on_logs(struct list_head *logs, u32 seed) | ||
336 | { | ||
337 | struct nilfs_segment_buffer *segbuf; | ||
338 | |||
339 | list_for_each_entry(segbuf, logs, sb_list) { | ||
340 | if (segbuf->sb_super_root) | ||
341 | nilfs_segbuf_fill_in_super_root_crc(segbuf, seed); | ||
342 | nilfs_segbuf_fill_in_segsum_crc(segbuf, seed); | ||
343 | nilfs_segbuf_fill_in_data_crc(segbuf, seed); | ||
344 | } | ||
345 | } | ||
346 | |||
337 | /* | 347 | /* |
338 | * BIO operations | 348 | * BIO operations |
339 | */ | 349 | */ |
diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index 94dfd3517bc0..fdf1c3b6d673 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h | |||
@@ -37,6 +37,7 @@ | |||
37 | * @sumbytes: Byte count of segment summary | 37 | * @sumbytes: Byte count of segment summary |
38 | * @nfileblk: Total number of file blocks | 38 | * @nfileblk: Total number of file blocks |
39 | * @seg_seq: Segment sequence number | 39 | * @seg_seq: Segment sequence number |
40 | * @cno: Checkpoint number | ||
40 | * @ctime: Creation time | 41 | * @ctime: Creation time |
41 | * @next: Block number of the next full segment | 42 | * @next: Block number of the next full segment |
42 | */ | 43 | */ |
@@ -48,6 +49,7 @@ struct nilfs_segsum_info { | |||
48 | unsigned long sumbytes; | 49 | unsigned long sumbytes; |
49 | unsigned long nfileblk; | 50 | unsigned long nfileblk; |
50 | u64 seg_seq; | 51 | u64 seg_seq; |
52 | __u64 cno; | ||
51 | time_t ctime; | 53 | time_t ctime; |
52 | sector_t next; | 54 | sector_t next; |
53 | }; | 55 | }; |
@@ -76,6 +78,7 @@ struct nilfs_segsum_info { | |||
76 | * @sb_rest_blocks: Number of residual blocks in the current segment | 78 | * @sb_rest_blocks: Number of residual blocks in the current segment |
77 | * @sb_segsum_buffers: List of buffers for segment summaries | 79 | * @sb_segsum_buffers: List of buffers for segment summaries |
78 | * @sb_payload_buffers: List of buffers for segment payload | 80 | * @sb_payload_buffers: List of buffers for segment payload |
81 | * @sb_super_root: Pointer to buffer storing a super root block (if exists) | ||
79 | * @sb_nbio: Number of flying bio requests | 82 | * @sb_nbio: Number of flying bio requests |
80 | * @sb_err: I/O error status | 83 | * @sb_err: I/O error status |
81 | * @sb_bio_event: Completion event of log writing | 84 | * @sb_bio_event: Completion event of log writing |
@@ -95,6 +98,7 @@ struct nilfs_segment_buffer { | |||
95 | /* Buffers */ | 98 | /* Buffers */ |
96 | struct list_head sb_segsum_buffers; | 99 | struct list_head sb_segsum_buffers; |
97 | struct list_head sb_payload_buffers; /* including super root */ | 100 | struct list_head sb_payload_buffers; /* including super root */ |
101 | struct buffer_head *sb_super_root; | ||
98 | 102 | ||
99 | /* io status */ | 103 | /* io status */ |
100 | int sb_nbio; | 104 | int sb_nbio; |
@@ -121,6 +125,7 @@ struct nilfs_segment_buffer { | |||
121 | b_assoc_buffers)) | 125 | b_assoc_buffers)) |
122 | #define NILFS_SEGBUF_BH_IS_LAST(bh, head) ((bh)->b_assoc_buffers.next == head) | 126 | #define NILFS_SEGBUF_BH_IS_LAST(bh, head) ((bh)->b_assoc_buffers.next == head) |
123 | 127 | ||
128 | extern struct kmem_cache *nilfs_segbuf_cachep; | ||
124 | 129 | ||
125 | int __init nilfs_init_segbuf_cache(void); | 130 | int __init nilfs_init_segbuf_cache(void); |
126 | void nilfs_destroy_segbuf_cache(void); | 131 | void nilfs_destroy_segbuf_cache(void); |
@@ -132,13 +137,11 @@ void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf, | |||
132 | struct nilfs_segment_buffer *prev); | 137 | struct nilfs_segment_buffer *prev); |
133 | void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64, | 138 | void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64, |
134 | struct the_nilfs *); | 139 | struct the_nilfs *); |
135 | int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned, time_t); | 140 | int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned, time_t, __u64); |
136 | int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *); | 141 | int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *); |
137 | int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *, | 142 | int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *, |
138 | struct buffer_head **); | 143 | struct buffer_head **); |
139 | void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *); | 144 | void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *); |
140 | void nilfs_segbuf_fill_in_segsum_crc(struct nilfs_segment_buffer *, u32); | ||
141 | void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *, u32); | ||
142 | 145 | ||
143 | static inline void | 146 | static inline void |
144 | nilfs_segbuf_add_segsum_buffer(struct nilfs_segment_buffer *segbuf, | 147 | nilfs_segbuf_add_segsum_buffer(struct nilfs_segment_buffer *segbuf, |
@@ -171,6 +174,7 @@ void nilfs_truncate_logs(struct list_head *logs, | |||
171 | struct nilfs_segment_buffer *last); | 174 | struct nilfs_segment_buffer *last); |
172 | int nilfs_write_logs(struct list_head *logs, struct the_nilfs *nilfs); | 175 | int nilfs_write_logs(struct list_head *logs, struct the_nilfs *nilfs); |
173 | int nilfs_wait_on_logs(struct list_head *logs); | 176 | int nilfs_wait_on_logs(struct list_head *logs); |
177 | void nilfs_add_checksums_on_logs(struct list_head *logs, u32 seed); | ||
174 | 178 | ||
175 | static inline void nilfs_destroy_logs(struct list_head *logs) | 179 | static inline void nilfs_destroy_logs(struct list_head *logs) |
176 | { | 180 | { |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 6a7dbd8451db..c9201649cc49 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -116,42 +116,6 @@ static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *, | |||
116 | #define nilfs_cnt32_lt(a, b) nilfs_cnt32_gt(b, a) | 116 | #define nilfs_cnt32_lt(a, b) nilfs_cnt32_gt(b, a) |
117 | #define nilfs_cnt32_le(a, b) nilfs_cnt32_ge(b, a) | 117 | #define nilfs_cnt32_le(a, b) nilfs_cnt32_ge(b, a) |
118 | 118 | ||
119 | /* | ||
120 | * Transaction | ||
121 | */ | ||
122 | static struct kmem_cache *nilfs_transaction_cachep; | ||
123 | |||
124 | /** | ||
125 | * nilfs_init_transaction_cache - create a cache for nilfs_transaction_info | ||
126 | * | ||
127 | * nilfs_init_transaction_cache() creates a slab cache for the struct | ||
128 | * nilfs_transaction_info. | ||
129 | * | ||
130 | * Return Value: On success, it returns 0. On error, one of the following | ||
131 | * negative error code is returned. | ||
132 | * | ||
133 | * %-ENOMEM - Insufficient memory available. | ||
134 | */ | ||
135 | int nilfs_init_transaction_cache(void) | ||
136 | { | ||
137 | nilfs_transaction_cachep = | ||
138 | kmem_cache_create("nilfs2_transaction_cache", | ||
139 | sizeof(struct nilfs_transaction_info), | ||
140 | 0, SLAB_RECLAIM_ACCOUNT, NULL); | ||
141 | return (nilfs_transaction_cachep == NULL) ? -ENOMEM : 0; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * nilfs_destroy_transaction_cache - destroy the cache for transaction info | ||
146 | * | ||
147 | * nilfs_destroy_transaction_cache() frees the slab cache for the struct | ||
148 | * nilfs_transaction_info. | ||
149 | */ | ||
150 | void nilfs_destroy_transaction_cache(void) | ||
151 | { | ||
152 | kmem_cache_destroy(nilfs_transaction_cachep); | ||
153 | } | ||
154 | |||
155 | static int nilfs_prepare_segment_lock(struct nilfs_transaction_info *ti) | 119 | static int nilfs_prepare_segment_lock(struct nilfs_transaction_info *ti) |
156 | { | 120 | { |
157 | struct nilfs_transaction_info *cur_ti = current->journal_info; | 121 | struct nilfs_transaction_info *cur_ti = current->journal_info; |
@@ -402,7 +366,8 @@ static int nilfs_segctor_reset_segment_buffer(struct nilfs_sc_info *sci) | |||
402 | 366 | ||
403 | if (nilfs_doing_gc()) | 367 | if (nilfs_doing_gc()) |
404 | flags = NILFS_SS_GC; | 368 | flags = NILFS_SS_GC; |
405 | err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime); | 369 | err = nilfs_segbuf_reset(segbuf, flags, sci->sc_seg_ctime, |
370 | sci->sc_sbi->s_nilfs->ns_cno); | ||
406 | if (unlikely(err)) | 371 | if (unlikely(err)) |
407 | return err; | 372 | return err; |
408 | 373 | ||
@@ -435,7 +400,7 @@ static int nilfs_segctor_add_super_root(struct nilfs_sc_info *sci) | |||
435 | return err; | 400 | return err; |
436 | segbuf = sci->sc_curseg; | 401 | segbuf = sci->sc_curseg; |
437 | } | 402 | } |
438 | err = nilfs_segbuf_extend_payload(segbuf, &sci->sc_super_root); | 403 | err = nilfs_segbuf_extend_payload(segbuf, &segbuf->sb_super_root); |
439 | if (likely(!err)) | 404 | if (likely(!err)) |
440 | segbuf->sb_sum.flags |= NILFS_SS_SR; | 405 | segbuf->sb_sum.flags |= NILFS_SS_SR; |
441 | return err; | 406 | return err; |
@@ -599,7 +564,7 @@ static void nilfs_write_file_node_binfo(struct nilfs_sc_info *sci, | |||
599 | *vblocknr = binfo->bi_v.bi_vblocknr; | 564 | *vblocknr = binfo->bi_v.bi_vblocknr; |
600 | } | 565 | } |
601 | 566 | ||
602 | struct nilfs_sc_operations nilfs_sc_file_ops = { | 567 | static struct nilfs_sc_operations nilfs_sc_file_ops = { |
603 | .collect_data = nilfs_collect_file_data, | 568 | .collect_data = nilfs_collect_file_data, |
604 | .collect_node = nilfs_collect_file_node, | 569 | .collect_node = nilfs_collect_file_node, |
605 | .collect_bmap = nilfs_collect_file_bmap, | 570 | .collect_bmap = nilfs_collect_file_bmap, |
@@ -649,7 +614,7 @@ static void nilfs_write_dat_node_binfo(struct nilfs_sc_info *sci, | |||
649 | *binfo_dat = binfo->bi_dat; | 614 | *binfo_dat = binfo->bi_dat; |
650 | } | 615 | } |
651 | 616 | ||
652 | struct nilfs_sc_operations nilfs_sc_dat_ops = { | 617 | static struct nilfs_sc_operations nilfs_sc_dat_ops = { |
653 | .collect_data = nilfs_collect_dat_data, | 618 | .collect_data = nilfs_collect_dat_data, |
654 | .collect_node = nilfs_collect_file_node, | 619 | .collect_node = nilfs_collect_file_node, |
655 | .collect_bmap = nilfs_collect_dat_bmap, | 620 | .collect_bmap = nilfs_collect_dat_bmap, |
@@ -657,7 +622,7 @@ struct nilfs_sc_operations nilfs_sc_dat_ops = { | |||
657 | .write_node_binfo = nilfs_write_dat_node_binfo, | 622 | .write_node_binfo = nilfs_write_dat_node_binfo, |
658 | }; | 623 | }; |
659 | 624 | ||
660 | struct nilfs_sc_operations nilfs_sc_dsync_ops = { | 625 | static struct nilfs_sc_operations nilfs_sc_dsync_ops = { |
661 | .collect_data = nilfs_collect_file_data, | 626 | .collect_data = nilfs_collect_file_data, |
662 | .collect_node = NULL, | 627 | .collect_node = NULL, |
663 | .collect_bmap = NULL, | 628 | .collect_bmap = NULL, |
@@ -932,43 +897,16 @@ static void nilfs_segctor_fill_in_file_bmap(struct nilfs_sc_info *sci, | |||
932 | } | 897 | } |
933 | } | 898 | } |
934 | 899 | ||
935 | /* | ||
936 | * CRC calculation routines | ||
937 | */ | ||
938 | static void nilfs_fill_in_super_root_crc(struct buffer_head *bh_sr, u32 seed) | ||
939 | { | ||
940 | struct nilfs_super_root *raw_sr = | ||
941 | (struct nilfs_super_root *)bh_sr->b_data; | ||
942 | u32 crc; | ||
943 | |||
944 | crc = crc32_le(seed, | ||
945 | (unsigned char *)raw_sr + sizeof(raw_sr->sr_sum), | ||
946 | NILFS_SR_BYTES - sizeof(raw_sr->sr_sum)); | ||
947 | raw_sr->sr_sum = cpu_to_le32(crc); | ||
948 | } | ||
949 | |||
950 | static void nilfs_segctor_fill_in_checksums(struct nilfs_sc_info *sci, | ||
951 | u32 seed) | ||
952 | { | ||
953 | struct nilfs_segment_buffer *segbuf; | ||
954 | |||
955 | if (sci->sc_super_root) | ||
956 | nilfs_fill_in_super_root_crc(sci->sc_super_root, seed); | ||
957 | |||
958 | list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) { | ||
959 | nilfs_segbuf_fill_in_segsum_crc(segbuf, seed); | ||
960 | nilfs_segbuf_fill_in_data_crc(segbuf, seed); | ||
961 | } | ||
962 | } | ||
963 | |||
964 | static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci, | 900 | static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci, |
965 | struct the_nilfs *nilfs) | 901 | struct the_nilfs *nilfs) |
966 | { | 902 | { |
967 | struct buffer_head *bh_sr = sci->sc_super_root; | 903 | struct buffer_head *bh_sr; |
968 | struct nilfs_super_root *raw_sr = | 904 | struct nilfs_super_root *raw_sr; |
969 | (struct nilfs_super_root *)bh_sr->b_data; | ||
970 | unsigned isz = nilfs->ns_inode_size; | 905 | unsigned isz = nilfs->ns_inode_size; |
971 | 906 | ||
907 | bh_sr = NILFS_LAST_SEGBUF(&sci->sc_segbufs)->sb_super_root; | ||
908 | raw_sr = (struct nilfs_super_root *)bh_sr->b_data; | ||
909 | |||
972 | raw_sr->sr_bytes = cpu_to_le16(NILFS_SR_BYTES); | 910 | raw_sr->sr_bytes = cpu_to_le16(NILFS_SR_BYTES); |
973 | raw_sr->sr_nongc_ctime | 911 | raw_sr->sr_nongc_ctime |
974 | = cpu_to_le64(nilfs_doing_gc() ? | 912 | = cpu_to_le64(nilfs_doing_gc() ? |
@@ -1491,7 +1429,6 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, | |||
1491 | 1429 | ||
1492 | /* Collection retry loop */ | 1430 | /* Collection retry loop */ |
1493 | for (;;) { | 1431 | for (;;) { |
1494 | sci->sc_super_root = NULL; | ||
1495 | sci->sc_nblk_this_inc = 0; | 1432 | sci->sc_nblk_this_inc = 0; |
1496 | sci->sc_curseg = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); | 1433 | sci->sc_curseg = NILFS_FIRST_SEGBUF(&sci->sc_segbufs); |
1497 | 1434 | ||
@@ -1568,7 +1505,7 @@ nilfs_segctor_update_payload_blocknr(struct nilfs_sc_info *sci, | |||
1568 | ssp.offset = sizeof(struct nilfs_segment_summary); | 1505 | ssp.offset = sizeof(struct nilfs_segment_summary); |
1569 | 1506 | ||
1570 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { | 1507 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { |
1571 | if (bh == sci->sc_super_root) | 1508 | if (bh == segbuf->sb_super_root) |
1572 | break; | 1509 | break; |
1573 | if (!finfo) { | 1510 | if (!finfo) { |
1574 | finfo = nilfs_segctor_map_segsum_entry( | 1511 | finfo = nilfs_segctor_map_segsum_entry( |
@@ -1729,7 +1666,7 @@ static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci, | |||
1729 | 1666 | ||
1730 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, | 1667 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, |
1731 | b_assoc_buffers) { | 1668 | b_assoc_buffers) { |
1732 | if (bh == sci->sc_super_root) { | 1669 | if (bh == segbuf->sb_super_root) { |
1733 | if (bh->b_page != bd_page) { | 1670 | if (bh->b_page != bd_page) { |
1734 | lock_page(bd_page); | 1671 | lock_page(bd_page); |
1735 | clear_page_dirty_for_io(bd_page); | 1672 | clear_page_dirty_for_io(bd_page); |
@@ -1848,7 +1785,7 @@ static void nilfs_clear_copied_buffers(struct list_head *list, int err) | |||
1848 | } | 1785 | } |
1849 | 1786 | ||
1850 | static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, | 1787 | static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, |
1851 | struct buffer_head *bh_sr, int err) | 1788 | int err) |
1852 | { | 1789 | { |
1853 | struct nilfs_segment_buffer *segbuf; | 1790 | struct nilfs_segment_buffer *segbuf; |
1854 | struct page *bd_page = NULL, *fs_page = NULL; | 1791 | struct page *bd_page = NULL, *fs_page = NULL; |
@@ -1869,7 +1806,7 @@ static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, | |||
1869 | 1806 | ||
1870 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, | 1807 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, |
1871 | b_assoc_buffers) { | 1808 | b_assoc_buffers) { |
1872 | if (bh == bh_sr) { | 1809 | if (bh == segbuf->sb_super_root) { |
1873 | if (bh->b_page != bd_page) { | 1810 | if (bh->b_page != bd_page) { |
1874 | end_page_writeback(bd_page); | 1811 | end_page_writeback(bd_page); |
1875 | bd_page = bh->b_page; | 1812 | bd_page = bh->b_page; |
@@ -1898,7 +1835,7 @@ static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci, | |||
1898 | 1835 | ||
1899 | list_splice_tail_init(&sci->sc_write_logs, &logs); | 1836 | list_splice_tail_init(&sci->sc_write_logs, &logs); |
1900 | ret = nilfs_wait_on_logs(&logs); | 1837 | ret = nilfs_wait_on_logs(&logs); |
1901 | nilfs_abort_logs(&logs, NULL, sci->sc_super_root, ret ? : err); | 1838 | nilfs_abort_logs(&logs, NULL, ret ? : err); |
1902 | 1839 | ||
1903 | list_splice_tail_init(&sci->sc_segbufs, &logs); | 1840 | list_splice_tail_init(&sci->sc_segbufs, &logs); |
1904 | nilfs_cancel_segusage(&logs, nilfs->ns_sufile); | 1841 | nilfs_cancel_segusage(&logs, nilfs->ns_sufile); |
@@ -1914,7 +1851,6 @@ static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci, | |||
1914 | } | 1851 | } |
1915 | 1852 | ||
1916 | nilfs_destroy_logs(&logs); | 1853 | nilfs_destroy_logs(&logs); |
1917 | sci->sc_super_root = NULL; | ||
1918 | } | 1854 | } |
1919 | 1855 | ||
1920 | static void nilfs_set_next_segment(struct the_nilfs *nilfs, | 1856 | static void nilfs_set_next_segment(struct the_nilfs *nilfs, |
@@ -1933,7 +1869,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1933 | struct nilfs_segment_buffer *segbuf; | 1869 | struct nilfs_segment_buffer *segbuf; |
1934 | struct page *bd_page = NULL, *fs_page = NULL; | 1870 | struct page *bd_page = NULL, *fs_page = NULL; |
1935 | struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; | 1871 | struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; |
1936 | int update_sr = (sci->sc_super_root != NULL); | 1872 | int update_sr = false; |
1937 | 1873 | ||
1938 | list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { | 1874 | list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { |
1939 | struct buffer_head *bh; | 1875 | struct buffer_head *bh; |
@@ -1964,11 +1900,12 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1964 | set_buffer_uptodate(bh); | 1900 | set_buffer_uptodate(bh); |
1965 | clear_buffer_dirty(bh); | 1901 | clear_buffer_dirty(bh); |
1966 | clear_buffer_nilfs_volatile(bh); | 1902 | clear_buffer_nilfs_volatile(bh); |
1967 | if (bh == sci->sc_super_root) { | 1903 | if (bh == segbuf->sb_super_root) { |
1968 | if (bh->b_page != bd_page) { | 1904 | if (bh->b_page != bd_page) { |
1969 | end_page_writeback(bd_page); | 1905 | end_page_writeback(bd_page); |
1970 | bd_page = bh->b_page; | 1906 | bd_page = bh->b_page; |
1971 | } | 1907 | } |
1908 | update_sr = true; | ||
1972 | break; | 1909 | break; |
1973 | } | 1910 | } |
1974 | if (bh->b_page != fs_page) { | 1911 | if (bh->b_page != fs_page) { |
@@ -2115,7 +2052,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2115 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 2052 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
2116 | struct the_nilfs *nilfs = sbi->s_nilfs; | 2053 | struct the_nilfs *nilfs = sbi->s_nilfs; |
2117 | struct page *failed_page; | 2054 | struct page *failed_page; |
2118 | int err, has_sr = 0; | 2055 | int err; |
2119 | 2056 | ||
2120 | sci->sc_stage.scnt = NILFS_ST_INIT; | 2057 | sci->sc_stage.scnt = NILFS_ST_INIT; |
2121 | 2058 | ||
@@ -2143,8 +2080,6 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2143 | if (unlikely(err)) | 2080 | if (unlikely(err)) |
2144 | goto failed; | 2081 | goto failed; |
2145 | 2082 | ||
2146 | has_sr = (sci->sc_super_root != NULL); | ||
2147 | |||
2148 | /* Avoid empty segment */ | 2083 | /* Avoid empty segment */ |
2149 | if (sci->sc_stage.scnt == NILFS_ST_DONE && | 2084 | if (sci->sc_stage.scnt == NILFS_ST_DONE && |
2150 | NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { | 2085 | NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { |
@@ -2159,7 +2094,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2159 | if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) | 2094 | if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) |
2160 | nilfs_segctor_fill_in_file_bmap(sci, sbi->s_ifile); | 2095 | nilfs_segctor_fill_in_file_bmap(sci, sbi->s_ifile); |
2161 | 2096 | ||
2162 | if (has_sr) { | 2097 | if (mode == SC_LSEG_SR && |
2098 | sci->sc_stage.scnt >= NILFS_ST_CPFILE) { | ||
2163 | err = nilfs_segctor_fill_in_checkpoint(sci); | 2099 | err = nilfs_segctor_fill_in_checkpoint(sci); |
2164 | if (unlikely(err)) | 2100 | if (unlikely(err)) |
2165 | goto failed_to_write; | 2101 | goto failed_to_write; |
@@ -2171,11 +2107,12 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2171 | /* Write partial segments */ | 2107 | /* Write partial segments */ |
2172 | err = nilfs_segctor_prepare_write(sci, &failed_page); | 2108 | err = nilfs_segctor_prepare_write(sci, &failed_page); |
2173 | if (err) { | 2109 | if (err) { |
2174 | nilfs_abort_logs(&sci->sc_segbufs, failed_page, | 2110 | nilfs_abort_logs(&sci->sc_segbufs, failed_page, err); |
2175 | sci->sc_super_root, err); | ||
2176 | goto failed_to_write; | 2111 | goto failed_to_write; |
2177 | } | 2112 | } |
2178 | nilfs_segctor_fill_in_checksums(sci, nilfs->ns_crc_seed); | 2113 | |
2114 | nilfs_add_checksums_on_logs(&sci->sc_segbufs, | ||
2115 | nilfs->ns_crc_seed); | ||
2179 | 2116 | ||
2180 | err = nilfs_segctor_write(sci, nilfs); | 2117 | err = nilfs_segctor_write(sci, nilfs); |
2181 | if (unlikely(err)) | 2118 | if (unlikely(err)) |
@@ -2196,8 +2133,6 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2196 | } | 2133 | } |
2197 | } while (sci->sc_stage.scnt != NILFS_ST_DONE); | 2134 | } while (sci->sc_stage.scnt != NILFS_ST_DONE); |
2198 | 2135 | ||
2199 | sci->sc_super_root = NULL; | ||
2200 | |||
2201 | out: | 2136 | out: |
2202 | nilfs_segctor_check_out_files(sci, sbi); | 2137 | nilfs_segctor_check_out_files(sci, sbi); |
2203 | return err; | 2138 | return err; |
@@ -2224,9 +2159,9 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2224 | static void nilfs_segctor_start_timer(struct nilfs_sc_info *sci) | 2159 | static void nilfs_segctor_start_timer(struct nilfs_sc_info *sci) |
2225 | { | 2160 | { |
2226 | spin_lock(&sci->sc_state_lock); | 2161 | spin_lock(&sci->sc_state_lock); |
2227 | if (sci->sc_timer && !(sci->sc_state & NILFS_SEGCTOR_COMMIT)) { | 2162 | if (!(sci->sc_state & NILFS_SEGCTOR_COMMIT)) { |
2228 | sci->sc_timer->expires = jiffies + sci->sc_interval; | 2163 | sci->sc_timer.expires = jiffies + sci->sc_interval; |
2229 | add_timer(sci->sc_timer); | 2164 | add_timer(&sci->sc_timer); |
2230 | sci->sc_state |= NILFS_SEGCTOR_COMMIT; | 2165 | sci->sc_state |= NILFS_SEGCTOR_COMMIT; |
2231 | } | 2166 | } |
2232 | spin_unlock(&sci->sc_state_lock); | 2167 | spin_unlock(&sci->sc_state_lock); |
@@ -2431,9 +2366,7 @@ static void nilfs_segctor_accept(struct nilfs_sc_info *sci) | |||
2431 | spin_lock(&sci->sc_state_lock); | 2366 | spin_lock(&sci->sc_state_lock); |
2432 | sci->sc_seq_accepted = sci->sc_seq_request; | 2367 | sci->sc_seq_accepted = sci->sc_seq_request; |
2433 | spin_unlock(&sci->sc_state_lock); | 2368 | spin_unlock(&sci->sc_state_lock); |
2434 | 2369 | del_timer_sync(&sci->sc_timer); | |
2435 | if (sci->sc_timer) | ||
2436 | del_timer_sync(sci->sc_timer); | ||
2437 | } | 2370 | } |
2438 | 2371 | ||
2439 | /** | 2372 | /** |
@@ -2459,9 +2392,9 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) | |||
2459 | sci->sc_flush_request &= ~FLUSH_DAT_BIT; | 2392 | sci->sc_flush_request &= ~FLUSH_DAT_BIT; |
2460 | 2393 | ||
2461 | /* re-enable timer if checkpoint creation was not done */ | 2394 | /* re-enable timer if checkpoint creation was not done */ |
2462 | if (sci->sc_timer && (sci->sc_state & NILFS_SEGCTOR_COMMIT) && | 2395 | if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && |
2463 | time_before(jiffies, sci->sc_timer->expires)) | 2396 | time_before(jiffies, sci->sc_timer.expires)) |
2464 | add_timer(sci->sc_timer); | 2397 | add_timer(&sci->sc_timer); |
2465 | } | 2398 | } |
2466 | spin_unlock(&sci->sc_state_lock); | 2399 | spin_unlock(&sci->sc_state_lock); |
2467 | } | 2400 | } |
@@ -2640,13 +2573,10 @@ static int nilfs_segctor_thread(void *arg) | |||
2640 | { | 2573 | { |
2641 | struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; | 2574 | struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; |
2642 | struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; | 2575 | struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; |
2643 | struct timer_list timer; | ||
2644 | int timeout = 0; | 2576 | int timeout = 0; |
2645 | 2577 | ||
2646 | init_timer(&timer); | 2578 | sci->sc_timer.data = (unsigned long)current; |
2647 | timer.data = (unsigned long)current; | 2579 | sci->sc_timer.function = nilfs_construction_timeout; |
2648 | timer.function = nilfs_construction_timeout; | ||
2649 | sci->sc_timer = &timer; | ||
2650 | 2580 | ||
2651 | /* start sync. */ | 2581 | /* start sync. */ |
2652 | sci->sc_task = current; | 2582 | sci->sc_task = current; |
@@ -2695,7 +2625,7 @@ static int nilfs_segctor_thread(void *arg) | |||
2695 | should_sleep = 0; | 2625 | should_sleep = 0; |
2696 | else if (sci->sc_state & NILFS_SEGCTOR_COMMIT) | 2626 | else if (sci->sc_state & NILFS_SEGCTOR_COMMIT) |
2697 | should_sleep = time_before(jiffies, | 2627 | should_sleep = time_before(jiffies, |
2698 | sci->sc_timer->expires); | 2628 | sci->sc_timer.expires); |
2699 | 2629 | ||
2700 | if (should_sleep) { | 2630 | if (should_sleep) { |
2701 | spin_unlock(&sci->sc_state_lock); | 2631 | spin_unlock(&sci->sc_state_lock); |
@@ -2704,7 +2634,7 @@ static int nilfs_segctor_thread(void *arg) | |||
2704 | } | 2634 | } |
2705 | finish_wait(&sci->sc_wait_daemon, &wait); | 2635 | finish_wait(&sci->sc_wait_daemon, &wait); |
2706 | timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && | 2636 | timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && |
2707 | time_after_eq(jiffies, sci->sc_timer->expires)); | 2637 | time_after_eq(jiffies, sci->sc_timer.expires)); |
2708 | 2638 | ||
2709 | if (nilfs_sb_dirty(nilfs) && nilfs_sb_need_update(nilfs)) | 2639 | if (nilfs_sb_dirty(nilfs) && nilfs_sb_need_update(nilfs)) |
2710 | set_nilfs_discontinued(nilfs); | 2640 | set_nilfs_discontinued(nilfs); |
@@ -2713,8 +2643,6 @@ static int nilfs_segctor_thread(void *arg) | |||
2713 | 2643 | ||
2714 | end_thread: | 2644 | end_thread: |
2715 | spin_unlock(&sci->sc_state_lock); | 2645 | spin_unlock(&sci->sc_state_lock); |
2716 | del_timer_sync(sci->sc_timer); | ||
2717 | sci->sc_timer = NULL; | ||
2718 | 2646 | ||
2719 | /* end sync. */ | 2647 | /* end sync. */ |
2720 | sci->sc_task = NULL; | 2648 | sci->sc_task = NULL; |
@@ -2750,13 +2678,6 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) | |||
2750 | } | 2678 | } |
2751 | } | 2679 | } |
2752 | 2680 | ||
2753 | static int nilfs_segctor_init(struct nilfs_sc_info *sci) | ||
2754 | { | ||
2755 | sci->sc_seq_done = sci->sc_seq_request; | ||
2756 | |||
2757 | return nilfs_segctor_start_thread(sci); | ||
2758 | } | ||
2759 | |||
2760 | /* | 2681 | /* |
2761 | * Setup & clean-up functions | 2682 | * Setup & clean-up functions |
2762 | */ | 2683 | */ |
@@ -2780,6 +2701,7 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi) | |||
2780 | INIT_LIST_HEAD(&sci->sc_write_logs); | 2701 | INIT_LIST_HEAD(&sci->sc_write_logs); |
2781 | INIT_LIST_HEAD(&sci->sc_gc_inodes); | 2702 | INIT_LIST_HEAD(&sci->sc_gc_inodes); |
2782 | INIT_LIST_HEAD(&sci->sc_copied_buffers); | 2703 | INIT_LIST_HEAD(&sci->sc_copied_buffers); |
2704 | init_timer(&sci->sc_timer); | ||
2783 | 2705 | ||
2784 | sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; | 2706 | sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; |
2785 | sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; | 2707 | sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; |
@@ -2846,6 +2768,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) | |||
2846 | 2768 | ||
2847 | down_write(&sbi->s_nilfs->ns_segctor_sem); | 2769 | down_write(&sbi->s_nilfs->ns_segctor_sem); |
2848 | 2770 | ||
2771 | del_timer_sync(&sci->sc_timer); | ||
2849 | kfree(sci); | 2772 | kfree(sci); |
2850 | } | 2773 | } |
2851 | 2774 | ||
@@ -2880,7 +2803,7 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi) | |||
2880 | return -ENOMEM; | 2803 | return -ENOMEM; |
2881 | 2804 | ||
2882 | nilfs_attach_writer(nilfs, sbi); | 2805 | nilfs_attach_writer(nilfs, sbi); |
2883 | err = nilfs_segctor_init(NILFS_SC(sbi)); | 2806 | err = nilfs_segctor_start_thread(NILFS_SC(sbi)); |
2884 | if (err) { | 2807 | if (err) { |
2885 | nilfs_detach_writer(nilfs, sbi); | 2808 | nilfs_detach_writer(nilfs, sbi); |
2886 | kfree(sbi->s_sc_info); | 2809 | kfree(sbi->s_sc_info); |
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 82dfd6a686b9..dca142361ccf 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h | |||
@@ -100,7 +100,6 @@ struct nilfs_segsum_pointer { | |||
100 | * @sc_write_logs: List of segment buffers to hold logs under writing | 100 | * @sc_write_logs: List of segment buffers to hold logs under writing |
101 | * @sc_segbuf_nblocks: Number of available blocks in segment buffers. | 101 | * @sc_segbuf_nblocks: Number of available blocks in segment buffers. |
102 | * @sc_curseg: Current segment buffer | 102 | * @sc_curseg: Current segment buffer |
103 | * @sc_super_root: Pointer to the super root buffer | ||
104 | * @sc_stage: Collection stage | 103 | * @sc_stage: Collection stage |
105 | * @sc_finfo_ptr: pointer to the current finfo struct in the segment summary | 104 | * @sc_finfo_ptr: pointer to the current finfo struct in the segment summary |
106 | * @sc_binfo_ptr: pointer to the current binfo struct in the segment summary | 105 | * @sc_binfo_ptr: pointer to the current binfo struct in the segment summary |
@@ -148,7 +147,6 @@ struct nilfs_sc_info { | |||
148 | struct list_head sc_write_logs; | 147 | struct list_head sc_write_logs; |
149 | unsigned long sc_segbuf_nblocks; | 148 | unsigned long sc_segbuf_nblocks; |
150 | struct nilfs_segment_buffer *sc_curseg; | 149 | struct nilfs_segment_buffer *sc_curseg; |
151 | struct buffer_head *sc_super_root; | ||
152 | 150 | ||
153 | struct nilfs_cstage sc_stage; | 151 | struct nilfs_cstage sc_stage; |
154 | 152 | ||
@@ -179,7 +177,7 @@ struct nilfs_sc_info { | |||
179 | unsigned long sc_lseg_stime; /* in 1/HZ seconds */ | 177 | unsigned long sc_lseg_stime; /* in 1/HZ seconds */ |
180 | unsigned long sc_watermark; | 178 | unsigned long sc_watermark; |
181 | 179 | ||
182 | struct timer_list *sc_timer; | 180 | struct timer_list sc_timer; |
183 | struct task_struct *sc_task; | 181 | struct task_struct *sc_task; |
184 | }; | 182 | }; |
185 | 183 | ||
@@ -219,6 +217,8 @@ enum { | |||
219 | */ | 217 | */ |
220 | #define NILFS_SC_DEFAULT_WATERMARK 3600 | 218 | #define NILFS_SC_DEFAULT_WATERMARK 3600 |
221 | 219 | ||
220 | /* super.c */ | ||
221 | extern struct kmem_cache *nilfs_transaction_cachep; | ||
222 | 222 | ||
223 | /* segment.c */ | 223 | /* segment.c */ |
224 | extern int nilfs_init_transaction_cache(void); | 224 | extern int nilfs_init_transaction_cache(void); |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 48145f505a6a..03b34b738993 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -67,6 +67,11 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " | |||
67 | "(NILFS)"); | 67 | "(NILFS)"); |
68 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
69 | 69 | ||
70 | struct kmem_cache *nilfs_inode_cachep; | ||
71 | struct kmem_cache *nilfs_transaction_cachep; | ||
72 | struct kmem_cache *nilfs_segbuf_cachep; | ||
73 | struct kmem_cache *nilfs_btree_path_cache; | ||
74 | |||
70 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 75 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
71 | 76 | ||
72 | /** | 77 | /** |
@@ -129,7 +134,6 @@ void nilfs_warning(struct super_block *sb, const char *function, | |||
129 | va_end(args); | 134 | va_end(args); |
130 | } | 135 | } |
131 | 136 | ||
132 | static struct kmem_cache *nilfs_inode_cachep; | ||
133 | 137 | ||
134 | struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) | 138 | struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs) |
135 | { | 139 | { |
@@ -155,34 +159,6 @@ void nilfs_destroy_inode(struct inode *inode) | |||
155 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); | 159 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); |
156 | } | 160 | } |
157 | 161 | ||
158 | static void init_once(void *obj) | ||
159 | { | ||
160 | struct nilfs_inode_info *ii = obj; | ||
161 | |||
162 | INIT_LIST_HEAD(&ii->i_dirty); | ||
163 | #ifdef CONFIG_NILFS_XATTR | ||
164 | init_rwsem(&ii->xattr_sem); | ||
165 | #endif | ||
166 | nilfs_btnode_cache_init_once(&ii->i_btnode_cache); | ||
167 | ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; | ||
168 | inode_init_once(&ii->vfs_inode); | ||
169 | } | ||
170 | |||
171 | static int nilfs_init_inode_cache(void) | ||
172 | { | ||
173 | nilfs_inode_cachep = kmem_cache_create("nilfs2_inode_cache", | ||
174 | sizeof(struct nilfs_inode_info), | ||
175 | 0, SLAB_RECLAIM_ACCOUNT, | ||
176 | init_once); | ||
177 | |||
178 | return (nilfs_inode_cachep == NULL) ? -ENOMEM : 0; | ||
179 | } | ||
180 | |||
181 | static inline void nilfs_destroy_inode_cache(void) | ||
182 | { | ||
183 | kmem_cache_destroy(nilfs_inode_cachep); | ||
184 | } | ||
185 | |||
186 | static void nilfs_clear_inode(struct inode *inode) | 162 | static void nilfs_clear_inode(struct inode *inode) |
187 | { | 163 | { |
188 | struct nilfs_inode_info *ii = NILFS_I(inode); | 164 | struct nilfs_inode_info *ii = NILFS_I(inode); |
@@ -266,8 +242,8 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb) | |||
266 | int err; | 242 | int err; |
267 | 243 | ||
268 | /* nilfs->sem must be locked by the caller. */ | 244 | /* nilfs->sem must be locked by the caller. */ |
269 | if (sbp[0]->s_magic != NILFS_SUPER_MAGIC) { | 245 | if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { |
270 | if (sbp[1] && sbp[1]->s_magic == NILFS_SUPER_MAGIC) | 246 | if (sbp[1] && sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) |
271 | nilfs_swap_super_block(nilfs); | 247 | nilfs_swap_super_block(nilfs); |
272 | else { | 248 | else { |
273 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", | 249 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", |
@@ -470,10 +446,10 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
470 | if (nilfs_test_opt(sbi, SNAPSHOT)) | 446 | if (nilfs_test_opt(sbi, SNAPSHOT)) |
471 | seq_printf(seq, ",cp=%llu", | 447 | seq_printf(seq, ",cp=%llu", |
472 | (unsigned long long int)sbi->s_snapshot_cno); | 448 | (unsigned long long int)sbi->s_snapshot_cno); |
473 | if (nilfs_test_opt(sbi, ERRORS_RO)) | ||
474 | seq_printf(seq, ",errors=remount-ro"); | ||
475 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | 449 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) |
476 | seq_printf(seq, ",errors=panic"); | 450 | seq_printf(seq, ",errors=panic"); |
451 | if (nilfs_test_opt(sbi, ERRORS_CONT)) | ||
452 | seq_printf(seq, ",errors=continue"); | ||
477 | if (nilfs_test_opt(sbi, STRICT_ORDER)) | 453 | if (nilfs_test_opt(sbi, STRICT_ORDER)) |
478 | seq_printf(seq, ",order=strict"); | 454 | seq_printf(seq, ",order=strict"); |
479 | if (nilfs_test_opt(sbi, NORECOVERY)) | 455 | if (nilfs_test_opt(sbi, NORECOVERY)) |
@@ -631,7 +607,7 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, | |||
631 | struct nilfs_super_block *sbp) | 607 | struct nilfs_super_block *sbp) |
632 | { | 608 | { |
633 | sbi->s_mount_opt = | 609 | sbi->s_mount_opt = |
634 | NILFS_MOUNT_ERRORS_CONT | NILFS_MOUNT_BARRIER; | 610 | NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; |
635 | } | 611 | } |
636 | 612 | ||
637 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) | 613 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) |
@@ -778,9 +754,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
778 | goto failed_sbi; | 754 | goto failed_sbi; |
779 | } | 755 | } |
780 | cno = sbi->s_snapshot_cno; | 756 | cno = sbi->s_snapshot_cno; |
781 | } else | 757 | } |
782 | /* Read-only mount */ | ||
783 | sbi->s_snapshot_cno = cno; | ||
784 | } | 758 | } |
785 | 759 | ||
786 | err = nilfs_attach_checkpoint(sbi, cno); | 760 | err = nilfs_attach_checkpoint(sbi, cno); |
@@ -849,7 +823,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
849 | struct the_nilfs *nilfs = sbi->s_nilfs; | 823 | struct the_nilfs *nilfs = sbi->s_nilfs; |
850 | unsigned long old_sb_flags; | 824 | unsigned long old_sb_flags; |
851 | struct nilfs_mount_options old_opts; | 825 | struct nilfs_mount_options old_opts; |
852 | int err; | 826 | int was_snapshot, err; |
853 | 827 | ||
854 | lock_kernel(); | 828 | lock_kernel(); |
855 | 829 | ||
@@ -857,6 +831,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
857 | old_sb_flags = sb->s_flags; | 831 | old_sb_flags = sb->s_flags; |
858 | old_opts.mount_opt = sbi->s_mount_opt; | 832 | old_opts.mount_opt = sbi->s_mount_opt; |
859 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | 833 | old_opts.snapshot_cno = sbi->s_snapshot_cno; |
834 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); | ||
860 | 835 | ||
861 | if (!parse_options(data, sb)) { | 836 | if (!parse_options(data, sb)) { |
862 | err = -EINVAL; | 837 | err = -EINVAL; |
@@ -864,20 +839,32 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
864 | } | 839 | } |
865 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); | 840 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); |
866 | 841 | ||
867 | if ((*flags & MS_RDONLY) && | 842 | err = -EINVAL; |
868 | sbi->s_snapshot_cno != old_opts.snapshot_cno) { | 843 | if (was_snapshot) { |
869 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 844 | if (!(*flags & MS_RDONLY)) { |
870 | "remount to a different snapshot.\n", | 845 | printk(KERN_ERR "NILFS (device %s): cannot remount " |
871 | sb->s_id); | 846 | "snapshot read/write.\n", |
872 | err = -EINVAL; | 847 | sb->s_id); |
873 | goto restore_opts; | 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 | } | ||
874 | } | 862 | } |
875 | 863 | ||
876 | if (!nilfs_valid_fs(nilfs)) { | 864 | if (!nilfs_valid_fs(nilfs)) { |
877 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 865 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
878 | "remount because the filesystem is in an " | 866 | "remount because the filesystem is in an " |
879 | "incomplete recovery state.\n", sb->s_id); | 867 | "incomplete recovery state.\n", sb->s_id); |
880 | err = -EINVAL; | ||
881 | goto restore_opts; | 868 | goto restore_opts; |
882 | } | 869 | } |
883 | 870 | ||
@@ -888,9 +875,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
888 | nilfs_detach_segment_constructor(sbi); | 875 | nilfs_detach_segment_constructor(sbi); |
889 | sb->s_flags |= MS_RDONLY; | 876 | sb->s_flags |= MS_RDONLY; |
890 | 877 | ||
891 | sbi->s_snapshot_cno = nilfs_last_cno(nilfs); | ||
892 | /* nilfs_set_opt(sbi, SNAPSHOT); */ | ||
893 | |||
894 | /* | 878 | /* |
895 | * Remounting a valid RW partition RDONLY, so set | 879 | * Remounting a valid RW partition RDONLY, so set |
896 | * the RDONLY flag and then mark the partition as valid again. | 880 | * the RDONLY flag and then mark the partition as valid again. |
@@ -909,24 +893,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
909 | * store the current valid flag. (It may have been changed | 893 | * store the current valid flag. (It may have been changed |
910 | * by fsck since we originally mounted the partition.) | 894 | * by fsck since we originally mounted the partition.) |
911 | */ | 895 | */ |
912 | if (nilfs->ns_current && nilfs->ns_current != sbi) { | ||
913 | printk(KERN_WARNING "NILFS (device %s): couldn't " | ||
914 | "remount because an RW-mount exists.\n", | ||
915 | sb->s_id); | ||
916 | err = -EBUSY; | ||
917 | goto restore_opts; | ||
918 | } | ||
919 | if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) { | ||
920 | printk(KERN_WARNING "NILFS (device %s): couldn't " | ||
921 | "remount because the current RO-mount is not " | ||
922 | "the latest one.\n", | ||
923 | sb->s_id); | ||
924 | err = -EINVAL; | ||
925 | goto restore_opts; | ||
926 | } | ||
927 | sb->s_flags &= ~MS_RDONLY; | 896 | sb->s_flags &= ~MS_RDONLY; |
928 | nilfs_clear_opt(sbi, SNAPSHOT); | ||
929 | sbi->s_snapshot_cno = 0; | ||
930 | 897 | ||
931 | err = nilfs_attach_segment_constructor(sbi); | 898 | err = nilfs_attach_segment_constructor(sbi); |
932 | if (err) | 899 | if (err) |
@@ -935,8 +902,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
935 | down_write(&nilfs->ns_sem); | 902 | down_write(&nilfs->ns_sem); |
936 | nilfs_setup_super(sbi); | 903 | nilfs_setup_super(sbi); |
937 | up_write(&nilfs->ns_sem); | 904 | up_write(&nilfs->ns_sem); |
938 | |||
939 | nilfs->ns_current = sbi; | ||
940 | } | 905 | } |
941 | out: | 906 | out: |
942 | up_write(&nilfs->ns_super_sem); | 907 | up_write(&nilfs->ns_super_sem); |
@@ -1022,10 +987,14 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1022 | { | 987 | { |
1023 | struct nilfs_super_data sd; | 988 | struct nilfs_super_data sd; |
1024 | struct super_block *s; | 989 | struct super_block *s; |
990 | fmode_t mode = FMODE_READ; | ||
1025 | struct the_nilfs *nilfs; | 991 | struct the_nilfs *nilfs; |
1026 | int err, need_to_close = 1; | 992 | int err, need_to_close = 1; |
1027 | 993 | ||
1028 | sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); | 994 | if (!(flags & MS_RDONLY)) |
995 | mode |= FMODE_WRITE; | ||
996 | |||
997 | sd.bdev = open_bdev_exclusive(dev_name, mode, fs_type); | ||
1029 | if (IS_ERR(sd.bdev)) | 998 | if (IS_ERR(sd.bdev)) |
1030 | return PTR_ERR(sd.bdev); | 999 | return PTR_ERR(sd.bdev); |
1031 | 1000 | ||
@@ -1092,10 +1061,12 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1092 | 1061 | ||
1093 | /* New superblock instance created */ | 1062 | /* New superblock instance created */ |
1094 | s->s_flags = flags; | 1063 | s->s_flags = flags; |
1064 | s->s_mode = mode; | ||
1095 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); | 1065 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); |
1096 | sb_set_blocksize(s, block_size(sd.bdev)); | 1066 | sb_set_blocksize(s, block_size(sd.bdev)); |
1097 | 1067 | ||
1098 | err = nilfs_fill_super(s, data, flags & MS_VERBOSE, nilfs); | 1068 | err = nilfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0, |
1069 | nilfs); | ||
1099 | if (err) | 1070 | if (err) |
1100 | goto cancel_new; | 1071 | goto cancel_new; |
1101 | 1072 | ||
@@ -1106,7 +1077,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1106 | mutex_unlock(&nilfs->ns_mount_mutex); | 1077 | mutex_unlock(&nilfs->ns_mount_mutex); |
1107 | put_nilfs(nilfs); | 1078 | put_nilfs(nilfs); |
1108 | if (need_to_close) | 1079 | if (need_to_close) |
1109 | close_bdev_exclusive(sd.bdev, flags); | 1080 | close_bdev_exclusive(sd.bdev, mode); |
1110 | simple_set_mnt(mnt, s); | 1081 | simple_set_mnt(mnt, s); |
1111 | return 0; | 1082 | return 0; |
1112 | 1083 | ||
@@ -1114,7 +1085,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1114 | mutex_unlock(&nilfs->ns_mount_mutex); | 1085 | mutex_unlock(&nilfs->ns_mount_mutex); |
1115 | put_nilfs(nilfs); | 1086 | put_nilfs(nilfs); |
1116 | failed: | 1087 | failed: |
1117 | close_bdev_exclusive(sd.bdev, flags); | 1088 | close_bdev_exclusive(sd.bdev, mode); |
1118 | 1089 | ||
1119 | return err; | 1090 | return err; |
1120 | 1091 | ||
@@ -1124,7 +1095,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1124 | put_nilfs(nilfs); | 1095 | put_nilfs(nilfs); |
1125 | deactivate_locked_super(s); | 1096 | deactivate_locked_super(s); |
1126 | /* | 1097 | /* |
1127 | * deactivate_super() invokes close_bdev_exclusive(). | 1098 | * deactivate_locked_super() invokes close_bdev_exclusive(). |
1128 | * We must finish all post-cleaning before this call; | 1099 | * We must finish all post-cleaning before this call; |
1129 | * put_nilfs() needs the block device. | 1100 | * put_nilfs() needs the block device. |
1130 | */ | 1101 | */ |
@@ -1139,54 +1110,93 @@ struct file_system_type nilfs_fs_type = { | |||
1139 | .fs_flags = FS_REQUIRES_DEV, | 1110 | .fs_flags = FS_REQUIRES_DEV, |
1140 | }; | 1111 | }; |
1141 | 1112 | ||
1142 | static int __init init_nilfs_fs(void) | 1113 | static void nilfs_inode_init_once(void *obj) |
1143 | { | 1114 | { |
1144 | int err; | 1115 | struct nilfs_inode_info *ii = obj; |
1145 | |||
1146 | err = nilfs_init_inode_cache(); | ||
1147 | if (err) | ||
1148 | goto failed; | ||
1149 | 1116 | ||
1150 | err = nilfs_init_transaction_cache(); | 1117 | INIT_LIST_HEAD(&ii->i_dirty); |
1151 | if (err) | 1118 | #ifdef CONFIG_NILFS_XATTR |
1152 | goto failed_inode_cache; | 1119 | init_rwsem(&ii->xattr_sem); |
1120 | #endif | ||
1121 | nilfs_btnode_cache_init_once(&ii->i_btnode_cache); | ||
1122 | ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; | ||
1123 | inode_init_once(&ii->vfs_inode); | ||
1124 | } | ||
1153 | 1125 | ||
1154 | err = nilfs_init_segbuf_cache(); | 1126 | static void nilfs_segbuf_init_once(void *obj) |
1155 | if (err) | 1127 | { |
1156 | goto failed_transaction_cache; | 1128 | memset(obj, 0, sizeof(struct nilfs_segment_buffer)); |
1129 | } | ||
1157 | 1130 | ||
1158 | err = nilfs_btree_path_cache_init(); | 1131 | static void nilfs_destroy_cachep(void) |
1159 | if (err) | 1132 | { |
1160 | goto failed_segbuf_cache; | 1133 | if (nilfs_inode_cachep) |
1134 | kmem_cache_destroy(nilfs_inode_cachep); | ||
1135 | if (nilfs_transaction_cachep) | ||
1136 | kmem_cache_destroy(nilfs_transaction_cachep); | ||
1137 | if (nilfs_segbuf_cachep) | ||
1138 | kmem_cache_destroy(nilfs_segbuf_cachep); | ||
1139 | if (nilfs_btree_path_cache) | ||
1140 | kmem_cache_destroy(nilfs_btree_path_cache); | ||
1141 | } | ||
1161 | 1142 | ||
1162 | err = register_filesystem(&nilfs_fs_type); | 1143 | static int __init nilfs_init_cachep(void) |
1163 | if (err) | 1144 | { |
1164 | goto failed_btree_path_cache; | 1145 | nilfs_inode_cachep = kmem_cache_create("nilfs2_inode_cache", |
1146 | sizeof(struct nilfs_inode_info), 0, | ||
1147 | SLAB_RECLAIM_ACCOUNT, nilfs_inode_init_once); | ||
1148 | if (!nilfs_inode_cachep) | ||
1149 | goto fail; | ||
1150 | |||
1151 | nilfs_transaction_cachep = kmem_cache_create("nilfs2_transaction_cache", | ||
1152 | sizeof(struct nilfs_transaction_info), 0, | ||
1153 | SLAB_RECLAIM_ACCOUNT, NULL); | ||
1154 | if (!nilfs_transaction_cachep) | ||
1155 | goto fail; | ||
1156 | |||
1157 | nilfs_segbuf_cachep = kmem_cache_create("nilfs2_segbuf_cache", | ||
1158 | sizeof(struct nilfs_segment_buffer), 0, | ||
1159 | SLAB_RECLAIM_ACCOUNT, nilfs_segbuf_init_once); | ||
1160 | if (!nilfs_segbuf_cachep) | ||
1161 | goto fail; | ||
1162 | |||
1163 | nilfs_btree_path_cache = kmem_cache_create("nilfs2_btree_path_cache", | ||
1164 | sizeof(struct nilfs_btree_path) * NILFS_BTREE_LEVEL_MAX, | ||
1165 | 0, 0, NULL); | ||
1166 | if (!nilfs_btree_path_cache) | ||
1167 | goto fail; | ||
1165 | 1168 | ||
1166 | return 0; | 1169 | return 0; |
1167 | 1170 | ||
1168 | failed_btree_path_cache: | 1171 | fail: |
1169 | nilfs_btree_path_cache_destroy(); | 1172 | nilfs_destroy_cachep(); |
1173 | return -ENOMEM; | ||
1174 | } | ||
1175 | |||
1176 | static int __init init_nilfs_fs(void) | ||
1177 | { | ||
1178 | int err; | ||
1170 | 1179 | ||
1171 | failed_segbuf_cache: | 1180 | err = nilfs_init_cachep(); |
1172 | nilfs_destroy_segbuf_cache(); | 1181 | if (err) |
1182 | goto fail; | ||
1173 | 1183 | ||
1174 | failed_transaction_cache: | 1184 | err = register_filesystem(&nilfs_fs_type); |
1175 | nilfs_destroy_transaction_cache(); | 1185 | if (err) |
1186 | goto free_cachep; | ||
1176 | 1187 | ||
1177 | failed_inode_cache: | 1188 | printk(KERN_INFO "NILFS version 2 loaded\n"); |
1178 | nilfs_destroy_inode_cache(); | 1189 | return 0; |
1179 | 1190 | ||
1180 | failed: | 1191 | free_cachep: |
1192 | nilfs_destroy_cachep(); | ||
1193 | fail: | ||
1181 | return err; | 1194 | return err; |
1182 | } | 1195 | } |
1183 | 1196 | ||
1184 | static void __exit exit_nilfs_fs(void) | 1197 | static void __exit exit_nilfs_fs(void) |
1185 | { | 1198 | { |
1186 | nilfs_destroy_segbuf_cache(); | 1199 | nilfs_destroy_cachep(); |
1187 | nilfs_destroy_transaction_cache(); | ||
1188 | nilfs_destroy_inode_cache(); | ||
1189 | nilfs_btree_path_cache_destroy(); | ||
1190 | unregister_filesystem(&nilfs_fs_type); | 1200 | unregister_filesystem(&nilfs_fs_type); |
1191 | } | 1201 | } |
1192 | 1202 | ||
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 33871f7e4f01..a756168a21c2 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -486,11 +486,15 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, | |||
486 | printk(KERN_WARNING | 486 | printk(KERN_WARNING |
487 | "NILFS warning: unable to read secondary superblock\n"); | 487 | "NILFS warning: unable to read secondary superblock\n"); |
488 | 488 | ||
489 | /* | ||
490 | * Compare two super blocks and set 1 in swp if the secondary | ||
491 | * super block is valid and newer. Otherwise, set 0 in swp. | ||
492 | */ | ||
489 | valid[0] = nilfs_valid_sb(sbp[0]); | 493 | valid[0] = nilfs_valid_sb(sbp[0]); |
490 | valid[1] = nilfs_valid_sb(sbp[1]); | 494 | valid[1] = nilfs_valid_sb(sbp[1]); |
491 | swp = valid[1] && | 495 | swp = valid[1] && (!valid[0] || |
492 | (!valid[0] || | 496 | le64_to_cpu(sbp[1]->s_last_cno) > |
493 | le64_to_cpu(sbp[1]->s_wtime) > le64_to_cpu(sbp[0]->s_wtime)); | 497 | le64_to_cpu(sbp[0]->s_last_cno)); |
494 | 498 | ||
495 | if (valid[swp] && nilfs_sb2_bad_offset(sbp[swp], sb2off)) { | 499 | if (valid[swp] && nilfs_sb2_bad_offset(sbp[swp], sb2off)) { |
496 | brelse(sbh[1]); | 500 | brelse(sbh[1]); |