diff options
Diffstat (limited to 'fs/nilfs2')
| -rw-r--r-- | fs/nilfs2/btree.c | 47 | ||||
| -rw-r--r-- | fs/nilfs2/segment.c | 7 |
2 files changed, 48 insertions, 6 deletions
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index b2e3ff347620..ecdbae19a766 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | #include "alloc.h" | 31 | #include "alloc.h" |
| 32 | #include "dat.h" | 32 | #include "dat.h" |
| 33 | 33 | ||
| 34 | static void __nilfs_btree_init(struct nilfs_bmap *bmap); | ||
| 35 | |||
| 34 | static struct nilfs_btree_path *nilfs_btree_alloc_path(void) | 36 | static struct nilfs_btree_path *nilfs_btree_alloc_path(void) |
| 35 | { | 37 | { |
| 36 | struct nilfs_btree_path *path; | 38 | struct nilfs_btree_path *path; |
| @@ -368,6 +370,34 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, | |||
| 368 | return ret; | 370 | return ret; |
| 369 | } | 371 | } |
| 370 | 372 | ||
| 373 | /** | ||
| 374 | * nilfs_btree_root_broken - verify consistency of btree root node | ||
| 375 | * @node: btree root node to be examined | ||
| 376 | * @ino: inode number | ||
| 377 | * | ||
| 378 | * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned. | ||
| 379 | */ | ||
| 380 | static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, | ||
| 381 | unsigned long ino) | ||
| 382 | { | ||
| 383 | int level, flags, nchildren; | ||
| 384 | int ret = 0; | ||
| 385 | |||
| 386 | level = nilfs_btree_node_get_level(node); | ||
| 387 | flags = nilfs_btree_node_get_flags(node); | ||
| 388 | nchildren = nilfs_btree_node_get_nchildren(node); | ||
| 389 | |||
| 390 | if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || | ||
| 391 | level > NILFS_BTREE_LEVEL_MAX || | ||
| 392 | nchildren < 0 || | ||
| 393 | nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { | ||
| 394 | pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n", | ||
| 395 | ino, level, flags, nchildren); | ||
| 396 | ret = 1; | ||
| 397 | } | ||
| 398 | return ret; | ||
| 399 | } | ||
| 400 | |||
| 371 | int nilfs_btree_broken_node_block(struct buffer_head *bh) | 401 | int nilfs_btree_broken_node_block(struct buffer_head *bh) |
| 372 | { | 402 | { |
| 373 | int ret; | 403 | int ret; |
| @@ -1713,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree, | |||
| 1713 | 1743 | ||
| 1714 | /* convert and insert */ | 1744 | /* convert and insert */ |
| 1715 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; | 1745 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; |
| 1716 | nilfs_btree_init(btree); | 1746 | __nilfs_btree_init(btree); |
| 1717 | if (nreq != NULL) { | 1747 | if (nreq != NULL) { |
| 1718 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); | 1748 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); |
| 1719 | nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); | 1749 | nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); |
| @@ -2294,12 +2324,23 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { | |||
| 2294 | .bop_gather_data = NULL, | 2324 | .bop_gather_data = NULL, |
| 2295 | }; | 2325 | }; |
| 2296 | 2326 | ||
| 2297 | int nilfs_btree_init(struct nilfs_bmap *bmap) | 2327 | static void __nilfs_btree_init(struct nilfs_bmap *bmap) |
| 2298 | { | 2328 | { |
| 2299 | bmap->b_ops = &nilfs_btree_ops; | 2329 | bmap->b_ops = &nilfs_btree_ops; |
| 2300 | bmap->b_nchildren_per_block = | 2330 | bmap->b_nchildren_per_block = |
| 2301 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); | 2331 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); |
| 2302 | return 0; | 2332 | } |
| 2333 | |||
| 2334 | int nilfs_btree_init(struct nilfs_bmap *bmap) | ||
| 2335 | { | ||
| 2336 | int ret = 0; | ||
| 2337 | |||
| 2338 | __nilfs_btree_init(bmap); | ||
| 2339 | |||
| 2340 | if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), | ||
| 2341 | bmap->b_inode->i_ino)) | ||
| 2342 | ret = -EIO; | ||
| 2343 | return ret; | ||
| 2303 | } | 2344 | } |
| 2304 | 2345 | ||
| 2305 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) | 2346 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 469086b9f99b..0c3f303baf32 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -1907,6 +1907,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, | |||
| 1907 | struct the_nilfs *nilfs) | 1907 | struct the_nilfs *nilfs) |
| 1908 | { | 1908 | { |
| 1909 | struct nilfs_inode_info *ii, *n; | 1909 | struct nilfs_inode_info *ii, *n; |
| 1910 | int during_mount = !(sci->sc_super->s_flags & MS_ACTIVE); | ||
| 1910 | int defer_iput = false; | 1911 | int defer_iput = false; |
| 1911 | 1912 | ||
| 1912 | spin_lock(&nilfs->ns_inode_lock); | 1913 | spin_lock(&nilfs->ns_inode_lock); |
| @@ -1919,10 +1920,10 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, | |||
| 1919 | brelse(ii->i_bh); | 1920 | brelse(ii->i_bh); |
| 1920 | ii->i_bh = NULL; | 1921 | ii->i_bh = NULL; |
| 1921 | list_del_init(&ii->i_dirty); | 1922 | list_del_init(&ii->i_dirty); |
| 1922 | if (!ii->vfs_inode.i_nlink) { | 1923 | if (!ii->vfs_inode.i_nlink || during_mount) { |
| 1923 | /* | 1924 | /* |
| 1924 | * Defer calling iput() to avoid a deadlock | 1925 | * Defer calling iput() to avoid deadlocks if |
| 1925 | * over I_SYNC flag for inodes with i_nlink == 0 | 1926 | * i_nlink == 0 or mount is not yet finished. |
| 1926 | */ | 1927 | */ |
| 1927 | list_add_tail(&ii->i_dirty, &sci->sc_iput_queue); | 1928 | list_add_tail(&ii->i_dirty, &sci->sc_iput_queue); |
| 1928 | defer_iput = true; | 1929 | defer_iput = true; |
