Commit 82e938bd authored by Andreas Gruenbacher's avatar Andreas Gruenbacher
Browse files

gfs2: Upgrade shared glocks for atime updates



Commit 20f82999 ("gfs2: Rework read and page fault locking") lifted
the glock lock taking from the low-level ->readpage and ->readahead
address space operations to the higher-level ->read_iter file and
->fault vm operations.  The glocks are still taken in LM_ST_SHARED mode
only.  On filesystems mounted without the noatime option, ->read_iter
sometimes needs to update the atime as well, though.  Right now, this
leads to a failed locking mode assertion in gfs2_dirty_inode.

Fix that by introducing a new update_time inode operation.  There, if
the glock is held non-exclusively, upgrade it to an exclusive lock.

Reported-by: default avatarAlexander Aring <aahringo@redhat.com>
Fixes: 20f82999 ("gfs2: Rework read and page fault locking")
Cc: stable@vger.kernel.org # v5.8+
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent f39e7d3a
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -2116,6 +2116,25 @@ loff_t gfs2_seek_hole(struct file *file, loff_t offset)
	return vfs_setpos(file, ret, inode->i_sb->s_maxbytes);
}

static int gfs2_update_time(struct inode *inode, struct timespec64 *time,
			    int flags)
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_glock *gl = ip->i_gl;
	struct gfs2_holder *gh;
	int error;

	gh = gfs2_glock_is_locked_by_me(gl);
	if (gh && !gfs2_glock_is_held_excl(gl)) {
		gfs2_glock_dq(gh);
		gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, gh);
		error = gfs2_glock_nq(gh);
		if (error)
			return error;
	}
	return generic_update_time(inode, time, flags);
}

const struct inode_operations gfs2_file_iops = {
	.permission = gfs2_permission,
	.setattr = gfs2_setattr,
@@ -2124,6 +2143,7 @@ const struct inode_operations gfs2_file_iops = {
	.fiemap = gfs2_fiemap,
	.get_acl = gfs2_get_acl,
	.set_acl = gfs2_set_acl,
	.update_time = gfs2_update_time,
};

const struct inode_operations gfs2_dir_iops = {
@@ -2143,6 +2163,7 @@ const struct inode_operations gfs2_dir_iops = {
	.fiemap = gfs2_fiemap,
	.get_acl = gfs2_get_acl,
	.set_acl = gfs2_set_acl,
	.update_time = gfs2_update_time,
	.atomic_open = gfs2_atomic_open,
};