| .. | .. |
|---|
| 9 | 9 | #include "xfs_format.h" |
|---|
| 10 | 10 | #include "xfs_trans_resv.h" |
|---|
| 11 | 11 | #include "xfs_mount.h" |
|---|
| 12 | | -#include "xfs_defer.h" |
|---|
| 13 | | -#include "xfs_btree.h" |
|---|
| 14 | | -#include "xfs_bit.h" |
|---|
| 15 | 12 | #include "xfs_log_format.h" |
|---|
| 16 | | -#include "xfs_trans.h" |
|---|
| 17 | | -#include "xfs_sb.h" |
|---|
| 18 | 13 | #include "xfs_inode.h" |
|---|
| 19 | 14 | #include "xfs_icache.h" |
|---|
| 20 | 15 | #include "xfs_dir2.h" |
|---|
| 21 | 16 | #include "xfs_dir2_priv.h" |
|---|
| 22 | | -#include "xfs_ialloc.h" |
|---|
| 23 | | -#include "scrub/xfs_scrub.h" |
|---|
| 24 | 17 | #include "scrub/scrub.h" |
|---|
| 25 | 18 | #include "scrub/common.h" |
|---|
| 26 | | -#include "scrub/trace.h" |
|---|
| 27 | 19 | |
|---|
| 28 | 20 | /* Set us up to scrub parents. */ |
|---|
| 29 | 21 | int |
|---|
| .. | .. |
|---|
| 40 | 32 | |
|---|
| 41 | 33 | struct xchk_parent_ctx { |
|---|
| 42 | 34 | struct dir_context dc; |
|---|
| 35 | + struct xfs_scrub *sc; |
|---|
| 43 | 36 | xfs_ino_t ino; |
|---|
| 44 | 37 | xfs_nlink_t nlink; |
|---|
| 38 | + bool cancelled; |
|---|
| 45 | 39 | }; |
|---|
| 46 | 40 | |
|---|
| 47 | 41 | /* Look for a single entry in a directory pointing to an inode. */ |
|---|
| .. | .. |
|---|
| 55 | 49 | unsigned type) |
|---|
| 56 | 50 | { |
|---|
| 57 | 51 | struct xchk_parent_ctx *spc; |
|---|
| 52 | + int error = 0; |
|---|
| 58 | 53 | |
|---|
| 59 | 54 | spc = container_of(dc, struct xchk_parent_ctx, dc); |
|---|
| 60 | 55 | if (spc->ino == ino) |
|---|
| 61 | 56 | spc->nlink++; |
|---|
| 62 | | - return 0; |
|---|
| 57 | + |
|---|
| 58 | + /* |
|---|
| 59 | + * If we're facing a fatal signal, bail out. Store the cancellation |
|---|
| 60 | + * status separately because the VFS readdir code squashes error codes |
|---|
| 61 | + * into short directory reads. |
|---|
| 62 | + */ |
|---|
| 63 | + if (xchk_should_terminate(spc->sc, &error)) |
|---|
| 64 | + spc->cancelled = true; |
|---|
| 65 | + |
|---|
| 66 | + return error; |
|---|
| 63 | 67 | } |
|---|
| 64 | 68 | |
|---|
| 65 | 69 | /* Count the number of dentries in the parent dir that point to this inode. */ |
|---|
| .. | .. |
|---|
| 70 | 74 | xfs_nlink_t *nlink) |
|---|
| 71 | 75 | { |
|---|
| 72 | 76 | struct xchk_parent_ctx spc = { |
|---|
| 73 | | - .dc.actor = xchk_parent_actor, |
|---|
| 74 | | - .dc.pos = 0, |
|---|
| 75 | | - .ino = sc->ip->i_ino, |
|---|
| 76 | | - .nlink = 0, |
|---|
| 77 | + .dc.actor = xchk_parent_actor, |
|---|
| 78 | + .ino = sc->ip->i_ino, |
|---|
| 79 | + .sc = sc, |
|---|
| 77 | 80 | }; |
|---|
| 78 | 81 | size_t bufsize; |
|---|
| 79 | 82 | loff_t oldpos; |
|---|
| .. | .. |
|---|
| 87 | 90 | * if there is one. |
|---|
| 88 | 91 | */ |
|---|
| 89 | 92 | lock_mode = xfs_ilock_data_map_shared(parent); |
|---|
| 90 | | - if (parent->i_d.di_nextents > 0) |
|---|
| 91 | | - error = xfs_dir3_data_readahead(parent, 0, -1); |
|---|
| 93 | + if (parent->i_df.if_nextents > 0) |
|---|
| 94 | + error = xfs_dir3_data_readahead(parent, 0, 0); |
|---|
| 92 | 95 | xfs_iunlock(parent, lock_mode); |
|---|
| 93 | 96 | if (error) |
|---|
| 94 | 97 | return error; |
|---|
| .. | .. |
|---|
| 105 | 108 | error = xfs_readdir(sc->tp, parent, &spc.dc, bufsize); |
|---|
| 106 | 109 | if (error) |
|---|
| 107 | 110 | goto out; |
|---|
| 111 | + if (spc.cancelled) { |
|---|
| 112 | + error = -EAGAIN; |
|---|
| 113 | + goto out; |
|---|
| 114 | + } |
|---|
| 108 | 115 | if (oldpos == spc.dc.pos) |
|---|
| 109 | 116 | break; |
|---|
| 110 | 117 | oldpos = spc.dc.pos; |
|---|
| .. | .. |
|---|
| 320 | 327 | * If we failed to lock the parent inode even after a retry, just mark |
|---|
| 321 | 328 | * this scrub incomplete and return. |
|---|
| 322 | 329 | */ |
|---|
| 323 | | - if (sc->try_harder && error == -EDEADLOCK) { |
|---|
| 330 | + if ((sc->flags & XCHK_TRY_HARDER) && error == -EDEADLOCK) { |
|---|
| 324 | 331 | error = 0; |
|---|
| 325 | 332 | xchk_set_incomplete(sc); |
|---|
| 326 | 333 | } |
|---|