gfs2: Don't update inode timestamps for direct writes

During direct reads and writes, the caller is holding the inode glock in
deferred mode, which doesn't allow metadata updates.  However, a previous
change caused callers to update the inode modification time before carrying out
direct writes, which caused the inode glock to be converted to exclusive mode
for the timestamp update, only to be immediately converted back to deferred
mode for the direct write.  This locks out other direct readers and writers
and wreaks havoc on performance.

Fix that by reverting to not updating the inode modification time for direct
writes.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
Andreas Gruenbacher 2023-09-20 18:17:39 +02:00
parent 21d9067efc
commit 089f4eb003

View File

@ -1120,14 +1120,16 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (ret)
goto out_unlock;
ret = file_update_time(file);
if (ret)
goto out_unlock;
if (iocb->ki_flags & IOCB_DIRECT) {
struct address_space *mapping = file->f_mapping;
ssize_t buffered, ret2;
/*
* Note that under direct I/O, we don't allow and inode
* timestamp updates, so we're not calling file_update_time()
* here.
*/
ret = gfs2_file_direct_write(iocb, from, &gh);
if (ret < 0 || !iov_iter_count(from))
goto out_unlock;
@ -1154,6 +1156,10 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (!ret || ret2 > 0)
ret += ret2;
} else {
ret = file_update_time(file);
if (ret)
goto out_unlock;
ret = gfs2_file_buffered_write(iocb, from, &gh);
if (likely(ret > 0))
ret = generic_write_sync(iocb, ret);