summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2023-09-20 19:17:39 +0300
committerAndreas Gruenbacher <agruenba@redhat.com>2023-09-22 14:42:33 +0300
commit089f4eb003dc2265036aac99c02aa99d6b5c4ac7 (patch)
tree0a5f1579da77547642ddaa1c56c6fa5dbfbd8124
parent21d9067efc7fe94d2bc6f7c7ce71834d5766bbd8 (diff)
downloadlinux-089f4eb003dc2265036aac99c02aa99d6b5c4ac7.tar.xz
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>
-rw-r--r--fs/gfs2/file.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index f2700477a300..5bc103b031e2 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -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);