]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
gfs2: Don't update inode timestamps for direct writes
authorAndreas Gruenbacher <agruenba@redhat.com>
Wed, 20 Sep 2023 16:17:39 +0000 (18:17 +0200)
committerAndreas Gruenbacher <agruenba@redhat.com>
Fri, 22 Sep 2023 11:42:33 +0000 (13:42 +0200)
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>
fs/gfs2/file.c

index f2700477a3001bcad1e50b9e1868d48e12cb969b..5bc103b031e291495bf9b83ae4f3bc56f27a5f8a 100644 (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);