@@ -92,6 +92,101 @@ xfs_scrub_btree_set_corrupt(
92
92
__return_address );
93
93
}
94
94
95
+ /*
96
+ * Make sure this record is in order and doesn't stray outside of the parent
97
+ * keys.
98
+ */
99
+ STATIC void
100
+ xfs_scrub_btree_rec (
101
+ struct xfs_scrub_btree * bs )
102
+ {
103
+ struct xfs_btree_cur * cur = bs -> cur ;
104
+ union xfs_btree_rec * rec ;
105
+ union xfs_btree_key key ;
106
+ union xfs_btree_key hkey ;
107
+ union xfs_btree_key * keyp ;
108
+ struct xfs_btree_block * block ;
109
+ struct xfs_btree_block * keyblock ;
110
+ struct xfs_buf * bp ;
111
+
112
+ block = xfs_btree_get_block (cur , 0 , & bp );
113
+ rec = xfs_btree_rec_addr (cur , cur -> bc_ptrs [0 ], block );
114
+
115
+ trace_xfs_scrub_btree_rec (bs -> sc , cur , 0 );
116
+
117
+ /* If this isn't the first record, are they in order? */
118
+ if (!bs -> firstrec && !cur -> bc_ops -> recs_inorder (cur , & bs -> lastrec , rec ))
119
+ xfs_scrub_btree_set_corrupt (bs -> sc , cur , 0 );
120
+ bs -> firstrec = false;
121
+ memcpy (& bs -> lastrec , rec , cur -> bc_ops -> rec_len );
122
+
123
+ if (cur -> bc_nlevels == 1 )
124
+ return ;
125
+
126
+ /* Is this at least as large as the parent low key? */
127
+ cur -> bc_ops -> init_key_from_rec (& key , rec );
128
+ keyblock = xfs_btree_get_block (cur , 1 , & bp );
129
+ keyp = xfs_btree_key_addr (cur , cur -> bc_ptrs [1 ], keyblock );
130
+ if (cur -> bc_ops -> diff_two_keys (cur , & key , keyp ) < 0 )
131
+ xfs_scrub_btree_set_corrupt (bs -> sc , cur , 1 );
132
+
133
+ if (!(cur -> bc_flags & XFS_BTREE_OVERLAPPING ))
134
+ return ;
135
+
136
+ /* Is this no larger than the parent high key? */
137
+ cur -> bc_ops -> init_high_key_from_rec (& hkey , rec );
138
+ keyp = xfs_btree_high_key_addr (cur , cur -> bc_ptrs [1 ], keyblock );
139
+ if (cur -> bc_ops -> diff_two_keys (cur , keyp , & hkey ) < 0 )
140
+ xfs_scrub_btree_set_corrupt (bs -> sc , cur , 1 );
141
+ }
142
+
143
+ /*
144
+ * Make sure this key is in order and doesn't stray outside of the parent
145
+ * keys.
146
+ */
147
+ STATIC void
148
+ xfs_scrub_btree_key (
149
+ struct xfs_scrub_btree * bs ,
150
+ int level )
151
+ {
152
+ struct xfs_btree_cur * cur = bs -> cur ;
153
+ union xfs_btree_key * key ;
154
+ union xfs_btree_key * keyp ;
155
+ struct xfs_btree_block * block ;
156
+ struct xfs_btree_block * keyblock ;
157
+ struct xfs_buf * bp ;
158
+
159
+ block = xfs_btree_get_block (cur , level , & bp );
160
+ key = xfs_btree_key_addr (cur , cur -> bc_ptrs [level ], block );
161
+
162
+ trace_xfs_scrub_btree_key (bs -> sc , cur , level );
163
+
164
+ /* If this isn't the first key, are they in order? */
165
+ if (!bs -> firstkey [level ] &&
166
+ !cur -> bc_ops -> keys_inorder (cur , & bs -> lastkey [level ], key ))
167
+ xfs_scrub_btree_set_corrupt (bs -> sc , cur , level );
168
+ bs -> firstkey [level ] = false;
169
+ memcpy (& bs -> lastkey [level ], key , cur -> bc_ops -> key_len );
170
+
171
+ if (level + 1 >= cur -> bc_nlevels )
172
+ return ;
173
+
174
+ /* Is this at least as large as the parent low key? */
175
+ keyblock = xfs_btree_get_block (cur , level + 1 , & bp );
176
+ keyp = xfs_btree_key_addr (cur , cur -> bc_ptrs [level + 1 ], keyblock );
177
+ if (cur -> bc_ops -> diff_two_keys (cur , key , keyp ) < 0 )
178
+ xfs_scrub_btree_set_corrupt (bs -> sc , cur , level );
179
+
180
+ if (!(cur -> bc_flags & XFS_BTREE_OVERLAPPING ))
181
+ return ;
182
+
183
+ /* Is this no larger than the parent high key? */
184
+ key = xfs_btree_high_key_addr (cur , cur -> bc_ptrs [level ], block );
185
+ keyp = xfs_btree_high_key_addr (cur , cur -> bc_ptrs [level + 1 ], keyblock );
186
+ if (cur -> bc_ops -> diff_two_keys (cur , keyp , key ) < 0 )
187
+ xfs_scrub_btree_set_corrupt (bs -> sc , cur , level );
188
+ }
189
+
95
190
/*
96
191
* Check a btree pointer. Returns true if it's ok to use this pointer.
97
192
* Callers do not need to set the corrupt flag.
@@ -278,6 +373,7 @@ xfs_scrub_btree(
278
373
struct xfs_scrub_btree bs = {0 };
279
374
union xfs_btree_ptr ptr ;
280
375
union xfs_btree_ptr * pp ;
376
+ union xfs_btree_rec * recp ;
281
377
struct xfs_btree_block * block ;
282
378
int level ;
283
379
struct xfs_buf * bp ;
@@ -328,7 +424,16 @@ xfs_scrub_btree(
328
424
continue ;
329
425
}
330
426
331
- if (xfs_scrub_should_terminate (sc , & error ))
427
+ /* Records in order for scrub? */
428
+ xfs_scrub_btree_rec (& bs );
429
+
430
+ /* Call out to the record checker. */
431
+ recp = xfs_btree_rec_addr (cur , cur -> bc_ptrs [0 ], block );
432
+ error = bs .scrub_rec (& bs , recp );
433
+ if (error )
434
+ break ;
435
+ if (xfs_scrub_should_terminate (sc , & error ) ||
436
+ (sc -> sm -> sm_flags & XFS_SCRUB_OFLAG_CORRUPT ))
332
437
break ;
333
438
334
439
cur -> bc_ptrs [level ]++ ;
@@ -343,6 +448,9 @@ xfs_scrub_btree(
343
448
continue ;
344
449
}
345
450
451
+ /* Keys in order for scrub? */
452
+ xfs_scrub_btree_key (& bs , level );
453
+
346
454
/* Drill another level deeper. */
347
455
pp = xfs_btree_ptr_addr (cur , cur -> bc_ptrs [level ], block );
348
456
if (!xfs_scrub_btree_ptr_ok (& bs , level , pp )) {
0 commit comments