aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2016-06-06 23:04:43 -0400
committerTheodore Ts'o <tytso@mit.edu>2016-06-06 23:04:43 -0400
commit127e2291bf02c39bba58eb9b8096a2670319a5bb (patch)
treef5ea01341e61431ec5b5236900208ae26b5c6948 /lib
parentbe5ce275259e6216b618d3900786b365669a0b42 (diff)
downloade2fsprogs-127e2291bf02c39bba58eb9b8096a2670319a5bb.tar.gz
libext2fs: fix Direct I/O fallback code so it implements RMW correctly
There is a bug in Unix I/O manager where if an aligned I/O is required, it does not correctly do the read-modify-write cycle correctly. Specifically, it was not doing an lseek between the read and the write calls, so the update was going to block N+1 instead of block N. Oops. Fortunately in practice we almost never use this fallback path, so file systems weren't getting horribly corrupted, because (a) we almost never use Direct I/O in e2fsprogs, at least not by default, and (b) when we do the buffers end up being aligned anyway, so it's OK. We only noticed this because the new Undo I/O manager in e2fsprogs 1.43 was doing unaligned I/O and FreeBSD requires that I/O requests be aligned even if you are not doing Direct I/O, and the e2undo regression tests were all failing as a result. Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'lib')
-rw-r--r--lib/ext2fs/unix_io.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 23f22e30f..4403aa0e6 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -282,6 +282,10 @@ static errcode_t raw_write_blk(io_channel channel,
if (size > channel->block_size)
actual = channel->block_size;
memcpy(data->bounce, buf, actual);
+ if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
+ retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
+ goto error_out;
+ }
actual = write(data->dev, data->bounce, channel->block_size);
if (actual != channel->block_size)
goto short_write;