.. | .. |
---|
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 | } |
---|