Skip to content

fix seek and write to block start zeros rest of block after written data (#188) #189

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

Conversation

yanshay
Copy link

@yanshay yanshay commented Jun 7, 2025

Fix for #188 where seeking to offset of block size multiple and then writing, writes the data and zero the leftover of the block size instead of keeping the data that was there.
Includes also test for seek+write at both offset that worked and offset that didn't work.

@@ -878,7 +878,9 @@ where
Err(e) => return Err(e),
};
let to_copy = core::cmp::min(block_avail, bytes_to_write - written);
let block = if block_offset != 0 || data.open_files[file_idx].current_offset < data.open_files[file_idx].entry.size {
let block = if block_offset != 0
Copy link
Member

Choose a reason for hiding this comment

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

I think I would prefer something like:

            let block = if (block_offset == 0) && (to_copy == Block::LEN) {
                // we're replacing the whole Block, so the previous contents
                // are irrelevant
                data.block_cache.blank_mut(block_idx)
            } else {
                debug!("Reading for partial block write");
                data.block_cache
                    .read_mut(block_idx)
                    .map_err(Error::DeviceError)?
            };

This also passes your new test case.

Copy link
Member

Choose a reason for hiding this comment

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

I believe that your fix would mean a write of 512 bytes at the start of the file would do a read-modify-write, when a write is sufficient.

Copy link
Author

@yanshay yanshay Jun 7, 2025

Choose a reason for hiding this comment

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

erased previously written command, got confused a bit.

What does to_copy end up being there?
bytes_to_write - written is the amount of total data left to write.
block_avail - is it the size of a available in the block starting the write point? so if block_offset is 0 it means it would be Block::LEN ?

Copy link
Member

Choose a reason for hiding this comment

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

So I replied to your erased comment. Deleting my replies.

Copy link
Author

Choose a reason for hiding this comment

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

I don't have any preference, not really very familiar with the code. Let me know your preference and I'll modify it, I trust your judgement better than mine here.

Copy link
Member

Choose a reason for hiding this comment

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

to_copy is the amount of stuff we are writing to this block (see the slice copy that happens after). block_avail is how much stuff in this block (starting at the beginning of the block, because you cannot have holes in files when using FAT) is actually valid.

This might be better:

            let block = if (block_offset == 0) && (to_copy == block_avail) {
                // we're replacing the whole Block, so the previous contents
                // are irrelevant
                data.block_cache.blank_mut(block_idx)
            } else {
                debug!("Reading for partial block write");
                data.block_cache
                    .read_mut(block_idx)
                    .map_err(Error::DeviceError)?
            };

Copy link
Member

Choose a reason for hiding this comment

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

Consider a file that is 1026 bytes long. We write 514 bytes starting at offset 511.

We should:

  1. Read-modify-write Block 0 in the file, replacing block[511]
  2. Write Block 1 in the file.
  3. Read-modify write Block 2 in the file, replacing block[0] but leaving block[1] unchanged (and leaving block[2..512] unchanged as well).

Consider a file that is 1026 bytes long. We write 515 bytes starting at offset 511.

We should:

  1. Read-modify-write Block 0 in the file, replacing block[511]
  2. Write Block 1 in the file
  3. Write Block 2 - it contains two data bytes at block[0..2] and 510 zero bytes after that, but the zeroes are beyond the EOF.

Copy link
Author

Choose a reason for hiding this comment

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

I made the update based on the above and also updated the changelog.
Anything else required?

@yanshay yanshay force-pushed the yanshay_fix_seek_write_block_start branch from 2b0f1d0 to 8ad3628 Compare June 7, 2025 16:56
@thejpster
Copy link
Member

Thank you!

@thejpster thejpster added this pull request to the merge queue Jun 7, 2025
Merged via the queue into rust-embedded-community:develop with commit 5a67cfb Jun 7, 2025
7 checks passed
thejpster added a commit that referenced this pull request Jun 7, 2025
Backport of #189 to fix #188

Bumps to 0.8.2
thejpster added a commit that referenced this pull request Jun 7, 2025
Backport of #189 to fix #188

Bumps to 0.8.2
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.

2 participants