]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
gfs2: Add LM_FLAG_OUTER glock holder flag
authorAndreas Gruenbacher <agruenba@redhat.com>
Thu, 13 May 2021 08:46:08 +0000 (10:46 +0200)
committerAndreas Gruenbacher <agruenba@redhat.com>
Wed, 2 Jun 2021 09:47:03 +0000 (11:47 +0200)
When a glock holder has the LM_FLAG_OUTER flag set, we set the
current_holds_glock() flag upon taking the lock.  With that flag set, we can
then recognize when trying to take an "inner" glock and react accordingly.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/glock.c
fs/gfs2/glock.h

index d9cb261f55b06cf421de7f77c34ae71751d78ba1..f6cae2ee1c83e79ee7881a5e45cbb92f87fa2c6e 100644 (file)
@@ -1427,6 +1427,11 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
        if (glock_blocked_by_withdraw(gl) && !(gh->gh_flags & LM_FLAG_NOEXP))
                return -EIO;
 
+       if (gh->gh_flags & LM_FLAG_OUTER) {
+               BUG_ON(current_holds_glock());
+               set_current_holds_glock(true);
+       }
+
        if (test_bit(GLF_LRU, &gl->gl_flags))
                gfs2_glock_remove_from_lru(gl);
 
@@ -1514,6 +1519,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
                __gfs2_glock_queue_work(gl, delay);
        }
        spin_unlock(&gl->gl_lockref.lock);
+
+       if (gh->gh_flags & LM_FLAG_OUTER) {
+               BUG_ON(!current_holds_glock());
+               set_current_holds_glock(false);
+       }
 }
 
 void gfs2_glock_dq_wait(struct gfs2_holder *gh)
@@ -2068,6 +2078,8 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
                *p++ = 'p';
        if (flags & LM_FLAG_NODE_SCOPE)
                *p++ = 'n';
+       if (flags & LM_FLAG_OUTER)
+               *p++ = 'o';
        if (flags & GL_ASYNC)
                *p++ = 'a';
        if (flags & GL_EXACT)
index f0ef6fd24ba4dba214b650acf1c6c211755c2e23..8b145269fb143d3ae032ecdcdeb2f73756553ba3 100644 (file)
@@ -94,6 +94,12 @@ static inline bool gfs2_holder_is_compatible(struct gfs2_holder *gh, int state)
  * This holder agrees to share the lock within this node. In other words,
  * the glock is held in EX mode according to DLM, but local holders on the
  * same node can share it.
+ *
+ * LM_FLAG_OUTER
+ * Use set_current_holds_glock() to indicate when the current task is holding
+ * this "upper" glock, and current_holds_glock() to detect when the current
+ * task is trying to take another glock.  Used to prevent deadlocks involving
+ * the inode glock during page faults.
  */
 
 #define LM_FLAG_TRY            0x0001
@@ -102,9 +108,10 @@ static inline bool gfs2_holder_is_compatible(struct gfs2_holder *gh, int state)
 #define LM_FLAG_ANY            0x0008
 #define LM_FLAG_PRIORITY       0x0010
 #define LM_FLAG_NODE_SCOPE     0x0020
-#define GL_ASYNC               0x0040
-#define GL_EXACT               0x0080
-#define GL_SKIP                        0x0100
+#define LM_FLAG_OUTER          0x0040
+#define GL_ASYNC               0x0080
+#define GL_EXACT               0x0100
+#define GL_SKIP                        0x0200
 #define GL_NOCACHE             0x0400
   
 /*