diff options
-rw-r--r-- | fs/gfs2/glock.c | 10 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 2 | ||||
-rw-r--r-- | fs/gfs2/super.c | 30 |
3 files changed, 39 insertions, 3 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 11d48b964047..5ad757f0ce60 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -171,7 +171,7 @@ void gfs2_glock_free(struct gfs2_glock *gl) | |||
171 | * | 171 | * |
172 | */ | 172 | */ |
173 | 173 | ||
174 | static void gfs2_glock_hold(struct gfs2_glock *gl) | 174 | void gfs2_glock_hold(struct gfs2_glock *gl) |
175 | { | 175 | { |
176 | GLOCK_BUG_ON(gl, __lockref_is_dead(&gl->gl_lockref)); | 176 | GLOCK_BUG_ON(gl, __lockref_is_dead(&gl->gl_lockref)); |
177 | lockref_get(&gl->gl_lockref); | 177 | lockref_get(&gl->gl_lockref); |
@@ -264,6 +264,14 @@ static void __gfs2_glock_put(struct gfs2_glock *gl) | |||
264 | sdp->sd_lockstruct.ls_ops->lm_put_lock(gl); | 264 | sdp->sd_lockstruct.ls_ops->lm_put_lock(gl); |
265 | } | 265 | } |
266 | 266 | ||
267 | /* | ||
268 | * Cause the glock to be put in work queue context. | ||
269 | */ | ||
270 | void gfs2_glock_queue_put(struct gfs2_glock *gl) | ||
271 | { | ||
272 | gfs2_glock_queue_work(gl, 0); | ||
273 | } | ||
274 | |||
267 | /** | 275 | /** |
268 | * gfs2_glock_put() - Decrement reference count on glock | 276 | * gfs2_glock_put() - Decrement reference count on glock |
269 | * @gl: The glock to put | 277 | * @gl: The glock to put |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 526d2123f758..5e12220cc0c2 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -182,7 +182,9 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl) | |||
182 | extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | 182 | extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, |
183 | const struct gfs2_glock_operations *glops, | 183 | const struct gfs2_glock_operations *glops, |
184 | int create, struct gfs2_glock **glp); | 184 | int create, struct gfs2_glock **glp); |
185 | extern void gfs2_glock_hold(struct gfs2_glock *gl); | ||
185 | extern void gfs2_glock_put(struct gfs2_glock *gl); | 186 | extern void gfs2_glock_put(struct gfs2_glock *gl); |
187 | extern void gfs2_glock_queue_put(struct gfs2_glock *gl); | ||
186 | extern void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, | 188 | extern void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, |
187 | u16 flags, struct gfs2_holder *gh); | 189 | u16 flags, struct gfs2_holder *gh); |
188 | extern void gfs2_holder_reinit(unsigned int state, u16 flags, | 190 | extern void gfs2_holder_reinit(unsigned int state, u16 flags, |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 6c39bb1ec100..4089dbe617a6 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1502,6 +1502,22 @@ out_qs: | |||
1502 | } | 1502 | } |
1503 | 1503 | ||
1504 | /** | 1504 | /** |
1505 | * gfs2_glock_put_eventually | ||
1506 | * @gl: The glock to put | ||
1507 | * | ||
1508 | * When under memory pressure, trigger a deferred glock put to make sure we | ||
1509 | * won't call into DLM and deadlock. Otherwise, put the glock directly. | ||
1510 | */ | ||
1511 | |||
1512 | static void gfs2_glock_put_eventually(struct gfs2_glock *gl) | ||
1513 | { | ||
1514 | if (current->flags & PF_MEMALLOC) | ||
1515 | gfs2_glock_queue_put(gl); | ||
1516 | else | ||
1517 | gfs2_glock_put(gl); | ||
1518 | } | ||
1519 | |||
1520 | /** | ||
1505 | * gfs2_evict_inode - Remove an inode from cache | 1521 | * gfs2_evict_inode - Remove an inode from cache |
1506 | * @inode: The inode to evict | 1522 | * @inode: The inode to evict |
1507 | * | 1523 | * |
@@ -1564,6 +1580,12 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1564 | goto out_truncate; | 1580 | goto out_truncate; |
1565 | } | 1581 | } |
1566 | 1582 | ||
1583 | /* | ||
1584 | * The inode may have been recreated in the meantime. | ||
1585 | */ | ||
1586 | if (inode->i_nlink) | ||
1587 | goto out_truncate; | ||
1588 | |||
1567 | alloc_failed: | 1589 | alloc_failed: |
1568 | if (gfs2_holder_initialized(&ip->i_iopen_gh) && | 1590 | if (gfs2_holder_initialized(&ip->i_iopen_gh) && |
1569 | test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) { | 1591 | test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) { |
@@ -1653,12 +1675,16 @@ out: | |||
1653 | glock_clear_object(ip->i_gl, ip); | 1675 | glock_clear_object(ip->i_gl, ip); |
1654 | wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); | 1676 | wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); |
1655 | gfs2_glock_add_to_lru(ip->i_gl); | 1677 | gfs2_glock_add_to_lru(ip->i_gl); |
1656 | gfs2_glock_put(ip->i_gl); | 1678 | gfs2_glock_put_eventually(ip->i_gl); |
1657 | ip->i_gl = NULL; | 1679 | ip->i_gl = NULL; |
1658 | if (gfs2_holder_initialized(&ip->i_iopen_gh)) { | 1680 | if (gfs2_holder_initialized(&ip->i_iopen_gh)) { |
1659 | glock_clear_object(ip->i_iopen_gh.gh_gl, ip); | 1681 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; |
1682 | |||
1683 | glock_clear_object(gl, ip); | ||
1660 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; | 1684 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; |
1685 | gfs2_glock_hold(gl); | ||
1661 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1686 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1687 | gfs2_glock_put_eventually(gl); | ||
1662 | } | 1688 | } |
1663 | } | 1689 | } |
1664 | 1690 | ||