@@ -17,7 +17,7 @@ void BlockPrefetcher::PrefetchIfNeeded(
1717 const size_t readahead_size, bool is_for_compaction,
1818 const bool no_sequential_checking, const ReadOptions& read_options,
1919 const std::function<void (bool , uint64_t &, uint64_t &)>& readaheadsize_cb,
20- bool is_async_io_prefetch) {
20+ bool is_async_io_prefetch, PrefetchDirection direction ) {
2121 if (read_options.read_tier == ReadTier::kBlockCacheTier ) {
2222 // Disable prefetching when IO disallowed. (Note that we haven't allocated
2323 // any buffers yet despite the various tracked settings.)
@@ -28,13 +28,15 @@ void BlockPrefetcher::PrefetchIfNeeded(
2828 readahead_params.initial_readahead_size = readahead_size;
2929 readahead_params.max_readahead_size = readahead_size;
3030 readahead_params.num_buffers = is_async_io_prefetch ? 2 : 1 ;
31+ readahead_params.direction = direction;
3132
3233 const size_t len = BlockBasedTable::BlockSizeWithTrailer (handle);
3334 const size_t offset = handle.offset ();
3435 if (is_for_compaction) {
3536 if (!rep->file ->use_direct_io () && compaction_readahead_size_ > 0 ) {
3637 // If FS supports prefetching (readahead_limit_ will be non zero in that
3738 // case) and current block exists in prefetch buffer then return.
39+ // Compaction is always forward.
3840 if (offset + len <= readahead_limit_) {
3941 return ;
4042 }
@@ -108,12 +110,29 @@ void BlockPrefetcher::PrefetchIfNeeded(
108110
109111 // If FS supports prefetching (readahead_limit_ will be non zero in that case)
110112 // and current block exists in prefetch buffer then return.
111- if (offset + len <= readahead_limit_) {
113+ bool in_prefetch_range = false ;
114+ if (direction == PrefetchDirection::kForward ) {
115+ in_prefetch_range = (offset + len <= readahead_limit_);
116+ } else {
117+ // For backward, prefetch_start_ tracks lower bound of prefetched range.
118+ // If prefetch_start_ is 0 it means not set yet, treat as miss.
119+ in_prefetch_range = (prefetch_start_ != 0 && offset >= prefetch_start_ &&
120+ offset + len <= readahead_limit_);
121+ // Alternative simple check for backward: offset >= prefetch_start_
122+ // We'll use offset >= prefetch_start_ as indicator current block is within
123+ // prefetched window.
124+ if (prefetch_start_ != 0 ) {
125+ in_prefetch_range = (offset >= prefetch_start_);
126+ } else {
127+ in_prefetch_range = false ;
128+ }
129+ }
130+ if (in_prefetch_range) {
112131 UpdateReadPattern (offset, len);
113132 return ;
114133 }
115134
116- if (!IsBlockSequential (offset)) {
135+ if (!IsBlockSequential (offset, len, direction )) {
117136 UpdateReadPattern (offset, len);
118137 ResetValues (rep->table_options .initial_auto_readahead_size );
119138 return ;
@@ -148,11 +167,31 @@ void BlockPrefetcher::PrefetchIfNeeded(
148167 }
149168
150169 if (rep->fs_prefetch_support ) {
151- s = rep->file ->Prefetch (
152- opts, handle.offset (),
153- BlockBasedTable::BlockSizeWithTrailer (handle) + readahead_size_);
170+ uint64_t prefetch_offset;
171+ size_t prefetch_len;
172+ if (direction == PrefetchDirection::kForward ) {
173+ prefetch_offset = handle.offset ();
174+ prefetch_len =
175+ BlockBasedTable::BlockSizeWithTrailer (handle) + readahead_size_;
176+ } else {
177+ // Backward: prefetch from offset - readahead_size_ to offset + len
178+ uint64_t curr_offset = handle.offset ();
179+ uint64_t start =
180+ curr_offset > readahead_size_ ? curr_offset - readahead_size_ : 0 ;
181+ prefetch_offset = start;
182+ prefetch_len =
183+ curr_offset - start + BlockBasedTable::BlockSizeWithTrailer (handle);
184+ }
185+ s = rep->file ->Prefetch (opts, prefetch_offset, prefetch_len);
154186 if (s.ok ()) {
155- readahead_limit_ = offset + len + readahead_size_;
187+ if (direction == PrefetchDirection::kForward ) {
188+ readahead_limit_ = offset + len + readahead_size_;
189+ prefetch_start_ =
190+ offset; // not really used for forward but for completeness
191+ } else {
192+ prefetch_start_ = prefetch_offset;
193+ readahead_limit_ = offset + len;
194+ }
156195 // Keep exponentially increasing readahead size until
157196 // max_auto_readahead_size.
158197 readahead_size_ = std::min (max_auto_readahead_size, readahead_size_ * 2 );
0 commit comments