OSDN Git Service

gfs2: Upgrade shared glocks for atime updates
authorAndreas Gruenbacher <agruenba@redhat.com>
Wed, 25 Nov 2020 22:37:18 +0000 (23:37 +0100)
committerAndreas Gruenbacher <agruenba@redhat.com>
Thu, 26 Nov 2020 18:58:25 +0000 (19:58 +0100)
Commit 20f829999c38 ("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: Alexander Aring <aahringo@redhat.com>
Fixes: 20f829999c38 ("gfs2: Rework read and page fault locking")
Cc: stable@vger.kernel.org # v5.8+
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/inode.c

index 077ccb1..eed1a1b 100644 (file)
@@ -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,
 };