Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix --block-io #310

Merged
merged 1 commit into from
Apr 23, 2024
Merged

Fix --block-io #310

merged 1 commit into from
Apr 23, 2024

Conversation

cvonelm
Copy link
Member

@cvonelm cvonelm commented Nov 27, 2023

Due to a bug, when the multi-reader switches from one reader with later events to one that has earlier events, a block I/O event was discarded from the reader with the later events. This predictably led to event loss.

Further, the insert event was switched from block_rq_insert to block_bio_queue. The reason for this is that block_rq_insert never matched the amount of data reported by block_rq_issue and block_rq_complete. I could not find another block_rq_* tracepoint that accounts for the block I/O request that do not enter through block_rq_insert. However, block_bio_queue matches the amount of data that block_rq_issue and block_rq_complete report.

This results in somewhat of a mismatch, as block_bio_* is one level higher up than block_rq_. This is most notable in that one block_bio_queue "struct bio" is split into multiple (usually less than 10) "struct rq" on the block_rq_ level.

I remedy this situation by only writing the first block_rq_insert/issue event that I encounter (which is the one with the matching sector to the block_bio_queue event) and discarding the others.

We might want to discuss if using the timestamp of the last block_rq_* event is the more correct variant.

This Fixes #290

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty file?


BlockDevice dev = block_device_for<RecordBlock>(event);

if (sector_cache_.count(dev) == 0 && sector_cache_[dev].count(event->sector) == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (sector_cache_.count(dev) == 0 && sector_cache_[dev].count(event->sector) == 0)
if (sector_cache_.count(dev) == 0 || sector_cache_.at(dev).count(event->sector) == 0 || sector_cache_.at(dev).at(event->sector) == 0 )

it can't be both, right?


BlockDevice dev = block_device_for<RecordBlock>(event);

if (sector_cache_.count(dev) == 0 && sector_cache_[dev].count(event->sector) == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (sector_cache_.count(dev) == 0 && sector_cache_[dev].count(event->sector) == 0)
if (sector_cache_.count(dev) == 0 || sector_cache_.at(dev).count(event->sector) == 0)

this only not crashes because you use operator[]

Comment on lines 110 to 114
if (sector_cache_.count(dev) == 0)
{
sector_cache_.emplace(std::piecewise_construct, std::forward_as_tuple(dev),
std::forward_as_tuple(std::map<uint64_t, uint64_t>()));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary, as you use operator[] and only default arguments.

sector_cache_.emplace(std::piecewise_construct, std::forward_as_tuple(dev),
std::forward_as_tuple(std::map<uint64_t, uint64_t>()));
}
sector_cache_[dev][event->sector] = size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sector_cache_[dev][event->sector] = size;
sector_cache_[dev][event->sector] += size;

why not accumulate instead of overwriting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to accumulate here? We want to cache the size of that specific queue-ing operation here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if there's another request for the same sector?

handle, size, event->sector);
handle, sector_cache_[dev][event->sector],
event->sector);
sector_cache_[dev].erase(event->sector);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sector_cache_[dev].erase(event->sector);
sector_cache_[dev][event->sector] = 0;

@cvonelm cvonelm force-pushed the issue-290-block-io-broken branch from 39cbc61 to 5c9696f Compare March 14, 2024 06:44
uint64_t sector; // the accessed sector on the device

uint32_t nr_sector; // the number of sector_cache_ written
// 512) for complete: the error code of the operation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment no verb?

sector_cache_.emplace(std::piecewise_construct, std::forward_as_tuple(dev),
std::forward_as_tuple(std::map<uint64_t, uint64_t>()));
}
sector_cache_[dev][event->sector] = size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if there's another request for the same sector?

Due to a bug, when the multi-reader switches from one reader with later
events to one that has earlier events, a block I/O event was discarded
from the reader with the later events. This predictably led to event
loss.

Further, the insert event was switched from block_rq_insert to
block_bio_queue. The reason for this is that block_rq_insert never
matched the amount of data reported by block_rq_issue and
block_rq_complete. I could not find another block_rq_* tracepoint that
accounts for the block I/O request that do not enter through
block_rq_insert. However, block_bio_queue matches the amount of data
that block_rq_issue and block_rq_complete report.

This results in somewhat of a mismatch, as block_bio_* is one level
higher up than block_rq_*. This is most notable in that one
block_bio_queue "struct bio" is split into multiple (usually less than
10) "struct rq" on the block_rq_* level.

I remedy this situation by only writing the first block_rq_insert/issue
event that I encounter (which is the one with the matching sector to the
block_bio_queue event) and discarding the others.

We might want to discuss if using the timestamp of the last
block_rq_* event is the more correct variant.
@cvonelm cvonelm force-pushed the issue-290-block-io-broken branch from 931a8f8 to c7dcbcb Compare April 23, 2024 15:58
@cvonelm cvonelm merged commit bcf8fd2 into master Apr 23, 2024
41 checks passed
@cvonelm cvonelm deleted the issue-290-block-io-broken branch April 23, 2024 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

--block-io doesnt capture NVMe device read/writes.
2 participants