diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-11-19 01:26:20 -0500 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2011-01-10 00:05:45 -0500 |
commit | e828949e5b42bfd234ee537cdb7c5e3a577958a3 (patch) | |
tree | c2e259a3020acdb943669fb01e5a7dc5598a6fe9 /fs | |
parent | b004a5eb0babec7ef91558f73315ef49e5a1f285 (diff) |
nilfs2: call nilfs_error inside bmap routines
Some functions using nilfs bmap routines can wrongly return invalid
argument error (i.e. -EINVAL) that bmap returns as an internal code
for btree corruption.
This fixes the issue by catching and converting the internal EINVAL to
EIO and calling nilfs_error function inside bmap routines.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nilfs2/bmap.c | 45 | ||||
-rw-r--r-- | fs/nilfs2/ifile.c | 11 | ||||
-rw-r--r-- | fs/nilfs2/inode.c | 19 | ||||
-rw-r--r-- | fs/nilfs2/mdt.c | 6 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 30 |
5 files changed, 48 insertions, 63 deletions
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 8b782b062baa..4b7aeb34cc75 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
@@ -38,6 +38,19 @@ struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap) | |||
38 | return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode)); | 38 | return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode)); |
39 | } | 39 | } |
40 | 40 | ||
41 | static int nilfs_bmap_convert_error(struct nilfs_bmap *bmap, | ||
42 | const char *fname, int err) | ||
43 | { | ||
44 | struct inode *inode = bmap->b_inode; | ||
45 | |||
46 | if (err == -EINVAL) { | ||
47 | nilfs_error(inode->i_sb, fname, | ||
48 | "broken bmap (inode number=%lu)\n", inode->i_ino); | ||
49 | err = -EIO; | ||
50 | } | ||
51 | return err; | ||
52 | } | ||
53 | |||
41 | /** | 54 | /** |
42 | * nilfs_bmap_lookup_at_level - find a data block or node block | 55 | * nilfs_bmap_lookup_at_level - find a data block or node block |
43 | * @bmap: bmap | 56 | * @bmap: bmap |
@@ -66,8 +79,10 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level, | |||
66 | 79 | ||
67 | down_read(&bmap->b_sem); | 80 | down_read(&bmap->b_sem); |
68 | ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp); | 81 | ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp); |
69 | if (ret < 0) | 82 | if (ret < 0) { |
83 | ret = nilfs_bmap_convert_error(bmap, __func__, ret); | ||
70 | goto out; | 84 | goto out; |
85 | } | ||
71 | if (NILFS_BMAP_USE_VBN(bmap)) { | 86 | if (NILFS_BMAP_USE_VBN(bmap)) { |
72 | ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp, | 87 | ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp, |
73 | &blocknr); | 88 | &blocknr); |
@@ -88,7 +103,8 @@ int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp, | |||
88 | down_read(&bmap->b_sem); | 103 | down_read(&bmap->b_sem); |
89 | ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks); | 104 | ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks); |
90 | up_read(&bmap->b_sem); | 105 | up_read(&bmap->b_sem); |
91 | return ret; | 106 | |
107 | return nilfs_bmap_convert_error(bmap, __func__, ret); | ||
92 | } | 108 | } |
93 | 109 | ||
94 | static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | 110 | static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) |
@@ -144,7 +160,8 @@ int nilfs_bmap_insert(struct nilfs_bmap *bmap, | |||
144 | down_write(&bmap->b_sem); | 160 | down_write(&bmap->b_sem); |
145 | ret = nilfs_bmap_do_insert(bmap, key, rec); | 161 | ret = nilfs_bmap_do_insert(bmap, key, rec); |
146 | up_write(&bmap->b_sem); | 162 | up_write(&bmap->b_sem); |
147 | return ret; | 163 | |
164 | return nilfs_bmap_convert_error(bmap, __func__, ret); | ||
148 | } | 165 | } |
149 | 166 | ||
150 | static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) | 167 | static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) |
@@ -180,9 +197,12 @@ int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key) | |||
180 | 197 | ||
181 | down_read(&bmap->b_sem); | 198 | down_read(&bmap->b_sem); |
182 | ret = bmap->b_ops->bop_last_key(bmap, &lastkey); | 199 | ret = bmap->b_ops->bop_last_key(bmap, &lastkey); |
183 | if (!ret) | ||
184 | *key = lastkey; | ||
185 | up_read(&bmap->b_sem); | 200 | up_read(&bmap->b_sem); |
201 | |||
202 | if (ret < 0) | ||
203 | ret = nilfs_bmap_convert_error(bmap, __func__, ret); | ||
204 | else | ||
205 | *key = lastkey; | ||
186 | return ret; | 206 | return ret; |
187 | } | 207 | } |
188 | 208 | ||
@@ -210,7 +230,8 @@ int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key) | |||
210 | down_write(&bmap->b_sem); | 230 | down_write(&bmap->b_sem); |
211 | ret = nilfs_bmap_do_delete(bmap, key); | 231 | ret = nilfs_bmap_do_delete(bmap, key); |
212 | up_write(&bmap->b_sem); | 232 | up_write(&bmap->b_sem); |
213 | return ret; | 233 | |
234 | return nilfs_bmap_convert_error(bmap, __func__, ret); | ||
214 | } | 235 | } |
215 | 236 | ||
216 | static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key) | 237 | static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key) |
@@ -261,7 +282,8 @@ int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key) | |||
261 | down_write(&bmap->b_sem); | 282 | down_write(&bmap->b_sem); |
262 | ret = nilfs_bmap_do_truncate(bmap, key); | 283 | ret = nilfs_bmap_do_truncate(bmap, key); |
263 | up_write(&bmap->b_sem); | 284 | up_write(&bmap->b_sem); |
264 | return ret; | 285 | |
286 | return nilfs_bmap_convert_error(bmap, __func__, ret); | ||
265 | } | 287 | } |
266 | 288 | ||
267 | /** | 289 | /** |
@@ -300,7 +322,8 @@ int nilfs_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh) | |||
300 | down_write(&bmap->b_sem); | 322 | down_write(&bmap->b_sem); |
301 | ret = bmap->b_ops->bop_propagate(bmap, bh); | 323 | ret = bmap->b_ops->bop_propagate(bmap, bh); |
302 | up_write(&bmap->b_sem); | 324 | up_write(&bmap->b_sem); |
303 | return ret; | 325 | |
326 | return nilfs_bmap_convert_error(bmap, __func__, ret); | ||
304 | } | 327 | } |
305 | 328 | ||
306 | /** | 329 | /** |
@@ -344,7 +367,8 @@ int nilfs_bmap_assign(struct nilfs_bmap *bmap, | |||
344 | down_write(&bmap->b_sem); | 367 | down_write(&bmap->b_sem); |
345 | ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo); | 368 | ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo); |
346 | up_write(&bmap->b_sem); | 369 | up_write(&bmap->b_sem); |
347 | return ret; | 370 | |
371 | return nilfs_bmap_convert_error(bmap, __func__, ret); | ||
348 | } | 372 | } |
349 | 373 | ||
350 | /** | 374 | /** |
@@ -373,7 +397,8 @@ int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
373 | down_write(&bmap->b_sem); | 397 | down_write(&bmap->b_sem); |
374 | ret = bmap->b_ops->bop_mark(bmap, key, level); | 398 | ret = bmap->b_ops->bop_mark(bmap, key, level); |
375 | up_write(&bmap->b_sem); | 399 | up_write(&bmap->b_sem); |
376 | return ret; | 400 | |
401 | return nilfs_bmap_convert_error(bmap, __func__, ret); | ||
377 | } | 402 | } |
378 | 403 | ||
379 | /** | 404 | /** |
diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c index 9f8a2da67f90..bfc73d3a30ed 100644 --- a/fs/nilfs2/ifile.c +++ b/fs/nilfs2/ifile.c | |||
@@ -149,14 +149,9 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino, | |||
149 | } | 149 | } |
150 | 150 | ||
151 | err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh); | 151 | err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh); |
152 | if (unlikely(err)) { | 152 | if (unlikely(err)) |
153 | if (err == -EINVAL) | 153 | nilfs_warning(sb, __func__, "unable to read inode: %lu", |
154 | nilfs_error(sb, __func__, "ifile is broken"); | 154 | (unsigned long) ino); |
155 | else | ||
156 | nilfs_warning(sb, __func__, | ||
157 | "unable to read inode: %lu", | ||
158 | (unsigned long) ino); | ||
159 | } | ||
160 | return err; | 155 | return err; |
161 | } | 156 | } |
162 | 157 | ||
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 77b48c8fab17..550b1788981e 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -96,11 +96,6 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, | |||
96 | inode->i_ino, | 96 | inode->i_ino, |
97 | (unsigned long long)blkoff); | 97 | (unsigned long long)blkoff); |
98 | err = 0; | 98 | err = 0; |
99 | } else if (err == -EINVAL) { | ||
100 | nilfs_error(inode->i_sb, __func__, | ||
101 | "broken bmap (inode=%lu)\n", | ||
102 | inode->i_ino); | ||
103 | err = -EIO; | ||
104 | } | 99 | } |
105 | nilfs_transaction_abort(inode->i_sb); | 100 | nilfs_transaction_abort(inode->i_sb); |
106 | goto out; | 101 | goto out; |
@@ -629,7 +624,7 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, | |||
629 | 624 | ||
630 | if (!test_bit(NILFS_I_BMAP, &ii->i_state)) | 625 | if (!test_bit(NILFS_I_BMAP, &ii->i_state)) |
631 | return; | 626 | return; |
632 | repeat: | 627 | repeat: |
633 | ret = nilfs_bmap_last_key(ii->i_bmap, &b); | 628 | ret = nilfs_bmap_last_key(ii->i_bmap, &b); |
634 | if (ret == -ENOENT) | 629 | if (ret == -ENOENT) |
635 | return; | 630 | return; |
@@ -646,14 +641,10 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, | |||
646 | nilfs_bmap_truncate(ii->i_bmap, b) == 0)) | 641 | nilfs_bmap_truncate(ii->i_bmap, b) == 0)) |
647 | goto repeat; | 642 | goto repeat; |
648 | 643 | ||
649 | failed: | 644 | failed: |
650 | if (ret == -EINVAL) | 645 | nilfs_warning(ii->vfs_inode.i_sb, __func__, |
651 | nilfs_error(ii->vfs_inode.i_sb, __func__, | 646 | "failed to truncate bmap (ino=%lu, err=%d)", |
652 | "bmap is broken (ino=%lu)", ii->vfs_inode.i_ino); | 647 | ii->vfs_inode.i_ino, ret); |
653 | else | ||
654 | nilfs_warning(ii->vfs_inode.i_sb, __func__, | ||
655 | "failed to truncate bmap (ino=%lu, err=%d)", | ||
656 | ii->vfs_inode.i_ino, ret); | ||
657 | } | 648 | } |
658 | 649 | ||
659 | void nilfs_truncate(struct inode *inode) | 650 | void nilfs_truncate(struct inode *inode) |
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 39a5b84e2c9f..f5d4b184eaf9 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
@@ -237,8 +237,6 @@ static int nilfs_mdt_read_block(struct inode *inode, unsigned long block, | |||
237 | * | 237 | * |
238 | * %-ENOENT - the specified block does not exist (hole block) | 238 | * %-ENOENT - the specified block does not exist (hole block) |
239 | * | 239 | * |
240 | * %-EINVAL - bmap is broken. (the caller should call nilfs_error()) | ||
241 | * | ||
242 | * %-EROFS - Read only filesystem (for create mode) | 240 | * %-EROFS - Read only filesystem (for create mode) |
243 | */ | 241 | */ |
244 | int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create, | 242 | int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create, |
@@ -273,8 +271,6 @@ int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create, | |||
273 | * %-ENOMEM - Insufficient memory available. | 271 | * %-ENOMEM - Insufficient memory available. |
274 | * | 272 | * |
275 | * %-EIO - I/O error | 273 | * %-EIO - I/O error |
276 | * | ||
277 | * %-EINVAL - bmap is broken. (the caller should call nilfs_error()) | ||
278 | */ | 274 | */ |
279 | int nilfs_mdt_delete_block(struct inode *inode, unsigned long block) | 275 | int nilfs_mdt_delete_block(struct inode *inode, unsigned long block) |
280 | { | 276 | { |
@@ -350,8 +346,6 @@ int nilfs_mdt_forget_block(struct inode *inode, unsigned long block) | |||
350 | * %-EIO - I/O error | 346 | * %-EIO - I/O error |
351 | * | 347 | * |
352 | * %-ENOENT - the specified block does not exist (hole block) | 348 | * %-ENOENT - the specified block does not exist (hole block) |
353 | * | ||
354 | * %-EINVAL - bmap is broken. (the caller should call nilfs_error()) | ||
355 | */ | 349 | */ |
356 | int nilfs_mdt_mark_block_dirty(struct inode *inode, unsigned long block) | 350 | int nilfs_mdt_mark_block_dirty(struct inode *inode, unsigned long block) |
357 | { | 351 | { |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 687d090cea34..d3d2f4396f72 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -504,17 +504,6 @@ static int nilfs_segctor_add_file_block(struct nilfs_sc_info *sci, | |||
504 | return err; | 504 | return err; |
505 | } | 505 | } |
506 | 506 | ||
507 | static int nilfs_handle_bmap_error(int err, const char *fname, | ||
508 | struct inode *inode, struct super_block *sb) | ||
509 | { | ||
510 | if (err == -EINVAL) { | ||
511 | nilfs_error(sb, fname, "broken bmap (inode=%lu)\n", | ||
512 | inode->i_ino); | ||
513 | err = -EIO; | ||
514 | } | ||
515 | return err; | ||
516 | } | ||
517 | |||
518 | /* | 507 | /* |
519 | * Callback functions that enumerate, mark, and collect dirty blocks | 508 | * Callback functions that enumerate, mark, and collect dirty blocks |
520 | */ | 509 | */ |
@@ -524,9 +513,8 @@ static int nilfs_collect_file_data(struct nilfs_sc_info *sci, | |||
524 | int err; | 513 | int err; |
525 | 514 | ||
526 | err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); | 515 | err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); |
527 | if (unlikely(err < 0)) | 516 | if (err < 0) |
528 | return nilfs_handle_bmap_error(err, __func__, inode, | 517 | return err; |
529 | sci->sc_super); | ||
530 | 518 | ||
531 | err = nilfs_segctor_add_file_block(sci, bh, inode, | 519 | err = nilfs_segctor_add_file_block(sci, bh, inode, |
532 | sizeof(struct nilfs_binfo_v)); | 520 | sizeof(struct nilfs_binfo_v)); |
@@ -539,13 +527,7 @@ static int nilfs_collect_file_node(struct nilfs_sc_info *sci, | |||
539 | struct buffer_head *bh, | 527 | struct buffer_head *bh, |
540 | struct inode *inode) | 528 | struct inode *inode) |
541 | { | 529 | { |
542 | int err; | 530 | return nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); |
543 | |||
544 | err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); | ||
545 | if (unlikely(err < 0)) | ||
546 | return nilfs_handle_bmap_error(err, __func__, inode, | ||
547 | sci->sc_super); | ||
548 | return 0; | ||
549 | } | 531 | } |
550 | 532 | ||
551 | static int nilfs_collect_file_bmap(struct nilfs_sc_info *sci, | 533 | static int nilfs_collect_file_bmap(struct nilfs_sc_info *sci, |
@@ -588,9 +570,8 @@ static int nilfs_collect_dat_data(struct nilfs_sc_info *sci, | |||
588 | int err; | 570 | int err; |
589 | 571 | ||
590 | err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); | 572 | err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); |
591 | if (unlikely(err < 0)) | 573 | if (err < 0) |
592 | return nilfs_handle_bmap_error(err, __func__, inode, | 574 | return err; |
593 | sci->sc_super); | ||
594 | 575 | ||
595 | err = nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64)); | 576 | err = nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64)); |
596 | if (!err) | 577 | if (!err) |
@@ -1563,7 +1544,6 @@ nilfs_segctor_update_payload_blocknr(struct nilfs_sc_info *sci, | |||
1563 | return 0; | 1544 | return 0; |
1564 | 1545 | ||
1565 | failed_bmap: | 1546 | failed_bmap: |
1566 | err = nilfs_handle_bmap_error(err, __func__, inode, sci->sc_super); | ||
1567 | return err; | 1547 | return err; |
1568 | } | 1548 | } |
1569 | 1549 | ||