Merge tag 'vfio-for-v3.10' of git://github.com/awilliam/linux-vfio
[cascardo/linux.git] / fs / gfs2 / log.c
index 9a2ca8b..b404f48 100644 (file)
@@ -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)) >