Comments

Currently concurrent reads/writes are atomic only wrt individual pages,
however are not on the system call. This may cause read() to return data
mixed from several different writes, which I do not think it is good
approach. We might argue that application doing this is broken, but
actually this is something we can easily do on filesystem level without
significant performance issues, so we can be consistent. Also POSIX
mentions this as well and XFS filesystem already has this feature.
This commit adds new rw_semaphore into ext4_inode structure. We take
read lock every time we read data from a file (via ext4_file_read() or
ext4_file_splice_read()) and also when we write data in direct io mode,
since in this mode application should know exactly what it is doing.
Then we take write lock when we write into a file (via ext4_file_write()
and ext4_file_splice_write()), except the direct io when we take read
lock and unaligned direct io which is already serialized in different
manner. Also we are locking ext4_truncate() as well so we are consistent
and preserve atomicity.
This should not have any significant performance impact since we still
allow concurrent reads from the same inode and concurrent writes are
serialized already by i_mutex. The only type of load which will feel the
performance hit is the case of writing into an inode while reading from
it and vice versa. In this case, if reads/writes are exclusive it might
not need locking, however tracking this would be expensive.
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
---
fs/ext4/ext4.h | 5 ++++
fs/ext4/file.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++----
fs/ext4/inode.c | 7 ++++++
fs/ext4/super.c | 1 +
4 files changed, 66 insertions(+), 5 deletions(-)