summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/glock.c57
-rw-r--r--fs/gfs2/glock.h2
-rw-r--r--fs/gfs2/glops.c2
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/rgrp.c2
-rw-r--r--fs/gfs2/super.c2
6 files changed, 45 insertions, 22 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 1565fdf32ac0..b184375df9bd 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -975,6 +975,26 @@ static bool gfs2_try_evict(struct gfs2_glock *gl)
return evicted;
}
+bool gfs2_queue_try_to_evict(struct gfs2_glock *gl)
+{
+ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+
+ if (test_and_set_bit(GLF_TRY_TO_EVICT, &gl->gl_flags))
+ return false;
+ return queue_delayed_work(sdp->sd_delete_wq,
+ &gl->gl_delete, 0);
+}
+
+static bool gfs2_queue_verify_evict(struct gfs2_glock *gl)
+{
+ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+
+ if (test_and_set_bit(GLF_VERIFY_EVICT, &gl->gl_flags))
+ return false;
+ return queue_delayed_work(sdp->sd_delete_wq,
+ &gl->gl_delete, 5 * HZ);
+}
+
static void delete_work_func(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
@@ -983,7 +1003,7 @@ static void delete_work_func(struct work_struct *work)
struct inode *inode;
u64 no_addr = gl->gl_name.ln_number;
- if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
+ if (test_and_clear_bit(GLF_TRY_TO_EVICT, &gl->gl_flags)) {
/*
* If we can evict the inode, give the remote node trying to
* delete the inode some time before verifying that the delete
@@ -1002,22 +1022,25 @@ static void delete_work_func(struct work_struct *work)
* step entirely.
*/
if (gfs2_try_evict(gl)) {
- if (gfs2_queue_delete_work(gl, 5 * HZ))
+ if (gfs2_queue_verify_evict(gl))
return;
}
goto out;
}
- inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino,
- GFS2_BLKST_UNLINKED);
- if (IS_ERR(inode)) {
- if (PTR_ERR(inode) == -EAGAIN &&
- (gfs2_queue_delete_work(gl, 5 * HZ)))
+ if (test_and_clear_bit(GLF_VERIFY_EVICT, &gl->gl_flags)) {
+ inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino,
+ GFS2_BLKST_UNLINKED);
+ if (IS_ERR(inode)) {
+ if (PTR_ERR(inode) == -EAGAIN &&
+ gfs2_queue_verify_evict(gl))
return;
- } else {
- d_prune_aliases(inode);
- iput(inode);
+ } else {
+ d_prune_aliases(inode);
+ iput(inode);
+ }
}
+
out:
gfs2_glock_put(gl);
}
@@ -2057,16 +2080,10 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
rhashtable_walk_exit(&iter);
}
-bool gfs2_queue_delete_work(struct gfs2_glock *gl, unsigned long delay)
-{
- struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
-
- return queue_delayed_work(sdp->sd_delete_wq,
- &gl->gl_delete, delay);
-}
-
void gfs2_cancel_delete_work(struct gfs2_glock *gl)
{
+ clear_bit(GLF_TRY_TO_EVICT, &gl->gl_flags);
+ clear_bit(GLF_VERIFY_EVICT, &gl->gl_flags);
if (cancel_delayed_work(&gl->gl_delete))
gfs2_glock_put(gl);
}
@@ -2298,6 +2315,10 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
*p++ = 'n';
if (test_bit(GLF_INSTANTIATE_IN_PROG, gflags))
*p++ = 'N';
+ if (test_bit(GLF_TRY_TO_EVICT, gflags))
+ *p++ = 'e';
+ if (test_bit(GLF_VERIFY_EVICT, gflags))
+ *p++ = 'E';
*p = 0;
return buf;
}
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index b9da61dbe550..1f1ba92c15a8 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -267,7 +267,7 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl,
extern void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
extern void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
-extern bool gfs2_queue_delete_work(struct gfs2_glock *gl, unsigned long delay);
+extern bool gfs2_queue_try_to_evict(struct gfs2_glock *gl);
extern void gfs2_cancel_delete_work(struct gfs2_glock *gl);
extern void gfs2_flush_delete_work(struct gfs2_sbd *sdp);
extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 68676bc78171..e4c585f16ddd 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -651,7 +651,7 @@ static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
if (gl->gl_demote_state == LM_ST_UNLOCKED &&
gl->gl_state == LM_ST_SHARED && ip) {
gl->gl_lockref.count++;
- if (!gfs2_queue_delete_work(gl, 0))
+ if (!gfs2_queue_try_to_evict(gl))
gl->gl_lockref.count--;
}
}
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 6e8a5f2d6b49..9b380125eb78 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -330,6 +330,8 @@ enum {
GLF_OBJECT = 14, /* Used only for tracing */
GLF_BLOCKING = 15,
GLF_FREEING = 16, /* Wait for glock to be freed */
+ GLF_TRY_TO_EVICT = 17, /* iopen glocks only */
+ GLF_VERIFY_EVICT = 18, /* iopen glocks only */
};
struct gfs2_glock {
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index f602fb844951..3b9b76e980ad 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1879,7 +1879,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
*/
ip = gl->gl_object;
- if (ip || !gfs2_queue_delete_work(gl, 0))
+ if (ip || !gfs2_queue_try_to_evict(gl))
gfs2_glock_put(gl);
else
found++;
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 0b5cda464787..7b0bfe41b5cc 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -954,7 +954,7 @@ static int gfs2_drop_inode(struct inode *inode)
struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
gfs2_glock_hold(gl);
- if (!gfs2_queue_delete_work(gl, 0))
+ if (!gfs2_queue_try_to_evict(gl))
gfs2_glock_queue_put(gl);
return 0;
}