Whamcloud - gitweb
libext2fs: fix Direct I/O fallback code so it implements RMW correctly
authorTheodore Ts'o <tytso@mit.edu>
Tue, 7 Jun 2016 03:04:43 +0000 (23:04 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 7 Jun 2016 03:04:43 +0000 (23:04 -0400)
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>
lib/ext2fs/unix_io.c

index 23f22e3..4403aa0 100644 (file)
@@ -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;