Commit e828949e5b42bfd234ee537cdb7c5e3a577958a3
1 parent
b004a5eb0b
Exists in
master
and in
7 other branches
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>
Showing 5 changed files with 48 additions and 63 deletions Side-by-side Diff
fs/nilfs2/bmap.c
... | ... | @@ -38,6 +38,19 @@ |
38 | 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 | 55 | * nilfs_bmap_lookup_at_level - find a data block or node block |
43 | 56 | * @bmap: bmap |
44 | 57 | |
... | ... | @@ -66,8 +79,10 @@ |
66 | 79 | |
67 | 80 | down_read(&bmap->b_sem); |
68 | 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 | 84 | goto out; |
85 | + } | |
71 | 86 | if (NILFS_BMAP_USE_VBN(bmap)) { |
72 | 87 | ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp, |
73 | 88 | &blocknr); |
... | ... | @@ -88,7 +103,8 @@ |
88 | 103 | down_read(&bmap->b_sem); |
89 | 104 | ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks); |
90 | 105 | up_read(&bmap->b_sem); |
91 | - return ret; | |
106 | + | |
107 | + return nilfs_bmap_convert_error(bmap, __func__, ret); | |
92 | 108 | } |
93 | 109 | |
94 | 110 | static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) |
... | ... | @@ -144,7 +160,8 @@ |
144 | 160 | down_write(&bmap->b_sem); |
145 | 161 | ret = nilfs_bmap_do_insert(bmap, key, rec); |
146 | 162 | up_write(&bmap->b_sem); |
147 | - return ret; | |
163 | + | |
164 | + return nilfs_bmap_convert_error(bmap, __func__, ret); | |
148 | 165 | } |
149 | 166 | |
150 | 167 | static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) |
151 | 168 | |
... | ... | @@ -180,9 +197,12 @@ |
180 | 197 | |
181 | 198 | down_read(&bmap->b_sem); |
182 | 199 | ret = bmap->b_ops->bop_last_key(bmap, &lastkey); |
183 | - if (!ret) | |
184 | - *key = lastkey; | |
185 | 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 | 206 | return ret; |
187 | 207 | } |
188 | 208 | |
... | ... | @@ -210,7 +230,8 @@ |
210 | 230 | down_write(&bmap->b_sem); |
211 | 231 | ret = nilfs_bmap_do_delete(bmap, key); |
212 | 232 | up_write(&bmap->b_sem); |
213 | - return ret; | |
233 | + | |
234 | + return nilfs_bmap_convert_error(bmap, __func__, ret); | |
214 | 235 | } |
215 | 236 | |
216 | 237 | static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key) |
... | ... | @@ -261,7 +282,8 @@ |
261 | 282 | down_write(&bmap->b_sem); |
262 | 283 | ret = nilfs_bmap_do_truncate(bmap, key); |
263 | 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 @@ |
300 | 322 | down_write(&bmap->b_sem); |
301 | 323 | ret = bmap->b_ops->bop_propagate(bmap, bh); |
302 | 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 @@ |
344 | 367 | down_write(&bmap->b_sem); |
345 | 368 | ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo); |
346 | 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 @@ |
373 | 397 | down_write(&bmap->b_sem); |
374 | 398 | ret = bmap->b_ops->bop_mark(bmap, key, level); |
375 | 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 | /** |
fs/nilfs2/ifile.c
... | ... | @@ -149,14 +149,9 @@ |
149 | 149 | } |
150 | 150 | |
151 | 151 | err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh); |
152 | - if (unlikely(err)) { | |
153 | - if (err == -EINVAL) | |
154 | - nilfs_error(sb, __func__, "ifile is broken"); | |
155 | - else | |
156 | - nilfs_warning(sb, __func__, | |
157 | - "unable to read inode: %lu", | |
158 | - (unsigned long) ino); | |
159 | - } | |
152 | + if (unlikely(err)) | |
153 | + nilfs_warning(sb, __func__, "unable to read inode: %lu", | |
154 | + (unsigned long) ino); | |
160 | 155 | return err; |
161 | 156 | } |
162 | 157 |
fs/nilfs2/inode.c
... | ... | @@ -96,11 +96,6 @@ |
96 | 96 | inode->i_ino, |
97 | 97 | (unsigned long long)blkoff); |
98 | 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 | 100 | nilfs_transaction_abort(inode->i_sb); |
106 | 101 | goto out; |
... | ... | @@ -629,7 +624,7 @@ |
629 | 624 | |
630 | 625 | if (!test_bit(NILFS_I_BMAP, &ii->i_state)) |
631 | 626 | return; |
632 | - repeat: | |
627 | +repeat: | |
633 | 628 | ret = nilfs_bmap_last_key(ii->i_bmap, &b); |
634 | 629 | if (ret == -ENOENT) |
635 | 630 | return; |
... | ... | @@ -646,14 +641,10 @@ |
646 | 641 | nilfs_bmap_truncate(ii->i_bmap, b) == 0)) |
647 | 642 | goto repeat; |
648 | 643 | |
649 | - failed: | |
650 | - if (ret == -EINVAL) | |
651 | - nilfs_error(ii->vfs_inode.i_sb, __func__, | |
652 | - "bmap is broken (ino=%lu)", ii->vfs_inode.i_ino); | |
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); | |
644 | +failed: | |
645 | + nilfs_warning(ii->vfs_inode.i_sb, __func__, | |
646 | + "failed to truncate bmap (ino=%lu, err=%d)", | |
647 | + ii->vfs_inode.i_ino, ret); | |
657 | 648 | } |
658 | 649 | |
659 | 650 | void nilfs_truncate(struct inode *inode) |
fs/nilfs2/mdt.c
... | ... | @@ -237,8 +237,6 @@ |
237 | 237 | * |
238 | 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 | 240 | * %-EROFS - Read only filesystem (for create mode) |
243 | 241 | */ |
244 | 242 | int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create, |
... | ... | @@ -273,8 +271,6 @@ |
273 | 271 | * %-ENOMEM - Insufficient memory available. |
274 | 272 | * |
275 | 273 | * %-EIO - I/O error |
276 | - * | |
277 | - * %-EINVAL - bmap is broken. (the caller should call nilfs_error()) | |
278 | 274 | */ |
279 | 275 | int nilfs_mdt_delete_block(struct inode *inode, unsigned long block) |
280 | 276 | { |
... | ... | @@ -350,8 +346,6 @@ |
350 | 346 | * %-EIO - I/O error |
351 | 347 | * |
352 | 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 | 350 | int nilfs_mdt_mark_block_dirty(struct inode *inode, unsigned long block) |
357 | 351 | { |
fs/nilfs2/segment.c
... | ... | @@ -504,17 +504,6 @@ |
504 | 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 | 508 | * Callback functions that enumerate, mark, and collect dirty blocks |
520 | 509 | */ |
... | ... | @@ -524,9 +513,8 @@ |
524 | 513 | int err; |
525 | 514 | |
526 | 515 | err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); |
527 | - if (unlikely(err < 0)) | |
528 | - return nilfs_handle_bmap_error(err, __func__, inode, | |
529 | - sci->sc_super); | |
516 | + if (err < 0) | |
517 | + return err; | |
530 | 518 | |
531 | 519 | err = nilfs_segctor_add_file_block(sci, bh, inode, |
532 | 520 | sizeof(struct nilfs_binfo_v)); |
... | ... | @@ -539,13 +527,7 @@ |
539 | 527 | struct buffer_head *bh, |
540 | 528 | struct inode *inode) |
541 | 529 | { |
542 | - int err; | |
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; | |
530 | + return nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); | |
549 | 531 | } |
550 | 532 | |
551 | 533 | static int nilfs_collect_file_bmap(struct nilfs_sc_info *sci, |
... | ... | @@ -588,9 +570,8 @@ |
588 | 570 | int err; |
589 | 571 | |
590 | 572 | err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); |
591 | - if (unlikely(err < 0)) | |
592 | - return nilfs_handle_bmap_error(err, __func__, inode, | |
593 | - sci->sc_super); | |
573 | + if (err < 0) | |
574 | + return err; | |
594 | 575 | |
595 | 576 | err = nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64)); |
596 | 577 | if (!err) |
... | ... | @@ -1563,7 +1544,6 @@ |
1563 | 1544 | return 0; |
1564 | 1545 | |
1565 | 1546 | failed_bmap: |
1566 | - err = nilfs_handle_bmap_error(err, __func__, inode, sci->sc_super); | |
1567 | 1547 | return err; |
1568 | 1548 | } |
1569 | 1549 |