|
@@ -73,7 +73,7 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
|
|
|
|
|
|
void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
|
|
|
{
|
|
|
- bd->bd_ail = NULL;
|
|
|
+ bd->bd_tr = NULL;
|
|
|
list_del_init(&bd->bd_ail_st_list);
|
|
|
list_del_init(&bd->bd_ail_gl_list);
|
|
|
atomic_dec(&bd->bd_gl->gl_ail_count);
|
|
@@ -90,7 +90,7 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
|
|
|
|
|
|
static int gfs2_ail1_start_one(struct gfs2_sbd *sdp,
|
|
|
struct writeback_control *wbc,
|
|
|
- struct gfs2_ail *ai)
|
|
|
+ struct gfs2_trans *tr)
|
|
|
__releases(&sdp->sd_ail_lock)
|
|
|
__acquires(&sdp->sd_ail_lock)
|
|
|
{
|
|
@@ -99,15 +99,15 @@ __acquires(&sdp->sd_ail_lock)
|
|
|
struct gfs2_bufdata *bd, *s;
|
|
|
struct buffer_head *bh;
|
|
|
|
|
|
- list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) {
|
|
|
+ list_for_each_entry_safe_reverse(bd, s, &tr->tr_ail1_list, bd_ail_st_list) {
|
|
|
bh = bd->bd_bh;
|
|
|
|
|
|
- gfs2_assert(sdp, bd->bd_ail == ai);
|
|
|
+ gfs2_assert(sdp, bd->bd_tr == tr);
|
|
|
|
|
|
if (!buffer_busy(bh)) {
|
|
|
if (!buffer_uptodate(bh))
|
|
|
gfs2_io_error_bh(sdp, bh);
|
|
|
- list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
|
|
|
+ list_move(&bd->bd_ail_st_list, &tr->tr_ail2_list);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -116,7 +116,7 @@ __acquires(&sdp->sd_ail_lock)
|
|
|
if (gl == bd->bd_gl)
|
|
|
continue;
|
|
|
gl = bd->bd_gl;
|
|
|
- list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list);
|
|
|
+ list_move(&bd->bd_ail_st_list, &tr->tr_ail1_list);
|
|
|
mapping = bh->b_page->mapping;
|
|
|
if (!mapping)
|
|
|
continue;
|
|
@@ -144,15 +144,15 @@ __acquires(&sdp->sd_ail_lock)
|
|
|
void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
|
|
|
{
|
|
|
struct list_head *head = &sdp->sd_ail1_list;
|
|
|
- struct gfs2_ail *ai;
|
|
|
+ struct gfs2_trans *tr;
|
|
|
|
|
|
trace_gfs2_ail_flush(sdp, wbc, 1);
|
|
|
spin_lock(&sdp->sd_ail_lock);
|
|
|
restart:
|
|
|
- list_for_each_entry_reverse(ai, head, ai_list) {
|
|
|
+ list_for_each_entry_reverse(tr, head, tr_list) {
|
|
|
if (wbc->nr_to_write <= 0)
|
|
|
break;
|
|
|
- if (gfs2_ail1_start_one(sdp, wbc, ai))
|
|
|
+ if (gfs2_ail1_start_one(sdp, wbc, tr))
|
|
|
goto restart;
|
|
|
}
|
|
|
spin_unlock(&sdp->sd_ail_lock);
|
|
@@ -183,20 +183,20 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp)
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
-static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
|
|
|
+static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|
|
{
|
|
|
struct gfs2_bufdata *bd, *s;
|
|
|
struct buffer_head *bh;
|
|
|
|
|
|
- list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list,
|
|
|
+ list_for_each_entry_safe_reverse(bd, s, &tr->tr_ail1_list,
|
|
|
bd_ail_st_list) {
|
|
|
bh = bd->bd_bh;
|
|
|
- gfs2_assert(sdp, bd->bd_ail == ai);
|
|
|
+ gfs2_assert(sdp, bd->bd_tr == tr);
|
|
|
if (buffer_busy(bh))
|
|
|
continue;
|
|
|
if (!buffer_uptodate(bh))
|
|
|
gfs2_io_error_bh(sdp, bh);
|
|
|
- list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
|
|
|
+ list_move(&bd->bd_ail_st_list, &tr->tr_ail2_list);
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -210,14 +210,14 @@ static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
|
|
|
|
|
|
static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
|
|
|
{
|
|
|
- struct gfs2_ail *ai, *s;
|
|
|
+ struct gfs2_trans *tr, *s;
|
|
|
int ret;
|
|
|
|
|
|
spin_lock(&sdp->sd_ail_lock);
|
|
|
- list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) {
|
|
|
- gfs2_ail1_empty_one(sdp, ai);
|
|
|
- if (list_empty(&ai->ai_ail1_list))
|
|
|
- list_move(&ai->ai_list, &sdp->sd_ail2_list);
|
|
|
+ list_for_each_entry_safe_reverse(tr, s, &sdp->sd_ail1_list, tr_list) {
|
|
|
+ gfs2_ail1_empty_one(sdp, tr);
|
|
|
+ if (list_empty(&tr->tr_ail1_list))
|
|
|
+ list_move(&tr->tr_list, &sdp->sd_ail2_list);
|
|
|
else
|
|
|
break;
|
|
|
}
|
|
@@ -229,13 +229,13 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
|
|
|
|
|
|
static void gfs2_ail1_wait(struct gfs2_sbd *sdp)
|
|
|
{
|
|
|
- struct gfs2_ail *ai;
|
|
|
+ struct gfs2_trans *tr;
|
|
|
struct gfs2_bufdata *bd;
|
|
|
struct buffer_head *bh;
|
|
|
|
|
|
spin_lock(&sdp->sd_ail_lock);
|
|
|
- list_for_each_entry_reverse(ai, &sdp->sd_ail1_list, ai_list) {
|
|
|
- list_for_each_entry(bd, &ai->ai_ail1_list, bd_ail_st_list) {
|
|
|
+ list_for_each_entry_reverse(tr, &sdp->sd_ail1_list, tr_list) {
|
|
|
+ list_for_each_entry(bd, &tr->tr_ail1_list, bd_ail_st_list) {
|
|
|
bh = bd->bd_bh;
|
|
|
if (!buffer_locked(bh))
|
|
|
continue;
|
|
@@ -256,40 +256,40 @@ static void gfs2_ail1_wait(struct gfs2_sbd *sdp)
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
-static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
|
|
|
+static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|
|
{
|
|
|
- struct list_head *head = &ai->ai_ail2_list;
|
|
|
+ struct list_head *head = &tr->tr_ail2_list;
|
|
|
struct gfs2_bufdata *bd;
|
|
|
|
|
|
while (!list_empty(head)) {
|
|
|
bd = list_entry(head->prev, struct gfs2_bufdata,
|
|
|
bd_ail_st_list);
|
|
|
- gfs2_assert(sdp, bd->bd_ail == ai);
|
|
|
+ gfs2_assert(sdp, bd->bd_tr == tr);
|
|
|
gfs2_remove_from_ail(bd);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
|
|
|
{
|
|
|
- struct gfs2_ail *ai, *safe;
|
|
|
+ struct gfs2_trans *tr, *safe;
|
|
|
unsigned int old_tail = sdp->sd_log_tail;
|
|
|
int wrap = (new_tail < old_tail);
|
|
|
int a, b, rm;
|
|
|
|
|
|
spin_lock(&sdp->sd_ail_lock);
|
|
|
|
|
|
- list_for_each_entry_safe(ai, safe, &sdp->sd_ail2_list, ai_list) {
|
|
|
- a = (old_tail <= ai->ai_first);
|
|
|
- b = (ai->ai_first < new_tail);
|
|
|
+ list_for_each_entry_safe(tr, safe, &sdp->sd_ail2_list, tr_list) {
|
|
|
+ a = (old_tail <= tr->tr_first);
|
|
|
+ b = (tr->tr_first < new_tail);
|
|
|
rm = (wrap) ? (a || b) : (a && b);
|
|
|
if (!rm)
|
|
|
continue;
|
|
|
|
|
|
- gfs2_ail2_empty_one(sdp, ai);
|
|
|
- list_del(&ai->ai_list);
|
|
|
- gfs2_assert_warn(sdp, list_empty(&ai->ai_ail1_list));
|
|
|
- gfs2_assert_warn(sdp, list_empty(&ai->ai_ail2_list));
|
|
|
- kfree(ai);
|
|
|
+ gfs2_ail2_empty_one(sdp, tr);
|
|
|
+ list_del(&tr->tr_list);
|
|
|
+ gfs2_assert_warn(sdp, list_empty(&tr->tr_ail1_list));
|
|
|
+ gfs2_assert_warn(sdp, list_empty(&tr->tr_ail2_list));
|
|
|
+ kfree(tr);
|
|
|
}
|
|
|
|
|
|
spin_unlock(&sdp->sd_ail_lock);
|
|
@@ -435,7 +435,7 @@ static unsigned int calc_reserved(struct gfs2_sbd *sdp)
|
|
|
|
|
|
static unsigned int current_tail(struct gfs2_sbd *sdp)
|
|
|
{
|
|
|
- struct gfs2_ail *ai;
|
|
|
+ struct gfs2_trans *tr;
|
|
|
unsigned int tail;
|
|
|
|
|
|
spin_lock(&sdp->sd_ail_lock);
|
|
@@ -443,8 +443,9 @@ static unsigned int current_tail(struct gfs2_sbd *sdp)
|
|
|
if (list_empty(&sdp->sd_ail1_list)) {
|
|
|
tail = sdp->sd_log_head;
|
|
|
} else {
|
|
|
- ai = list_entry(sdp->sd_ail1_list.prev, struct gfs2_ail, ai_list);
|
|
|
- tail = ai->ai_first;
|
|
|
+ tr = list_entry(sdp->sd_ail1_list.prev, struct gfs2_trans,
|
|
|
+ tr_list);
|
|
|
+ tail = tr->tr_first;
|
|
|
}
|
|
|
|
|
|
spin_unlock(&sdp->sd_ail_lock);
|
|
@@ -600,7 +601,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
|
|
|
|
|
|
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
|
|
{
|
|
|
- struct gfs2_ail *ai;
|
|
|
+ struct gfs2_trans *tr;
|
|
|
|
|
|
down_write(&sdp->sd_log_flush_lock);
|
|
|
|
|
@@ -611,9 +612,12 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
|
|
}
|
|
|
trace_gfs2_log_flush(sdp, 1);
|
|
|
|
|
|
- ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
|
|
|
- INIT_LIST_HEAD(&ai->ai_ail1_list);
|
|
|
- INIT_LIST_HEAD(&ai->ai_ail2_list);
|
|
|
+ tr = sdp->sd_log_tr;
|
|
|
+ if (tr) {
|
|
|
+ sdp->sd_log_tr = NULL;
|
|
|
+ INIT_LIST_HEAD(&tr->tr_ail1_list);
|
|
|
+ INIT_LIST_HEAD(&tr->tr_ail2_list);
|
|
|
+ }
|
|
|
|
|
|
if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) {
|
|
|
printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf,
|
|
@@ -630,7 +634,8 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
|
|
|
|
|
sdp->sd_log_flush_head = sdp->sd_log_head;
|
|
|
sdp->sd_log_flush_wrapped = 0;
|
|
|
- ai->ai_first = sdp->sd_log_flush_head;
|
|
|
+ if (tr)
|
|
|
+ tr->tr_first = sdp->sd_log_flush_head;
|
|
|
|
|
|
gfs2_ordered_write(sdp);
|
|
|
lops_before_commit(sdp);
|
|
@@ -643,7 +648,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
|
|
trace_gfs2_log_blocks(sdp, -1);
|
|
|
log_write_header(sdp, 0);
|
|
|
}
|
|
|
- lops_after_commit(sdp, ai);
|
|
|
+ lops_after_commit(sdp, tr);
|
|
|
|
|
|
gfs2_log_lock(sdp);
|
|
|
sdp->sd_log_head = sdp->sd_log_flush_head;
|
|
@@ -653,16 +658,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
|
|
sdp->sd_log_commited_revoke = 0;
|
|
|
|
|
|
spin_lock(&sdp->sd_ail_lock);
|
|
|
- if (!list_empty(&ai->ai_ail1_list)) {
|
|
|
- list_add(&ai->ai_list, &sdp->sd_ail1_list);
|
|
|
- ai = NULL;
|
|
|
+ if (tr && !list_empty(&tr->tr_ail1_list)) {
|
|
|
+ list_add(&tr->tr_list, &sdp->sd_ail1_list);
|
|
|
+ tr = NULL;
|
|
|
}
|
|
|
spin_unlock(&sdp->sd_ail_lock);
|
|
|
gfs2_log_unlock(sdp);
|
|
|
trace_gfs2_log_flush(sdp, 0);
|
|
|
up_write(&sdp->sd_log_flush_lock);
|
|
|
|
|
|
- kfree(ai);
|
|
|
+ kfree(tr);
|
|
|
}
|
|
|
|
|
|
static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|
@@ -687,6 +692,12 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|
|
sdp->sd_jdesc->jd_blocks);
|
|
|
sdp->sd_log_blks_reserved = reserved;
|
|
|
|
|
|
+ if (sdp->sd_log_tr == NULL &&
|
|
|
+ (tr->tr_num_buf_new || tr->tr_num_databuf_new)) {
|
|
|
+ gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl);
|
|
|
+ sdp->sd_log_tr = tr;
|
|
|
+ tr->tr_attached = 1;
|
|
|
+ }
|
|
|
gfs2_log_unlock(sdp);
|
|
|
}
|
|
|
|
|
@@ -708,7 +719,6 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|
|
void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|
|
{
|
|
|
log_refund(sdp, tr);
|
|
|
- up_read(&sdp->sd_log_flush_lock);
|
|
|
|
|
|
if (atomic_read(&sdp->sd_log_pinned) > atomic_read(&sdp->sd_log_thresh1) ||
|
|
|
((sdp->sd_jdesc->jd_blocks - atomic_read(&sdp->sd_log_blks_free)) >
|