Skip to content

Commit a72d240

Browse files
committed
gfs2: Allow some glocks to be used during withdraw
We need to allow some glocks to be enqueued, dequeued, promoted, and demoted when we're withdrawn. For example, to maintain metadata integrity, we should disallow the use of inode and rgrp glocks when withdrawn. Other glocks, like iopen or the transaction glocks may be safely used because none of their metadata goes through the journal. So in general, we should disallow all glocks with an address space, and allow all the others. One exception is: we need to allow our active journal to be demoted so others may recover it. Allowing glocks after withdraw gives us the ability to take appropriate action (in a following patch) to have our journal properly replayed by another node rather than just abandoning the current transactions and pretending nothing bad happened, leaving the other nodes free to modify the blocks we had in our journal, which may result in file system corruption. Signed-off-by: Bob Peterson <rpeterso@redhat.com>
1 parent 0d91061 commit a72d240

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed

fs/gfs2/glock.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,33 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
133133
}
134134
}
135135

136+
/**
137+
* glock_blocked_by_withdraw - determine if we can still use a glock
138+
* @gl: the glock
139+
*
140+
* We need to allow some glocks to be enqueued, dequeued, promoted, and demoted
141+
* when we're withdrawn. For example, to maintain metadata integrity, we should
142+
* disallow the use of inode and rgrp glocks when withdrawn. Other glocks, like
143+
* iopen or the transaction glocks may be safely used because none of their
144+
* metadata goes through the journal. So in general, we should disallow all
145+
* glocks that are journaled, and allow all the others. One exception is:
146+
* we need to allow our active journal to be promoted and demoted so others
147+
* may recover it and we can reacquire it when they're done.
148+
*/
149+
static bool glock_blocked_by_withdraw(struct gfs2_glock *gl)
150+
{
151+
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
152+
153+
if (likely(!gfs2_withdrawn(sdp)))
154+
return false;
155+
if (gl->gl_ops->go_flags & GLOF_NONDISK)
156+
return false;
157+
if (!sdp->sd_jdesc ||
158+
gl->gl_name.ln_number == sdp->sd_jdesc->jd_no_addr)
159+
return false;
160+
return true;
161+
}
162+
136163
void gfs2_glock_free(struct gfs2_glock *gl)
137164
{
138165
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
@@ -549,8 +576,7 @@ __acquires(&gl->gl_lockref.lock)
549576
unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0);
550577
int ret;
551578

552-
if (unlikely(gfs2_withdrawn(sdp)) &&
553-
target != LM_ST_UNLOCKED)
579+
if (target != LM_ST_UNLOCKED && glock_blocked_by_withdraw(gl))
554580
return;
555581
lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP |
556582
LM_FLAG_PRIORITY);
@@ -1194,10 +1220,9 @@ __acquires(&gl->gl_lockref.lock)
11941220
int gfs2_glock_nq(struct gfs2_holder *gh)
11951221
{
11961222
struct gfs2_glock *gl = gh->gh_gl;
1197-
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
11981223
int error = 0;
11991224

1200-
if (unlikely(gfs2_withdrawn(sdp)))
1225+
if (glock_blocked_by_withdraw(gl))
12011226
return -EIO;
12021227

12031228
if (test_bit(GLF_LRU, &gl->gl_flags))

fs/gfs2/glops.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
579579

580580
const struct gfs2_glock_operations gfs2_meta_glops = {
581581
.go_type = LM_TYPE_META,
582+
.go_flags = GLOF_NONDISK,
582583
};
583584

584585
const struct gfs2_glock_operations gfs2_inode_glops = {
@@ -605,30 +606,33 @@ const struct gfs2_glock_operations gfs2_freeze_glops = {
605606
.go_xmote_bh = freeze_go_xmote_bh,
606607
.go_demote_ok = freeze_go_demote_ok,
607608
.go_type = LM_TYPE_NONDISK,
609+
.go_flags = GLOF_NONDISK,
608610
};
609611

610612
const struct gfs2_glock_operations gfs2_iopen_glops = {
611613
.go_type = LM_TYPE_IOPEN,
612614
.go_callback = iopen_go_callback,
613-
.go_flags = GLOF_LRU,
615+
.go_flags = GLOF_LRU | GLOF_NONDISK,
614616
};
615617

616618
const struct gfs2_glock_operations gfs2_flock_glops = {
617619
.go_type = LM_TYPE_FLOCK,
618-
.go_flags = GLOF_LRU,
620+
.go_flags = GLOF_LRU | GLOF_NONDISK,
619621
};
620622

621623
const struct gfs2_glock_operations gfs2_nondisk_glops = {
622624
.go_type = LM_TYPE_NONDISK,
625+
.go_flags = GLOF_NONDISK,
623626
};
624627

625628
const struct gfs2_glock_operations gfs2_quota_glops = {
626629
.go_type = LM_TYPE_QUOTA,
627-
.go_flags = GLOF_LVB | GLOF_LRU,
630+
.go_flags = GLOF_LVB | GLOF_LRU | GLOF_NONDISK,
628631
};
629632

630633
const struct gfs2_glock_operations gfs2_journal_glops = {
631634
.go_type = LM_TYPE_JOURNAL,
635+
.go_flags = GLOF_NONDISK,
632636
};
633637

634638
const struct gfs2_glock_operations *gfs2_glops_list[] = {

fs/gfs2/incore.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,10 @@ struct gfs2_glock_operations {
244244
void (*go_callback)(struct gfs2_glock *gl, bool remote);
245245
const int go_type;
246246
const unsigned long go_flags;
247-
#define GLOF_ASPACE 1
248-
#define GLOF_LVB 2
249-
#define GLOF_LRU 4
247+
#define GLOF_ASPACE 1 /* address space attached */
248+
#define GLOF_LVB 2 /* Lock Value Block attached */
249+
#define GLOF_LRU 4 /* LRU managed */
250+
#define GLOF_NONDISK 8 /* not I/O related */
250251
};
251252

252253
enum {
@@ -541,6 +542,7 @@ struct gfs2_jdesc {
541542
struct list_head jd_revoke_list;
542543
unsigned int jd_replay_tail;
543544

545+
u64 jd_no_addr;
544546
};
545547

546548
struct gfs2_statfs_change_host {

fs/gfs2/ops_fstype.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
552552
mutex_lock(&sdp->sd_jindex_mutex);
553553

554554
for (;;) {
555+
struct gfs2_inode *jip;
556+
555557
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, ji_gh);
556558
if (error)
557559
break;
@@ -591,6 +593,8 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
591593

592594
spin_lock(&sdp->sd_jindex_spin);
593595
jd->jd_jid = sdp->sd_journals++;
596+
jip = GFS2_I(jd->jd_inode);
597+
jd->jd_no_addr = jip->i_no_addr;
594598
list_add_tail(&jd->jd_list, &sdp->sd_jindex_list);
595599
spin_unlock(&sdp->sd_jindex_spin);
596600
}

0 commit comments

Comments
 (0)