|
@@ -42,41 +42,41 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
|
|
|
/**
|
|
|
* __gfs2_ail_flush - remove all buffers for a given lock from the AIL
|
|
|
* @gl: the glock
|
|
|
+ * @fsync: set when called from fsync (not all buffers will be clean)
|
|
|
*
|
|
|
* None of the buffers should be dirty, locked, or pinned.
|
|
|
*/
|
|
|
|
|
|
-static void __gfs2_ail_flush(struct gfs2_glock *gl, unsigned long b_state)
|
|
|
+static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
|
|
|
{
|
|
|
struct gfs2_sbd *sdp = gl->gl_sbd;
|
|
|
struct list_head *head = &gl->gl_ail_list;
|
|
|
- struct gfs2_bufdata *bd;
|
|
|
+ struct gfs2_bufdata *bd, *tmp;
|
|
|
struct buffer_head *bh;
|
|
|
+ const unsigned long b_state = (1UL << BH_Dirty)|(1UL << BH_Pinned)|(1UL << BH_Lock);
|
|
|
sector_t blocknr;
|
|
|
|
|
|
+ gfs2_log_lock(sdp);
|
|
|
spin_lock(&sdp->sd_ail_lock);
|
|
|
- while (!list_empty(head)) {
|
|
|
- bd = list_entry(head->next, struct gfs2_bufdata,
|
|
|
- bd_ail_gl_list);
|
|
|
+ list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) {
|
|
|
bh = bd->bd_bh;
|
|
|
- blocknr = bh->b_blocknr;
|
|
|
- if (bh->b_state & b_state)
|
|
|
+ if (bh->b_state & b_state) {
|
|
|
+ if (fsync)
|
|
|
+ continue;
|
|
|
gfs2_ail_error(gl, bh);
|
|
|
+ }
|
|
|
+ blocknr = bh->b_blocknr;
|
|
|
bh->b_private = NULL;
|
|
|
gfs2_remove_from_ail(bd); /* drops ref on bh */
|
|
|
- spin_unlock(&sdp->sd_ail_lock);
|
|
|
|
|
|
bd->bd_bh = NULL;
|
|
|
bd->bd_blkno = blocknr;
|
|
|
|
|
|
- gfs2_log_lock(sdp);
|
|
|
gfs2_trans_add_revoke(sdp, bd);
|
|
|
- gfs2_log_unlock(sdp);
|
|
|
-
|
|
|
- spin_lock(&sdp->sd_ail_lock);
|
|
|
}
|
|
|
- gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count));
|
|
|
+ BUG_ON(!fsync && atomic_read(&gl->gl_ail_count));
|
|
|
spin_unlock(&sdp->sd_ail_lock);
|
|
|
+ gfs2_log_unlock(sdp);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -99,13 +99,13 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
|
|
|
BUG_ON(current->journal_info);
|
|
|
current->journal_info = &tr;
|
|
|
|
|
|
- __gfs2_ail_flush(gl, (1ul << BH_Dirty)|(1ul << BH_Pinned)|(1ul << BH_Lock));
|
|
|
+ __gfs2_ail_flush(gl, 0);
|
|
|
|
|
|
gfs2_trans_end(sdp);
|
|
|
gfs2_log_flush(sdp, NULL);
|
|
|
}
|
|
|
|
|
|
-void gfs2_ail_flush(struct gfs2_glock *gl)
|
|
|
+void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
|
|
|
{
|
|
|
struct gfs2_sbd *sdp = gl->gl_sbd;
|
|
|
unsigned int revokes = atomic_read(&gl->gl_ail_count);
|
|
@@ -117,7 +117,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl)
|
|
|
ret = gfs2_trans_begin(sdp, 0, revokes);
|
|
|
if (ret)
|
|
|
return;
|
|
|
- __gfs2_ail_flush(gl, (1ul << BH_Dirty)|(1ul << BH_Pinned));
|
|
|
+ __gfs2_ail_flush(gl, fsync);
|
|
|
gfs2_trans_end(sdp);
|
|
|
gfs2_log_flush(sdp, NULL);
|
|
|
}
|