diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 17:34:33 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 17:34:33 -0400 |
| commit | af8cb8aa38296ecc43aca7fae9e574db7b8ae0c4 (patch) | |
| tree | 636090652a055bff0930ad713e315ff185282330 | |
| parent | 6cdb5930a6fa0e35b236f4aa0e056001fe1384b4 (diff) | |
| parent | 41f4db0f48c72db3a93cc1a0b18368d9a9aca700 (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: (21 commits)
fs/Kconfig: move nilfs2 outside misc filesystems
nilfs2: convert nilfs_bmap_lookup to an inline function
nilfs2: allow btree code to directly call dat operations
nilfs2: add update functions of virtual block address to dat
nilfs2: remove individual gfp constants for each metadata file
nilfs2: stop zero-fill of btree path just before free it
nilfs2: remove unused btree argument from btree functions
nilfs2: remove nilfs_dat_abort_start and nilfs_dat_abort_free
nilfs2: shorten freeze period due to GC in write operation v3
nilfs2: add more check routines in mount process
nilfs2: An unassigned variable is assigned to a never used structure member
nilfs2: use GFP_NOIO for bio_alloc instead of GFP_NOWAIT
nilfs2: stop using periodic write_super callback
nilfs2: clean up nilfs_write_super
nilfs2: fix disorder of nilfs_write_super in nilfs_sync_fs
nilfs2: remove redundant super block commit
nilfs2: implement nilfs_show_options to display mount options in /proc/mounts
nilfs2: always lookup disk block address before reading metadata block
nilfs2: use semaphore to protect pointer to a writable FS-instance
nilfs2: fix format string compile warning (ino_t)
...
| -rw-r--r-- | fs/Kconfig | 2 | ||||
| -rw-r--r-- | fs/nilfs2/Kconfig | 2 | ||||
| -rw-r--r-- | fs/nilfs2/bmap.c | 151 | ||||
| -rw-r--r-- | fs/nilfs2/bmap.h | 76 | ||||
| -rw-r--r-- | fs/nilfs2/btree.c | 625 | ||||
| -rw-r--r-- | fs/nilfs2/cpfile.c | 11 | ||||
| -rw-r--r-- | fs/nilfs2/cpfile.h | 2 | ||||
| -rw-r--r-- | fs/nilfs2/dat.c | 42 | ||||
| -rw-r--r-- | fs/nilfs2/dat.h | 8 | ||||
| -rw-r--r-- | fs/nilfs2/direct.c | 161 | ||||
| -rw-r--r-- | fs/nilfs2/ifile.h | 1 | ||||
| -rw-r--r-- | fs/nilfs2/inode.c | 3 | ||||
| -rw-r--r-- | fs/nilfs2/ioctl.c | 26 | ||||
| -rw-r--r-- | fs/nilfs2/mdt.c | 40 | ||||
| -rw-r--r-- | fs/nilfs2/mdt.h | 3 | ||||
| -rw-r--r-- | fs/nilfs2/recovery.c | 3 | ||||
| -rw-r--r-- | fs/nilfs2/segbuf.c | 4 | ||||
| -rw-r--r-- | fs/nilfs2/segment.c | 7 | ||||
| -rw-r--r-- | fs/nilfs2/sufile.h | 1 | ||||
| -rw-r--r-- | fs/nilfs2/super.c | 100 | ||||
| -rw-r--r-- | fs/nilfs2/the_nilfs.c | 15 | ||||
| -rw-r--r-- | fs/nilfs2/the_nilfs.h | 43 |
22 files changed, 567 insertions, 759 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 0e7da7bb5d93..455aa207e67e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -43,6 +43,7 @@ source "fs/xfs/Kconfig" | |||
| 43 | source "fs/gfs2/Kconfig" | 43 | source "fs/gfs2/Kconfig" |
| 44 | source "fs/ocfs2/Kconfig" | 44 | source "fs/ocfs2/Kconfig" |
| 45 | source "fs/btrfs/Kconfig" | 45 | source "fs/btrfs/Kconfig" |
| 46 | source "fs/nilfs2/Kconfig" | ||
| 46 | 47 | ||
| 47 | endif # BLOCK | 48 | endif # BLOCK |
| 48 | 49 | ||
| @@ -186,7 +187,6 @@ source "fs/romfs/Kconfig" | |||
| 186 | source "fs/sysv/Kconfig" | 187 | source "fs/sysv/Kconfig" |
| 187 | source "fs/ufs/Kconfig" | 188 | source "fs/ufs/Kconfig" |
| 188 | source "fs/exofs/Kconfig" | 189 | source "fs/exofs/Kconfig" |
| 189 | source "fs/nilfs2/Kconfig" | ||
| 190 | 190 | ||
| 191 | endif # MISC_FILESYSTEMS | 191 | endif # MISC_FILESYSTEMS |
| 192 | 192 | ||
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig index 72da095d4009..251da07b2a1d 100644 --- a/fs/nilfs2/Kconfig +++ b/fs/nilfs2/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config NILFS2_FS | 1 | config NILFS2_FS |
| 2 | tristate "NILFS2 file system support (EXPERIMENTAL)" | 2 | tristate "NILFS2 file system support (EXPERIMENTAL)" |
| 3 | depends on BLOCK && EXPERIMENTAL | 3 | depends on EXPERIMENTAL |
| 4 | select CRC32 | 4 | select CRC32 |
| 5 | help | 5 | help |
| 6 | NILFS2 is a log-structured file system (LFS) supporting continuous | 6 | NILFS2 is a log-structured file system (LFS) supporting continuous |
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 99d58a028b94..08834df6ec68 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
| @@ -36,6 +36,26 @@ struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap) | |||
| 36 | return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode)); | 36 | return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode)); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | /** | ||
| 40 | * nilfs_bmap_lookup_at_level - find a data block or node block | ||
| 41 | * @bmap: bmap | ||
| 42 | * @key: key | ||
| 43 | * @level: level | ||
| 44 | * @ptrp: place to store the value associated to @key | ||
| 45 | * | ||
| 46 | * Description: nilfs_bmap_lookup_at_level() finds a record whose key | ||
| 47 | * matches @key in the block at @level of the bmap. | ||
| 48 | * | ||
| 49 | * Return Value: On success, 0 is returned and the record associated with @key | ||
| 50 | * is stored in the place pointed by @ptrp. On error, one of the following | ||
| 51 | * negative error codes is returned. | ||
| 52 | * | ||
| 53 | * %-EIO - I/O error. | ||
| 54 | * | ||
| 55 | * %-ENOMEM - Insufficient amount of memory available. | ||
| 56 | * | ||
| 57 | * %-ENOENT - A record associated with @key does not exist. | ||
| 58 | */ | ||
| 39 | int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level, | 59 | int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level, |
| 40 | __u64 *ptrp) | 60 | __u64 *ptrp) |
| 41 | { | 61 | { |
| @@ -69,39 +89,6 @@ int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp, | |||
| 69 | return ret; | 89 | return ret; |
| 70 | } | 90 | } |
| 71 | 91 | ||
| 72 | /** | ||
| 73 | * nilfs_bmap_lookup - find a record | ||
| 74 | * @bmap: bmap | ||
| 75 | * @key: key | ||
| 76 | * @recp: pointer to record | ||
| 77 | * | ||
| 78 | * Description: nilfs_bmap_lookup() finds a record whose key matches @key in | ||
| 79 | * @bmap. | ||
| 80 | * | ||
| 81 | * Return Value: On success, 0 is returned and the record associated with @key | ||
| 82 | * is stored in the place pointed by @recp. On error, one of the following | ||
| 83 | * negative error codes is returned. | ||
| 84 | * | ||
| 85 | * %-EIO - I/O error. | ||
| 86 | * | ||
| 87 | * %-ENOMEM - Insufficient amount of memory available. | ||
| 88 | * | ||
| 89 | * %-ENOENT - A record associated with @key does not exist. | ||
| 90 | */ | ||
| 91 | int nilfs_bmap_lookup(struct nilfs_bmap *bmap, | ||
| 92 | unsigned long key, | ||
| 93 | unsigned long *recp) | ||
| 94 | { | ||
| 95 | __u64 ptr; | ||
| 96 | int ret; | ||
| 97 | |||
| 98 | /* XXX: use macro for level 1 */ | ||
| 99 | ret = nilfs_bmap_lookup_at_level(bmap, key, 1, &ptr); | ||
| 100 | if (recp != NULL) | ||
| 101 | *recp = ptr; | ||
| 102 | return ret; | ||
| 103 | } | ||
| 104 | |||
| 105 | static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | 92 | static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) |
| 106 | { | 93 | { |
| 107 | __u64 keys[NILFS_BMAP_SMALL_HIGH + 1]; | 94 | __u64 keys[NILFS_BMAP_SMALL_HIGH + 1]; |
| @@ -469,104 +456,6 @@ __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap) | |||
| 469 | (entries_per_group / NILFS_BMAP_GROUP_DIV); | 456 | (entries_per_group / NILFS_BMAP_GROUP_DIV); |
| 470 | } | 457 | } |
| 471 | 458 | ||
| 472 | int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *bmap, | ||
| 473 | union nilfs_bmap_ptr_req *req) | ||
| 474 | { | ||
| 475 | return nilfs_dat_prepare_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req); | ||
| 476 | } | ||
| 477 | |||
| 478 | void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *bmap, | ||
| 479 | union nilfs_bmap_ptr_req *req) | ||
| 480 | { | ||
| 481 | nilfs_dat_commit_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req); | ||
| 482 | } | ||
| 483 | |||
| 484 | void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *bmap, | ||
| 485 | union nilfs_bmap_ptr_req *req) | ||
| 486 | { | ||
| 487 | nilfs_dat_abort_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req); | ||
| 488 | } | ||
| 489 | |||
| 490 | int nilfs_bmap_start_v(struct nilfs_bmap *bmap, union nilfs_bmap_ptr_req *req, | ||
| 491 | sector_t blocknr) | ||
| 492 | { | ||
| 493 | struct inode *dat = nilfs_bmap_get_dat(bmap); | ||
| 494 | int ret; | ||
| 495 | |||
| 496 | ret = nilfs_dat_prepare_start(dat, &req->bpr_req); | ||
| 497 | if (likely(!ret)) | ||
| 498 | nilfs_dat_commit_start(dat, &req->bpr_req, blocknr); | ||
| 499 | return ret; | ||
| 500 | } | ||
| 501 | |||
| 502 | int nilfs_bmap_prepare_end_v(struct nilfs_bmap *bmap, | ||
| 503 | union nilfs_bmap_ptr_req *req) | ||
| 504 | { | ||
| 505 | return nilfs_dat_prepare_end(nilfs_bmap_get_dat(bmap), &req->bpr_req); | ||
| 506 | } | ||
| 507 | |||
| 508 | void nilfs_bmap_commit_end_v(struct nilfs_bmap *bmap, | ||
| 509 | union nilfs_bmap_ptr_req *req) | ||
| 510 | { | ||
| 511 | nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req, | ||
| 512 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); | ||
| 513 | } | ||
| 514 | |||
| 515 | void nilfs_bmap_abort_end_v(struct nilfs_bmap *bmap, | ||
| 516 | union nilfs_bmap_ptr_req *req) | ||
| 517 | { | ||
| 518 | nilfs_dat_abort_end(nilfs_bmap_get_dat(bmap), &req->bpr_req); | ||
| 519 | } | ||
| 520 | |||
| 521 | int nilfs_bmap_move_v(const struct nilfs_bmap *bmap, __u64 vblocknr, | ||
| 522 | sector_t blocknr) | ||
| 523 | { | ||
| 524 | return nilfs_dat_move(nilfs_bmap_get_dat(bmap), vblocknr, blocknr); | ||
| 525 | } | ||
| 526 | |||
| 527 | int nilfs_bmap_mark_dirty(const struct nilfs_bmap *bmap, __u64 vblocknr) | ||
| 528 | { | ||
| 529 | return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), vblocknr); | ||
| 530 | } | ||
| 531 | |||
| 532 | int nilfs_bmap_prepare_update_v(struct nilfs_bmap *bmap, | ||
| 533 | union nilfs_bmap_ptr_req *oldreq, | ||
| 534 | union nilfs_bmap_ptr_req *newreq) | ||
| 535 | { | ||
| 536 | struct inode *dat = nilfs_bmap_get_dat(bmap); | ||
| 537 | int ret; | ||
| 538 | |||
| 539 | ret = nilfs_dat_prepare_end(dat, &oldreq->bpr_req); | ||
| 540 | if (ret < 0) | ||
| 541 | return ret; | ||
| 542 | ret = nilfs_dat_prepare_alloc(dat, &newreq->bpr_req); | ||
| 543 | if (ret < 0) | ||
| 544 | nilfs_dat_abort_end(dat, &oldreq->bpr_req); | ||
| 545 | |||
| 546 | return ret; | ||
| 547 | } | ||
| 548 | |||
| 549 | void nilfs_bmap_commit_update_v(struct nilfs_bmap *bmap, | ||
| 550 | union nilfs_bmap_ptr_req *oldreq, | ||
| 551 | union nilfs_bmap_ptr_req *newreq) | ||
| 552 | { | ||
| 553 | struct inode *dat = nilfs_bmap_get_dat(bmap); | ||
| 554 | |||
| 555 | nilfs_dat_commit_end(dat, &oldreq->bpr_req, | ||
| 556 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); | ||
| 557 | nilfs_dat_commit_alloc(dat, &newreq->bpr_req); | ||
| 558 | } | ||
| 559 | |||
| 560 | void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap, | ||
| 561 | union nilfs_bmap_ptr_req *oldreq, | ||
| 562 | union nilfs_bmap_ptr_req *newreq) | ||
| 563 | { | ||
| 564 | struct inode *dat = nilfs_bmap_get_dat(bmap); | ||
| 565 | |||
| 566 | nilfs_dat_abort_end(dat, &oldreq->bpr_req); | ||
| 567 | nilfs_dat_abort_alloc(dat, &newreq->bpr_req); | ||
| 568 | } | ||
| 569 | |||
| 570 | static struct lock_class_key nilfs_bmap_dat_lock_key; | 459 | static struct lock_class_key nilfs_bmap_dat_lock_key; |
| 571 | static struct lock_class_key nilfs_bmap_mdt_lock_key; | 460 | static struct lock_class_key nilfs_bmap_mdt_lock_key; |
| 572 | 461 | ||
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index b2890cdcef12..9980d7dbab91 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/buffer_head.h> | 28 | #include <linux/buffer_head.h> |
| 29 | #include <linux/nilfs2_fs.h> | 29 | #include <linux/nilfs2_fs.h> |
| 30 | #include "alloc.h" | 30 | #include "alloc.h" |
| 31 | #include "dat.h" | ||
| 31 | 32 | ||
| 32 | #define NILFS_BMAP_INVALID_PTR 0 | 33 | #define NILFS_BMAP_INVALID_PTR 0 |
| 33 | 34 | ||
| @@ -141,7 +142,6 @@ struct nilfs_bmap { | |||
| 141 | int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); | 142 | int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); |
| 142 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); | 143 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); |
| 143 | void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); | 144 | void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); |
| 144 | int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *); | ||
| 145 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); | 145 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); |
| 146 | int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); | 146 | int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); |
| 147 | int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); | 147 | int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); |
| @@ -160,90 +160,76 @@ void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); | |||
| 160 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); | 160 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); |
| 161 | 161 | ||
| 162 | 162 | ||
| 163 | static inline int nilfs_bmap_lookup(struct nilfs_bmap *bmap, __u64 key, | ||
| 164 | __u64 *ptr) | ||
| 165 | { | ||
| 166 | return nilfs_bmap_lookup_at_level(bmap, key, 1, ptr); | ||
| 167 | } | ||
| 168 | |||
| 163 | /* | 169 | /* |
| 164 | * Internal use only | 170 | * Internal use only |
| 165 | */ | 171 | */ |
| 166 | struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *); | 172 | struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *); |
| 167 | int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *, | ||
| 168 | union nilfs_bmap_ptr_req *); | ||
| 169 | void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *, | ||
| 170 | union nilfs_bmap_ptr_req *); | ||
| 171 | void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *, | ||
| 172 | union nilfs_bmap_ptr_req *); | ||
| 173 | 173 | ||
| 174 | static inline int nilfs_bmap_prepare_alloc_ptr(struct nilfs_bmap *bmap, | 174 | static inline int nilfs_bmap_prepare_alloc_ptr(struct nilfs_bmap *bmap, |
| 175 | union nilfs_bmap_ptr_req *req) | 175 | union nilfs_bmap_ptr_req *req, |
| 176 | struct inode *dat) | ||
| 176 | { | 177 | { |
| 177 | if (NILFS_BMAP_USE_VBN(bmap)) | 178 | if (dat) |
| 178 | return nilfs_bmap_prepare_alloc_v(bmap, req); | 179 | return nilfs_dat_prepare_alloc(dat, &req->bpr_req); |
| 179 | /* ignore target ptr */ | 180 | /* ignore target ptr */ |
| 180 | req->bpr_ptr = bmap->b_last_allocated_ptr++; | 181 | req->bpr_ptr = bmap->b_last_allocated_ptr++; |
| 181 | return 0; | 182 | return 0; |
| 182 | } | 183 | } |
| 183 | 184 | ||
| 184 | static inline void nilfs_bmap_commit_alloc_ptr(struct nilfs_bmap *bmap, | 185 | static inline void nilfs_bmap_commit_alloc_ptr(struct nilfs_bmap *bmap, |
| 185 | union nilfs_bmap_ptr_req *req) | 186 | union nilfs_bmap_ptr_req *req, |
| 187 | struct inode *dat) | ||
| 186 | { | 188 | { |
| 187 | if (NILFS_BMAP_USE_VBN(bmap)) | 189 | if (dat) |
| 188 | nilfs_bmap_commit_alloc_v(bmap, req); | 190 | nilfs_dat_commit_alloc(dat, &req->bpr_req); |
| 189 | } | 191 | } |
| 190 | 192 | ||
| 191 | static inline void nilfs_bmap_abort_alloc_ptr(struct nilfs_bmap *bmap, | 193 | static inline void nilfs_bmap_abort_alloc_ptr(struct nilfs_bmap *bmap, |
| 192 | union nilfs_bmap_ptr_req *req) | 194 | union nilfs_bmap_ptr_req *req, |
| 195 | struct inode *dat) | ||
| 193 | { | 196 | { |
| 194 | if (NILFS_BMAP_USE_VBN(bmap)) | 197 | if (dat) |
| 195 | nilfs_bmap_abort_alloc_v(bmap, req); | 198 | nilfs_dat_abort_alloc(dat, &req->bpr_req); |
| 196 | else | 199 | else |
| 197 | bmap->b_last_allocated_ptr--; | 200 | bmap->b_last_allocated_ptr--; |
| 198 | } | 201 | } |
| 199 | 202 | ||
| 200 | int nilfs_bmap_prepare_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *); | ||
| 201 | void nilfs_bmap_commit_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *); | ||
| 202 | void nilfs_bmap_abort_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *); | ||
| 203 | |||
| 204 | static inline int nilfs_bmap_prepare_end_ptr(struct nilfs_bmap *bmap, | 203 | static inline int nilfs_bmap_prepare_end_ptr(struct nilfs_bmap *bmap, |
| 205 | union nilfs_bmap_ptr_req *req) | 204 | union nilfs_bmap_ptr_req *req, |
| 205 | struct inode *dat) | ||
| 206 | { | 206 | { |
| 207 | return NILFS_BMAP_USE_VBN(bmap) ? | 207 | return dat ? nilfs_dat_prepare_end(dat, &req->bpr_req) : 0; |
| 208 | nilfs_bmap_prepare_end_v(bmap, req) : 0; | ||
| 209 | } | 208 | } |
| 210 | 209 | ||
| 211 | static inline void nilfs_bmap_commit_end_ptr(struct nilfs_bmap *bmap, | 210 | static inline void nilfs_bmap_commit_end_ptr(struct nilfs_bmap *bmap, |
| 212 | union nilfs_bmap_ptr_req *req) | 211 | union nilfs_bmap_ptr_req *req, |
| 212 | struct inode *dat) | ||
| 213 | { | 213 | { |
| 214 | if (NILFS_BMAP_USE_VBN(bmap)) | 214 | if (dat) |
| 215 | nilfs_bmap_commit_end_v(bmap, req); | 215 | nilfs_dat_commit_end(dat, &req->bpr_req, |
| 216 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); | ||
| 216 | } | 217 | } |
| 217 | 218 | ||
| 218 | static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap, | 219 | static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap, |
| 219 | union nilfs_bmap_ptr_req *req) | 220 | union nilfs_bmap_ptr_req *req, |
| 221 | struct inode *dat) | ||
| 220 | { | 222 | { |
| 221 | if (NILFS_BMAP_USE_VBN(bmap)) | 223 | if (dat) |
| 222 | nilfs_bmap_abort_end_v(bmap, req); | 224 | nilfs_dat_abort_end(dat, &req->bpr_req); |
| 223 | } | 225 | } |
| 224 | 226 | ||
| 225 | int nilfs_bmap_start_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *, | ||
| 226 | sector_t); | ||
| 227 | int nilfs_bmap_move_v(const struct nilfs_bmap *, __u64, sector_t); | ||
| 228 | int nilfs_bmap_mark_dirty(const struct nilfs_bmap *, __u64); | ||
| 229 | |||
| 230 | |||
| 231 | __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, | 227 | __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, |
| 232 | const struct buffer_head *); | 228 | const struct buffer_head *); |
| 233 | 229 | ||
| 234 | __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64); | 230 | __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64); |
| 235 | __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *); | 231 | __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *); |
| 236 | 232 | ||
| 237 | int nilfs_bmap_prepare_update_v(struct nilfs_bmap *, | ||
| 238 | union nilfs_bmap_ptr_req *, | ||
| 239 | union nilfs_bmap_ptr_req *); | ||
| 240 | void nilfs_bmap_commit_update_v(struct nilfs_bmap *, | ||
| 241 | union nilfs_bmap_ptr_req *, | ||
| 242 | union nilfs_bmap_ptr_req *); | ||
| 243 | void nilfs_bmap_abort_update_v(struct nilfs_bmap *, | ||
| 244 | union nilfs_bmap_ptr_req *, | ||
| 245 | union nilfs_bmap_ptr_req *); | ||
| 246 | |||
| 247 | void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int); | 233 | void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int); |
| 248 | void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int); | 234 | void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int); |
| 249 | 235 | ||
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index aa412724b64e..e25b507a474f 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
| @@ -71,21 +71,17 @@ void nilfs_btree_path_cache_destroy(void) | |||
| 71 | kmem_cache_destroy(nilfs_btree_path_cache); | 71 | kmem_cache_destroy(nilfs_btree_path_cache); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static inline struct nilfs_btree_path * | 74 | static inline struct nilfs_btree_path *nilfs_btree_alloc_path(void) |
| 75 | nilfs_btree_alloc_path(const struct nilfs_btree *btree) | ||
| 76 | { | 75 | { |
| 77 | return (struct nilfs_btree_path *) | 76 | return kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS); |
| 78 | kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS); | ||
| 79 | } | 77 | } |
| 80 | 78 | ||
| 81 | static inline void nilfs_btree_free_path(const struct nilfs_btree *btree, | 79 | static inline void nilfs_btree_free_path(struct nilfs_btree_path *path) |
| 82 | struct nilfs_btree_path *path) | ||
| 83 | { | 80 | { |
| 84 | kmem_cache_free(nilfs_btree_path_cache, path); | 81 | kmem_cache_free(nilfs_btree_path_cache, path); |
| 85 | } | 82 | } |
| 86 | 83 | ||
| 87 | static void nilfs_btree_init_path(const struct nilfs_btree *btree, | 84 | static void nilfs_btree_init_path(struct nilfs_btree_path *path) |
| 88 | struct nilfs_btree_path *path) | ||
| 89 | { | 85 | { |
| 90 | int level; | 86 | int level; |
| 91 | 87 | ||
| @@ -101,26 +97,13 @@ static void nilfs_btree_init_path(const struct nilfs_btree *btree, | |||
| 101 | } | 97 | } |
| 102 | } | 98 | } |
| 103 | 99 | ||
| 104 | static void nilfs_btree_clear_path(const struct nilfs_btree *btree, | 100 | static void nilfs_btree_release_path(struct nilfs_btree_path *path) |
| 105 | struct nilfs_btree_path *path) | ||
| 106 | { | 101 | { |
| 107 | int level; | 102 | int level; |
| 108 | 103 | ||
| 109 | for (level = NILFS_BTREE_LEVEL_DATA; | 104 | for (level = NILFS_BTREE_LEVEL_DATA; level < NILFS_BTREE_LEVEL_MAX; |
| 110 | level < NILFS_BTREE_LEVEL_MAX; | 105 | level++) |
| 111 | level++) { | 106 | brelse(path[level].bp_bh); |
| 112 | if (path[level].bp_bh != NULL) { | ||
| 113 | brelse(path[level].bp_bh); | ||
| 114 | path[level].bp_bh = NULL; | ||
| 115 | } | ||
| 116 | /* sib_bh is released or deleted by prepare or commit | ||
| 117 | * operations. */ | ||
| 118 | path[level].bp_sib_bh = NULL; | ||
| 119 | path[level].bp_index = 0; | ||
| 120 | path[level].bp_oldreq.bpr_ptr = NILFS_BMAP_INVALID_PTR; | ||
| 121 | path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR; | ||
| 122 | path[level].bp_op = NULL; | ||
| 123 | } | ||
| 124 | } | 107 | } |
| 125 | 108 | ||
| 126 | /* | 109 | /* |
| @@ -148,129 +131,110 @@ static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, | |||
| 148 | } | 131 | } |
| 149 | 132 | ||
| 150 | static inline int | 133 | static inline int |
| 151 | nilfs_btree_node_get_flags(const struct nilfs_btree *btree, | 134 | nilfs_btree_node_get_flags(const struct nilfs_btree_node *node) |
| 152 | const struct nilfs_btree_node *node) | ||
| 153 | { | 135 | { |
| 154 | return node->bn_flags; | 136 | return node->bn_flags; |
| 155 | } | 137 | } |
| 156 | 138 | ||
| 157 | static inline void | 139 | static inline void |
| 158 | nilfs_btree_node_set_flags(struct nilfs_btree *btree, | 140 | nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags) |
| 159 | struct nilfs_btree_node *node, | ||
| 160 | int flags) | ||
| 161 | { | 141 | { |
| 162 | node->bn_flags = flags; | 142 | node->bn_flags = flags; |
| 163 | } | 143 | } |
| 164 | 144 | ||
| 165 | static inline int nilfs_btree_node_root(const struct nilfs_btree *btree, | 145 | static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node) |
| 166 | const struct nilfs_btree_node *node) | ||
| 167 | { | 146 | { |
| 168 | return nilfs_btree_node_get_flags(btree, node) & NILFS_BTREE_NODE_ROOT; | 147 | return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT; |
| 169 | } | 148 | } |
| 170 | 149 | ||
| 171 | static inline int | 150 | static inline int |
| 172 | nilfs_btree_node_get_level(const struct nilfs_btree *btree, | 151 | nilfs_btree_node_get_level(const struct nilfs_btree_node *node) |
| 173 | const struct nilfs_btree_node *node) | ||
| 174 | { | 152 | { |
| 175 | return node->bn_level; | 153 | return node->bn_level; |
| 176 | } | 154 | } |
| 177 | 155 | ||
| 178 | static inline void | 156 | static inline void |
| 179 | nilfs_btree_node_set_level(struct nilfs_btree *btree, | 157 | nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level) |
| 180 | struct nilfs_btree_node *node, | ||
| 181 | int level) | ||
| 182 | { | 158 | { |
| 183 | node->bn_level = level; | 159 | node->bn_level = level; |
| 184 | } | 160 | } |
| 185 | 161 | ||
| 186 | static inline int | 162 | static inline int |
| 187 | nilfs_btree_node_get_nchildren(const struct nilfs_btree *btree, | 163 | nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node) |
| 188 | const struct nilfs_btree_node *node) | ||
| 189 | { | 164 | { |
| 190 | return le16_to_cpu(node->bn_nchildren); | 165 | return le16_to_cpu(node->bn_nchildren); |
| 191 | } | 166 | } |
| 192 | 167 | ||
| 193 | static inline void | 168 | static inline void |
| 194 | nilfs_btree_node_set_nchildren(struct nilfs_btree *btree, | 169 | nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren) |
| 195 | struct nilfs_btree_node *node, | ||
| 196 | int nchildren) | ||
| 197 | { | 170 | { |
| 198 | node->bn_nchildren = cpu_to_le16(nchildren); | 171 | node->bn_nchildren = cpu_to_le16(nchildren); |
| 199 | } | 172 | } |
| 200 | 173 | ||
| 201 | static inline int | 174 | static inline int nilfs_btree_node_size(const struct nilfs_btree *btree) |
| 202 | nilfs_btree_node_size(const struct nilfs_btree *btree) | ||
| 203 | { | 175 | { |
| 204 | return 1 << btree->bt_bmap.b_inode->i_blkbits; | 176 | return 1 << btree->bt_bmap.b_inode->i_blkbits; |
| 205 | } | 177 | } |
| 206 | 178 | ||
| 207 | static inline int | 179 | static inline int |
| 208 | nilfs_btree_node_nchildren_min(const struct nilfs_btree *btree, | 180 | nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node, |
| 209 | const struct nilfs_btree_node *node) | 181 | const struct nilfs_btree *btree) |
| 210 | { | 182 | { |
| 211 | return nilfs_btree_node_root(btree, node) ? | 183 | return nilfs_btree_node_root(node) ? |
| 212 | NILFS_BTREE_ROOT_NCHILDREN_MIN : | 184 | NILFS_BTREE_ROOT_NCHILDREN_MIN : |
| 213 | NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); | 185 | NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); |
| 214 | } | 186 | } |
| 215 | 187 | ||
| 216 | static inline int | 188 | static inline int |
| 217 | nilfs_btree_node_nchildren_max(const struct nilfs_btree *btree, | 189 | nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node, |
| 218 | const struct nilfs_btree_node *node) | 190 | const struct nilfs_btree *btree) |
| 219 | { | 191 | { |
| 220 | return nilfs_btree_node_root(btree, node) ? | 192 | return nilfs_btree_node_root(node) ? |
| 221 | NILFS_BTREE_ROOT_NCHILDREN_MAX : | 193 | NILFS_BTREE_ROOT_NCHILDREN_MAX : |
| 222 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree)); | 194 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree)); |
| 223 | } | 195 | } |
| 224 | 196 | ||
| 225 | static inline __le64 * | 197 | static inline __le64 * |
| 226 | nilfs_btree_node_dkeys(const struct nilfs_btree *btree, | 198 | nilfs_btree_node_dkeys(const struct nilfs_btree_node *node) |
| 227 | const struct nilfs_btree_node *node) | ||
| 228 | { | 199 | { |
| 229 | return (__le64 *)((char *)(node + 1) + | 200 | return (__le64 *)((char *)(node + 1) + |
| 230 | (nilfs_btree_node_root(btree, node) ? | 201 | (nilfs_btree_node_root(node) ? |
| 231 | 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); | 202 | 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); |
| 232 | } | 203 | } |
| 233 | 204 | ||
| 234 | static inline __le64 * | 205 | static inline __le64 * |
| 235 | nilfs_btree_node_dptrs(const struct nilfs_btree *btree, | 206 | nilfs_btree_node_dptrs(const struct nilfs_btree_node *node, |
| 236 | const struct nilfs_btree_node *node) | 207 | const struct nilfs_btree *btree) |
| 237 | { | 208 | { |
| 238 | return (__le64 *)(nilfs_btree_node_dkeys(btree, node) + | 209 | return (__le64 *)(nilfs_btree_node_dkeys(node) + |
| 239 | nilfs_btree_node_nchildren_max(btree, node)); | 210 | nilfs_btree_node_nchildren_max(node, btree)); |
| 240 | } | 211 | } |
| 241 | 212 | ||
| 242 | static inline __u64 | 213 | static inline __u64 |
| 243 | nilfs_btree_node_get_key(const struct nilfs_btree *btree, | 214 | nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index) |
| 244 | const struct nilfs_btree_node *node, int index) | ||
| 245 | { | 215 | { |
| 246 | return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(btree, node) + | 216 | return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index)); |
| 247 | index)); | ||
| 248 | } | 217 | } |
| 249 | 218 | ||
| 250 | static inline void | 219 | static inline void |
| 251 | nilfs_btree_node_set_key(struct nilfs_btree *btree, | 220 | nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key) |
| 252 | struct nilfs_btree_node *node, int index, __u64 key) | ||
| 253 | { | 221 | { |
| 254 | *(nilfs_btree_node_dkeys(btree, node) + index) = | 222 | *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key); |
| 255 | nilfs_bmap_key_to_dkey(key); | ||
| 256 | } | 223 | } |
| 257 | 224 | ||
| 258 | static inline __u64 | 225 | static inline __u64 |
| 259 | nilfs_btree_node_get_ptr(const struct nilfs_btree *btree, | 226 | nilfs_btree_node_get_ptr(const struct nilfs_btree *btree, |
| 260 | const struct nilfs_btree_node *node, | 227 | const struct nilfs_btree_node *node, int index) |
| 261 | int index) | ||
| 262 | { | 228 | { |
| 263 | return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(btree, node) + | 229 | return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) + |
| 264 | index)); | 230 | index)); |
| 265 | } | 231 | } |
| 266 | 232 | ||
| 267 | static inline void | 233 | static inline void |
| 268 | nilfs_btree_node_set_ptr(struct nilfs_btree *btree, | 234 | nilfs_btree_node_set_ptr(struct nilfs_btree *btree, |
| 269 | struct nilfs_btree_node *node, | 235 | struct nilfs_btree_node *node, int index, __u64 ptr) |
| 270 | int index, | ||
| 271 | __u64 ptr) | ||
| 272 | { | 236 | { |
| 273 | *(nilfs_btree_node_dptrs(btree, node) + index) = | 237 | *(nilfs_btree_node_dptrs(node, btree) + index) = |
| 274 | nilfs_bmap_ptr_to_dptr(ptr); | 238 | nilfs_bmap_ptr_to_dptr(ptr); |
| 275 | } | 239 | } |
| 276 | 240 | ||
| @@ -283,12 +247,12 @@ static void nilfs_btree_node_init(struct nilfs_btree *btree, | |||
| 283 | __le64 *dptrs; | 247 | __le64 *dptrs; |
| 284 | int i; | 248 | int i; |
| 285 | 249 | ||
| 286 | nilfs_btree_node_set_flags(btree, node, flags); | 250 | nilfs_btree_node_set_flags(node, flags); |
| 287 | nilfs_btree_node_set_level(btree, node, level); | 251 | nilfs_btree_node_set_level(node, level); |
| 288 | nilfs_btree_node_set_nchildren(btree, node, nchildren); | 252 | nilfs_btree_node_set_nchildren(node, nchildren); |
| 289 | 253 | ||
| 290 | dkeys = nilfs_btree_node_dkeys(btree, node); | 254 | dkeys = nilfs_btree_node_dkeys(node); |
| 291 | dptrs = nilfs_btree_node_dptrs(btree, node); | 255 | dptrs = nilfs_btree_node_dptrs(node, btree); |
| 292 | for (i = 0; i < nchildren; i++) { | 256 | for (i = 0; i < nchildren; i++) { |
| 293 | dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]); | 257 | dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]); |
| 294 | dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]); | 258 | dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]); |
| @@ -305,13 +269,13 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree, | |||
| 305 | __le64 *ldptrs, *rdptrs; | 269 | __le64 *ldptrs, *rdptrs; |
| 306 | int lnchildren, rnchildren; | 270 | int lnchildren, rnchildren; |
| 307 | 271 | ||
| 308 | ldkeys = nilfs_btree_node_dkeys(btree, left); | 272 | ldkeys = nilfs_btree_node_dkeys(left); |
| 309 | ldptrs = nilfs_btree_node_dptrs(btree, left); | 273 | ldptrs = nilfs_btree_node_dptrs(left, btree); |
| 310 | lnchildren = nilfs_btree_node_get_nchildren(btree, left); | 274 | lnchildren = nilfs_btree_node_get_nchildren(left); |
| 311 | 275 | ||
| 312 | rdkeys = nilfs_btree_node_dkeys(btree, right); | 276 | rdkeys = nilfs_btree_node_dkeys(right); |
| 313 | rdptrs = nilfs_btree_node_dptrs(btree, right); | 277 | rdptrs = nilfs_btree_node_dptrs(right, btree); |
| 314 | rnchildren = nilfs_btree_node_get_nchildren(btree, right); | 278 | rnchildren = nilfs_btree_node_get_nchildren(right); |
| 315 | 279 | ||
| 316 | memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys)); | 280 | memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys)); |
| 317 | memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs)); | 281 | memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs)); |
| @@ -320,8 +284,8 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree, | |||
| 320 | 284 | ||
| 321 | lnchildren += n; | 285 | lnchildren += n; |
| 322 | rnchildren -= n; | 286 | rnchildren -= n; |
| 323 | nilfs_btree_node_set_nchildren(btree, left, lnchildren); | 287 | nilfs_btree_node_set_nchildren(left, lnchildren); |
| 324 | nilfs_btree_node_set_nchildren(btree, right, rnchildren); | 288 | nilfs_btree_node_set_nchildren(right, rnchildren); |
| 325 | } | 289 | } |
| 326 | 290 | ||
| 327 | /* Assume that the buffer heads corresponding to left and right are locked. */ | 291 | /* Assume that the buffer heads corresponding to left and right are locked. */ |
| @@ -334,13 +298,13 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree, | |||
| 334 | __le64 *ldptrs, *rdptrs; | 298 | __le64 *ldptrs, *rdptrs; |
| 335 | int lnchildren, rnchildren; | 299 | int lnchildren, rnchildren; |
| 336 | 300 | ||
| 337 | ldkeys = nilfs_btree_node_dkeys(btree, left); | 301 | ldkeys = nilfs_btree_node_dkeys(left); |
| 338 | ldptrs = nilfs_btree_node_dptrs(btree, left); | 302 | ldptrs = nilfs_btree_node_dptrs(left, btree); |
| 339 | lnchildren = nilfs_btree_node_get_nchildren(btree, left); | 303 | lnchildren = nilfs_btree_node_get_nchildren(left); |
| 340 | 304 | ||
| 341 | rdkeys = nilfs_btree_node_dkeys(btree, right); | 305 | rdkeys = nilfs_btree_node_dkeys(right); |
| 342 | rdptrs = nilfs_btree_node_dptrs(btree, right); | 306 | rdptrs = nilfs_btree_node_dptrs(right, btree); |
| 343 | rnchildren = nilfs_btree_node_get_nchildren(btree, right); | 307 | rnchildren = nilfs_btree_node_get_nchildren(right); |
| 344 | 308 | ||
| 345 | memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys)); | 309 | memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys)); |
| 346 | memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs)); | 310 | memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs)); |
| @@ -349,8 +313,8 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree, | |||
| 349 | 313 | ||
| 350 | lnchildren -= n; | 314 | lnchildren -= n; |
| 351 | rnchildren += n; | 315 | rnchildren += n; |
| 352 | nilfs_btree_node_set_nchildren(btree, left, lnchildren); | 316 | nilfs_btree_node_set_nchildren(left, lnchildren); |
| 353 | nilfs_btree_node_set_nchildren(btree, right, rnchildren); | 317 | nilfs_btree_node_set_nchildren(right, rnchildren); |
| 354 | } | 318 | } |
| 355 | 319 | ||
| 356 | /* Assume that the buffer head corresponding to node is locked. */ | 320 | /* Assume that the buffer head corresponding to node is locked. */ |
| @@ -362,9 +326,9 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree, | |||
| 362 | __le64 *dptrs; | 326 | __le64 *dptrs; |
| 363 | int nchildren; | 327 | int nchildren; |
| 364 | 328 | ||
| 365 | dkeys = nilfs_btree_node_dkeys(btree, node); | 329 | dkeys = nilfs_btree_node_dkeys(node); |
| 366 | dptrs = nilfs_btree_node_dptrs(btree, node); | 330 | dptrs = nilfs_btree_node_dptrs(node, btree); |
| 367 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 331 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 368 | if (index < nchildren) { | 332 | if (index < nchildren) { |
| 369 | memmove(dkeys + index + 1, dkeys + index, | 333 | memmove(dkeys + index + 1, dkeys + index, |
| 370 | (nchildren - index) * sizeof(*dkeys)); | 334 | (nchildren - index) * sizeof(*dkeys)); |
| @@ -374,7 +338,7 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree, | |||
| 374 | dkeys[index] = nilfs_bmap_key_to_dkey(key); | 338 | dkeys[index] = nilfs_bmap_key_to_dkey(key); |
| 375 | dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr); | 339 | dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr); |
| 376 | nchildren++; | 340 | nchildren++; |
| 377 | nilfs_btree_node_set_nchildren(btree, node, nchildren); | 341 | nilfs_btree_node_set_nchildren(node, nchildren); |
| 378 | } | 342 | } |
| 379 | 343 | ||
| 380 | /* Assume that the buffer head corresponding to node is locked. */ | 344 | /* Assume that the buffer head corresponding to node is locked. */ |
| @@ -388,11 +352,11 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree, | |||
| 388 | __le64 *dptrs; | 352 | __le64 *dptrs; |
| 389 | int nchildren; | 353 | int nchildren; |
| 390 | 354 | ||
| 391 | dkeys = nilfs_btree_node_dkeys(btree, node); | 355 | dkeys = nilfs_btree_node_dkeys(node); |
| 392 | dptrs = nilfs_btree_node_dptrs(btree, node); | 356 | dptrs = nilfs_btree_node_dptrs(node, btree); |
| 393 | key = nilfs_bmap_dkey_to_key(dkeys[index]); | 357 | key = nilfs_bmap_dkey_to_key(dkeys[index]); |
| 394 | ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]); | 358 | ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]); |
| 395 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 359 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 396 | if (keyp != NULL) | 360 | if (keyp != NULL) |
| 397 | *keyp = key; | 361 | *keyp = key; |
| 398 | if (ptrp != NULL) | 362 | if (ptrp != NULL) |
| @@ -405,11 +369,10 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree, | |||
| 405 | (nchildren - index - 1) * sizeof(*dptrs)); | 369 | (nchildren - index - 1) * sizeof(*dptrs)); |
| 406 | } | 370 | } |
| 407 | nchildren--; | 371 | nchildren--; |
| 408 | nilfs_btree_node_set_nchildren(btree, node, nchildren); | 372 | nilfs_btree_node_set_nchildren(node, nchildren); |
| 409 | } | 373 | } |
| 410 | 374 | ||
| 411 | static int nilfs_btree_node_lookup(const struct nilfs_btree *btree, | 375 | static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node, |
| 412 | const struct nilfs_btree_node *node, | ||
| 413 | __u64 key, int *indexp) | 376 | __u64 key, int *indexp) |
| 414 | { | 377 | { |
| 415 | __u64 nkey; | 378 | __u64 nkey; |
| @@ -417,12 +380,12 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree *btree, | |||
| 417 | 380 | ||
| 418 | /* binary search */ | 381 | /* binary search */ |
| 419 | low = 0; | 382 | low = 0; |
| 420 | high = nilfs_btree_node_get_nchildren(btree, node) - 1; | 383 | high = nilfs_btree_node_get_nchildren(node) - 1; |
| 421 | index = 0; | 384 | index = 0; |
| 422 | s = 0; | 385 | s = 0; |
| 423 | while (low <= high) { | 386 | while (low <= high) { |
| 424 | index = (low + high) / 2; | 387 | index = (low + high) / 2; |
| 425 | nkey = nilfs_btree_node_get_key(btree, node, index); | 388 | nkey = nilfs_btree_node_get_key(node, index); |
| 426 | if (nkey == key) { | 389 | if (nkey == key) { |
| 427 | s = 0; | 390 | s = 0; |
| 428 | goto out; | 391 | goto out; |
| @@ -436,9 +399,8 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree *btree, | |||
| 436 | } | 399 | } |
| 437 | 400 | ||
| 438 | /* adjust index */ | 401 | /* adjust index */ |
| 439 | if (nilfs_btree_node_get_level(btree, node) > | 402 | if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) { |
| 440 | NILFS_BTREE_LEVEL_NODE_MIN) { | 403 | if (s > 0 && index > 0) |
| 441 | if ((s > 0) && (index > 0)) | ||
| 442 | index--; | 404 | index--; |
| 443 | } else if (s < 0) | 405 | } else if (s < 0) |
| 444 | index++; | 406 | index++; |
| @@ -456,25 +418,20 @@ nilfs_btree_get_root(const struct nilfs_btree *btree) | |||
| 456 | } | 418 | } |
| 457 | 419 | ||
| 458 | static inline struct nilfs_btree_node * | 420 | static inline struct nilfs_btree_node * |
| 459 | nilfs_btree_get_nonroot_node(const struct nilfs_btree *btree, | 421 | nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level) |
| 460 | const struct nilfs_btree_path *path, | ||
| 461 | int level) | ||
| 462 | { | 422 | { |
| 463 | return (struct nilfs_btree_node *)path[level].bp_bh->b_data; | 423 | return (struct nilfs_btree_node *)path[level].bp_bh->b_data; |
| 464 | } | 424 | } |
| 465 | 425 | ||
| 466 | static inline struct nilfs_btree_node * | 426 | static inline struct nilfs_btree_node * |
| 467 | nilfs_btree_get_sib_node(const struct nilfs_btree *btree, | 427 | nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level) |
| 468 | const struct nilfs_btree_path *path, | ||
| 469 | int level) | ||
| 470 | { | 428 | { |
| 471 | return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data; | 429 | return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data; |
| 472 | } | 430 | } |
| 473 | 431 | ||
| 474 | static inline int nilfs_btree_height(const struct nilfs_btree *btree) | 432 | static inline int nilfs_btree_height(const struct nilfs_btree *btree) |
| 475 | { | 433 | { |
| 476 | return nilfs_btree_node_get_level(btree, nilfs_btree_get_root(btree)) | 434 | return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1; |
| 477 | + 1; | ||
| 478 | } | 435 | } |
| 479 | 436 | ||
| 480 | static inline struct nilfs_btree_node * | 437 | static inline struct nilfs_btree_node * |
| @@ -484,7 +441,7 @@ nilfs_btree_get_node(const struct nilfs_btree *btree, | |||
| 484 | { | 441 | { |
| 485 | return (level == nilfs_btree_height(btree) - 1) ? | 442 | return (level == nilfs_btree_height(btree) - 1) ? |
| 486 | nilfs_btree_get_root(btree) : | 443 | nilfs_btree_get_root(btree) : |
| 487 | nilfs_btree_get_nonroot_node(btree, path, level); | 444 | nilfs_btree_get_nonroot_node(path, level); |
| 488 | } | 445 | } |
| 489 | 446 | ||
| 490 | static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | 447 | static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, |
| @@ -496,12 +453,11 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
| 496 | int level, index, found, ret; | 453 | int level, index, found, ret; |
| 497 | 454 | ||
| 498 | node = nilfs_btree_get_root(btree); | 455 | node = nilfs_btree_get_root(btree); |
| 499 | level = nilfs_btree_node_get_level(btree, node); | 456 | level = nilfs_btree_node_get_level(node); |
| 500 | if ((level < minlevel) || | 457 | if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0) |
| 501 | (nilfs_btree_node_get_nchildren(btree, node) <= 0)) | ||
| 502 | return -ENOENT; | 458 | return -ENOENT; |
| 503 | 459 | ||
| 504 | found = nilfs_btree_node_lookup(btree, node, key, &index); | 460 | found = nilfs_btree_node_lookup(node, key, &index); |
| 505 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 461 | ptr = nilfs_btree_node_get_ptr(btree, node, index); |
| 506 | path[level].bp_bh = NULL; | 462 | path[level].bp_bh = NULL; |
| 507 | path[level].bp_index = index; | 463 | path[level].bp_index = index; |
| @@ -510,14 +466,13 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
| 510 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); | 466 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); |
| 511 | if (ret < 0) | 467 | if (ret < 0) |
| 512 | return ret; | 468 | return ret; |
| 513 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 469 | node = nilfs_btree_get_nonroot_node(path, level); |
| 514 | BUG_ON(level != nilfs_btree_node_get_level(btree, node)); | 470 | BUG_ON(level != nilfs_btree_node_get_level(node)); |
| 515 | if (!found) | 471 | if (!found) |
| 516 | found = nilfs_btree_node_lookup(btree, node, key, | 472 | found = nilfs_btree_node_lookup(node, key, &index); |
| 517 | &index); | ||
| 518 | else | 473 | else |
| 519 | index = 0; | 474 | index = 0; |
| 520 | if (index < nilfs_btree_node_nchildren_max(btree, node)) | 475 | if (index < nilfs_btree_node_nchildren_max(node, btree)) |
| 521 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 476 | ptr = nilfs_btree_node_get_ptr(btree, node, index); |
| 522 | else { | 477 | else { |
| 523 | WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN); | 478 | WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN); |
| @@ -544,10 +499,10 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | |||
| 544 | int index, level, ret; | 499 | int index, level, ret; |
| 545 | 500 | ||
| 546 | node = nilfs_btree_get_root(btree); | 501 | node = nilfs_btree_get_root(btree); |
| 547 | index = nilfs_btree_node_get_nchildren(btree, node) - 1; | 502 | index = nilfs_btree_node_get_nchildren(node) - 1; |
| 548 | if (index < 0) | 503 | if (index < 0) |
| 549 | return -ENOENT; | 504 | return -ENOENT; |
| 550 | level = nilfs_btree_node_get_level(btree, node); | 505 | level = nilfs_btree_node_get_level(node); |
| 551 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 506 | ptr = nilfs_btree_node_get_ptr(btree, node, index); |
| 552 | path[level].bp_bh = NULL; | 507 | path[level].bp_bh = NULL; |
| 553 | path[level].bp_index = index; | 508 | path[level].bp_index = index; |
| @@ -556,15 +511,15 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | |||
| 556 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); | 511 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); |
| 557 | if (ret < 0) | 512 | if (ret < 0) |
| 558 | return ret; | 513 | return ret; |
| 559 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 514 | node = nilfs_btree_get_nonroot_node(path, level); |
| 560 | BUG_ON(level != nilfs_btree_node_get_level(btree, node)); | 515 | BUG_ON(level != nilfs_btree_node_get_level(node)); |
| 561 | index = nilfs_btree_node_get_nchildren(btree, node) - 1; | 516 | index = nilfs_btree_node_get_nchildren(node) - 1; |
| 562 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 517 | ptr = nilfs_btree_node_get_ptr(btree, node, index); |
| 563 | path[level].bp_index = index; | 518 | path[level].bp_index = index; |
| 564 | } | 519 | } |
| 565 | 520 | ||
| 566 | if (keyp != NULL) | 521 | if (keyp != NULL) |
| 567 | *keyp = nilfs_btree_node_get_key(btree, node, index); | 522 | *keyp = nilfs_btree_node_get_key(node, index); |
| 568 | if (ptrp != NULL) | 523 | if (ptrp != NULL) |
| 569 | *ptrp = ptr; | 524 | *ptrp = ptr; |
| 570 | 525 | ||
| @@ -580,18 +535,18 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, | |||
| 580 | int ret; | 535 | int ret; |
| 581 | 536 | ||
| 582 | btree = (struct nilfs_btree *)bmap; | 537 | btree = (struct nilfs_btree *)bmap; |
| 583 | path = nilfs_btree_alloc_path(btree); | 538 | path = nilfs_btree_alloc_path(); |
| 584 | if (path == NULL) | 539 | if (path == NULL) |
| 585 | return -ENOMEM; | 540 | return -ENOMEM; |
| 586 | nilfs_btree_init_path(btree, path); | 541 | nilfs_btree_init_path(path); |
| 587 | 542 | ||
| 588 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 543 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); |
| 589 | 544 | ||
| 590 | if (ptrp != NULL) | 545 | if (ptrp != NULL) |
| 591 | *ptrp = ptr; | 546 | *ptrp = ptr; |
| 592 | 547 | ||
| 593 | nilfs_btree_clear_path(btree, path); | 548 | nilfs_btree_release_path(path); |
| 594 | nilfs_btree_free_path(btree, path); | 549 | nilfs_btree_free_path(path); |
| 595 | 550 | ||
| 596 | return ret; | 551 | return ret; |
| 597 | } | 552 | } |
| @@ -608,10 +563,10 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
| 608 | int level = NILFS_BTREE_LEVEL_NODE_MIN; | 563 | int level = NILFS_BTREE_LEVEL_NODE_MIN; |
| 609 | int ret, cnt, index, maxlevel; | 564 | int ret, cnt, index, maxlevel; |
| 610 | 565 | ||
| 611 | path = nilfs_btree_alloc_path(btree); | 566 | path = nilfs_btree_alloc_path(); |
| 612 | if (path == NULL) | 567 | if (path == NULL) |
| 613 | return -ENOMEM; | 568 | return -ENOMEM; |
| 614 | nilfs_btree_init_path(btree, path); | 569 | nilfs_btree_init_path(path); |
| 615 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 570 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); |
| 616 | if (ret < 0) | 571 | if (ret < 0) |
| 617 | goto out; | 572 | goto out; |
| @@ -631,8 +586,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
| 631 | node = nilfs_btree_get_node(btree, path, level); | 586 | node = nilfs_btree_get_node(btree, path, level); |
| 632 | index = path[level].bp_index + 1; | 587 | index = path[level].bp_index + 1; |
| 633 | for (;;) { | 588 | for (;;) { |
| 634 | while (index < nilfs_btree_node_get_nchildren(btree, node)) { | 589 | while (index < nilfs_btree_node_get_nchildren(node)) { |
| 635 | if (nilfs_btree_node_get_key(btree, node, index) != | 590 | if (nilfs_btree_node_get_key(node, index) != |
| 636 | key + cnt) | 591 | key + cnt) |
| 637 | goto end; | 592 | goto end; |
| 638 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | 593 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); |
| @@ -653,8 +608,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
| 653 | /* look-up right sibling node */ | 608 | /* look-up right sibling node */ |
| 654 | node = nilfs_btree_get_node(btree, path, level + 1); | 609 | node = nilfs_btree_get_node(btree, path, level + 1); |
| 655 | index = path[level + 1].bp_index + 1; | 610 | index = path[level + 1].bp_index + 1; |
| 656 | if (index >= nilfs_btree_node_get_nchildren(btree, node) || | 611 | if (index >= nilfs_btree_node_get_nchildren(node) || |
| 657 | nilfs_btree_node_get_key(btree, node, index) != key + cnt) | 612 | nilfs_btree_node_get_key(node, index) != key + cnt) |
| 658 | break; | 613 | break; |
| 659 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | 614 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); |
| 660 | path[level + 1].bp_index = index; | 615 | path[level + 1].bp_index = index; |
| @@ -664,7 +619,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
| 664 | ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh); | 619 | ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh); |
| 665 | if (ret < 0) | 620 | if (ret < 0) |
| 666 | goto out; | 621 | goto out; |
| 667 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 622 | node = nilfs_btree_get_nonroot_node(path, level); |
| 668 | index = 0; | 623 | index = 0; |
| 669 | path[level].bp_index = index; | 624 | path[level].bp_index = index; |
| 670 | } | 625 | } |
| @@ -672,8 +627,8 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
| 672 | *ptrp = ptr; | 627 | *ptrp = ptr; |
| 673 | ret = cnt; | 628 | ret = cnt; |
| 674 | out: | 629 | out: |
| 675 | nilfs_btree_clear_path(btree, path); | 630 | nilfs_btree_release_path(path); |
| 676 | nilfs_btree_free_path(btree, path); | 631 | nilfs_btree_free_path(path); |
| 677 | return ret; | 632 | return ret; |
| 678 | } | 633 | } |
| 679 | 634 | ||
| @@ -685,9 +640,7 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree, | |||
| 685 | do { | 640 | do { |
| 686 | lock_buffer(path[level].bp_bh); | 641 | lock_buffer(path[level].bp_bh); |
| 687 | nilfs_btree_node_set_key( | 642 | nilfs_btree_node_set_key( |
| 688 | btree, | 643 | nilfs_btree_get_nonroot_node(path, level), |
| 689 | nilfs_btree_get_nonroot_node( | ||
| 690 | btree, path, level), | ||
| 691 | path[level].bp_index, key); | 644 | path[level].bp_index, key); |
| 692 | if (!buffer_dirty(path[level].bp_bh)) | 645 | if (!buffer_dirty(path[level].bp_bh)) |
| 693 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 646 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
| @@ -698,8 +651,7 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree, | |||
| 698 | 651 | ||
| 699 | /* root */ | 652 | /* root */ |
| 700 | if (level == nilfs_btree_height(btree) - 1) { | 653 | if (level == nilfs_btree_height(btree) - 1) { |
| 701 | nilfs_btree_node_set_key(btree, | 654 | nilfs_btree_node_set_key(nilfs_btree_get_root(btree), |
| 702 | nilfs_btree_get_root(btree), | ||
| 703 | path[level].bp_index, key); | 655 | path[level].bp_index, key); |
| 704 | } | 656 | } |
| 705 | } | 657 | } |
| @@ -712,7 +664,7 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree, | |||
| 712 | 664 | ||
| 713 | if (level < nilfs_btree_height(btree) - 1) { | 665 | if (level < nilfs_btree_height(btree) - 1) { |
| 714 | lock_buffer(path[level].bp_bh); | 666 | lock_buffer(path[level].bp_bh); |
| 715 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 667 | node = nilfs_btree_get_nonroot_node(path, level); |
| 716 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, | 668 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, |
| 717 | path[level].bp_index); | 669 | path[level].bp_index); |
| 718 | if (!buffer_dirty(path[level].bp_bh)) | 670 | if (!buffer_dirty(path[level].bp_bh)) |
| @@ -721,8 +673,8 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree, | |||
| 721 | 673 | ||
| 722 | if (path[level].bp_index == 0) | 674 | if (path[level].bp_index == 0) |
| 723 | nilfs_btree_promote_key(btree, path, level + 1, | 675 | nilfs_btree_promote_key(btree, path, level + 1, |
| 724 | nilfs_btree_node_get_key( | 676 | nilfs_btree_node_get_key(node, |
| 725 | btree, node, 0)); | 677 | 0)); |
| 726 | } else { | 678 | } else { |
| 727 | node = nilfs_btree_get_root(btree); | 679 | node = nilfs_btree_get_root(btree); |
| 728 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, | 680 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, |
| @@ -740,10 +692,10 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, | |||
| 740 | lock_buffer(path[level].bp_bh); | 692 | lock_buffer(path[level].bp_bh); |
| 741 | lock_buffer(path[level].bp_sib_bh); | 693 | lock_buffer(path[level].bp_sib_bh); |
| 742 | 694 | ||
| 743 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 695 | node = nilfs_btree_get_nonroot_node(path, level); |
| 744 | left = nilfs_btree_get_sib_node(btree, path, level); | 696 | left = nilfs_btree_get_sib_node(path, level); |
| 745 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 697 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 746 | lnchildren = nilfs_btree_node_get_nchildren(btree, left); | 698 | lnchildren = nilfs_btree_node_get_nchildren(left); |
| 747 | move = 0; | 699 | move = 0; |
| 748 | 700 | ||
| 749 | n = (nchildren + lnchildren + 1) / 2 - lnchildren; | 701 | n = (nchildren + lnchildren + 1) / 2 - lnchildren; |
| @@ -764,7 +716,7 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, | |||
| 764 | unlock_buffer(path[level].bp_sib_bh); | 716 | unlock_buffer(path[level].bp_sib_bh); |
| 765 | 717 | ||
| 766 | nilfs_btree_promote_key(btree, path, level + 1, | 718 | nilfs_btree_promote_key(btree, path, level + 1, |
| 767 | nilfs_btree_node_get_key(btree, node, 0)); | 719 | nilfs_btree_node_get_key(node, 0)); |
| 768 | 720 | ||
| 769 | if (move) { | 721 | if (move) { |
| 770 | brelse(path[level].bp_bh); | 722 | brelse(path[level].bp_bh); |
| @@ -791,10 +743,10 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, | |||
| 791 | lock_buffer(path[level].bp_bh); | 743 | lock_buffer(path[level].bp_bh); |
| 792 | lock_buffer(path[level].bp_sib_bh); | 744 | lock_buffer(path[level].bp_sib_bh); |
| 793 | 745 | ||
| 794 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 746 | node = nilfs_btree_get_nonroot_node(path, level); |
| 795 | right = nilfs_btree_get_sib_node(btree, path, level); | 747 | right = nilfs_btree_get_sib_node(path, level); |
| 796 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 748 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 797 | rnchildren = nilfs_btree_node_get_nchildren(btree, right); | 749 | rnchildren = nilfs_btree_node_get_nchildren(right); |
| 798 | move = 0; | 750 | move = 0; |
| 799 | 751 | ||
| 800 | n = (nchildren + rnchildren + 1) / 2 - rnchildren; | 752 | n = (nchildren + rnchildren + 1) / 2 - rnchildren; |
| @@ -816,15 +768,14 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, | |||
| 816 | 768 | ||
| 817 | path[level + 1].bp_index++; | 769 | path[level + 1].bp_index++; |
| 818 | nilfs_btree_promote_key(btree, path, level + 1, | 770 | nilfs_btree_promote_key(btree, path, level + 1, |
| 819 | nilfs_btree_node_get_key(btree, right, 0)); | 771 | nilfs_btree_node_get_key(right, 0)); |
| 820 | path[level + 1].bp_index--; | 772 | path[level + 1].bp_index--; |
| 821 | 773 | ||
| 822 | if (move) { | 774 | if (move) { |
| 823 | brelse(path[level].bp_bh); | 775 | brelse(path[level].bp_bh); |
| 824 | path[level].bp_bh = path[level].bp_sib_bh; | 776 | path[level].bp_bh = path[level].bp_sib_bh; |
| 825 | path[level].bp_sib_bh = NULL; | 777 | path[level].bp_sib_bh = NULL; |
| 826 | path[level].bp_index -= | 778 | path[level].bp_index -= nilfs_btree_node_get_nchildren(node); |
| 827 | nilfs_btree_node_get_nchildren(btree, node); | ||
| 828 | path[level + 1].bp_index++; | 779 | path[level + 1].bp_index++; |
| 829 | } else { | 780 | } else { |
| 830 | brelse(path[level].bp_sib_bh); | 781 | brelse(path[level].bp_sib_bh); |
| @@ -846,9 +797,9 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
| 846 | lock_buffer(path[level].bp_bh); | 797 | lock_buffer(path[level].bp_bh); |
| 847 | lock_buffer(path[level].bp_sib_bh); | 798 | lock_buffer(path[level].bp_sib_bh); |
| 848 | 799 | ||
| 849 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 800 | node = nilfs_btree_get_nonroot_node(path, level); |
| 850 | right = nilfs_btree_get_sib_node(btree, path, level); | 801 | right = nilfs_btree_get_sib_node(path, level); |
| 851 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 802 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 852 | move = 0; | 803 | move = 0; |
| 853 | 804 | ||
| 854 | n = (nchildren + 1) / 2; | 805 | n = (nchildren + 1) / 2; |
| @@ -867,16 +818,15 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
| 867 | unlock_buffer(path[level].bp_bh); | 818 | unlock_buffer(path[level].bp_bh); |
| 868 | unlock_buffer(path[level].bp_sib_bh); | 819 | unlock_buffer(path[level].bp_sib_bh); |
| 869 | 820 | ||
| 870 | newkey = nilfs_btree_node_get_key(btree, right, 0); | 821 | newkey = nilfs_btree_node_get_key(right, 0); |
| 871 | newptr = path[level].bp_newreq.bpr_ptr; | 822 | newptr = path[level].bp_newreq.bpr_ptr; |
| 872 | 823 | ||
| 873 | if (move) { | 824 | if (move) { |
| 874 | path[level].bp_index -= | 825 | path[level].bp_index -= nilfs_btree_node_get_nchildren(node); |
| 875 | nilfs_btree_node_get_nchildren(btree, node); | ||
| 876 | nilfs_btree_node_insert(btree, right, *keyp, *ptrp, | 826 | nilfs_btree_node_insert(btree, right, *keyp, *ptrp, |
| 877 | path[level].bp_index); | 827 | path[level].bp_index); |
| 878 | 828 | ||
| 879 | *keyp = nilfs_btree_node_get_key(btree, right, 0); | 829 | *keyp = nilfs_btree_node_get_key(right, 0); |
| 880 | *ptrp = path[level].bp_newreq.bpr_ptr; | 830 | *ptrp = path[level].bp_newreq.bpr_ptr; |
| 881 | 831 | ||
| 882 | brelse(path[level].bp_bh); | 832 | brelse(path[level].bp_bh); |
| @@ -885,7 +835,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
| 885 | } else { | 835 | } else { |
| 886 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); | 836 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); |
| 887 | 837 | ||
| 888 | *keyp = nilfs_btree_node_get_key(btree, right, 0); | 838 | *keyp = nilfs_btree_node_get_key(right, 0); |
| 889 | *ptrp = path[level].bp_newreq.bpr_ptr; | 839 | *ptrp = path[level].bp_newreq.bpr_ptr; |
| 890 | 840 | ||
| 891 | brelse(path[level].bp_sib_bh); | 841 | brelse(path[level].bp_sib_bh); |
| @@ -905,12 +855,12 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, | |||
| 905 | lock_buffer(path[level].bp_sib_bh); | 855 | lock_buffer(path[level].bp_sib_bh); |
| 906 | 856 | ||
| 907 | root = nilfs_btree_get_root(btree); | 857 | root = nilfs_btree_get_root(btree); |
| 908 | child = nilfs_btree_get_sib_node(btree, path, level); | 858 | child = nilfs_btree_get_sib_node(path, level); |
| 909 | 859 | ||
| 910 | n = nilfs_btree_node_get_nchildren(btree, root); | 860 | n = nilfs_btree_node_get_nchildren(root); |
| 911 | 861 | ||
| 912 | nilfs_btree_node_move_right(btree, root, child, n); | 862 | nilfs_btree_node_move_right(btree, root, child, n); |
| 913 | nilfs_btree_node_set_level(btree, root, level + 1); | 863 | nilfs_btree_node_set_level(root, level + 1); |
| 914 | 864 | ||
| 915 | if (!buffer_dirty(path[level].bp_sib_bh)) | 865 | if (!buffer_dirty(path[level].bp_sib_bh)) |
| 916 | nilfs_btnode_mark_dirty(path[level].bp_sib_bh); | 866 | nilfs_btnode_mark_dirty(path[level].bp_sib_bh); |
| @@ -922,7 +872,7 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, | |||
| 922 | 872 | ||
| 923 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); | 873 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); |
| 924 | 874 | ||
| 925 | *keyp = nilfs_btree_node_get_key(btree, child, 0); | 875 | *keyp = nilfs_btree_node_get_key(child, 0); |
| 926 | *ptrp = path[level].bp_newreq.bpr_ptr; | 876 | *ptrp = path[level].bp_newreq.bpr_ptr; |
| 927 | } | 877 | } |
| 928 | 878 | ||
| @@ -990,26 +940,29 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
| 990 | struct nilfs_btree_node *node, *parent, *sib; | 940 | struct nilfs_btree_node *node, *parent, *sib; |
| 991 | __u64 sibptr; | 941 | __u64 sibptr; |
| 992 | int pindex, level, ret; | 942 | int pindex, level, ret; |
| 943 | struct inode *dat = NULL; | ||
| 993 | 944 | ||
| 994 | stats->bs_nblocks = 0; | 945 | stats->bs_nblocks = 0; |
| 995 | level = NILFS_BTREE_LEVEL_DATA; | 946 | level = NILFS_BTREE_LEVEL_DATA; |
| 996 | 947 | ||
| 997 | /* allocate a new ptr for data block */ | 948 | /* allocate a new ptr for data block */ |
| 998 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) | 949 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) { |
| 999 | path[level].bp_newreq.bpr_ptr = | 950 | path[level].bp_newreq.bpr_ptr = |
| 1000 | nilfs_btree_find_target_v(btree, path, key); | 951 | nilfs_btree_find_target_v(btree, path, key); |
| 952 | dat = nilfs_bmap_get_dat(&btree->bt_bmap); | ||
| 953 | } | ||
| 1001 | 954 | ||
| 1002 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 955 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, |
| 1003 | &path[level].bp_newreq); | 956 | &path[level].bp_newreq, dat); |
| 1004 | if (ret < 0) | 957 | if (ret < 0) |
| 1005 | goto err_out_data; | 958 | goto err_out_data; |
| 1006 | 959 | ||
| 1007 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; | 960 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; |
| 1008 | level < nilfs_btree_height(btree) - 1; | 961 | level < nilfs_btree_height(btree) - 1; |
| 1009 | level++) { | 962 | level++) { |
| 1010 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 963 | node = nilfs_btree_get_nonroot_node(path, level); |
| 1011 | if (nilfs_btree_node_get_nchildren(btree, node) < | 964 | if (nilfs_btree_node_get_nchildren(node) < |
| 1012 | nilfs_btree_node_nchildren_max(btree, node)) { | 965 | nilfs_btree_node_nchildren_max(node, btree)) { |
| 1013 | path[level].bp_op = nilfs_btree_do_insert; | 966 | path[level].bp_op = nilfs_btree_do_insert; |
| 1014 | stats->bs_nblocks++; | 967 | stats->bs_nblocks++; |
| 1015 | goto out; | 968 | goto out; |
| @@ -1026,8 +979,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
| 1026 | if (ret < 0) | 979 | if (ret < 0) |
| 1027 | goto err_out_child_node; | 980 | goto err_out_child_node; |
| 1028 | sib = (struct nilfs_btree_node *)bh->b_data; | 981 | sib = (struct nilfs_btree_node *)bh->b_data; |
| 1029 | if (nilfs_btree_node_get_nchildren(btree, sib) < | 982 | if (nilfs_btree_node_get_nchildren(sib) < |
| 1030 | nilfs_btree_node_nchildren_max(btree, sib)) { | 983 | nilfs_btree_node_nchildren_max(sib, btree)) { |
| 1031 | path[level].bp_sib_bh = bh; | 984 | path[level].bp_sib_bh = bh; |
| 1032 | path[level].bp_op = nilfs_btree_carry_left; | 985 | path[level].bp_op = nilfs_btree_carry_left; |
| 1033 | stats->bs_nblocks++; | 986 | stats->bs_nblocks++; |
| @@ -1038,15 +991,15 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
| 1038 | 991 | ||
| 1039 | /* right sibling */ | 992 | /* right sibling */ |
| 1040 | if (pindex < | 993 | if (pindex < |
| 1041 | nilfs_btree_node_get_nchildren(btree, parent) - 1) { | 994 | nilfs_btree_node_get_nchildren(parent) - 1) { |
| 1042 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 995 | sibptr = nilfs_btree_node_get_ptr(btree, parent, |
| 1043 | pindex + 1); | 996 | pindex + 1); |
| 1044 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 997 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
| 1045 | if (ret < 0) | 998 | if (ret < 0) |
| 1046 | goto err_out_child_node; | 999 | goto err_out_child_node; |
| 1047 | sib = (struct nilfs_btree_node *)bh->b_data; | 1000 | sib = (struct nilfs_btree_node *)bh->b_data; |
| 1048 | if (nilfs_btree_node_get_nchildren(btree, sib) < | 1001 | if (nilfs_btree_node_get_nchildren(sib) < |
| 1049 | nilfs_btree_node_nchildren_max(btree, sib)) { | 1002 | nilfs_btree_node_nchildren_max(sib, btree)) { |
| 1050 | path[level].bp_sib_bh = bh; | 1003 | path[level].bp_sib_bh = bh; |
| 1051 | path[level].bp_op = nilfs_btree_carry_right; | 1004 | path[level].bp_op = nilfs_btree_carry_right; |
| 1052 | stats->bs_nblocks++; | 1005 | stats->bs_nblocks++; |
| @@ -1059,7 +1012,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
| 1059 | path[level].bp_newreq.bpr_ptr = | 1012 | path[level].bp_newreq.bpr_ptr = |
| 1060 | path[level - 1].bp_newreq.bpr_ptr + 1; | 1013 | path[level - 1].bp_newreq.bpr_ptr + 1; |
| 1061 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1014 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, |
| 1062 | &path[level].bp_newreq); | 1015 | &path[level].bp_newreq, dat); |
| 1063 | if (ret < 0) | 1016 | if (ret < 0) |
| 1064 | goto err_out_child_node; | 1017 | goto err_out_child_node; |
| 1065 | ret = nilfs_btree_get_new_block(btree, | 1018 | ret = nilfs_btree_get_new_block(btree, |
| @@ -1081,8 +1034,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
| 1081 | 1034 | ||
| 1082 | /* root */ | 1035 | /* root */ |
| 1083 | node = nilfs_btree_get_root(btree); | 1036 | node = nilfs_btree_get_root(btree); |
| 1084 | if (nilfs_btree_node_get_nchildren(btree, node) < | 1037 | if (nilfs_btree_node_get_nchildren(node) < |
| 1085 | nilfs_btree_node_nchildren_max(btree, node)) { | 1038 | nilfs_btree_node_nchildren_max(node, btree)) { |
| 1086 | path[level].bp_op = nilfs_btree_do_insert; | 1039 | path[level].bp_op = nilfs_btree_do_insert; |
| 1087 | stats->bs_nblocks++; | 1040 | stats->bs_nblocks++; |
| 1088 | goto out; | 1041 | goto out; |
| @@ -1091,7 +1044,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
| 1091 | /* grow */ | 1044 | /* grow */ |
| 1092 | path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; | 1045 | path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; |
| 1093 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1046 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, |
| 1094 | &path[level].bp_newreq); | 1047 | &path[level].bp_newreq, dat); |
| 1095 | if (ret < 0) | 1048 | if (ret < 0) |
| 1096 | goto err_out_child_node; | 1049 | goto err_out_child_node; |
| 1097 | ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr, | 1050 | ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr, |
| @@ -1119,16 +1072,18 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
| 1119 | 1072 | ||
| 1120 | /* error */ | 1073 | /* error */ |
| 1121 | err_out_curr_node: | 1074 | err_out_curr_node: |
| 1122 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq); | 1075 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq, |
| 1076 | dat); | ||
| 1123 | err_out_child_node: | 1077 | err_out_child_node: |
| 1124 | for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { | 1078 | for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { |
| 1125 | nilfs_btnode_delete(path[level].bp_sib_bh); | 1079 | nilfs_btnode_delete(path[level].bp_sib_bh); |
| 1126 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, | 1080 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, |
| 1127 | &path[level].bp_newreq); | 1081 | &path[level].bp_newreq, dat); |
| 1128 | 1082 | ||
| 1129 | } | 1083 | } |
| 1130 | 1084 | ||
| 1131 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq); | 1085 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq, |
| 1086 | dat); | ||
| 1132 | err_out_data: | 1087 | err_out_data: |
| 1133 | *levelp = level; | 1088 | *levelp = level; |
| 1134 | stats->bs_nblocks = 0; | 1089 | stats->bs_nblocks = 0; |
| @@ -1139,16 +1094,19 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree, | |||
| 1139 | struct nilfs_btree_path *path, | 1094 | struct nilfs_btree_path *path, |
| 1140 | int maxlevel, __u64 key, __u64 ptr) | 1095 | int maxlevel, __u64 key, __u64 ptr) |
| 1141 | { | 1096 | { |
| 1097 | struct inode *dat = NULL; | ||
| 1142 | int level; | 1098 | int level; |
| 1143 | 1099 | ||
| 1144 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); | 1100 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); |
| 1145 | ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; | 1101 | ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; |
| 1146 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) | 1102 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) { |
| 1147 | nilfs_btree_set_target_v(btree, key, ptr); | 1103 | nilfs_btree_set_target_v(btree, key, ptr); |
| 1104 | dat = nilfs_bmap_get_dat(&btree->bt_bmap); | ||
| 1105 | } | ||
| 1148 | 1106 | ||
| 1149 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { | 1107 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { |
| 1150 | nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap, | 1108 | nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap, |
| 1151 | &path[level - 1].bp_newreq); | 1109 | &path[level - 1].bp_newreq, dat); |
| 1152 | path[level].bp_op(btree, path, level, &key, &ptr); | 1110 | path[level].bp_op(btree, path, level, &key, &ptr); |
| 1153 | } | 1111 | } |
| 1154 | 1112 | ||
| @@ -1164,10 +1122,10 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
| 1164 | int level, ret; | 1122 | int level, ret; |
| 1165 | 1123 | ||
| 1166 | btree = (struct nilfs_btree *)bmap; | 1124 | btree = (struct nilfs_btree *)bmap; |
| 1167 | path = nilfs_btree_alloc_path(btree); | 1125 | path = nilfs_btree_alloc_path(); |
| 1168 | if (path == NULL) | 1126 | if (path == NULL) |
| 1169 | return -ENOMEM; | 1127 | return -ENOMEM; |
| 1170 | nilfs_btree_init_path(btree, path); | 1128 | nilfs_btree_init_path(path); |
| 1171 | 1129 | ||
| 1172 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1130 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
| 1173 | NILFS_BTREE_LEVEL_NODE_MIN); | 1131 | NILFS_BTREE_LEVEL_NODE_MIN); |
| @@ -1184,8 +1142,8 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
| 1184 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); | 1142 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); |
| 1185 | 1143 | ||
| 1186 | out: | 1144 | out: |
| 1187 | nilfs_btree_clear_path(btree, path); | 1145 | nilfs_btree_release_path(path); |
| 1188 | nilfs_btree_free_path(btree, path); | 1146 | nilfs_btree_free_path(path); |
| 1189 | return ret; | 1147 | return ret; |
| 1190 | } | 1148 | } |
| 1191 | 1149 | ||
| @@ -1197,7 +1155,7 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree, | |||
| 1197 | 1155 | ||
| 1198 | if (level < nilfs_btree_height(btree) - 1) { | 1156 | if (level < nilfs_btree_height(btree) - 1) { |
| 1199 | lock_buffer(path[level].bp_bh); | 1157 | lock_buffer(path[level].bp_bh); |
| 1200 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 1158 | node = nilfs_btree_get_nonroot_node(path, level); |
| 1201 | nilfs_btree_node_delete(btree, node, keyp, ptrp, | 1159 | nilfs_btree_node_delete(btree, node, keyp, ptrp, |
| 1202 | path[level].bp_index); | 1160 | path[level].bp_index); |
| 1203 | if (!buffer_dirty(path[level].bp_bh)) | 1161 | if (!buffer_dirty(path[level].bp_bh)) |
| @@ -1205,7 +1163,7 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree, | |||
| 1205 | unlock_buffer(path[level].bp_bh); | 1163 | unlock_buffer(path[level].bp_bh); |
| 1206 | if (path[level].bp_index == 0) | 1164 | if (path[level].bp_index == 0) |
| 1207 | nilfs_btree_promote_key(btree, path, level + 1, | 1165 | nilfs_btree_promote_key(btree, path, level + 1, |
| 1208 | nilfs_btree_node_get_key(btree, node, 0)); | 1166 | nilfs_btree_node_get_key(node, 0)); |
| 1209 | } else { | 1167 | } else { |
| 1210 | node = nilfs_btree_get_root(btree); | 1168 | node = nilfs_btree_get_root(btree); |
| 1211 | nilfs_btree_node_delete(btree, node, keyp, ptrp, | 1169 | nilfs_btree_node_delete(btree, node, keyp, ptrp, |
| @@ -1225,10 +1183,10 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | |||
| 1225 | lock_buffer(path[level].bp_bh); | 1183 | lock_buffer(path[level].bp_bh); |
| 1226 | lock_buffer(path[level].bp_sib_bh); | 1184 | lock_buffer(path[level].bp_sib_bh); |
| 1227 | 1185 | ||
| 1228 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 1186 | node = nilfs_btree_get_nonroot_node(path, level); |
| 1229 | left = nilfs_btree_get_sib_node(btree, path, level); | 1187 | left = nilfs_btree_get_sib_node(path, level); |
| 1230 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 1188 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 1231 | lnchildren = nilfs_btree_node_get_nchildren(btree, left); | 1189 | lnchildren = nilfs_btree_node_get_nchildren(left); |
| 1232 | 1190 | ||
| 1233 | n = (nchildren + lnchildren) / 2 - nchildren; | 1191 | n = (nchildren + lnchildren) / 2 - nchildren; |
| 1234 | 1192 | ||
| @@ -1243,7 +1201,7 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | |||
| 1243 | unlock_buffer(path[level].bp_sib_bh); | 1201 | unlock_buffer(path[level].bp_sib_bh); |
| 1244 | 1202 | ||
| 1245 | nilfs_btree_promote_key(btree, path, level + 1, | 1203 | nilfs_btree_promote_key(btree, path, level + 1, |
| 1246 | nilfs_btree_node_get_key(btree, node, 0)); | 1204 | nilfs_btree_node_get_key(node, 0)); |
| 1247 | 1205 | ||
| 1248 | brelse(path[level].bp_sib_bh); | 1206 | brelse(path[level].bp_sib_bh); |
| 1249 | path[level].bp_sib_bh = NULL; | 1207 | path[level].bp_sib_bh = NULL; |
| @@ -1262,10 +1220,10 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | |||
| 1262 | lock_buffer(path[level].bp_bh); | 1220 | lock_buffer(path[level].bp_bh); |
| 1263 | lock_buffer(path[level].bp_sib_bh); | 1221 | lock_buffer(path[level].bp_sib_bh); |
| 1264 | 1222 | ||
| 1265 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 1223 | node = nilfs_btree_get_nonroot_node(path, level); |
| 1266 | right = nilfs_btree_get_sib_node(btree, path, level); | 1224 | right = nilfs_btree_get_sib_node(path, level); |
| 1267 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 1225 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 1268 | rnchildren = nilfs_btree_node_get_nchildren(btree, right); | 1226 | rnchildren = nilfs_btree_node_get_nchildren(right); |
| 1269 | 1227 | ||
| 1270 | n = (nchildren + rnchildren) / 2 - nchildren; | 1228 | n = (nchildren + rnchildren) / 2 - nchildren; |
| 1271 | 1229 | ||
| @@ -1281,7 +1239,7 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | |||
| 1281 | 1239 | ||
| 1282 | path[level + 1].bp_index++; | 1240 | path[level + 1].bp_index++; |
| 1283 | nilfs_btree_promote_key(btree, path, level + 1, | 1241 | nilfs_btree_promote_key(btree, path, level + 1, |
| 1284 | nilfs_btree_node_get_key(btree, right, 0)); | 1242 | nilfs_btree_node_get_key(right, 0)); |
| 1285 | path[level + 1].bp_index--; | 1243 | path[level + 1].bp_index--; |
| 1286 | 1244 | ||
| 1287 | brelse(path[level].bp_sib_bh); | 1245 | brelse(path[level].bp_sib_bh); |
| @@ -1300,10 +1258,10 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, | |||
| 1300 | lock_buffer(path[level].bp_bh); | 1258 | lock_buffer(path[level].bp_bh); |
| 1301 | lock_buffer(path[level].bp_sib_bh); | 1259 | lock_buffer(path[level].bp_sib_bh); |
| 1302 | 1260 | ||
| 1303 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 1261 | node = nilfs_btree_get_nonroot_node(path, level); |
| 1304 | left = nilfs_btree_get_sib_node(btree, path, level); | 1262 | left = nilfs_btree_get_sib_node(path, level); |
| 1305 | 1263 | ||
| 1306 | n = nilfs_btree_node_get_nchildren(btree, node); | 1264 | n = nilfs_btree_node_get_nchildren(node); |
| 1307 | 1265 | ||
| 1308 | nilfs_btree_node_move_left(btree, left, node, n); | 1266 | nilfs_btree_node_move_left(btree, left, node, n); |
| 1309 | 1267 | ||
| @@ -1316,7 +1274,7 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, | |||
| 1316 | nilfs_btnode_delete(path[level].bp_bh); | 1274 | nilfs_btnode_delete(path[level].bp_bh); |
| 1317 | path[level].bp_bh = path[level].bp_sib_bh; | 1275 | path[level].bp_bh = path[level].bp_sib_bh; |
| 1318 | path[level].bp_sib_bh = NULL; | 1276 | path[level].bp_sib_bh = NULL; |
| 1319 | path[level].bp_index += nilfs_btree_node_get_nchildren(btree, left); | 1277 | path[level].bp_index += nilfs_btree_node_get_nchildren(left); |
| 1320 | } | 1278 | } |
| 1321 | 1279 | ||
| 1322 | static void nilfs_btree_concat_right(struct nilfs_btree *btree, | 1280 | static void nilfs_btree_concat_right(struct nilfs_btree *btree, |
| @@ -1331,10 +1289,10 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree, | |||
| 1331 | lock_buffer(path[level].bp_bh); | 1289 | lock_buffer(path[level].bp_bh); |
| 1332 | lock_buffer(path[level].bp_sib_bh); | 1290 | lock_buffer(path[level].bp_sib_bh); |
| 1333 | 1291 | ||
| 1334 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 1292 | node = nilfs_btree_get_nonroot_node(path, level); |
| 1335 | right = nilfs_btree_get_sib_node(btree, path, level); | 1293 | right = nilfs_btree_get_sib_node(path, level); |
| 1336 | 1294 | ||
| 1337 | n = nilfs_btree_node_get_nchildren(btree, right); | 1295 | n = nilfs_btree_node_get_nchildren(right); |
| 1338 | 1296 | ||
| 1339 | nilfs_btree_node_move_left(btree, node, right, n); | 1297 | nilfs_btree_node_move_left(btree, node, right, n); |
| 1340 | 1298 | ||
| @@ -1360,11 +1318,11 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree, | |||
| 1360 | 1318 | ||
| 1361 | lock_buffer(path[level].bp_bh); | 1319 | lock_buffer(path[level].bp_bh); |
| 1362 | root = nilfs_btree_get_root(btree); | 1320 | root = nilfs_btree_get_root(btree); |
| 1363 | child = nilfs_btree_get_nonroot_node(btree, path, level); | 1321 | child = nilfs_btree_get_nonroot_node(path, level); |
| 1364 | 1322 | ||
| 1365 | nilfs_btree_node_delete(btree, root, NULL, NULL, 0); | 1323 | nilfs_btree_node_delete(btree, root, NULL, NULL, 0); |
| 1366 | nilfs_btree_node_set_level(btree, root, level); | 1324 | nilfs_btree_node_set_level(root, level); |
| 1367 | n = nilfs_btree_node_get_nchildren(btree, child); | 1325 | n = nilfs_btree_node_get_nchildren(child); |
| 1368 | nilfs_btree_node_move_left(btree, root, child, n); | 1326 | nilfs_btree_node_move_left(btree, root, child, n); |
| 1369 | unlock_buffer(path[level].bp_bh); | 1327 | unlock_buffer(path[level].bp_bh); |
| 1370 | 1328 | ||
| @@ -1376,7 +1334,8 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree, | |||
| 1376 | static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | 1334 | static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, |
| 1377 | struct nilfs_btree_path *path, | 1335 | struct nilfs_btree_path *path, |
| 1378 | int *levelp, | 1336 | int *levelp, |
| 1379 | struct nilfs_bmap_stats *stats) | 1337 | struct nilfs_bmap_stats *stats, |
| 1338 | struct inode *dat) | ||
| 1380 | { | 1339 | { |
| 1381 | struct buffer_head *bh; | 1340 | struct buffer_head *bh; |
| 1382 | struct nilfs_btree_node *node, *parent, *sib; | 1341 | struct nilfs_btree_node *node, *parent, *sib; |
| @@ -1388,17 +1347,17 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1388 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; | 1347 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; |
| 1389 | level < nilfs_btree_height(btree) - 1; | 1348 | level < nilfs_btree_height(btree) - 1; |
| 1390 | level++) { | 1349 | level++) { |
| 1391 | node = nilfs_btree_get_nonroot_node(btree, path, level); | 1350 | node = nilfs_btree_get_nonroot_node(path, level); |
| 1392 | path[level].bp_oldreq.bpr_ptr = | 1351 | path[level].bp_oldreq.bpr_ptr = |
| 1393 | nilfs_btree_node_get_ptr(btree, node, | 1352 | nilfs_btree_node_get_ptr(btree, node, |
| 1394 | path[level].bp_index); | 1353 | path[level].bp_index); |
| 1395 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, | 1354 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, |
| 1396 | &path[level].bp_oldreq); | 1355 | &path[level].bp_oldreq, dat); |
| 1397 | if (ret < 0) | 1356 | if (ret < 0) |
| 1398 | goto err_out_child_node; | 1357 | goto err_out_child_node; |
| 1399 | 1358 | ||
| 1400 | if (nilfs_btree_node_get_nchildren(btree, node) > | 1359 | if (nilfs_btree_node_get_nchildren(node) > |
| 1401 | nilfs_btree_node_nchildren_min(btree, node)) { | 1360 | nilfs_btree_node_nchildren_min(node, btree)) { |
| 1402 | path[level].bp_op = nilfs_btree_do_delete; | 1361 | path[level].bp_op = nilfs_btree_do_delete; |
| 1403 | stats->bs_nblocks++; | 1362 | stats->bs_nblocks++; |
| 1404 | goto out; | 1363 | goto out; |
| @@ -1415,8 +1374,8 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1415 | if (ret < 0) | 1374 | if (ret < 0) |
| 1416 | goto err_out_curr_node; | 1375 | goto err_out_curr_node; |
| 1417 | sib = (struct nilfs_btree_node *)bh->b_data; | 1376 | sib = (struct nilfs_btree_node *)bh->b_data; |
| 1418 | if (nilfs_btree_node_get_nchildren(btree, sib) > | 1377 | if (nilfs_btree_node_get_nchildren(sib) > |
| 1419 | nilfs_btree_node_nchildren_min(btree, sib)) { | 1378 | nilfs_btree_node_nchildren_min(sib, btree)) { |
| 1420 | path[level].bp_sib_bh = bh; | 1379 | path[level].bp_sib_bh = bh; |
| 1421 | path[level].bp_op = nilfs_btree_borrow_left; | 1380 | path[level].bp_op = nilfs_btree_borrow_left; |
| 1422 | stats->bs_nblocks++; | 1381 | stats->bs_nblocks++; |
| @@ -1428,7 +1387,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1428 | /* continue; */ | 1387 | /* continue; */ |
| 1429 | } | 1388 | } |
| 1430 | } else if (pindex < | 1389 | } else if (pindex < |
| 1431 | nilfs_btree_node_get_nchildren(btree, parent) - 1) { | 1390 | nilfs_btree_node_get_nchildren(parent) - 1) { |
| 1432 | /* right sibling */ | 1391 | /* right sibling */ |
| 1433 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1392 | sibptr = nilfs_btree_node_get_ptr(btree, parent, |
| 1434 | pindex + 1); | 1393 | pindex + 1); |
| @@ -1436,8 +1395,8 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1436 | if (ret < 0) | 1395 | if (ret < 0) |
| 1437 | goto err_out_curr_node; | 1396 | goto err_out_curr_node; |
| 1438 | sib = (struct nilfs_btree_node *)bh->b_data; | 1397 | sib = (struct nilfs_btree_node *)bh->b_data; |
| 1439 | if (nilfs_btree_node_get_nchildren(btree, sib) > | 1398 | if (nilfs_btree_node_get_nchildren(sib) > |
| 1440 | nilfs_btree_node_nchildren_min(btree, sib)) { | 1399 | nilfs_btree_node_nchildren_min(sib, btree)) { |
| 1441 | path[level].bp_sib_bh = bh; | 1400 | path[level].bp_sib_bh = bh; |
| 1442 | path[level].bp_op = nilfs_btree_borrow_right; | 1401 | path[level].bp_op = nilfs_btree_borrow_right; |
| 1443 | stats->bs_nblocks++; | 1402 | stats->bs_nblocks++; |
| @@ -1452,7 +1411,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1452 | /* no siblings */ | 1411 | /* no siblings */ |
| 1453 | /* the only child of the root node */ | 1412 | /* the only child of the root node */ |
| 1454 | WARN_ON(level != nilfs_btree_height(btree) - 2); | 1413 | WARN_ON(level != nilfs_btree_height(btree) - 2); |
| 1455 | if (nilfs_btree_node_get_nchildren(btree, node) - 1 <= | 1414 | if (nilfs_btree_node_get_nchildren(node) - 1 <= |
| 1456 | NILFS_BTREE_ROOT_NCHILDREN_MAX) { | 1415 | NILFS_BTREE_ROOT_NCHILDREN_MAX) { |
| 1457 | path[level].bp_op = nilfs_btree_shrink; | 1416 | path[level].bp_op = nilfs_btree_shrink; |
| 1458 | stats->bs_nblocks += 2; | 1417 | stats->bs_nblocks += 2; |
| @@ -1471,7 +1430,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1471 | nilfs_btree_node_get_ptr(btree, node, path[level].bp_index); | 1430 | nilfs_btree_node_get_ptr(btree, node, path[level].bp_index); |
| 1472 | 1431 | ||
| 1473 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, | 1432 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, |
| 1474 | &path[level].bp_oldreq); | 1433 | &path[level].bp_oldreq, dat); |
| 1475 | if (ret < 0) | 1434 | if (ret < 0) |
| 1476 | goto err_out_child_node; | 1435 | goto err_out_child_node; |
| 1477 | 1436 | ||
| @@ -1486,12 +1445,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1486 | 1445 | ||
| 1487 | /* error */ | 1446 | /* error */ |
| 1488 | err_out_curr_node: | 1447 | err_out_curr_node: |
| 1489 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq); | 1448 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat); |
| 1490 | err_out_child_node: | 1449 | err_out_child_node: |
| 1491 | for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { | 1450 | for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { |
| 1492 | brelse(path[level].bp_sib_bh); | 1451 | brelse(path[level].bp_sib_bh); |
| 1493 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, | 1452 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, |
| 1494 | &path[level].bp_oldreq); | 1453 | &path[level].bp_oldreq, dat); |
| 1495 | } | 1454 | } |
| 1496 | *levelp = level; | 1455 | *levelp = level; |
| 1497 | stats->bs_nblocks = 0; | 1456 | stats->bs_nblocks = 0; |
| @@ -1500,13 +1459,13 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
| 1500 | 1459 | ||
| 1501 | static void nilfs_btree_commit_delete(struct nilfs_btree *btree, | 1460 | static void nilfs_btree_commit_delete(struct nilfs_btree *btree, |
| 1502 | struct nilfs_btree_path *path, | 1461 | struct nilfs_btree_path *path, |
| 1503 | int maxlevel) | 1462 | int maxlevel, struct inode *dat) |
| 1504 | { | 1463 | { |
| 1505 | int level; | 1464 | int level; |
| 1506 | 1465 | ||
| 1507 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { | 1466 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { |
| 1508 | nilfs_bmap_commit_end_ptr(&btree->bt_bmap, | 1467 | nilfs_bmap_commit_end_ptr(&btree->bt_bmap, |
| 1509 | &path[level].bp_oldreq); | 1468 | &path[level].bp_oldreq, dat); |
| 1510 | path[level].bp_op(btree, path, level, NULL, NULL); | 1469 | path[level].bp_op(btree, path, level, NULL, NULL); |
| 1511 | } | 1470 | } |
| 1512 | 1471 | ||
| @@ -1520,27 +1479,32 @@ static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) | |||
| 1520 | struct nilfs_btree *btree; | 1479 | struct nilfs_btree *btree; |
| 1521 | struct nilfs_btree_path *path; | 1480 | struct nilfs_btree_path *path; |
| 1522 | struct nilfs_bmap_stats stats; | 1481 | struct nilfs_bmap_stats stats; |
| 1482 | struct inode *dat; | ||
| 1523 | int level, ret; | 1483 | int level, ret; |
| 1524 | 1484 | ||
| 1525 | btree = (struct nilfs_btree *)bmap; | 1485 | btree = (struct nilfs_btree *)bmap; |
| 1526 | path = nilfs_btree_alloc_path(btree); | 1486 | path = nilfs_btree_alloc_path(); |
| 1527 | if (path == NULL) | 1487 | if (path == NULL) |
| 1528 | return -ENOMEM; | 1488 | return -ENOMEM; |
| 1529 | nilfs_btree_init_path(btree, path); | 1489 | nilfs_btree_init_path(path); |
| 1530 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1490 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
| 1531 | NILFS_BTREE_LEVEL_NODE_MIN); | 1491 | NILFS_BTREE_LEVEL_NODE_MIN); |
| 1532 | if (ret < 0) | 1492 | if (ret < 0) |
| 1533 | goto out; | 1493 | goto out; |
| 1534 | 1494 | ||
| 1535 | ret = nilfs_btree_prepare_delete(btree, path, &level, &stats); | 1495 | |
| 1496 | dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ? | ||
| 1497 | nilfs_bmap_get_dat(&btree->bt_bmap) : NULL; | ||
| 1498 | |||
| 1499 | ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat); | ||
| 1536 | if (ret < 0) | 1500 | if (ret < 0) |
| 1537 | goto out; | 1501 | goto out; |
| 1538 | nilfs_btree_commit_delete(btree, path, level); | 1502 | nilfs_btree_commit_delete(btree, path, level, dat); |
| 1539 | nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); | 1503 | nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); |
| 1540 | 1504 | ||
| 1541 | out: | 1505 | out: |
| 1542 | nilfs_btree_clear_path(btree, path); | 1506 | nilfs_btree_release_path(path); |
| 1543 | nilfs_btree_free_path(btree, path); | 1507 | nilfs_btree_free_path(path); |
| 1544 | return ret; | 1508 | return ret; |
| 1545 | } | 1509 | } |
| 1546 | 1510 | ||
| @@ -1551,15 +1515,15 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | |||
| 1551 | int ret; | 1515 | int ret; |
| 1552 | 1516 | ||
| 1553 | btree = (struct nilfs_btree *)bmap; | 1517 | btree = (struct nilfs_btree *)bmap; |
| 1554 | path = nilfs_btree_alloc_path(btree); | 1518 | path = nilfs_btree_alloc_path(); |
| 1555 | if (path == NULL) | 1519 | if (path == NULL) |
| 1556 | return -ENOMEM; | 1520 | return -ENOMEM; |
| 1557 | nilfs_btree_init_path(btree, path); | 1521 | nilfs_btree_init_path(path); |
| 1558 | 1522 | ||
| 1559 | ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL); | 1523 | ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL); |
| 1560 | 1524 | ||
| 1561 | nilfs_btree_clear_path(btree, path); | 1525 | nilfs_btree_release_path(path); |
| 1562 | nilfs_btree_free_path(btree, path); | 1526 | nilfs_btree_free_path(path); |
| 1563 | 1527 | ||
| 1564 | return ret; | 1528 | return ret; |
| 1565 | } | 1529 | } |
| @@ -1581,7 +1545,7 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | |||
| 1581 | node = root; | 1545 | node = root; |
| 1582 | break; | 1546 | break; |
| 1583 | case 3: | 1547 | case 3: |
| 1584 | nchildren = nilfs_btree_node_get_nchildren(btree, root); | 1548 | nchildren = nilfs_btree_node_get_nchildren(root); |
| 1585 | if (nchildren > 1) | 1549 | if (nchildren > 1) |
| 1586 | return 0; | 1550 | return 0; |
| 1587 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); | 1551 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); |
| @@ -1594,10 +1558,10 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | |||
| 1594 | return 0; | 1558 | return 0; |
| 1595 | } | 1559 | } |
| 1596 | 1560 | ||
| 1597 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 1561 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 1598 | maxkey = nilfs_btree_node_get_key(btree, node, nchildren - 1); | 1562 | maxkey = nilfs_btree_node_get_key(node, nchildren - 1); |
| 1599 | nextmaxkey = (nchildren > 1) ? | 1563 | nextmaxkey = (nchildren > 1) ? |
| 1600 | nilfs_btree_node_get_key(btree, node, nchildren - 2) : 0; | 1564 | nilfs_btree_node_get_key(node, nchildren - 2) : 0; |
| 1601 | if (bh != NULL) | 1565 | if (bh != NULL) |
| 1602 | brelse(bh); | 1566 | brelse(bh); |
| 1603 | 1567 | ||
| @@ -1623,7 +1587,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | |||
| 1623 | node = root; | 1587 | node = root; |
| 1624 | break; | 1588 | break; |
| 1625 | case 3: | 1589 | case 3: |
| 1626 | nchildren = nilfs_btree_node_get_nchildren(btree, root); | 1590 | nchildren = nilfs_btree_node_get_nchildren(root); |
| 1627 | WARN_ON(nchildren > 1); | 1591 | WARN_ON(nchildren > 1); |
| 1628 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); | 1592 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); |
| 1629 | ret = nilfs_btree_get_block(btree, ptr, &bh); | 1593 | ret = nilfs_btree_get_block(btree, ptr, &bh); |
| @@ -1636,11 +1600,11 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | |||
| 1636 | return -EINVAL; | 1600 | return -EINVAL; |
| 1637 | } | 1601 | } |
| 1638 | 1602 | ||
| 1639 | nchildren = nilfs_btree_node_get_nchildren(btree, node); | 1603 | nchildren = nilfs_btree_node_get_nchildren(node); |
| 1640 | if (nchildren < nitems) | 1604 | if (nchildren < nitems) |
| 1641 | nitems = nchildren; | 1605 | nitems = nchildren; |
| 1642 | dkeys = nilfs_btree_node_dkeys(btree, node); | 1606 | dkeys = nilfs_btree_node_dkeys(node); |
| 1643 | dptrs = nilfs_btree_node_dptrs(btree, node); | 1607 | dptrs = nilfs_btree_node_dptrs(node, btree); |
| 1644 | for (i = 0; i < nitems; i++) { | 1608 | for (i = 0; i < nitems; i++) { |
| 1645 | keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]); | 1609 | keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]); |
| 1646 | ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]); | 1610 | ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]); |
| @@ -1660,18 +1624,20 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
| 1660 | struct nilfs_bmap_stats *stats) | 1624 | struct nilfs_bmap_stats *stats) |
| 1661 | { | 1625 | { |
| 1662 | struct buffer_head *bh; | 1626 | struct buffer_head *bh; |
| 1663 | struct nilfs_btree *btree; | 1627 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; |
| 1628 | struct inode *dat = NULL; | ||
| 1664 | int ret; | 1629 | int ret; |
| 1665 | 1630 | ||
| 1666 | btree = (struct nilfs_btree *)bmap; | ||
| 1667 | stats->bs_nblocks = 0; | 1631 | stats->bs_nblocks = 0; |
| 1668 | 1632 | ||
| 1669 | /* for data */ | 1633 | /* for data */ |
| 1670 | /* cannot find near ptr */ | 1634 | /* cannot find near ptr */ |
| 1671 | if (NILFS_BMAP_USE_VBN(bmap)) | 1635 | if (NILFS_BMAP_USE_VBN(bmap)) { |
| 1672 | dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key); | 1636 | dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key); |
| 1637 | dat = nilfs_bmap_get_dat(bmap); | ||
| 1638 | } | ||
| 1673 | 1639 | ||
| 1674 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq); | 1640 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat); |
| 1675 | if (ret < 0) | 1641 | if (ret < 0) |
| 1676 | return ret; | 1642 | return ret; |
| 1677 | 1643 | ||
| @@ -1679,7 +1645,7 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
| 1679 | stats->bs_nblocks++; | 1645 | stats->bs_nblocks++; |
| 1680 | if (nreq != NULL) { | 1646 | if (nreq != NULL) { |
| 1681 | nreq->bpr_ptr = dreq->bpr_ptr + 1; | 1647 | nreq->bpr_ptr = dreq->bpr_ptr + 1; |
| 1682 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq); | 1648 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat); |
| 1683 | if (ret < 0) | 1649 | if (ret < 0) |
| 1684 | goto err_out_dreq; | 1650 | goto err_out_dreq; |
| 1685 | 1651 | ||
| @@ -1696,9 +1662,9 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
| 1696 | 1662 | ||
| 1697 | /* error */ | 1663 | /* error */ |
| 1698 | err_out_nreq: | 1664 | err_out_nreq: |
| 1699 | nilfs_bmap_abort_alloc_ptr(bmap, nreq); | 1665 | nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat); |
| 1700 | err_out_dreq: | 1666 | err_out_dreq: |
| 1701 | nilfs_bmap_abort_alloc_ptr(bmap, dreq); | 1667 | nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat); |
| 1702 | stats->bs_nblocks = 0; | 1668 | stats->bs_nblocks = 0; |
| 1703 | return ret; | 1669 | return ret; |
| 1704 | 1670 | ||
| @@ -1713,8 +1679,9 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | |||
| 1713 | union nilfs_bmap_ptr_req *nreq, | 1679 | union nilfs_bmap_ptr_req *nreq, |
| 1714 | struct buffer_head *bh) | 1680 | struct buffer_head *bh) |
| 1715 | { | 1681 | { |
| 1716 | struct nilfs_btree *btree; | 1682 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; |
| 1717 | struct nilfs_btree_node *node; | 1683 | struct nilfs_btree_node *node; |
| 1684 | struct inode *dat; | ||
| 1718 | __u64 tmpptr; | 1685 | __u64 tmpptr; |
| 1719 | 1686 | ||
| 1720 | /* free resources */ | 1687 | /* free resources */ |
| @@ -1725,11 +1692,11 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | |||
| 1725 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); | 1692 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); |
| 1726 | 1693 | ||
| 1727 | /* convert and insert */ | 1694 | /* convert and insert */ |
| 1728 | btree = (struct nilfs_btree *)bmap; | 1695 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; |
| 1729 | nilfs_btree_init(bmap); | 1696 | nilfs_btree_init(bmap); |
| 1730 | if (nreq != NULL) { | 1697 | if (nreq != NULL) { |
| 1731 | nilfs_bmap_commit_alloc_ptr(bmap, dreq); | 1698 | nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat); |
| 1732 | nilfs_bmap_commit_alloc_ptr(bmap, nreq); | 1699 | nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat); |
| 1733 | 1700 | ||
| 1734 | /* create child node at level 1 */ | 1701 | /* create child node at level 1 */ |
| 1735 | lock_buffer(bh); | 1702 | lock_buffer(bh); |
| @@ -1751,7 +1718,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | |||
| 1751 | nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, | 1718 | nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, |
| 1752 | 2, 1, &keys[0], &tmpptr); | 1719 | 2, 1, &keys[0], &tmpptr); |
| 1753 | } else { | 1720 | } else { |
| 1754 | nilfs_bmap_commit_alloc_ptr(bmap, dreq); | 1721 | nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat); |
| 1755 | 1722 | ||
| 1756 | /* create root node at level 1 */ | 1723 | /* create root node at level 1 */ |
| 1757 | node = nilfs_btree_get_root(btree); | 1724 | node = nilfs_btree_get_root(btree); |
| @@ -1822,7 +1789,7 @@ static int nilfs_btree_propagate_p(struct nilfs_btree *btree, | |||
| 1822 | 1789 | ||
| 1823 | static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | 1790 | static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, |
| 1824 | struct nilfs_btree_path *path, | 1791 | struct nilfs_btree_path *path, |
| 1825 | int level) | 1792 | int level, struct inode *dat) |
| 1826 | { | 1793 | { |
| 1827 | struct nilfs_btree_node *parent; | 1794 | struct nilfs_btree_node *parent; |
| 1828 | int ret; | 1795 | int ret; |
| @@ -1832,9 +1799,8 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | |||
| 1832 | nilfs_btree_node_get_ptr(btree, parent, | 1799 | nilfs_btree_node_get_ptr(btree, parent, |
| 1833 | path[level + 1].bp_index); | 1800 | path[level + 1].bp_index); |
| 1834 | path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; | 1801 | path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; |
| 1835 | ret = nilfs_bmap_prepare_update_v(&btree->bt_bmap, | 1802 | ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req, |
| 1836 | &path[level].bp_oldreq, | 1803 | &path[level].bp_newreq.bpr_req); |
| 1837 | &path[level].bp_newreq); | ||
| 1838 | if (ret < 0) | 1804 | if (ret < 0) |
| 1839 | return ret; | 1805 | return ret; |
| 1840 | 1806 | ||
| @@ -1846,9 +1812,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | |||
| 1846 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1812 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, |
| 1847 | &path[level].bp_ctxt); | 1813 | &path[level].bp_ctxt); |
| 1848 | if (ret < 0) { | 1814 | if (ret < 0) { |
| 1849 | nilfs_bmap_abort_update_v(&btree->bt_bmap, | 1815 | nilfs_dat_abort_update(dat, |
| 1850 | &path[level].bp_oldreq, | 1816 | &path[level].bp_oldreq.bpr_req, |
| 1851 | &path[level].bp_newreq); | 1817 | &path[level].bp_newreq.bpr_req); |
| 1852 | return ret; | 1818 | return ret; |
| 1853 | } | 1819 | } |
| 1854 | } | 1820 | } |
| @@ -1858,13 +1824,13 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | |||
| 1858 | 1824 | ||
| 1859 | static void nilfs_btree_commit_update_v(struct nilfs_btree *btree, | 1825 | static void nilfs_btree_commit_update_v(struct nilfs_btree *btree, |
| 1860 | struct nilfs_btree_path *path, | 1826 | struct nilfs_btree_path *path, |
| 1861 | int level) | 1827 | int level, struct inode *dat) |
| 1862 | { | 1828 | { |
| 1863 | struct nilfs_btree_node *parent; | 1829 | struct nilfs_btree_node *parent; |
| 1864 | 1830 | ||
| 1865 | nilfs_bmap_commit_update_v(&btree->bt_bmap, | 1831 | nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req, |
| 1866 | &path[level].bp_oldreq, | 1832 | &path[level].bp_newreq.bpr_req, |
| 1867 | &path[level].bp_newreq); | 1833 | btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS); |
| 1868 | 1834 | ||
| 1869 | if (buffer_nilfs_node(path[level].bp_bh)) { | 1835 | if (buffer_nilfs_node(path[level].bp_bh)) { |
| 1870 | nilfs_btnode_commit_change_key( | 1836 | nilfs_btnode_commit_change_key( |
| @@ -1881,11 +1847,10 @@ static void nilfs_btree_commit_update_v(struct nilfs_btree *btree, | |||
| 1881 | 1847 | ||
| 1882 | static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, | 1848 | static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, |
| 1883 | struct nilfs_btree_path *path, | 1849 | struct nilfs_btree_path *path, |
| 1884 | int level) | 1850 | int level, struct inode *dat) |
| 1885 | { | 1851 | { |
| 1886 | nilfs_bmap_abort_update_v(&btree->bt_bmap, | 1852 | nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req, |
| 1887 | &path[level].bp_oldreq, | 1853 | &path[level].bp_newreq.bpr_req); |
| 1888 | &path[level].bp_newreq); | ||
| 1889 | if (buffer_nilfs_node(path[level].bp_bh)) | 1854 | if (buffer_nilfs_node(path[level].bp_bh)) |
| 1890 | nilfs_btnode_abort_change_key( | 1855 | nilfs_btnode_abort_change_key( |
| 1891 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1856 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, |
| @@ -1894,14 +1859,14 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, | |||
| 1894 | 1859 | ||
| 1895 | static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, | 1860 | static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, |
| 1896 | struct nilfs_btree_path *path, | 1861 | struct nilfs_btree_path *path, |
| 1897 | int minlevel, | 1862 | int minlevel, int *maxlevelp, |
| 1898 | int *maxlevelp) | 1863 | struct inode *dat) |
| 1899 | { | 1864 | { |
| 1900 | int level, ret; | 1865 | int level, ret; |
| 1901 | 1866 | ||
| 1902 | level = minlevel; | 1867 | level = minlevel; |
| 1903 | if (!buffer_nilfs_volatile(path[level].bp_bh)) { | 1868 | if (!buffer_nilfs_volatile(path[level].bp_bh)) { |
| 1904 | ret = nilfs_btree_prepare_update_v(btree, path, level); | 1869 | ret = nilfs_btree_prepare_update_v(btree, path, level, dat); |
| 1905 | if (ret < 0) | 1870 | if (ret < 0) |
| 1906 | return ret; | 1871 | return ret; |
| 1907 | } | 1872 | } |
| @@ -1909,7 +1874,7 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, | |||
| 1909 | !buffer_dirty(path[level].bp_bh)) { | 1874 | !buffer_dirty(path[level].bp_bh)) { |
| 1910 | 1875 | ||
| 1911 | WARN_ON(buffer_nilfs_volatile(path[level].bp_bh)); | 1876 | WARN_ON(buffer_nilfs_volatile(path[level].bp_bh)); |
| 1912 | ret = nilfs_btree_prepare_update_v(btree, path, level); | 1877 | ret = nilfs_btree_prepare_update_v(btree, path, level, dat); |
| 1913 | if (ret < 0) | 1878 | if (ret < 0) |
| 1914 | goto out; | 1879 | goto out; |
| 1915 | } | 1880 | } |
| @@ -1921,39 +1886,40 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, | |||
| 1921 | /* error */ | 1886 | /* error */ |
| 1922 | out: | 1887 | out: |
| 1923 | while (--level > minlevel) | 1888 | while (--level > minlevel) |
| 1924 | nilfs_btree_abort_update_v(btree, path, level); | 1889 | nilfs_btree_abort_update_v(btree, path, level, dat); |
| 1925 | if (!buffer_nilfs_volatile(path[level].bp_bh)) | 1890 | if (!buffer_nilfs_volatile(path[level].bp_bh)) |
| 1926 | nilfs_btree_abort_update_v(btree, path, level); | 1891 | nilfs_btree_abort_update_v(btree, path, level, dat); |
| 1927 | return ret; | 1892 | return ret; |
| 1928 | } | 1893 | } |
| 1929 | 1894 | ||
| 1930 | static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree, | 1895 | static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree, |
| 1931 | struct nilfs_btree_path *path, | 1896 | struct nilfs_btree_path *path, |
| 1932 | int minlevel, | 1897 | int minlevel, int maxlevel, |
| 1933 | int maxlevel, | 1898 | struct buffer_head *bh, |
| 1934 | struct buffer_head *bh) | 1899 | struct inode *dat) |
| 1935 | { | 1900 | { |
| 1936 | int level; | 1901 | int level; |
| 1937 | 1902 | ||
| 1938 | if (!buffer_nilfs_volatile(path[minlevel].bp_bh)) | 1903 | if (!buffer_nilfs_volatile(path[minlevel].bp_bh)) |
| 1939 | nilfs_btree_commit_update_v(btree, path, minlevel); | 1904 | nilfs_btree_commit_update_v(btree, path, minlevel, dat); |
| 1940 | 1905 | ||
| 1941 | for (level = minlevel + 1; level <= maxlevel; level++) | 1906 | for (level = minlevel + 1; level <= maxlevel; level++) |
| 1942 | nilfs_btree_commit_update_v(btree, path, level); | 1907 | nilfs_btree_commit_update_v(btree, path, level, dat); |
| 1943 | } | 1908 | } |
| 1944 | 1909 | ||
| 1945 | static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | 1910 | static int nilfs_btree_propagate_v(struct nilfs_btree *btree, |
| 1946 | struct nilfs_btree_path *path, | 1911 | struct nilfs_btree_path *path, |
| 1947 | int level, | 1912 | int level, struct buffer_head *bh) |
| 1948 | struct buffer_head *bh) | ||
| 1949 | { | 1913 | { |
| 1950 | int maxlevel, ret; | 1914 | int maxlevel, ret; |
| 1951 | struct nilfs_btree_node *parent; | 1915 | struct nilfs_btree_node *parent; |
| 1916 | struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap); | ||
| 1952 | __u64 ptr; | 1917 | __u64 ptr; |
| 1953 | 1918 | ||
| 1954 | get_bh(bh); | 1919 | get_bh(bh); |
| 1955 | path[level].bp_bh = bh; | 1920 | path[level].bp_bh = bh; |
| 1956 | ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel); | 1921 | ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel, |
| 1922 | dat); | ||
| 1957 | if (ret < 0) | 1923 | if (ret < 0) |
| 1958 | goto out; | 1924 | goto out; |
| 1959 | 1925 | ||
| @@ -1961,12 +1927,12 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | |||
| 1961 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1927 | parent = nilfs_btree_get_node(btree, path, level + 1); |
| 1962 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 1928 | ptr = nilfs_btree_node_get_ptr(btree, parent, |
| 1963 | path[level + 1].bp_index); | 1929 | path[level + 1].bp_index); |
| 1964 | ret = nilfs_bmap_mark_dirty(&btree->bt_bmap, ptr); | 1930 | ret = nilfs_dat_mark_dirty(dat, ptr); |
| 1965 | if (ret < 0) | 1931 | if (ret < 0) |
| 1966 | goto out; | 1932 | goto out; |
| 1967 | } | 1933 | } |
| 1968 | 1934 | ||
| 1969 | nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh); | 1935 | nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat); |
| 1970 | 1936 | ||
| 1971 | out: | 1937 | out: |
| 1972 | brelse(path[level].bp_bh); | 1938 | brelse(path[level].bp_bh); |
| @@ -1986,15 +1952,15 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
| 1986 | WARN_ON(!buffer_dirty(bh)); | 1952 | WARN_ON(!buffer_dirty(bh)); |
| 1987 | 1953 | ||
| 1988 | btree = (struct nilfs_btree *)bmap; | 1954 | btree = (struct nilfs_btree *)bmap; |
| 1989 | path = nilfs_btree_alloc_path(btree); | 1955 | path = nilfs_btree_alloc_path(); |
| 1990 | if (path == NULL) | 1956 | if (path == NULL) |
| 1991 | return -ENOMEM; | 1957 | return -ENOMEM; |
| 1992 | nilfs_btree_init_path(btree, path); | 1958 | nilfs_btree_init_path(path); |
| 1993 | 1959 | ||
| 1994 | if (buffer_nilfs_node(bh)) { | 1960 | if (buffer_nilfs_node(bh)) { |
| 1995 | node = (struct nilfs_btree_node *)bh->b_data; | 1961 | node = (struct nilfs_btree_node *)bh->b_data; |
| 1996 | key = nilfs_btree_node_get_key(btree, node, 0); | 1962 | key = nilfs_btree_node_get_key(node, 0); |
| 1997 | level = nilfs_btree_node_get_level(btree, node); | 1963 | level = nilfs_btree_node_get_level(node); |
| 1998 | } else { | 1964 | } else { |
| 1999 | key = nilfs_bmap_data_get_key(bmap, bh); | 1965 | key = nilfs_bmap_data_get_key(bmap, bh); |
| 2000 | level = NILFS_BTREE_LEVEL_DATA; | 1966 | level = NILFS_BTREE_LEVEL_DATA; |
| @@ -2013,8 +1979,8 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
| 2013 | nilfs_btree_propagate_p(btree, path, level, bh); | 1979 | nilfs_btree_propagate_p(btree, path, level, bh); |
| 2014 | 1980 | ||
| 2015 | out: | 1981 | out: |
| 2016 | nilfs_btree_clear_path(btree, path); | 1982 | nilfs_btree_release_path(path); |
| 2017 | nilfs_btree_free_path(btree, path); | 1983 | nilfs_btree_free_path(path); |
| 2018 | 1984 | ||
| 2019 | return ret; | 1985 | return ret; |
| 2020 | } | 1986 | } |
| @@ -2022,7 +1988,7 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
| 2022 | static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap, | 1988 | static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap, |
| 2023 | struct buffer_head *bh) | 1989 | struct buffer_head *bh) |
| 2024 | { | 1990 | { |
| 2025 | return nilfs_bmap_mark_dirty(bmap, bh->b_blocknr); | 1991 | return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr); |
| 2026 | } | 1992 | } |
| 2027 | 1993 | ||
| 2028 | static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | 1994 | static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, |
| @@ -2037,12 +2003,12 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | |||
| 2037 | 2003 | ||
| 2038 | get_bh(bh); | 2004 | get_bh(bh); |
| 2039 | node = (struct nilfs_btree_node *)bh->b_data; | 2005 | node = (struct nilfs_btree_node *)bh->b_data; |
| 2040 | key = nilfs_btree_node_get_key(btree, node, 0); | 2006 | key = nilfs_btree_node_get_key(node, 0); |
| 2041 | level = nilfs_btree_node_get_level(btree, node); | 2007 | level = nilfs_btree_node_get_level(node); |
| 2042 | list_for_each(head, &lists[level]) { | 2008 | list_for_each(head, &lists[level]) { |
| 2043 | cbh = list_entry(head, struct buffer_head, b_assoc_buffers); | 2009 | cbh = list_entry(head, struct buffer_head, b_assoc_buffers); |
| 2044 | cnode = (struct nilfs_btree_node *)cbh->b_data; | 2010 | cnode = (struct nilfs_btree_node *)cbh->b_data; |
| 2045 | ckey = nilfs_btree_node_get_key(btree, cnode, 0); | 2011 | ckey = nilfs_btree_node_get_key(cnode, 0); |
| 2046 | if (key < ckey) | 2012 | if (key < ckey) |
| 2047 | break; | 2013 | break; |
| 2048 | } | 2014 | } |
| @@ -2120,8 +2086,7 @@ static int nilfs_btree_assign_p(struct nilfs_btree *btree, | |||
| 2120 | nilfs_btree_node_set_ptr(btree, parent, | 2086 | nilfs_btree_node_set_ptr(btree, parent, |
| 2121 | path[level + 1].bp_index, blocknr); | 2087 | path[level + 1].bp_index, blocknr); |
| 2122 | 2088 | ||
| 2123 | key = nilfs_btree_node_get_key(btree, parent, | 2089 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); |
| 2124 | path[level + 1].bp_index); | ||
| 2125 | /* on-disk format */ | 2090 | /* on-disk format */ |
| 2126 | binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2091 | binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key); |
| 2127 | binfo->bi_dat.bi_level = level; | 2092 | binfo->bi_dat.bi_level = level; |
| @@ -2137,6 +2102,7 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, | |||
| 2137 | union nilfs_binfo *binfo) | 2102 | union nilfs_binfo *binfo) |
| 2138 | { | 2103 | { |
| 2139 | struct nilfs_btree_node *parent; | 2104 | struct nilfs_btree_node *parent; |
| 2105 | struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap); | ||
| 2140 | __u64 key; | 2106 | __u64 key; |
| 2141 | __u64 ptr; | 2107 | __u64 ptr; |
| 2142 | union nilfs_bmap_ptr_req req; | 2108 | union nilfs_bmap_ptr_req req; |
| @@ -2146,12 +2112,12 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, | |||
| 2146 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 2112 | ptr = nilfs_btree_node_get_ptr(btree, parent, |
| 2147 | path[level + 1].bp_index); | 2113 | path[level + 1].bp_index); |
| 2148 | req.bpr_ptr = ptr; | 2114 | req.bpr_ptr = ptr; |
| 2149 | ret = nilfs_bmap_start_v(&btree->bt_bmap, &req, blocknr); | 2115 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); |
| 2150 | if (unlikely(ret < 0)) | 2116 | if (ret < 0) |
| 2151 | return ret; | 2117 | return ret; |
| 2118 | nilfs_dat_commit_start(dat, &req.bpr_req, blocknr); | ||
| 2152 | 2119 | ||
| 2153 | key = nilfs_btree_node_get_key(btree, parent, | 2120 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); |
| 2154 | path[level + 1].bp_index); | ||
| 2155 | /* on-disk format */ | 2121 | /* on-disk format */ |
| 2156 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); | 2122 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); |
| 2157 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2123 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); |
| @@ -2171,15 +2137,15 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
| 2171 | int level, ret; | 2137 | int level, ret; |
| 2172 | 2138 | ||
| 2173 | btree = (struct nilfs_btree *)bmap; | 2139 | btree = (struct nilfs_btree *)bmap; |
| 2174 | path = nilfs_btree_alloc_path(btree); | 2140 | path = nilfs_btree_alloc_path(); |
| 2175 | if (path == NULL) | 2141 | if (path == NULL) |
| 2176 | return -ENOMEM; | 2142 | return -ENOMEM; |
| 2177 | nilfs_btree_init_path(btree, path); | 2143 | nilfs_btree_init_path(path); |
| 2178 | 2144 | ||
| 2179 | if (buffer_nilfs_node(*bh)) { | 2145 | if (buffer_nilfs_node(*bh)) { |
| 2180 | node = (struct nilfs_btree_node *)(*bh)->b_data; | 2146 | node = (struct nilfs_btree_node *)(*bh)->b_data; |
| 2181 | key = nilfs_btree_node_get_key(btree, node, 0); | 2147 | key = nilfs_btree_node_get_key(node, 0); |
| 2182 | level = nilfs_btree_node_get_level(btree, node); | 2148 | level = nilfs_btree_node_get_level(node); |
| 2183 | } else { | 2149 | } else { |
| 2184 | key = nilfs_bmap_data_get_key(bmap, *bh); | 2150 | key = nilfs_bmap_data_get_key(bmap, *bh); |
| 2185 | level = NILFS_BTREE_LEVEL_DATA; | 2151 | level = NILFS_BTREE_LEVEL_DATA; |
| @@ -2196,8 +2162,8 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
| 2196 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); | 2162 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); |
| 2197 | 2163 | ||
| 2198 | out: | 2164 | out: |
| 2199 | nilfs_btree_clear_path(btree, path); | 2165 | nilfs_btree_release_path(path); |
| 2200 | nilfs_btree_free_path(btree, path); | 2166 | nilfs_btree_free_path(path); |
| 2201 | 2167 | ||
| 2202 | return ret; | 2168 | return ret; |
| 2203 | } | 2169 | } |
| @@ -2207,19 +2173,18 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, | |||
| 2207 | sector_t blocknr, | 2173 | sector_t blocknr, |
| 2208 | union nilfs_binfo *binfo) | 2174 | union nilfs_binfo *binfo) |
| 2209 | { | 2175 | { |
| 2210 | struct nilfs_btree *btree; | ||
| 2211 | struct nilfs_btree_node *node; | 2176 | struct nilfs_btree_node *node; |
| 2212 | __u64 key; | 2177 | __u64 key; |
| 2213 | int ret; | 2178 | int ret; |
| 2214 | 2179 | ||
| 2215 | btree = (struct nilfs_btree *)bmap; | 2180 | ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr, |
| 2216 | ret = nilfs_bmap_move_v(bmap, (*bh)->b_blocknr, blocknr); | 2181 | blocknr); |
| 2217 | if (ret < 0) | 2182 | if (ret < 0) |
| 2218 | return ret; | 2183 | return ret; |
| 2219 | 2184 | ||
| 2220 | if (buffer_nilfs_node(*bh)) { | 2185 | if (buffer_nilfs_node(*bh)) { |
| 2221 | node = (struct nilfs_btree_node *)(*bh)->b_data; | 2186 | node = (struct nilfs_btree_node *)(*bh)->b_data; |
| 2222 | key = nilfs_btree_node_get_key(btree, node, 0); | 2187 | key = nilfs_btree_node_get_key(node, 0); |
| 2223 | } else | 2188 | } else |
| 2224 | key = nilfs_bmap_data_get_key(bmap, *bh); | 2189 | key = nilfs_bmap_data_get_key(bmap, *bh); |
| 2225 | 2190 | ||
| @@ -2239,10 +2204,10 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
| 2239 | int ret; | 2204 | int ret; |
| 2240 | 2205 | ||
| 2241 | btree = (struct nilfs_btree *)bmap; | 2206 | btree = (struct nilfs_btree *)bmap; |
| 2242 | path = nilfs_btree_alloc_path(btree); | 2207 | path = nilfs_btree_alloc_path(); |
| 2243 | if (path == NULL) | 2208 | if (path == NULL) |
| 2244 | return -ENOMEM; | 2209 | return -ENOMEM; |
| 2245 | nilfs_btree_init_path(btree, path); | 2210 | nilfs_btree_init_path(path); |
| 2246 | 2211 | ||
| 2247 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); | 2212 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); |
| 2248 | if (ret < 0) { | 2213 | if (ret < 0) { |
| @@ -2262,8 +2227,8 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
| 2262 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 2227 | nilfs_bmap_set_dirty(&btree->bt_bmap); |
| 2263 | 2228 | ||
| 2264 | out: | 2229 | out: |
| 2265 | nilfs_btree_clear_path(btree, path); | 2230 | nilfs_btree_release_path(path); |
| 2266 | nilfs_btree_free_path(btree, path); | 2231 | nilfs_btree_free_path(path); |
| 2267 | return ret; | 2232 | return ret; |
| 2268 | } | 2233 | } |
| 2269 | 2234 | ||
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index aec942cf79e3..1c6cfb59128d 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c | |||
| @@ -815,8 +815,10 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) | |||
| 815 | void *kaddr; | 815 | void *kaddr; |
| 816 | int ret; | 816 | int ret; |
| 817 | 817 | ||
| 818 | if (cno == 0) | 818 | /* CP number is invalid if it's zero or larger than the |
| 819 | return -ENOENT; /* checkpoint number 0 is invalid */ | 819 | largest exist one.*/ |
| 820 | if (cno == 0 || cno >= nilfs_mdt_cno(cpfile)) | ||
| 821 | return -ENOENT; | ||
| 820 | down_read(&NILFS_MDT(cpfile)->mi_sem); | 822 | down_read(&NILFS_MDT(cpfile)->mi_sem); |
| 821 | 823 | ||
| 822 | ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); | 824 | ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); |
| @@ -824,7 +826,10 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno) | |||
| 824 | goto out; | 826 | goto out; |
| 825 | kaddr = kmap_atomic(bh->b_page, KM_USER0); | 827 | kaddr = kmap_atomic(bh->b_page, KM_USER0); |
| 826 | cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); | 828 | cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); |
| 827 | ret = nilfs_checkpoint_snapshot(cp); | 829 | if (nilfs_checkpoint_invalid(cp)) |
| 830 | ret = -ENOENT; | ||
| 831 | else | ||
| 832 | ret = nilfs_checkpoint_snapshot(cp); | ||
| 828 | kunmap_atomic(kaddr, KM_USER0); | 833 | kunmap_atomic(kaddr, KM_USER0); |
| 829 | brelse(bh); | 834 | brelse(bh); |
| 830 | 835 | ||
diff --git a/fs/nilfs2/cpfile.h b/fs/nilfs2/cpfile.h index 788a45950197..debea896e701 100644 --- a/fs/nilfs2/cpfile.h +++ b/fs/nilfs2/cpfile.h | |||
| @@ -27,8 +27,6 @@ | |||
| 27 | #include <linux/buffer_head.h> | 27 | #include <linux/buffer_head.h> |
| 28 | #include <linux/nilfs2_fs.h> | 28 | #include <linux/nilfs2_fs.h> |
| 29 | 29 | ||
| 30 | #define NILFS_CPFILE_GFP NILFS_MDT_GFP | ||
| 31 | |||
| 32 | 30 | ||
| 33 | int nilfs_cpfile_get_checkpoint(struct inode *, __u64, int, | 31 | int nilfs_cpfile_get_checkpoint(struct inode *, __u64, int, |
| 34 | struct nilfs_checkpoint **, | 32 | struct nilfs_checkpoint **, |
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 8927ca27e6f7..1ff8e15bd36b 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c | |||
| @@ -109,12 +109,6 @@ void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req) | |||
| 109 | nilfs_palloc_commit_free_entry(dat, req); | 109 | nilfs_palloc_commit_free_entry(dat, req); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | void nilfs_dat_abort_free(struct inode *dat, struct nilfs_palloc_req *req) | ||
| 113 | { | ||
| 114 | nilfs_dat_abort_entry(dat, req); | ||
| 115 | nilfs_palloc_abort_free_entry(dat, req); | ||
| 116 | } | ||
| 117 | |||
| 118 | int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req) | 112 | int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req) |
| 119 | { | 113 | { |
| 120 | int ret; | 114 | int ret; |
| @@ -140,11 +134,6 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req, | |||
| 140 | nilfs_dat_commit_entry(dat, req); | 134 | nilfs_dat_commit_entry(dat, req); |
| 141 | } | 135 | } |
| 142 | 136 | ||
| 143 | void nilfs_dat_abort_start(struct inode *dat, struct nilfs_palloc_req *req) | ||
| 144 | { | ||
| 145 | nilfs_dat_abort_entry(dat, req); | ||
| 146 | } | ||
| 147 | |||
| 148 | int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) | 137 | int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) |
| 149 | { | 138 | { |
| 150 | struct nilfs_dat_entry *entry; | 139 | struct nilfs_dat_entry *entry; |
| @@ -222,6 +211,37 @@ void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req) | |||
| 222 | nilfs_dat_abort_entry(dat, req); | 211 | nilfs_dat_abort_entry(dat, req); |
| 223 | } | 212 | } |
| 224 | 213 | ||
| 214 | int nilfs_dat_prepare_update(struct inode *dat, | ||
| 215 | struct nilfs_palloc_req *oldreq, | ||
| 216 | struct nilfs_palloc_req *newreq) | ||
| 217 | { | ||
| 218 | int ret; | ||
| 219 | |||
| 220 | ret = nilfs_dat_prepare_end(dat, oldreq); | ||
| 221 | if (!ret) { | ||
| 222 | ret = nilfs_dat_prepare_alloc(dat, newreq); | ||
| 223 | if (ret < 0) | ||
| 224 | nilfs_dat_abort_end(dat, oldreq); | ||
| 225 | } | ||
| 226 | return ret; | ||
| 227 | } | ||
| 228 | |||
| 229 | void nilfs_dat_commit_update(struct inode *dat, | ||
| 230 | struct nilfs_palloc_req *oldreq, | ||
| 231 | struct nilfs_palloc_req *newreq, int dead) | ||
| 232 | { | ||
| 233 | nilfs_dat_commit_end(dat, oldreq, dead); | ||
| 234 | nilfs_dat_commit_alloc(dat, newreq); | ||
| 235 | } | ||
| 236 | |||
| 237 | void nilfs_dat_abort_update(struct inode *dat, | ||
| 238 | struct nilfs_palloc_req *oldreq, | ||
| 239 | struct nilfs_palloc_req *newreq) | ||
| 240 | { | ||
| 241 | nilfs_dat_abort_end(dat, oldreq); | ||
| 242 | nilfs_dat_abort_alloc(dat, newreq); | ||
| 243 | } | ||
| 244 | |||
| 225 | /** | 245 | /** |
| 226 | * nilfs_dat_mark_dirty - | 246 | * nilfs_dat_mark_dirty - |
| 227 | * @dat: DAT file inode | 247 | * @dat: DAT file inode |
diff --git a/fs/nilfs2/dat.h b/fs/nilfs2/dat.h index d328b81eead4..406070d3ff49 100644 --- a/fs/nilfs2/dat.h +++ b/fs/nilfs2/dat.h | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/buffer_head.h> | 27 | #include <linux/buffer_head.h> |
| 28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
| 29 | 29 | ||
| 30 | #define NILFS_DAT_GFP NILFS_MDT_GFP | ||
| 31 | 30 | ||
| 32 | struct nilfs_palloc_req; | 31 | struct nilfs_palloc_req; |
| 33 | 32 | ||
| @@ -39,10 +38,15 @@ void nilfs_dat_abort_alloc(struct inode *, struct nilfs_palloc_req *); | |||
| 39 | int nilfs_dat_prepare_start(struct inode *, struct nilfs_palloc_req *); | 38 | int nilfs_dat_prepare_start(struct inode *, struct nilfs_palloc_req *); |
| 40 | void nilfs_dat_commit_start(struct inode *, struct nilfs_palloc_req *, | 39 | void nilfs_dat_commit_start(struct inode *, struct nilfs_palloc_req *, |
| 41 | sector_t); | 40 | sector_t); |
| 42 | void nilfs_dat_abort_start(struct inode *, struct nilfs_palloc_req *); | ||
| 43 | int nilfs_dat_prepare_end(struct inode *, struct nilfs_palloc_req *); | 41 | int nilfs_dat_prepare_end(struct inode *, struct nilfs_palloc_req *); |
| 44 | void nilfs_dat_commit_end(struct inode *, struct nilfs_palloc_req *, int); | 42 | void nilfs_dat_commit_end(struct inode *, struct nilfs_palloc_req *, int); |
| 45 | void nilfs_dat_abort_end(struct inode *, struct nilfs_palloc_req *); | 43 | void nilfs_dat_abort_end(struct inode *, struct nilfs_palloc_req *); |
| 44 | int nilfs_dat_prepare_update(struct inode *, struct nilfs_palloc_req *, | ||
| 45 | struct nilfs_palloc_req *); | ||
| 46 | void nilfs_dat_commit_update(struct inode *, struct nilfs_palloc_req *, | ||
| 47 | struct nilfs_palloc_req *, int); | ||
| 48 | void nilfs_dat_abort_update(struct inode *, struct nilfs_palloc_req *, | ||
| 49 | struct nilfs_palloc_req *); | ||
| 46 | 50 | ||
| 47 | int nilfs_dat_mark_dirty(struct inode *, __u64); | 51 | int nilfs_dat_mark_dirty(struct inode *, __u64); |
| 48 | int nilfs_dat_freev(struct inode *, __u64 *, size_t); | 52 | int nilfs_dat_freev(struct inode *, __u64 *, size_t); |
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 342d9765df8d..d369ac718277 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c | |||
| @@ -125,106 +125,64 @@ static void nilfs_direct_set_target_v(struct nilfs_direct *direct, | |||
| 125 | direct->d_bmap.b_last_allocated_ptr = ptr; | 125 | direct->d_bmap.b_last_allocated_ptr = ptr; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | static int nilfs_direct_prepare_insert(struct nilfs_direct *direct, | ||
| 129 | __u64 key, | ||
| 130 | union nilfs_bmap_ptr_req *req, | ||
| 131 | struct nilfs_bmap_stats *stats) | ||
| 132 | { | ||
| 133 | int ret; | ||
| 134 | |||
| 135 | if (NILFS_BMAP_USE_VBN(&direct->d_bmap)) | ||
| 136 | req->bpr_ptr = nilfs_direct_find_target_v(direct, key); | ||
| 137 | ret = nilfs_bmap_prepare_alloc_ptr(&direct->d_bmap, req); | ||
| 138 | if (ret < 0) | ||
| 139 | return ret; | ||
| 140 | |||
| 141 | stats->bs_nblocks = 1; | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static void nilfs_direct_commit_insert(struct nilfs_direct *direct, | ||
| 146 | union nilfs_bmap_ptr_req *req, | ||
| 147 | __u64 key, __u64 ptr) | ||
| 148 | { | ||
| 149 | struct buffer_head *bh; | ||
| 150 | |||
| 151 | /* ptr must be a pointer to a buffer head. */ | ||
| 152 | bh = (struct buffer_head *)((unsigned long)ptr); | ||
| 153 | set_buffer_nilfs_volatile(bh); | ||
| 154 | |||
| 155 | nilfs_bmap_commit_alloc_ptr(&direct->d_bmap, req); | ||
| 156 | nilfs_direct_set_ptr(direct, key, req->bpr_ptr); | ||
| 157 | |||
| 158 | if (!nilfs_bmap_dirty(&direct->d_bmap)) | ||
| 159 | nilfs_bmap_set_dirty(&direct->d_bmap); | ||
| 160 | |||
| 161 | if (NILFS_BMAP_USE_VBN(&direct->d_bmap)) | ||
| 162 | nilfs_direct_set_target_v(direct, key, req->bpr_ptr); | ||
| 163 | } | ||
| 164 | |||
| 165 | static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | 128 | static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) |
| 166 | { | 129 | { |
| 167 | struct nilfs_direct *direct; | 130 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; |
| 168 | union nilfs_bmap_ptr_req req; | 131 | union nilfs_bmap_ptr_req req; |
| 169 | struct nilfs_bmap_stats stats; | 132 | struct inode *dat = NULL; |
| 133 | struct buffer_head *bh; | ||
| 170 | int ret; | 134 | int ret; |
| 171 | 135 | ||
| 172 | direct = (struct nilfs_direct *)bmap; | ||
| 173 | if (key > NILFS_DIRECT_KEY_MAX) | 136 | if (key > NILFS_DIRECT_KEY_MAX) |
| 174 | return -ENOENT; | 137 | return -ENOENT; |
| 175 | if (nilfs_direct_get_ptr(direct, key) != NILFS_BMAP_INVALID_PTR) | 138 | if (nilfs_direct_get_ptr(direct, key) != NILFS_BMAP_INVALID_PTR) |
| 176 | return -EEXIST; | 139 | return -EEXIST; |
| 177 | 140 | ||
| 178 | ret = nilfs_direct_prepare_insert(direct, key, &req, &stats); | 141 | if (NILFS_BMAP_USE_VBN(bmap)) { |
| 179 | if (ret < 0) | 142 | req.bpr_ptr = nilfs_direct_find_target_v(direct, key); |
| 180 | return ret; | 143 | dat = nilfs_bmap_get_dat(bmap); |
| 181 | nilfs_direct_commit_insert(direct, &req, key, ptr); | 144 | } |
| 182 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); | 145 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat); |
| 146 | if (!ret) { | ||
| 147 | /* ptr must be a pointer to a buffer head. */ | ||
| 148 | bh = (struct buffer_head *)((unsigned long)ptr); | ||
| 149 | set_buffer_nilfs_volatile(bh); | ||
| 183 | 150 | ||
| 184 | return 0; | 151 | nilfs_bmap_commit_alloc_ptr(bmap, &req, dat); |
| 185 | } | 152 | nilfs_direct_set_ptr(direct, key, req.bpr_ptr); |
| 186 | 153 | ||
| 187 | static int nilfs_direct_prepare_delete(struct nilfs_direct *direct, | 154 | if (!nilfs_bmap_dirty(bmap)) |
| 188 | union nilfs_bmap_ptr_req *req, | 155 | nilfs_bmap_set_dirty(bmap); |
| 189 | __u64 key, | ||
| 190 | struct nilfs_bmap_stats *stats) | ||
| 191 | { | ||
| 192 | int ret; | ||
| 193 | 156 | ||
| 194 | req->bpr_ptr = nilfs_direct_get_ptr(direct, key); | 157 | if (NILFS_BMAP_USE_VBN(bmap)) |
| 195 | ret = nilfs_bmap_prepare_end_ptr(&direct->d_bmap, req); | 158 | nilfs_direct_set_target_v(direct, key, req.bpr_ptr); |
| 196 | if (!ret) | ||
| 197 | stats->bs_nblocks = 1; | ||
| 198 | return ret; | ||
| 199 | } | ||
| 200 | 159 | ||
| 201 | static void nilfs_direct_commit_delete(struct nilfs_direct *direct, | 160 | nilfs_bmap_add_blocks(bmap, 1); |
| 202 | union nilfs_bmap_ptr_req *req, | 161 | } |
| 203 | __u64 key) | 162 | return ret; |
| 204 | { | ||
| 205 | nilfs_bmap_commit_end_ptr(&direct->d_bmap, req); | ||
| 206 | nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR); | ||
| 207 | } | 163 | } |
| 208 | 164 | ||
| 209 | static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) | 165 | static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) |
| 210 | { | 166 | { |
| 211 | struct nilfs_direct *direct; | 167 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; |
| 212 | union nilfs_bmap_ptr_req req; | 168 | union nilfs_bmap_ptr_req req; |
| 213 | struct nilfs_bmap_stats stats; | 169 | struct inode *dat; |
| 214 | int ret; | 170 | int ret; |
| 215 | 171 | ||
| 216 | direct = (struct nilfs_direct *)bmap; | 172 | if (key > NILFS_DIRECT_KEY_MAX || |
| 217 | if ((key > NILFS_DIRECT_KEY_MAX) || | ||
| 218 | nilfs_direct_get_ptr(direct, key) == NILFS_BMAP_INVALID_PTR) | 173 | nilfs_direct_get_ptr(direct, key) == NILFS_BMAP_INVALID_PTR) |
| 219 | return -ENOENT; | 174 | return -ENOENT; |
| 220 | 175 | ||
| 221 | ret = nilfs_direct_prepare_delete(direct, &req, key, &stats); | 176 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; |
| 222 | if (ret < 0) | 177 | req.bpr_ptr = nilfs_direct_get_ptr(direct, key); |
| 223 | return ret; | ||
| 224 | nilfs_direct_commit_delete(direct, &req, key); | ||
| 225 | nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); | ||
| 226 | 178 | ||
| 227 | return 0; | 179 | ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat); |
| 180 | if (!ret) { | ||
| 181 | nilfs_bmap_commit_end_ptr(bmap, &req, dat); | ||
| 182 | nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR); | ||
| 183 | nilfs_bmap_sub_blocks(bmap, 1); | ||
| 184 | } | ||
| 185 | return ret; | ||
| 228 | } | 186 | } |
| 229 | 187 | ||
| 230 | static int nilfs_direct_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | 188 | static int nilfs_direct_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) |
| @@ -310,59 +268,56 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, | |||
| 310 | return 0; | 268 | return 0; |
| 311 | } | 269 | } |
| 312 | 270 | ||
| 313 | static int nilfs_direct_propagate_v(struct nilfs_direct *direct, | 271 | static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, |
| 314 | struct buffer_head *bh) | 272 | struct buffer_head *bh) |
| 315 | { | 273 | { |
| 316 | union nilfs_bmap_ptr_req oldreq, newreq; | 274 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; |
| 275 | struct nilfs_palloc_req oldreq, newreq; | ||
| 276 | struct inode *dat; | ||
| 317 | __u64 key; | 277 | __u64 key; |
| 318 | __u64 ptr; | 278 | __u64 ptr; |
| 319 | int ret; | 279 | int ret; |
| 320 | 280 | ||
| 321 | key = nilfs_bmap_data_get_key(&direct->d_bmap, bh); | 281 | if (!NILFS_BMAP_USE_VBN(bmap)) |
| 282 | return 0; | ||
| 283 | |||
| 284 | dat = nilfs_bmap_get_dat(bmap); | ||
| 285 | key = nilfs_bmap_data_get_key(bmap, bh); | ||
| 322 | ptr = nilfs_direct_get_ptr(direct, key); | 286 | ptr = nilfs_direct_get_ptr(direct, key); |
| 323 | if (!buffer_nilfs_volatile(bh)) { | 287 | if (!buffer_nilfs_volatile(bh)) { |
| 324 | oldreq.bpr_ptr = ptr; | 288 | oldreq.pr_entry_nr = ptr; |
| 325 | newreq.bpr_ptr = ptr; | 289 | newreq.pr_entry_nr = ptr; |
| 326 | ret = nilfs_bmap_prepare_update_v(&direct->d_bmap, &oldreq, | 290 | ret = nilfs_dat_prepare_update(dat, &oldreq, &newreq); |
| 327 | &newreq); | ||
| 328 | if (ret < 0) | 291 | if (ret < 0) |
| 329 | return ret; | 292 | return ret; |
| 330 | nilfs_bmap_commit_update_v(&direct->d_bmap, &oldreq, &newreq); | 293 | nilfs_dat_commit_update(dat, &oldreq, &newreq, |
| 294 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); | ||
| 331 | set_buffer_nilfs_volatile(bh); | 295 | set_buffer_nilfs_volatile(bh); |
| 332 | nilfs_direct_set_ptr(direct, key, newreq.bpr_ptr); | 296 | nilfs_direct_set_ptr(direct, key, newreq.pr_entry_nr); |
| 333 | } else | 297 | } else |
| 334 | ret = nilfs_bmap_mark_dirty(&direct->d_bmap, ptr); | 298 | ret = nilfs_dat_mark_dirty(dat, ptr); |
| 335 | 299 | ||
| 336 | return ret; | 300 | return ret; |
| 337 | } | 301 | } |
| 338 | 302 | ||
| 339 | static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, | ||
| 340 | struct buffer_head *bh) | ||
| 341 | { | ||
| 342 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
| 343 | |||
| 344 | return NILFS_BMAP_USE_VBN(bmap) ? | ||
| 345 | nilfs_direct_propagate_v(direct, bh) : 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | static int nilfs_direct_assign_v(struct nilfs_direct *direct, | 303 | static int nilfs_direct_assign_v(struct nilfs_direct *direct, |
| 349 | __u64 key, __u64 ptr, | 304 | __u64 key, __u64 ptr, |
| 350 | struct buffer_head **bh, | 305 | struct buffer_head **bh, |
| 351 | sector_t blocknr, | 306 | sector_t blocknr, |
| 352 | union nilfs_binfo *binfo) | 307 | union nilfs_binfo *binfo) |
| 353 | { | 308 | { |
| 309 | struct inode *dat = nilfs_bmap_get_dat(&direct->d_bmap); | ||
| 354 | union nilfs_bmap_ptr_req req; | 310 | union nilfs_bmap_ptr_req req; |
| 355 | int ret; | 311 | int ret; |
| 356 | 312 | ||
| 357 | req.bpr_ptr = ptr; | 313 | req.bpr_ptr = ptr; |
| 358 | ret = nilfs_bmap_start_v(&direct->d_bmap, &req, blocknr); | 314 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); |
| 359 | if (unlikely(ret < 0)) | 315 | if (!ret) { |
| 360 | return ret; | 316 | nilfs_dat_commit_start(dat, &req.bpr_req, blocknr); |
| 361 | 317 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); | |
| 362 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); | 318 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); |
| 363 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 319 | } |
| 364 | 320 | return ret; | |
| 365 | return 0; | ||
| 366 | } | 321 | } |
| 367 | 322 | ||
| 368 | static int nilfs_direct_assign_p(struct nilfs_direct *direct, | 323 | static int nilfs_direct_assign_p(struct nilfs_direct *direct, |
diff --git a/fs/nilfs2/ifile.h b/fs/nilfs2/ifile.h index 5d30a35679b5..ecc3ba76db47 100644 --- a/fs/nilfs2/ifile.h +++ b/fs/nilfs2/ifile.h | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include "mdt.h" | 31 | #include "mdt.h" |
| 32 | #include "alloc.h" | 32 | #include "alloc.h" |
| 33 | 33 | ||
| 34 | #define NILFS_IFILE_GFP NILFS_MDT_GFP | ||
| 35 | 34 | ||
| 36 | static inline struct nilfs_inode * | 35 | static inline struct nilfs_inode * |
| 37 | nilfs_ifile_map_inode(struct inode *ifile, ino_t ino, struct buffer_head *ibh) | 36 | nilfs_ifile_map_inode(struct inode *ifile, ino_t ino, struct buffer_head *ibh) |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index fe9d8f2a13f8..807e584b163d 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
| @@ -430,7 +430,8 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, | |||
| 430 | 430 | ||
| 431 | raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, bh); | 431 | raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, bh); |
| 432 | 432 | ||
| 433 | if (nilfs_read_inode_common(inode, raw_inode)) | 433 | err = nilfs_read_inode_common(inode, raw_inode); |
| 434 | if (err) | ||
| 434 | goto failed_unmap; | 435 | goto failed_unmap; |
| 435 | 436 | ||
| 436 | if (S_ISREG(inode->i_mode)) { | 437 | if (S_ISREG(inode->i_mode)) { |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 6ea5f872e2de..6572ea4bc4df 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -442,12 +442,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, | |||
| 442 | const char *msg; | 442 | const char *msg; |
| 443 | int ret; | 443 | int ret; |
| 444 | 444 | ||
| 445 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); | ||
| 446 | if (ret < 0) { | ||
| 447 | msg = "cannot read source blocks"; | ||
| 448 | goto failed; | ||
| 449 | } | ||
| 450 | |||
| 451 | ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]); | 445 | ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]); |
| 452 | if (ret < 0) { | 446 | if (ret < 0) { |
| 453 | /* | 447 | /* |
| @@ -548,7 +542,25 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
| 548 | } | 542 | } |
| 549 | } | 543 | } |
| 550 | 544 | ||
| 551 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); | 545 | /* |
| 546 | * nilfs_ioctl_move_blocks() will call nilfs_gc_iget(), | ||
| 547 | * which will operates an inode list without blocking. | ||
| 548 | * To protect the list from concurrent operations, | ||
| 549 | * nilfs_ioctl_move_blocks should be atomic operation. | ||
| 550 | */ | ||
| 551 | if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) { | ||
| 552 | ret = -EBUSY; | ||
| 553 | goto out_free; | ||
| 554 | } | ||
| 555 | |||
| 556 | ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); | ||
| 557 | if (ret < 0) | ||
| 558 | printk(KERN_ERR "NILFS: GC failed during preparation: " | ||
| 559 | "cannot read source blocks: err=%d\n", ret); | ||
| 560 | else | ||
| 561 | ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); | ||
| 562 | |||
| 563 | clear_nilfs_gc_running(nilfs); | ||
| 552 | 564 | ||
| 553 | out_free: | 565 | out_free: |
| 554 | while (--n >= 0) | 566 | while (--n >= 0) |
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 2dfd47714ae5..156bf6091a96 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
| @@ -103,15 +103,12 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block, | |||
| 103 | goto failed_unlock; | 103 | goto failed_unlock; |
| 104 | 104 | ||
| 105 | err = -EEXIST; | 105 | err = -EEXIST; |
| 106 | if (buffer_uptodate(bh) || buffer_mapped(bh)) | 106 | if (buffer_uptodate(bh)) |
| 107 | goto failed_bh; | 107 | goto failed_bh; |
| 108 | #if 0 | 108 | |
| 109 | /* The uptodate flag is not protected by the page lock, but | ||
| 110 | the mapped flag is. Thus, we don't have to wait the buffer. */ | ||
| 111 | wait_on_buffer(bh); | 109 | wait_on_buffer(bh); |
| 112 | if (buffer_uptodate(bh)) | 110 | if (buffer_uptodate(bh)) |
| 113 | goto failed_bh; | 111 | goto failed_bh; |
| 114 | #endif | ||
| 115 | 112 | ||
| 116 | bh->b_bdev = nilfs->ns_bdev; | 113 | bh->b_bdev = nilfs->ns_bdev; |
| 117 | err = nilfs_mdt_insert_new_block(inode, block, bh, init_block); | 114 | err = nilfs_mdt_insert_new_block(inode, block, bh, init_block); |
| @@ -139,7 +136,7 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, | |||
| 139 | int mode, struct buffer_head **out_bh) | 136 | int mode, struct buffer_head **out_bh) |
| 140 | { | 137 | { |
| 141 | struct buffer_head *bh; | 138 | struct buffer_head *bh; |
| 142 | unsigned long blknum = 0; | 139 | __u64 blknum = 0; |
| 143 | int ret = -ENOMEM; | 140 | int ret = -ENOMEM; |
| 144 | 141 | ||
| 145 | bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0); | 142 | bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0); |
| @@ -162,17 +159,15 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, | |||
| 162 | unlock_buffer(bh); | 159 | unlock_buffer(bh); |
| 163 | goto out; | 160 | goto out; |
| 164 | } | 161 | } |
| 165 | if (!buffer_mapped(bh)) { /* unused buffer */ | 162 | |
| 166 | ret = nilfs_bmap_lookup(NILFS_I(inode)->i_bmap, blkoff, | 163 | ret = nilfs_bmap_lookup(NILFS_I(inode)->i_bmap, blkoff, &blknum); |
| 167 | &blknum); | 164 | if (unlikely(ret)) { |
| 168 | if (unlikely(ret)) { | 165 | unlock_buffer(bh); |
| 169 | unlock_buffer(bh); | 166 | goto failed_bh; |
| 170 | goto failed_bh; | ||
| 171 | } | ||
| 172 | bh->b_bdev = NILFS_MDT(inode)->mi_nilfs->ns_bdev; | ||
| 173 | bh->b_blocknr = blknum; | ||
| 174 | set_buffer_mapped(bh); | ||
| 175 | } | 167 | } |
| 168 | bh->b_bdev = NILFS_MDT(inode)->mi_nilfs->ns_bdev; | ||
| 169 | bh->b_blocknr = (sector_t)blknum; | ||
| 170 | set_buffer_mapped(bh); | ||
| 176 | 171 | ||
| 177 | bh->b_end_io = end_buffer_read_sync; | 172 | bh->b_end_io = end_buffer_read_sync; |
| 178 | get_bh(bh); | 173 | get_bh(bh); |
| @@ -402,6 +397,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | |||
| 402 | struct inode *inode = container_of(page->mapping, | 397 | struct inode *inode = container_of(page->mapping, |
| 403 | struct inode, i_data); | 398 | struct inode, i_data); |
| 404 | struct super_block *sb = inode->i_sb; | 399 | struct super_block *sb = inode->i_sb; |
| 400 | struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs; | ||
| 405 | struct nilfs_sb_info *writer = NULL; | 401 | struct nilfs_sb_info *writer = NULL; |
| 406 | int err = 0; | 402 | int err = 0; |
| 407 | 403 | ||
| @@ -411,9 +407,10 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | |||
| 411 | if (page->mapping->assoc_mapping) | 407 | if (page->mapping->assoc_mapping) |
| 412 | return 0; /* Do not request flush for shadow page cache */ | 408 | return 0; /* Do not request flush for shadow page cache */ |
| 413 | if (!sb) { | 409 | if (!sb) { |
| 414 | writer = nilfs_get_writer(NILFS_MDT(inode)->mi_nilfs); | 410 | down_read(&nilfs->ns_writer_sem); |
| 411 | writer = nilfs->ns_writer; | ||
| 415 | if (!writer) { | 412 | if (!writer) { |
| 416 | nilfs_put_writer(NILFS_MDT(inode)->mi_nilfs); | 413 | up_read(&nilfs->ns_writer_sem); |
| 417 | return -EROFS; | 414 | return -EROFS; |
| 418 | } | 415 | } |
| 419 | sb = writer->s_super; | 416 | sb = writer->s_super; |
| @@ -425,7 +422,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | |||
| 425 | nilfs_flush_segment(sb, inode->i_ino); | 422 | nilfs_flush_segment(sb, inode->i_ino); |
| 426 | 423 | ||
| 427 | if (writer) | 424 | if (writer) |
| 428 | nilfs_put_writer(NILFS_MDT(inode)->mi_nilfs); | 425 | up_read(&nilfs->ns_writer_sem); |
| 429 | return err; | 426 | return err; |
| 430 | } | 427 | } |
| 431 | 428 | ||
| @@ -516,9 +513,10 @@ nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb, | |||
| 516 | } | 513 | } |
| 517 | 514 | ||
| 518 | struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb, | 515 | struct inode *nilfs_mdt_new(struct the_nilfs *nilfs, struct super_block *sb, |
| 519 | ino_t ino, gfp_t gfp_mask) | 516 | ino_t ino) |
| 520 | { | 517 | { |
| 521 | struct inode *inode = nilfs_mdt_new_common(nilfs, sb, ino, gfp_mask); | 518 | struct inode *inode = nilfs_mdt_new_common(nilfs, sb, ino, |
| 519 | NILFS_MDT_GFP); | ||
| 522 | 520 | ||
| 523 | if (!inode) | 521 | if (!inode) |
| 524 | return NULL; | 522 | return NULL; |
diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index df683e0bca6a..431599733c9b 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h | |||
| @@ -74,8 +74,7 @@ int nilfs_mdt_forget_block(struct inode *, unsigned long); | |||
| 74 | int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); | 74 | int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); |
| 75 | int nilfs_mdt_fetch_dirty(struct inode *); | 75 | int nilfs_mdt_fetch_dirty(struct inode *); |
| 76 | 76 | ||
| 77 | struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t, | 77 | struct inode *nilfs_mdt_new(struct the_nilfs *, struct super_block *, ino_t); |
| 78 | gfp_t); | ||
| 79 | struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *, | 78 | struct inode *nilfs_mdt_new_common(struct the_nilfs *, struct super_block *, |
| 80 | ino_t, gfp_t); | 79 | ino_t, gfp_t); |
| 81 | void nilfs_mdt_destroy(struct inode *); | 80 | void nilfs_mdt_destroy(struct inode *); |
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index d80cc71be749..6dc83591d118 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c | |||
| @@ -552,7 +552,8 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi, | |||
| 552 | printk(KERN_WARNING | 552 | printk(KERN_WARNING |
| 553 | "NILFS warning: error recovering data block " | 553 | "NILFS warning: error recovering data block " |
| 554 | "(err=%d, ino=%lu, block-offset=%llu)\n", | 554 | "(err=%d, ino=%lu, block-offset=%llu)\n", |
| 555 | err, rb->ino, (unsigned long long)rb->blkoff); | 555 | err, (unsigned long)rb->ino, |
| 556 | (unsigned long long)rb->blkoff); | ||
| 556 | if (!err2) | 557 | if (!err2) |
| 557 | err2 = err; | 558 | err2 = err; |
| 558 | next: | 559 | next: |
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 9e3fe17bb96b..e6d9e37fa241 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c | |||
| @@ -316,10 +316,10 @@ static struct bio *nilfs_alloc_seg_bio(struct super_block *sb, sector_t start, | |||
| 316 | { | 316 | { |
| 317 | struct bio *bio; | 317 | struct bio *bio; |
| 318 | 318 | ||
| 319 | bio = bio_alloc(GFP_NOWAIT, nr_vecs); | 319 | bio = bio_alloc(GFP_NOIO, nr_vecs); |
| 320 | if (bio == NULL) { | 320 | if (bio == NULL) { |
| 321 | while (!bio && (nr_vecs >>= 1)) | 321 | while (!bio && (nr_vecs >>= 1)) |
| 322 | bio = bio_alloc(GFP_NOWAIT, nr_vecs); | 322 | bio = bio_alloc(GFP_NOIO, nr_vecs); |
| 323 | } | 323 | } |
| 324 | if (likely(bio)) { | 324 | if (likely(bio)) { |
| 325 | bio->bi_bdev = sb->s_bdev; | 325 | bio->bi_bdev = sb->s_bdev; |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 51ff3d0a4ee2..683df89dbae5 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -2501,7 +2501,8 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, | |||
| 2501 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && | 2501 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && |
| 2502 | nilfs_discontinued(nilfs)) { | 2502 | nilfs_discontinued(nilfs)) { |
| 2503 | down_write(&nilfs->ns_sem); | 2503 | down_write(&nilfs->ns_sem); |
| 2504 | req->sb_err = nilfs_commit_super(sbi, 0); | 2504 | req->sb_err = nilfs_commit_super(sbi, |
| 2505 | nilfs_altsb_need_update(nilfs)); | ||
| 2505 | up_write(&nilfs->ns_sem); | 2506 | up_write(&nilfs->ns_sem); |
| 2506 | } | 2507 | } |
| 2507 | } | 2508 | } |
| @@ -2689,6 +2690,7 @@ static int nilfs_segctor_thread(void *arg) | |||
| 2689 | } else { | 2690 | } else { |
| 2690 | DEFINE_WAIT(wait); | 2691 | DEFINE_WAIT(wait); |
| 2691 | int should_sleep = 1; | 2692 | int should_sleep = 1; |
| 2693 | struct the_nilfs *nilfs; | ||
| 2692 | 2694 | ||
| 2693 | prepare_to_wait(&sci->sc_wait_daemon, &wait, | 2695 | prepare_to_wait(&sci->sc_wait_daemon, &wait, |
| 2694 | TASK_INTERRUPTIBLE); | 2696 | TASK_INTERRUPTIBLE); |
| @@ -2709,6 +2711,9 @@ static int nilfs_segctor_thread(void *arg) | |||
| 2709 | finish_wait(&sci->sc_wait_daemon, &wait); | 2711 | finish_wait(&sci->sc_wait_daemon, &wait); |
| 2710 | timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && | 2712 | timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && |
| 2711 | time_after_eq(jiffies, sci->sc_timer->expires)); | 2713 | time_after_eq(jiffies, sci->sc_timer->expires)); |
| 2714 | nilfs = sci->sc_sbi->s_nilfs; | ||
| 2715 | if (sci->sc_super->s_dirt && nilfs_sb_need_update(nilfs)) | ||
| 2716 | set_nilfs_discontinued(nilfs); | ||
| 2712 | } | 2717 | } |
| 2713 | goto loop; | 2718 | goto loop; |
| 2714 | 2719 | ||
diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h index a2c4d76c3366..0e99e5c0bd0f 100644 --- a/fs/nilfs2/sufile.h +++ b/fs/nilfs2/sufile.h | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <linux/nilfs2_fs.h> | 28 | #include <linux/nilfs2_fs.h> |
| 29 | #include "mdt.h" | 29 | #include "mdt.h" |
| 30 | 30 | ||
| 31 | #define NILFS_SUFILE_GFP NILFS_MDT_GFP | ||
| 32 | 31 | ||
| 33 | static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) | 32 | static inline unsigned long nilfs_sufile_get_nsegments(struct inode *sufile) |
| 34 | { | 33 | { |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 151964f0de4c..55f3d6b60732 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -50,6 +50,8 @@ | |||
| 50 | #include <linux/writeback.h> | 50 | #include <linux/writeback.h> |
| 51 | #include <linux/kobject.h> | 51 | #include <linux/kobject.h> |
| 52 | #include <linux/exportfs.h> | 52 | #include <linux/exportfs.h> |
| 53 | #include <linux/seq_file.h> | ||
| 54 | #include <linux/mount.h> | ||
| 53 | #include "nilfs.h" | 55 | #include "nilfs.h" |
| 54 | #include "mdt.h" | 56 | #include "mdt.h" |
| 55 | #include "alloc.h" | 57 | #include "alloc.h" |
| @@ -65,7 +67,6 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " | |||
| 65 | "(NILFS)"); | 67 | "(NILFS)"); |
| 66 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
| 67 | 69 | ||
| 68 | static void nilfs_write_super(struct super_block *sb); | ||
| 69 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 70 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
| 70 | 71 | ||
| 71 | /** | 72 | /** |
| @@ -311,9 +312,6 @@ static void nilfs_put_super(struct super_block *sb) | |||
| 311 | 312 | ||
| 312 | lock_kernel(); | 313 | lock_kernel(); |
| 313 | 314 | ||
| 314 | if (sb->s_dirt) | ||
| 315 | nilfs_write_super(sb); | ||
| 316 | |||
| 317 | nilfs_detach_segment_constructor(sbi); | 315 | nilfs_detach_segment_constructor(sbi); |
| 318 | 316 | ||
| 319 | if (!(sb->s_flags & MS_RDONLY)) { | 317 | if (!(sb->s_flags & MS_RDONLY)) { |
| @@ -336,63 +334,21 @@ static void nilfs_put_super(struct super_block *sb) | |||
| 336 | unlock_kernel(); | 334 | unlock_kernel(); |
| 337 | } | 335 | } |
| 338 | 336 | ||
| 339 | /** | 337 | static int nilfs_sync_fs(struct super_block *sb, int wait) |
| 340 | * nilfs_write_super - write super block(s) of NILFS | ||
| 341 | * @sb: super_block | ||
| 342 | * | ||
| 343 | * nilfs_write_super() gets a fs-dependent lock, writes super block(s), and | ||
| 344 | * clears s_dirt. This function is called in the section protected by | ||
| 345 | * lock_super(). | ||
| 346 | * | ||
| 347 | * The s_dirt flag is managed by each filesystem and we protect it by ns_sem | ||
| 348 | * of the struct the_nilfs. Lock order must be as follows: | ||
| 349 | * | ||
| 350 | * 1. lock_super() | ||
| 351 | * 2. down_write(&nilfs->ns_sem) | ||
| 352 | * | ||
| 353 | * Inside NILFS, locking ns_sem is enough to protect s_dirt and the buffer | ||
| 354 | * of the super block (nilfs->ns_sbp[]). | ||
| 355 | * | ||
| 356 | * In most cases, VFS functions call lock_super() before calling these | ||
| 357 | * methods. So we must be careful not to bring on deadlocks when using | ||
| 358 | * lock_super(); see generic_shutdown_super(), write_super(), and so on. | ||
| 359 | * | ||
| 360 | * Note that order of lock_kernel() and lock_super() depends on contexts | ||
| 361 | * of VFS. We should also note that lock_kernel() can be used in its | ||
| 362 | * protective section and only the outermost one has an effect. | ||
| 363 | */ | ||
| 364 | static void nilfs_write_super(struct super_block *sb) | ||
| 365 | { | 338 | { |
| 366 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 339 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
| 367 | struct the_nilfs *nilfs = sbi->s_nilfs; | 340 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 368 | |||
| 369 | down_write(&nilfs->ns_sem); | ||
| 370 | if (!(sb->s_flags & MS_RDONLY)) { | ||
| 371 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
| 372 | u64 t = get_seconds(); | ||
| 373 | int dupsb; | ||
| 374 | |||
| 375 | if (!nilfs_discontinued(nilfs) && t >= nilfs->ns_sbwtime[0] && | ||
| 376 | t < nilfs->ns_sbwtime[0] + NILFS_SB_FREQ) { | ||
| 377 | up_write(&nilfs->ns_sem); | ||
| 378 | return; | ||
| 379 | } | ||
| 380 | dupsb = sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ; | ||
| 381 | nilfs_commit_super(sbi, dupsb); | ||
| 382 | } | ||
| 383 | sb->s_dirt = 0; | ||
| 384 | up_write(&nilfs->ns_sem); | ||
| 385 | } | ||
| 386 | |||
| 387 | static int nilfs_sync_fs(struct super_block *sb, int wait) | ||
| 388 | { | ||
| 389 | int err = 0; | 341 | int err = 0; |
| 390 | 342 | ||
| 391 | nilfs_write_super(sb); | ||
| 392 | |||
| 393 | /* This function is called when super block should be written back */ | 343 | /* This function is called when super block should be written back */ |
| 394 | if (wait) | 344 | if (wait) |
| 395 | err = nilfs_construct_segment(sb); | 345 | err = nilfs_construct_segment(sb); |
| 346 | |||
| 347 | down_write(&nilfs->ns_sem); | ||
| 348 | if (sb->s_dirt) | ||
| 349 | nilfs_commit_super(sbi, 1); | ||
| 350 | up_write(&nilfs->ns_sem); | ||
| 351 | |||
| 396 | return err; | 352 | return err; |
| 397 | } | 353 | } |
| 398 | 354 | ||
| @@ -407,8 +363,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
| 407 | list_add(&sbi->s_list, &nilfs->ns_supers); | 363 | list_add(&sbi->s_list, &nilfs->ns_supers); |
| 408 | up_write(&nilfs->ns_super_sem); | 364 | up_write(&nilfs->ns_super_sem); |
| 409 | 365 | ||
| 410 | sbi->s_ifile = nilfs_mdt_new( | 366 | sbi->s_ifile = nilfs_mdt_new(nilfs, sbi->s_super, NILFS_IFILE_INO); |
| 411 | nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP); | ||
| 412 | if (!sbi->s_ifile) | 367 | if (!sbi->s_ifile) |
| 413 | return -ENOMEM; | 368 | return -ENOMEM; |
| 414 | 369 | ||
| @@ -529,6 +484,26 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 529 | return 0; | 484 | return 0; |
| 530 | } | 485 | } |
| 531 | 486 | ||
| 487 | static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | ||
| 488 | { | ||
| 489 | struct super_block *sb = vfs->mnt_sb; | ||
| 490 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | ||
| 491 | |||
| 492 | if (!nilfs_test_opt(sbi, BARRIER)) | ||
| 493 | seq_printf(seq, ",barrier=off"); | ||
| 494 | if (nilfs_test_opt(sbi, SNAPSHOT)) | ||
| 495 | seq_printf(seq, ",cp=%llu", | ||
| 496 | (unsigned long long int)sbi->s_snapshot_cno); | ||
| 497 | if (nilfs_test_opt(sbi, ERRORS_RO)) | ||
| 498 | seq_printf(seq, ",errors=remount-ro"); | ||
| 499 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | ||
| 500 | seq_printf(seq, ",errors=panic"); | ||
| 501 | if (nilfs_test_opt(sbi, STRICT_ORDER)) | ||
| 502 | seq_printf(seq, ",order=strict"); | ||
| 503 | |||
| 504 | return 0; | ||
| 505 | } | ||
| 506 | |||
| 532 | static struct super_operations nilfs_sops = { | 507 | static struct super_operations nilfs_sops = { |
| 533 | .alloc_inode = nilfs_alloc_inode, | 508 | .alloc_inode = nilfs_alloc_inode, |
| 534 | .destroy_inode = nilfs_destroy_inode, | 509 | .destroy_inode = nilfs_destroy_inode, |
| @@ -538,7 +513,7 @@ static struct super_operations nilfs_sops = { | |||
| 538 | /* .drop_inode = nilfs_drop_inode, */ | 513 | /* .drop_inode = nilfs_drop_inode, */ |
| 539 | .delete_inode = nilfs_delete_inode, | 514 | .delete_inode = nilfs_delete_inode, |
| 540 | .put_super = nilfs_put_super, | 515 | .put_super = nilfs_put_super, |
| 541 | .write_super = nilfs_write_super, | 516 | /* .write_super = nilfs_write_super, */ |
| 542 | .sync_fs = nilfs_sync_fs, | 517 | .sync_fs = nilfs_sync_fs, |
| 543 | /* .write_super_lockfs */ | 518 | /* .write_super_lockfs */ |
| 544 | /* .unlockfs */ | 519 | /* .unlockfs */ |
| @@ -546,7 +521,7 @@ static struct super_operations nilfs_sops = { | |||
| 546 | .remount_fs = nilfs_remount, | 521 | .remount_fs = nilfs_remount, |
| 547 | .clear_inode = nilfs_clear_inode, | 522 | .clear_inode = nilfs_clear_inode, |
| 548 | /* .umount_begin */ | 523 | /* .umount_begin */ |
| 549 | /* .show_options */ | 524 | .show_options = nilfs_show_options |
| 550 | }; | 525 | }; |
| 551 | 526 | ||
| 552 | static struct inode * | 527 | static struct inode * |
| @@ -816,10 +791,15 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
| 816 | 791 | ||
| 817 | if (sb->s_flags & MS_RDONLY) { | 792 | if (sb->s_flags & MS_RDONLY) { |
| 818 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | 793 | if (nilfs_test_opt(sbi, SNAPSHOT)) { |
| 794 | down_read(&nilfs->ns_segctor_sem); | ||
| 819 | err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, | 795 | err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, |
| 820 | sbi->s_snapshot_cno); | 796 | sbi->s_snapshot_cno); |
| 821 | if (err < 0) | 797 | up_read(&nilfs->ns_segctor_sem); |
| 798 | if (err < 0) { | ||
| 799 | if (err == -ENOENT) | ||
| 800 | err = -EINVAL; | ||
| 822 | goto failed_sbi; | 801 | goto failed_sbi; |
| 802 | } | ||
| 823 | if (!err) { | 803 | if (!err) { |
| 824 | printk(KERN_ERR | 804 | printk(KERN_ERR |
| 825 | "NILFS: The specified checkpoint is " | 805 | "NILFS: The specified checkpoint is " |
| @@ -1127,10 +1107,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 1127 | */ | 1107 | */ |
| 1128 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); | 1108 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); |
| 1129 | 1109 | ||
| 1130 | if (!sd.cno) | ||
| 1131 | /* trying to get the latest checkpoint. */ | ||
| 1132 | sd.cno = nilfs_last_cno(nilfs); | ||
| 1133 | |||
| 1134 | /* | 1110 | /* |
| 1135 | * Get super block instance holding the nilfs_sb_info struct. | 1111 | * Get super block instance holding the nilfs_sb_info struct. |
| 1136 | * A new instance is allocated if no existing mount is present or | 1112 | * A new instance is allocated if no existing mount is present or |
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 8b8889825716..d4168e269c5d 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
| @@ -68,12 +68,11 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev) | |||
| 68 | 68 | ||
| 69 | nilfs->ns_bdev = bdev; | 69 | nilfs->ns_bdev = bdev; |
| 70 | atomic_set(&nilfs->ns_count, 1); | 70 | atomic_set(&nilfs->ns_count, 1); |
| 71 | atomic_set(&nilfs->ns_writer_refcount, -1); | ||
| 72 | atomic_set(&nilfs->ns_ndirtyblks, 0); | 71 | atomic_set(&nilfs->ns_ndirtyblks, 0); |
| 73 | init_rwsem(&nilfs->ns_sem); | 72 | init_rwsem(&nilfs->ns_sem); |
| 74 | init_rwsem(&nilfs->ns_super_sem); | 73 | init_rwsem(&nilfs->ns_super_sem); |
| 75 | mutex_init(&nilfs->ns_mount_mutex); | 74 | mutex_init(&nilfs->ns_mount_mutex); |
| 76 | mutex_init(&nilfs->ns_writer_mutex); | 75 | init_rwsem(&nilfs->ns_writer_sem); |
| 77 | INIT_LIST_HEAD(&nilfs->ns_list); | 76 | INIT_LIST_HEAD(&nilfs->ns_list); |
| 78 | INIT_LIST_HEAD(&nilfs->ns_supers); | 77 | INIT_LIST_HEAD(&nilfs->ns_supers); |
| 79 | spin_lock_init(&nilfs->ns_last_segment_lock); | 78 | spin_lock_init(&nilfs->ns_last_segment_lock); |
| @@ -188,23 +187,19 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, | |||
| 188 | inode_size = nilfs->ns_inode_size; | 187 | inode_size = nilfs->ns_inode_size; |
| 189 | 188 | ||
| 190 | err = -ENOMEM; | 189 | err = -ENOMEM; |
| 191 | nilfs->ns_dat = nilfs_mdt_new( | 190 | nilfs->ns_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); |
| 192 | nilfs, NULL, NILFS_DAT_INO, NILFS_DAT_GFP); | ||
| 193 | if (unlikely(!nilfs->ns_dat)) | 191 | if (unlikely(!nilfs->ns_dat)) |
| 194 | goto failed; | 192 | goto failed; |
| 195 | 193 | ||
| 196 | nilfs->ns_gc_dat = nilfs_mdt_new( | 194 | nilfs->ns_gc_dat = nilfs_mdt_new(nilfs, NULL, NILFS_DAT_INO); |
| 197 | nilfs, NULL, NILFS_DAT_INO, NILFS_DAT_GFP); | ||
| 198 | if (unlikely(!nilfs->ns_gc_dat)) | 195 | if (unlikely(!nilfs->ns_gc_dat)) |
| 199 | goto failed_dat; | 196 | goto failed_dat; |
| 200 | 197 | ||
| 201 | nilfs->ns_cpfile = nilfs_mdt_new( | 198 | nilfs->ns_cpfile = nilfs_mdt_new(nilfs, NULL, NILFS_CPFILE_INO); |
| 202 | nilfs, NULL, NILFS_CPFILE_INO, NILFS_CPFILE_GFP); | ||
| 203 | if (unlikely(!nilfs->ns_cpfile)) | 199 | if (unlikely(!nilfs->ns_cpfile)) |
| 204 | goto failed_gc_dat; | 200 | goto failed_gc_dat; |
| 205 | 201 | ||
| 206 | nilfs->ns_sufile = nilfs_mdt_new( | 202 | nilfs->ns_sufile = nilfs_mdt_new(nilfs, NULL, NILFS_SUFILE_INO); |
| 207 | nilfs, NULL, NILFS_SUFILE_INO, NILFS_SUFILE_GFP); | ||
| 208 | if (unlikely(!nilfs->ns_sufile)) | 203 | if (unlikely(!nilfs->ns_sufile)) |
| 209 | goto failed_cpfile; | 204 | goto failed_cpfile; |
| 210 | 205 | ||
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 1b9caafb8662..20abd55881e0 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
| @@ -37,6 +37,7 @@ enum { | |||
| 37 | THE_NILFS_LOADED, /* Roll-back/roll-forward has done and | 37 | THE_NILFS_LOADED, /* Roll-back/roll-forward has done and |
| 38 | the latest checkpoint was loaded */ | 38 | the latest checkpoint was loaded */ |
| 39 | THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ | 39 | THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ |
| 40 | THE_NILFS_GC_RUNNING, /* gc process is running */ | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | /** | 43 | /** |
| @@ -50,8 +51,7 @@ enum { | |||
| 50 | * @ns_sem: semaphore for shared states | 51 | * @ns_sem: semaphore for shared states |
| 51 | * @ns_super_sem: semaphore for global operations across super block instances | 52 | * @ns_super_sem: semaphore for global operations across super block instances |
| 52 | * @ns_mount_mutex: mutex protecting mount process of nilfs | 53 | * @ns_mount_mutex: mutex protecting mount process of nilfs |
| 53 | * @ns_writer_mutex: mutex protecting ns_writer attach/detach | 54 | * @ns_writer_sem: semaphore protecting ns_writer attach/detach |
| 54 | * @ns_writer_refcount: number of referrers on ns_writer | ||
| 55 | * @ns_current: back pointer to current mount | 55 | * @ns_current: back pointer to current mount |
| 56 | * @ns_sbh: buffer heads of on-disk super blocks | 56 | * @ns_sbh: buffer heads of on-disk super blocks |
| 57 | * @ns_sbp: pointers to super block data | 57 | * @ns_sbp: pointers to super block data |
| @@ -100,8 +100,7 @@ struct the_nilfs { | |||
| 100 | struct rw_semaphore ns_sem; | 100 | struct rw_semaphore ns_sem; |
| 101 | struct rw_semaphore ns_super_sem; | 101 | struct rw_semaphore ns_super_sem; |
| 102 | struct mutex ns_mount_mutex; | 102 | struct mutex ns_mount_mutex; |
| 103 | struct mutex ns_writer_mutex; | 103 | struct rw_semaphore ns_writer_sem; |
| 104 | atomic_t ns_writer_refcount; | ||
| 105 | 104 | ||
| 106 | /* | 105 | /* |
| 107 | * components protected by ns_super_sem | 106 | * components protected by ns_super_sem |
| @@ -197,11 +196,26 @@ static inline int nilfs_##name(struct the_nilfs *nilfs) \ | |||
| 197 | THE_NILFS_FNS(INIT, init) | 196 | THE_NILFS_FNS(INIT, init) |
| 198 | THE_NILFS_FNS(LOADED, loaded) | 197 | THE_NILFS_FNS(LOADED, loaded) |
| 199 | THE_NILFS_FNS(DISCONTINUED, discontinued) | 198 | THE_NILFS_FNS(DISCONTINUED, discontinued) |
| 199 | THE_NILFS_FNS(GC_RUNNING, gc_running) | ||
| 200 | 200 | ||
| 201 | /* Minimum interval of periodical update of superblocks (in seconds) */ | 201 | /* Minimum interval of periodical update of superblocks (in seconds) */ |
| 202 | #define NILFS_SB_FREQ 10 | 202 | #define NILFS_SB_FREQ 10 |
| 203 | #define NILFS_ALTSB_FREQ 60 /* spare superblock */ | 203 | #define NILFS_ALTSB_FREQ 60 /* spare superblock */ |
| 204 | 204 | ||
| 205 | static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) | ||
| 206 | { | ||
| 207 | u64 t = get_seconds(); | ||
| 208 | return t < nilfs->ns_sbwtime[0] || | ||
| 209 | t > nilfs->ns_sbwtime[0] + NILFS_SB_FREQ; | ||
| 210 | } | ||
| 211 | |||
| 212 | static inline int nilfs_altsb_need_update(struct the_nilfs *nilfs) | ||
| 213 | { | ||
| 214 | u64 t = get_seconds(); | ||
| 215 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
| 216 | return sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ; | ||
| 217 | } | ||
| 218 | |||
| 205 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); | 219 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); |
| 206 | struct the_nilfs *find_or_create_nilfs(struct block_device *); | 220 | struct the_nilfs *find_or_create_nilfs(struct block_device *); |
| 207 | void put_nilfs(struct the_nilfs *); | 221 | void put_nilfs(struct the_nilfs *); |
| @@ -221,34 +235,21 @@ static inline void get_nilfs(struct the_nilfs *nilfs) | |||
| 221 | atomic_inc(&nilfs->ns_count); | 235 | atomic_inc(&nilfs->ns_count); |
| 222 | } | 236 | } |
| 223 | 237 | ||
| 224 | static inline struct nilfs_sb_info *nilfs_get_writer(struct the_nilfs *nilfs) | ||
| 225 | { | ||
| 226 | if (atomic_inc_and_test(&nilfs->ns_writer_refcount)) | ||
| 227 | mutex_lock(&nilfs->ns_writer_mutex); | ||
| 228 | return nilfs->ns_writer; | ||
| 229 | } | ||
| 230 | |||
| 231 | static inline void nilfs_put_writer(struct the_nilfs *nilfs) | ||
| 232 | { | ||
| 233 | if (atomic_add_negative(-1, &nilfs->ns_writer_refcount)) | ||
| 234 | mutex_unlock(&nilfs->ns_writer_mutex); | ||
| 235 | } | ||
| 236 | |||
| 237 | static inline void | 238 | static inline void |
| 238 | nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | 239 | nilfs_attach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) |
| 239 | { | 240 | { |
| 240 | mutex_lock(&nilfs->ns_writer_mutex); | 241 | down_write(&nilfs->ns_writer_sem); |
| 241 | nilfs->ns_writer = sbi; | 242 | nilfs->ns_writer = sbi; |
| 242 | mutex_unlock(&nilfs->ns_writer_mutex); | 243 | up_write(&nilfs->ns_writer_sem); |
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | static inline void | 246 | static inline void |
| 246 | nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | 247 | nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) |
| 247 | { | 248 | { |
| 248 | mutex_lock(&nilfs->ns_writer_mutex); | 249 | down_write(&nilfs->ns_writer_sem); |
| 249 | if (sbi == nilfs->ns_writer) | 250 | if (sbi == nilfs->ns_writer) |
| 250 | nilfs->ns_writer = NULL; | 251 | nilfs->ns_writer = NULL; |
| 251 | mutex_unlock(&nilfs->ns_writer_mutex); | 252 | up_write(&nilfs->ns_writer_sem); |
| 252 | } | 253 | } |
| 253 | 254 | ||
| 254 | static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) | 255 | static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) |
