13
13
#include "extents.h"
14
14
#include "journal.h"
15
15
#include "replicas.h"
16
+ #include "subvolume.h"
16
17
#include "trace.h"
17
18
18
19
#include <linux/prefetch.h>
@@ -683,6 +684,55 @@ static void bch2_btree_iter_verify_entry_exit(struct btree_iter *iter)
683
684
bkey_cmp (iter -> pos , iter -> k .p ) > 0 );
684
685
}
685
686
687
+ static int bch2_btree_iter_verify_ret (struct btree_iter * iter , struct bkey_s_c k )
688
+ {
689
+ struct btree_trans * trans = iter -> trans ;
690
+ struct btree_iter copy ;
691
+ struct bkey_s_c prev ;
692
+ int ret = 0 ;
693
+
694
+ if (!bch2_debug_check_iterators )
695
+ return 0 ;
696
+
697
+ if (!(iter -> flags & BTREE_ITER_FILTER_SNAPSHOTS ))
698
+ return 0 ;
699
+
700
+ if (bkey_err (k ) || !k .k )
701
+ return 0 ;
702
+
703
+ BUG_ON (!bch2_snapshot_is_ancestor (trans -> c ,
704
+ iter -> snapshot ,
705
+ k .k -> p .snapshot ));
706
+
707
+ bch2_trans_iter_init (trans , & copy , iter -> btree_id , iter -> pos ,
708
+ BTREE_ITER_ALL_SNAPSHOTS );
709
+ prev = bch2_btree_iter_prev (& copy );
710
+ if (!prev .k )
711
+ goto out ;
712
+
713
+ ret = bkey_err (prev );
714
+ if (ret )
715
+ goto out ;
716
+
717
+ if (!bkey_cmp (prev .k -> p , k .k -> p ) &&
718
+ bch2_snapshot_is_ancestor (trans -> c , iter -> snapshot ,
719
+ prev .k -> p .snapshot ) > 0 ) {
720
+ char buf1 [100 ], buf2 [200 ];
721
+
722
+ bch2_bkey_to_text (& PBUF (buf1 ), k .k );
723
+ bch2_bkey_to_text (& PBUF (buf2 ), prev .k );
724
+
725
+ panic ("iter snap %u\n"
726
+ "k %s\n"
727
+ "prev %s\n" ,
728
+ iter -> snapshot ,
729
+ buf1 , buf2 );
730
+ }
731
+ out :
732
+ bch2_trans_iter_exit (trans , & copy );
733
+ return ret ;
734
+ }
735
+
686
736
#else
687
737
688
738
static inline void bch2_btree_path_verify_level (struct btree_trans * trans ,
@@ -691,6 +741,7 @@ static inline void bch2_btree_path_verify(struct btree_trans *trans,
691
741
struct btree_path * path ) {}
692
742
static inline void bch2_btree_iter_verify (struct btree_iter * iter ) {}
693
743
static inline void bch2_btree_iter_verify_entry_exit (struct btree_iter * iter ) {}
744
+ static inline int bch2_btree_iter_verify_ret (struct btree_iter * iter , struct bkey_s_c k ) { return 0 ; }
694
745
695
746
#endif
696
747
@@ -2004,11 +2055,25 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
2004
2055
}
2005
2056
2006
2057
if (likely (k .k )) {
2007
- if (likely (!bkey_deleted (k .k )))
2008
- break ;
2058
+ /*
2059
+ * We can never have a key in a leaf node at POS_MAX, so
2060
+ * we don't have to check these successor() calls:
2061
+ */
2062
+ if ((iter -> flags & BTREE_ITER_FILTER_SNAPSHOTS ) &&
2063
+ !bch2_snapshot_is_ancestor (trans -> c ,
2064
+ iter -> snapshot ,
2065
+ k .k -> p .snapshot )) {
2066
+ search_key = bpos_successor (k .k -> p );
2067
+ continue ;
2068
+ }
2009
2069
2010
- /* Advance to next key: */
2011
- search_key = bkey_successor (iter , k .k -> p );
2070
+ if (bkey_whiteout (k .k ) &&
2071
+ !(iter -> flags & BTREE_ITER_ALL_SNAPSHOTS )) {
2072
+ search_key = bkey_successor (iter , k .k -> p );
2073
+ continue ;
2074
+ }
2075
+
2076
+ break ;
2012
2077
} else if (likely (bpos_cmp (iter -> path -> l [0 ].b -> key .k .p , SPOS_MAX ))) {
2013
2078
/* Advance to next leaf node: */
2014
2079
search_key = bpos_successor (iter -> path -> l [0 ].b -> key .k .p );
@@ -2029,6 +2094,9 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
2029
2094
else if (bkey_cmp (bkey_start_pos (k .k ), iter -> pos ) > 0 )
2030
2095
iter -> pos = bkey_start_pos (k .k );
2031
2096
2097
+ if (iter -> flags & BTREE_ITER_FILTER_SNAPSHOTS )
2098
+ iter -> pos .snapshot = iter -> snapshot ;
2099
+
2032
2100
cmp = bpos_cmp (k .k -> p , iter -> path -> pos );
2033
2101
if (cmp ) {
2034
2102
iter -> path = bch2_btree_path_make_mut (trans , iter -> path ,
@@ -2041,6 +2109,10 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
2041
2109
2042
2110
bch2_btree_iter_verify_entry_exit (iter );
2043
2111
bch2_btree_iter_verify (iter );
2112
+ ret = bch2_btree_iter_verify_ret (iter , k );
2113
+ if (unlikely (ret ))
2114
+ return bkey_s_c_err (ret );
2115
+
2044
2116
return k ;
2045
2117
}
2046
2118
@@ -2064,14 +2136,20 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
2064
2136
{
2065
2137
struct btree_trans * trans = iter -> trans ;
2066
2138
struct bpos search_key = iter -> pos ;
2139
+ struct btree_path * saved_path = NULL ;
2067
2140
struct bkey_s_c k ;
2141
+ struct bkey saved_k ;
2142
+ const struct bch_val * saved_v ;
2068
2143
int ret ;
2069
2144
2070
2145
EBUG_ON (iter -> path -> cached || iter -> path -> level );
2071
2146
EBUG_ON (iter -> flags & BTREE_ITER_WITH_UPDATES );
2072
2147
bch2_btree_iter_verify (iter );
2073
2148
bch2_btree_iter_verify_entry_exit (iter );
2074
2149
2150
+ if (iter -> flags & BTREE_ITER_FILTER_SNAPSHOTS )
2151
+ search_key .snapshot = U32_MAX ;
2152
+
2075
2153
while (1 ) {
2076
2154
iter -> path = btree_path_set_pos (trans , iter -> path , search_key ,
2077
2155
iter -> flags & BTREE_ITER_INTENT );
@@ -2088,12 +2166,55 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
2088
2166
& iter -> path -> l [0 ], & iter -> k );
2089
2167
if (!k .k ||
2090
2168
((iter -> flags & BTREE_ITER_IS_EXTENTS )
2091
- ? bkey_cmp (bkey_start_pos (k .k ), iter -> pos ) >= 0
2092
- : bkey_cmp (k .k -> p , iter -> pos ) > 0 ))
2169
+ ? bpos_cmp (bkey_start_pos (k .k ), search_key ) >= 0
2170
+ : bpos_cmp (k .k -> p , search_key ) > 0 ))
2093
2171
k = btree_path_level_prev (trans , iter -> path ,
2094
2172
& iter -> path -> l [0 ], & iter -> k );
2095
2173
2096
2174
if (likely (k .k )) {
2175
+ if (iter -> flags & BTREE_ITER_FILTER_SNAPSHOTS ) {
2176
+ if (k .k -> p .snapshot == iter -> snapshot )
2177
+ goto got_key ;
2178
+
2179
+ /*
2180
+ * If we have a saved candidate, and we're no
2181
+ * longer at the same _key_ (not pos), return
2182
+ * that candidate
2183
+ */
2184
+ if (saved_path && bkey_cmp (k .k -> p , saved_k .p )) {
2185
+ bch2_path_put (trans , iter -> path ,
2186
+ iter -> flags & BTREE_ITER_INTENT );
2187
+ iter -> path = saved_path ;
2188
+ saved_path = NULL ;
2189
+ iter -> k = saved_k ;
2190
+ k .v = saved_v ;
2191
+ goto got_key ;
2192
+ }
2193
+
2194
+ if (bch2_snapshot_is_ancestor (iter -> trans -> c ,
2195
+ iter -> snapshot ,
2196
+ k .k -> p .snapshot )) {
2197
+ if (saved_path )
2198
+ bch2_path_put (trans , saved_path ,
2199
+ iter -> flags & BTREE_ITER_INTENT );
2200
+ saved_path = btree_path_clone (trans , iter -> path ,
2201
+ iter -> flags & BTREE_ITER_INTENT );
2202
+ saved_k = * k .k ;
2203
+ saved_v = k .v ;
2204
+ }
2205
+
2206
+ search_key = bpos_predecessor (k .k -> p );
2207
+ continue ;
2208
+ }
2209
+ got_key :
2210
+ if (bkey_whiteout (k .k ) &&
2211
+ !(iter -> flags & BTREE_ITER_ALL_SNAPSHOTS )) {
2212
+ search_key = bkey_predecessor (iter , k .k -> p );
2213
+ if (iter -> flags & BTREE_ITER_FILTER_SNAPSHOTS )
2214
+ search_key .snapshot = U32_MAX ;
2215
+ continue ;
2216
+ }
2217
+
2097
2218
break ;
2098
2219
} else if (likely (bpos_cmp (iter -> path -> l [0 ].b -> data -> min_key , POS_MIN ))) {
2099
2220
/* Advance to previous leaf node: */
@@ -2111,7 +2232,12 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
2111
2232
/* Extents can straddle iter->pos: */
2112
2233
if (bkey_cmp (k .k -> p , iter -> pos ) < 0 )
2113
2234
iter -> pos = k .k -> p ;
2235
+
2236
+ if (iter -> flags & BTREE_ITER_FILTER_SNAPSHOTS )
2237
+ iter -> pos .snapshot = iter -> snapshot ;
2114
2238
out :
2239
+ if (saved_path )
2240
+ bch2_path_put (trans , saved_path , iter -> flags & BTREE_ITER_INTENT );
2115
2241
iter -> path -> should_be_locked = true;
2116
2242
2117
2243
bch2_btree_iter_verify_entry_exit (iter );
@@ -2160,7 +2286,8 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
2160
2286
if (unlikely (ret ))
2161
2287
return bkey_s_c_err (ret );
2162
2288
2163
- if (!(iter -> flags & BTREE_ITER_IS_EXTENTS )) {
2289
+ if ((iter -> flags & BTREE_ITER_CACHED ) ||
2290
+ !(iter -> flags & (BTREE_ITER_IS_EXTENTS |BTREE_ITER_FILTER_SNAPSHOTS ))) {
2164
2291
struct bkey_i * next_update ;
2165
2292
2166
2293
next_update = btree_trans_peek_updates (iter );
@@ -2209,22 +2336,28 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
2209
2336
if (bkey_cmp (iter -> pos , next ) < 0 ) {
2210
2337
bkey_init (& iter -> k );
2211
2338
iter -> k .p = iter -> pos ;
2212
- bch2_key_resize (& iter -> k ,
2213
- min_t (u64 , KEY_SIZE_MAX ,
2214
- (next .inode == iter -> pos .inode
2215
- ? next .offset
2216
- : KEY_OFFSET_MAX ) -
2217
- iter -> pos .offset ));
2339
+
2340
+ if (iter -> flags & BTREE_ITER_IS_EXTENTS ) {
2341
+ bch2_key_resize (& iter -> k ,
2342
+ min_t (u64 , KEY_SIZE_MAX ,
2343
+ (next .inode == iter -> pos .inode
2344
+ ? next .offset
2345
+ : KEY_OFFSET_MAX ) -
2346
+ iter -> pos .offset ));
2347
+ EBUG_ON (!iter -> k .size );
2348
+ }
2218
2349
2219
2350
k = (struct bkey_s_c ) { & iter -> k , NULL };
2220
- EBUG_ON (!k .k -> size );
2221
2351
}
2222
2352
}
2223
2353
2224
2354
iter -> path -> should_be_locked = true;
2225
2355
2226
2356
bch2_btree_iter_verify_entry_exit (iter );
2227
2357
bch2_btree_iter_verify (iter );
2358
+ ret = bch2_btree_iter_verify_ret (iter , k );
2359
+ if (unlikely (ret ))
2360
+ return bkey_s_c_err (ret );
2228
2361
2229
2362
return k ;
2230
2363
}
@@ -2392,6 +2525,13 @@ static void __bch2_trans_iter_init(struct btree_trans *trans,
2392
2525
if (!btree_type_has_snapshots (btree_id ) &&
2393
2526
!(flags & __BTREE_ITER_ALL_SNAPSHOTS ))
2394
2527
flags &= ~BTREE_ITER_ALL_SNAPSHOTS ;
2528
+ #if 0
2529
+ /* let's have this be explicitly set: */
2530
+ if ((flags & BTREE_ITER_TYPE ) != BTREE_ITER_NODES &&
2531
+ btree_type_has_snapshots (btree_id ) &&
2532
+ !(flags & BTREE_ITER_ALL_SNAPSHOTS ))
2533
+ flags |= BTREE_ITER_FILTER_SNAPSHOTS ;
2534
+ #endif
2395
2535
2396
2536
if (!(flags & BTREE_ITER_ALL_SNAPSHOTS ))
2397
2537
pos .snapshot = btree_type_has_snapshots (btree_id )
0 commit comments