diff options
author | Bob Peterson <rpeterso@redhat.com> | 2022-01-18 17:30:18 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-02-16 14:56:18 +0300 |
commit | 4134396f99d25fa0b718cf9be1c9957fcf15ceb6 (patch) | |
tree | e3609c2fd88f2566085c591df03b39abf7c111a2 /fs/gfs2 | |
parent | 71f46f3d1bf29ee5b0a53dc21462125f754491dd (diff) | |
download | linux-4134396f99d25fa0b718cf9be1c9957fcf15ceb6.tar.xz |
gfs2: Fix gfs2_release for non-writers regression
commit d3add1a9519dcacd6e644ecac741c56cf18b67f5 upstream.
When a file is opened for writing, the vfs code (do_dentry_open)
calls get_write_access for the inode, thus incrementing the inode's write
count. That writer normally then creates a multi-block reservation for
the inode (i_res) that can be re-used by other writers, which speeds up
writes for applications that stupidly loop on open/write/close.
When the writes are all done, the multi-block reservation should be
deleted when the file is closed by the last "writer."
Commit 0ec9b9ea4f83 broke that concept when it moved the call to
gfs2_rs_delete before the check for FMODE_WRITE. Non-writers have no
business removing the multi-block reservations of writers. In fact, if
someone opens and closes the file for RO while a writer has a
multi-block reservation, the RO closer will delete the reservation
midway through the write, and this results in:
kernel BUG at fs/gfs2/rgrp.c:677! (or thereabouts) which is:
BUG_ON(rs->rs_requested); from function gfs2_rs_deltree.
This patch moves the check back inside the check for FMODE_WRITE.
Fixes: 0ec9b9ea4f83 ("gfs2: Check for active reservation in gfs2_release")
Cc: stable@vger.kernel.org # v5.12+
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/file.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index c559827cb6f9..f6d3b3e13d72 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -711,10 +711,11 @@ static int gfs2_release(struct inode *inode, struct file *file) kfree(file->private_data); file->private_data = NULL; - if (gfs2_rs_active(&ip->i_res)) - gfs2_rs_delete(ip, &inode->i_writecount); - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { + if (gfs2_rs_active(&ip->i_res)) + gfs2_rs_delete(ip, &inode->i_writecount); gfs2_qa_put(ip); + } return 0; } |