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 | |
| 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()
...
| -rw-r--r-- | Documentation/filesystems/nilfs2.txt | 4 | ||||
| -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 | ||||
| -rw-r--r-- | include/linux/nilfs2_fs.h | 17 |
14 files changed, 423 insertions, 350 deletions
diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt index cf6d0d85ca82..d3e7673995eb 100644 --- a/Documentation/filesystems/nilfs2.txt +++ b/Documentation/filesystems/nilfs2.txt | |||
| @@ -50,8 +50,8 @@ NILFS2 supports the following mount options: | |||
| 50 | (*) == default | 50 | (*) == default |
| 51 | 51 | ||
| 52 | nobarrier Disables barriers. | 52 | nobarrier Disables barriers. |
| 53 | errors=continue(*) Keep going on a filesystem error. | 53 | errors=continue Keep going on a filesystem error. |
| 54 | errors=remount-ro Remount the filesystem read-only on an error. | 54 | errors=remount-ro(*) Remount the filesystem read-only on an error. |
| 55 | errors=panic Panic and halt the machine if an error occurs. | 55 | errors=panic Panic and halt the machine if an error occurs. |
| 56 | cp=n Specify the checkpoint-number of the snapshot to be | 56 | cp=n Specify the checkpoint-number of the snapshot to be |
| 57 | mounted. Checkpoints and snapshots are listed by lscp | 57 | mounted. Checkpoints and snapshots are listed by lscp |
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]); |
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 640702e97457..8c2c6116e788 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h | |||
| @@ -199,16 +199,15 @@ struct nilfs_super_block { | |||
| 199 | __le32 s_creator_os; /* OS */ | 199 | __le32 s_creator_os; /* OS */ |
| 200 | __le16 s_def_resuid; /* Default uid for reserved blocks */ | 200 | __le16 s_def_resuid; /* Default uid for reserved blocks */ |
| 201 | __le16 s_def_resgid; /* Default gid for reserved blocks */ | 201 | __le16 s_def_resgid; /* Default gid for reserved blocks */ |
| 202 | __le32 s_first_ino; /* First non-reserved inode */ | 202 | __le32 s_first_ino; /* First non-reserved inode */ |
| 203 | 203 | ||
| 204 | __le16 s_inode_size; /* Size of an inode */ | 204 | __le16 s_inode_size; /* Size of an inode */ |
| 205 | __le16 s_dat_entry_size; /* Size of a dat entry */ | 205 | __le16 s_dat_entry_size; /* Size of a dat entry */ |
| 206 | __le16 s_checkpoint_size; /* Size of a checkpoint */ | 206 | __le16 s_checkpoint_size; /* Size of a checkpoint */ |
| 207 | __le16 s_segment_usage_size; /* Size of a segment usage */ | 207 | __le16 s_segment_usage_size; /* Size of a segment usage */ |
| 208 | 208 | ||
| 209 | __u8 s_uuid[16]; /* 128-bit uuid for volume */ | 209 | __u8 s_uuid[16]; /* 128-bit uuid for volume */ |
| 210 | char s_volume_name[16]; /* volume name */ | 210 | char s_volume_name[80]; /* volume name */ |
| 211 | char s_last_mounted[64]; /* directory where last mounted */ | ||
| 212 | 211 | ||
| 213 | __le32 s_c_interval; /* Commit interval of segment */ | 212 | __le32 s_c_interval; /* Commit interval of segment */ |
| 214 | __le32 s_c_block_max; /* Threshold of data amount for | 213 | __le32 s_c_block_max; /* Threshold of data amount for |
| @@ -377,6 +376,7 @@ union nilfs_binfo { | |||
| 377 | * @ss_nfinfo: number of finfo structures | 376 | * @ss_nfinfo: number of finfo structures |
| 378 | * @ss_sumbytes: total size of segment summary in bytes | 377 | * @ss_sumbytes: total size of segment summary in bytes |
| 379 | * @ss_pad: padding | 378 | * @ss_pad: padding |
| 379 | * @ss_cno: checkpoint number | ||
| 380 | */ | 380 | */ |
| 381 | struct nilfs_segment_summary { | 381 | struct nilfs_segment_summary { |
| 382 | __le32 ss_datasum; | 382 | __le32 ss_datasum; |
| @@ -391,6 +391,7 @@ struct nilfs_segment_summary { | |||
| 391 | __le32 ss_nfinfo; | 391 | __le32 ss_nfinfo; |
| 392 | __le32 ss_sumbytes; | 392 | __le32 ss_sumbytes; |
| 393 | __le32 ss_pad; | 393 | __le32 ss_pad; |
| 394 | __le64 ss_cno; | ||
| 394 | /* array of finfo structures */ | 395 | /* array of finfo structures */ |
| 395 | }; | 396 | }; |
| 396 | 397 | ||
| @@ -437,10 +438,10 @@ struct nilfs_palloc_group_desc { | |||
| 437 | 438 | ||
| 438 | /** | 439 | /** |
| 439 | * struct nilfs_dat_entry - disk address translation entry | 440 | * struct nilfs_dat_entry - disk address translation entry |
| 440 | * @dt_blocknr: block number | 441 | * @de_blocknr: block number |
| 441 | * @dt_start: start checkpoint number | 442 | * @de_start: start checkpoint number |
| 442 | * @dt_end: end checkpoint number | 443 | * @de_end: end checkpoint number |
| 443 | * @dt_rsv: reserved for future use | 444 | * @de_rsv: reserved for future use |
| 444 | */ | 445 | */ |
| 445 | struct nilfs_dat_entry { | 446 | struct nilfs_dat_entry { |
| 446 | __le64 de_blocknr; | 447 | __le64 de_blocknr; |
