Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Feb 2013 17:21:23 +0000 (09:21 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Feb 2013 17:21:23 +0000 (09:21 -0800)
Pull GFS2 updates from Steven Whitehouse:
 "This is one of the smallest collections of patches for the merge
  window for some time.  There are some clean ups relating to the
  transaction code and the shrinker, which are mostly in preparation for
  further development, but also make the code much easier to follow in
  these areas.

  There is a patch which allows the use of ->writepages even in the
  default ordered write mode for all writebacks.  This results in
  sending larger i/os to the block layer, and a subsequent increase in
  performance.  It also reduces the number of different i/o paths by
  one.

  There is also a bug fix reinstating the withdraw ack system which
  somehow got lost when the lock modules were merged into GFS2."

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
  GFS2: Reinstate withdraw ack system
  GFS2: Get a block reservation before resizing a file
  GFS2: Split glock lru processing into two parts
  GFS2: Use ->writepages for ordered writes
  GFS2: Clean up freeze code
  GFS2: Merge gfs2_attach_bufdata() into trans.c
  GFS2: Copy gfs2_trans_add_bh into new data/meta functions
  GFS2: Split gfs2_trans_add_bh() into two
  GFS2: Merge revoke adding functions
  GFS2: Separate LRU scanning from shrinker

23 files changed:
fs/gfs2/aops.c
fs/gfs2/bmap.c
fs/gfs2/dir.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/log.c
fs/gfs2/log.h
fs/gfs2/lops.c
fs/gfs2/lops.h
fs/gfs2/meta_io.c
fs/gfs2/meta_io.h
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/super.h
fs/gfs2/sys.c
fs/gfs2/trans.c
fs/gfs2/trans.h
fs/gfs2/util.c
fs/gfs2/xattr.c

index 30de4f2a2ea90f45d0108f2a571f9d1f233ed4e0..24f414f0ce61393e3caf3ce7c460ffbf40a8183b 100644 (file)
@@ -51,7 +51,7 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
                        continue;
                if (gfs2_is_jdata(ip))
                        set_buffer_uptodate(bh);
-               gfs2_trans_add_bh(ip->i_gl, bh, 0);
+               gfs2_trans_add_data(ip->i_gl, bh);
        }
 }
 
@@ -230,16 +230,14 @@ out_ignore:
 }
 
 /**
- * gfs2_writeback_writepages - Write a bunch of dirty pages back to disk
+ * gfs2_writepages - Write a bunch of dirty pages back to disk
  * @mapping: The mapping to write
  * @wbc: Write-back control
  *
- * For the data=writeback case we can already ignore buffer heads
- * and write whole extents at once. This is a big reduction in the
- * number of I/O requests we send and the bmap calls we make in this case.
+ * Used for both ordered and writeback modes.
  */
-static int gfs2_writeback_writepages(struct address_space *mapping,
-                                    struct writeback_control *wbc)
+static int gfs2_writepages(struct address_space *mapping,
+                          struct writeback_control *wbc)
 {
        return mpage_writepages(mapping, wbc, gfs2_get_block_noalloc);
 }
@@ -852,7 +850,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
                goto failed;
        }
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
 
        if (gfs2_is_stuffed(ip))
                return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
@@ -1102,7 +1100,7 @@ cannot_release:
 
 static const struct address_space_operations gfs2_writeback_aops = {
        .writepage = gfs2_writeback_writepage,
-       .writepages = gfs2_writeback_writepages,
+       .writepages = gfs2_writepages,
        .readpage = gfs2_readpage,
        .readpages = gfs2_readpages,
        .write_begin = gfs2_write_begin,
@@ -1118,6 +1116,7 @@ static const struct address_space_operations gfs2_writeback_aops = {
 
 static const struct address_space_operations gfs2_ordered_aops = {
        .writepage = gfs2_ordered_writepage,
+       .writepages = gfs2_writepages,
        .readpage = gfs2_readpage,
        .readpages = gfs2_readpages,
        .write_begin = gfs2_write_begin,
index a68e91bcef3ddf7d005665955ecff7909ccb171f..df686d13a7d25dcd7cd91a833af4fc77f48626ad 100644 (file)
@@ -22,6 +22,7 @@
 #include "meta_io.h"
 #include "quota.h"
 #include "rgrp.h"
+#include "log.h"
 #include "super.h"
 #include "trans.h"
 #include "dir.h"
@@ -93,7 +94,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
        if (!gfs2_is_jdata(ip))
                mark_buffer_dirty(bh);
        if (!gfs2_is_writeback(ip))
-               gfs2_trans_add_bh(ip->i_gl, bh, 0);
+               gfs2_trans_add_data(ip->i_gl, bh);
 
        if (release) {
                unlock_page(page);
@@ -153,7 +154,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
 
        /*  Set up the pointer to the new block  */
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        di = (struct gfs2_dinode *)dibh->b_data;
        gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 
@@ -405,7 +406,7 @@ static inline __be64 *gfs2_indirect_init(struct metapath *mp,
        BUG_ON(i < 1);
        BUG_ON(mp->mp_bh[i] != NULL);
        mp->mp_bh[i] = gfs2_meta_new(gl, bn);
-       gfs2_trans_add_bh(gl, mp->mp_bh[i], 1);
+       gfs2_trans_add_meta(gl, mp->mp_bh[i]);
        gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
        gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header));
        ptr += offset;
@@ -468,7 +469,7 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
        BUG_ON(sheight < 1);
        BUG_ON(dibh == NULL);
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
 
        if (height == sheight) {
                struct buffer_head *bh;
@@ -544,7 +545,7 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
                /* Branching from existing tree */
                case ALLOC_GROW_DEPTH:
                        if (i > 1 && i < height)
-                               gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1);
+                               gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[i-1]);
                        for (; i < height && n > 0; i++, n--)
                                gfs2_indirect_init(mp, ip->i_gl, i,
                                                   mp->mp_list[i-1], bn++);
@@ -556,7 +557,7 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
                case ALLOC_DATA:
                        BUG_ON(n > dblks);
                        BUG_ON(mp->mp_bh[end_of_metadata] == NULL);
-                       gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1);
+                       gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[end_of_metadata]);
                        dblks = n;
                        ptr = metapointer(end_of_metadata, mp);
                        dblock = bn;
@@ -796,8 +797,8 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 
        down_write(&ip->i_rw_mutex);
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
+       gfs2_trans_add_meta(ip->i_gl, bh);
 
        bstart = 0;
        blen = 0;
@@ -981,7 +982,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
        }
 
        if (!gfs2_is_writeback(ip))
-               gfs2_trans_add_bh(ip->i_gl, bh, 0);
+               gfs2_trans_add_data(ip->i_gl, bh);
 
        zero_user(page, offset, length);
        mark_buffer_dirty(bh);
@@ -1046,7 +1047,7 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
        if (error)
                goto out;
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
 
        if (gfs2_is_stuffed(ip)) {
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize);
@@ -1137,11 +1138,12 @@ static int trunc_end(struct gfs2_inode *ip)
                ip->i_height = 0;
                ip->i_goal = ip->i_no_addr;
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
+               gfs2_ordered_del_inode(ip);
        }
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
        ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG;
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
@@ -1246,7 +1248,7 @@ static int do_grow(struct inode *inode, u64 size)
 
        i_size_write(inode, size);
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
@@ -1286,6 +1288,10 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
 
        inode_dio_wait(inode);
 
+       ret = gfs2_rs_alloc(GFS2_I(inode));
+       if (ret)
+               return ret;
+
        oldsize = inode->i_size;
        if (newsize >= oldsize)
                return do_grow(inode, newsize);
index 9a35670fdc38e916df54315ad38c879f8a483820..7179478e5a28db863d119d9c7f2f883584f3330a 100644 (file)
@@ -93,7 +93,7 @@ int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
        struct buffer_head *bh;
 
        bh = gfs2_meta_new(ip->i_gl, block);
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, bh);
        gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
        gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
        *bhp = bh;
@@ -127,7 +127,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
        if (error)
                return error;
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
        if (ip->i_inode.i_size < offset + size)
                i_size_write(&ip->i_inode, offset + size);
@@ -209,7 +209,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
                if (error)
                        goto fail;
 
-               gfs2_trans_add_bh(ip->i_gl, bh, 1);
+               gfs2_trans_add_meta(ip->i_gl, bh);
                memcpy(bh->b_data + o, buf, amount);
                brelse(bh);
 
@@ -231,7 +231,7 @@ out:
                i_size_write(&ip->i_inode, offset + copied);
        ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 
@@ -647,7 +647,7 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh,
                return;
        }
 
-       gfs2_trans_add_bh(dip->i_gl, bh, 1);
+       gfs2_trans_add_meta(dip->i_gl, bh);
 
        /* If there is no prev entry, this is the first entry in the block.
           The de_rec_len is already as big as it needs to be.  Just zero
@@ -690,7 +690,7 @@ static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,
                offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
        totlen = be16_to_cpu(dent->de_rec_len);
        BUG_ON(offset + name->len > totlen);
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, bh);
        ndent = (struct gfs2_dirent *)((char *)dent + offset);
        dent->de_rec_len = cpu_to_be16(offset);
        gfs2_qstr2dirent(name, totlen - offset, ndent);
@@ -831,7 +831,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
                return NULL;
 
        gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, 1);
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, bh);
        gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
        leaf = (struct gfs2_leaf *)bh->b_data;
        leaf->lf_depth = cpu_to_be16(depth);
@@ -916,7 +916,7 @@ static int dir_make_exhash(struct inode *inode)
        /*  We're done with the new leaf block, now setup the new
            hash table.  */
 
-       gfs2_trans_add_bh(dip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(dip->i_gl, dibh);
        gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 
        lp = (__be64 *)(dibh->b_data + sizeof(struct gfs2_dinode));
@@ -976,7 +976,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
                return 1; /* can't split */
        }
 
-       gfs2_trans_add_bh(dip->i_gl, obh, 1);
+       gfs2_trans_add_meta(dip->i_gl, obh);
 
        nleaf = new_leaf(inode, &nbh, be16_to_cpu(oleaf->lf_depth) + 1);
        if (!nleaf) {
@@ -1069,7 +1069,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
 
        error = gfs2_meta_inode_buffer(dip, &dibh);
        if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
-               gfs2_trans_add_bh(dip->i_gl, dibh, 1);
+               gfs2_trans_add_meta(dip->i_gl, dibh);
                gfs2_add_inode_blocks(&dip->i_inode, 1);
                gfs2_dinode_out(dip, dibh->b_data);
                brelse(dibh);
@@ -1622,7 +1622,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
                        return error;
        } while(1);
 
-       gfs2_trans_add_bh(ip->i_gl, obh, 1);
+       gfs2_trans_add_meta(ip->i_gl, obh);
 
        leaf = new_leaf(inode, &bh, be16_to_cpu(oleaf->lf_depth));
        if (!leaf) {
@@ -1636,7 +1636,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
        error = gfs2_meta_inode_buffer(ip, &bh);
        if (error)
                return error;
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, bh);
        gfs2_add_inode_blocks(&ip->i_inode, 1);
        gfs2_dinode_out(ip, bh->b_data);
        brelse(bh);
@@ -1795,7 +1795,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
        if (IS_ERR(dent))
                return PTR_ERR(dent);
 
-       gfs2_trans_add_bh(dip->i_gl, bh, 1);
+       gfs2_trans_add_meta(dip->i_gl, bh);
        gfs2_inum_out(nip, dent);
        dent->de_type = cpu_to_be16(new_type);
 
@@ -1804,7 +1804,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
                error = gfs2_meta_inode_buffer(dip, &bh);
                if (error)
                        return error;
-               gfs2_trans_add_bh(dip->i_gl, bh, 1);
+               gfs2_trans_add_meta(dip->i_gl, bh);
        }
 
        dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
@@ -1917,7 +1917,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
        if (error)
                goto out_end_trans;
 
-       gfs2_trans_add_bh(dip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(dip->i_gl, dibh);
        /* On the last dealloc, make this a regular file in case we crash.
           (We don't want to free these blocks a second time.)  */
        if (last_dealloc)
index 991ab2d484dd888e9432dd66ecee92247e16fac9..06b7092a3f256eb8dc73bebdfe6574c1970c0fee 100644 (file)
@@ -276,7 +276,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
        error = gfs2_meta_inode_buffer(ip, &bh);
        if (error)
                goto out_trans_end;
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, bh);
        ip->i_diskflags = new_flags;
        gfs2_dinode_out(ip, bh->b_data);
        brelse(bh);
@@ -709,7 +709,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
        if (unlikely(error))
                return error;
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
 
        if (gfs2_is_stuffed(ip)) {
                error = gfs2_unstuff_dinode(ip, NULL);
index 992c5c0cb5045144f61f7d06032d61301ee484d6..cf35155467394b27f16d20fed8c57e8c6f40e016 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/rculist_bl.h>
 #include <linux/bit_spinlock.h>
 #include <linux/percpu.h>
+#include <linux/list_sort.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -1376,56 +1377,105 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
                gfs2_glock_put(gl);
 }
 
+static int glock_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+       struct gfs2_glock *gla, *glb;
 
-static int gfs2_shrink_glock_memory(struct shrinker *shrink,
-                                   struct shrink_control *sc)
+       gla = list_entry(a, struct gfs2_glock, gl_lru);
+       glb = list_entry(b, struct gfs2_glock, gl_lru);
+
+       if (gla->gl_name.ln_number > glb->gl_name.ln_number)
+               return 1;
+       if (gla->gl_name.ln_number < glb->gl_name.ln_number)
+               return -1;
+
+       return 0;
+}
+
+/**
+ * gfs2_dispose_glock_lru - Demote a list of glocks
+ * @list: The list to dispose of
+ *
+ * Disposing of glocks may involve disk accesses, so that here we sort
+ * the glocks by number (i.e. disk location of the inodes) so that if
+ * there are any such accesses, they'll be sent in order (mostly).
+ *
+ * Must be called under the lru_lock, but may drop and retake this
+ * lock. While the lru_lock is dropped, entries may vanish from the
+ * list, but no new entries will appear on the list (since it is
+ * private)
+ */
+
+static void gfs2_dispose_glock_lru(struct list_head *list)
+__releases(&lru_lock)
+__acquires(&lru_lock)
 {
        struct gfs2_glock *gl;
-       int may_demote;
-       int nr_skipped = 0;
-       int nr = sc->nr_to_scan;
-       gfp_t gfp_mask = sc->gfp_mask;
-       LIST_HEAD(skipped);
 
-       if (nr == 0)
-               goto out;
+       list_sort(NULL, list, glock_cmp);
 
-       if (!(gfp_mask & __GFP_FS))
-               return -1;
+       while(!list_empty(list)) {
+               gl = list_entry(list->next, struct gfs2_glock, gl_lru);
+               list_del_init(&gl->gl_lru);
+               clear_bit(GLF_LRU, &gl->gl_flags);
+               gfs2_glock_hold(gl);
+               spin_unlock(&lru_lock);
+               spin_lock(&gl->gl_spin);
+               if (demote_ok(gl))
+                       handle_callback(gl, LM_ST_UNLOCKED, 0);
+               WARN_ON(!test_and_clear_bit(GLF_LOCK, &gl->gl_flags));
+               smp_mb__after_clear_bit();
+               if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+                       gfs2_glock_put_nolock(gl);
+               spin_unlock(&gl->gl_spin);
+               spin_lock(&lru_lock);
+       }
+}
+
+/**
+ * gfs2_scan_glock_lru - Scan the LRU looking for locks to demote
+ * @nr: The number of entries to scan
+ *
+ * This function selects the entries on the LRU which are able to
+ * be demoted, and then kicks off the process by calling
+ * gfs2_dispose_glock_lru() above.
+ */
+
+static void gfs2_scan_glock_lru(int nr)
+{
+       struct gfs2_glock *gl;
+       LIST_HEAD(skipped);
+       LIST_HEAD(dispose);
 
        spin_lock(&lru_lock);
        while(nr && !list_empty(&lru_list)) {
                gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru);
-               list_del_init(&gl->gl_lru);
-               clear_bit(GLF_LRU, &gl->gl_flags);
-               atomic_dec(&lru_count);
 
                /* Test for being demotable */
                if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
-                       gfs2_glock_hold(gl);
-                       spin_unlock(&lru_lock);
-                       spin_lock(&gl->gl_spin);
-                       may_demote = demote_ok(gl);
-                       if (may_demote) {
-                               handle_callback(gl, LM_ST_UNLOCKED, 0);
-                               nr--;
-                       }
-                       clear_bit(GLF_LOCK, &gl->gl_flags);
-                       smp_mb__after_clear_bit();
-                       if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
-                               gfs2_glock_put_nolock(gl);
-                       spin_unlock(&gl->gl_spin);
-                       spin_lock(&lru_lock);
+                       list_move(&gl->gl_lru, &dispose);
+                       atomic_dec(&lru_count);
+                       nr--;
                        continue;
                }
-               nr_skipped++;
-               list_add(&gl->gl_lru, &skipped);
-               set_bit(GLF_LRU, &gl->gl_flags);
+
+               list_move(&gl->gl_lru, &skipped);
        }
        list_splice(&skipped, &lru_list);
-       atomic_add(nr_skipped, &lru_count);
+       if (!list_empty(&dispose))
+               gfs2_dispose_glock_lru(&dispose);
        spin_unlock(&lru_lock);
-out:
+}
+
+static int gfs2_shrink_glock_memory(struct shrinker *shrink,
+                                   struct shrink_control *sc)
+{
+       if (sc->nr_to_scan) {
+               if (!(sc->gfp_mask & __GFP_FS))
+                       return -1;
+               gfs2_scan_glock_lru(sc->nr_to_scan);
+       }
+
        return (atomic_read(&lru_count) / 100) * sysctl_vfs_cache_pressure;
 }
 
index c373a24fedd9f50a66f5d0ace7a2a542d5d581dc..e2601ba38ef56899869ff69e101f957f18313709 100644 (file)
@@ -52,7 +52,6 @@ struct gfs2_log_header_host {
  */
 
 struct gfs2_log_operations {
-       void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
        void (*lo_before_commit) (struct gfs2_sbd *sdp);
        void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai);
        void (*lo_before_scan) (struct gfs2_jdesc *jd,
@@ -341,6 +340,7 @@ enum {
        GIF_QD_LOCKED           = 1,
        GIF_ALLOC_FAILED        = 2,
        GIF_SW_PAGED            = 3,
+       GIF_ORDERED             = 4,
 };
 
 struct gfs2_inode {
@@ -357,6 +357,7 @@ struct gfs2_inode {
        struct gfs2_rgrpd *i_rgd;
        u64 i_goal;     /* goal block for allocations */
        struct rw_semaphore i_rw_mutex;
+       struct list_head i_ordered;
        struct list_head i_trunc_list;
        __be64 *i_hash_cache;
        u32 i_entries;
@@ -641,6 +642,7 @@ struct gfs2_sbd {
        wait_queue_head_t sd_glock_wait;
        atomic_t sd_glock_disposal;
        struct completion sd_locking_init;
+       struct completion sd_wdack;
        struct delayed_work sd_control_work;
 
        /* Inode Stuff */
@@ -723,6 +725,7 @@ struct gfs2_sbd {
        struct list_head sd_log_le_revoke;
        struct list_head sd_log_le_databuf;
        struct list_head sd_log_le_ordered;
+       spinlock_t sd_ordered_lock;
 
        atomic_t sd_log_thresh1;
        atomic_t sd_log_thresh2;
@@ -758,10 +761,7 @@ struct gfs2_sbd {
        unsigned int sd_replayed_blocks;
 
        /* For quiescing the filesystem */
-
        struct gfs2_holder sd_freeze_gh;
-       struct mutex sd_freeze_lock;
-       unsigned int sd_freeze_count;
 
        char sd_fsname[GFS2_FSNAME_LEN];
        char sd_table_name[GFS2_FSNAME_LEN];
index 2b6f5698ef18fb3ae489bc64e88ab5fd919855dd..db048a8ab6a859dc2466b56f61c59767f0244525 100644 (file)
@@ -447,7 +447,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
        struct timespec tv = CURRENT_TIME;
 
        dibh = gfs2_meta_new(ip->i_gl, ip->i_no_addr);
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI);
        gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
        di = (struct gfs2_dinode *)dibh->b_data;
@@ -584,7 +584,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
        if (error)
                goto fail_end_trans;
        set_nlink(&ip->i_inode, S_ISDIR(ip->i_inode.i_mode) ? 2 : 1);
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
        return 0;
@@ -931,7 +931,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
        if (error)
                goto out_brelse;
 
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        inc_nlink(&ip->i_inode);
        ip->i_inode.i_ctime = CURRENT_TIME;
        ihold(inode);
@@ -1412,7 +1412,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                if (error)
                        goto out_end_trans;
                ip->i_inode.i_ctime = CURRENT_TIME;
-               gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+               gfs2_trans_add_meta(ip->i_gl, dibh);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
index f4beeb9c81c1e5ee165e62c585b67d922f42553c..9a2ca8be76478bd18905a28291c4ab22f48a3d98 100644 (file)
@@ -482,70 +482,66 @@ static void log_flush_wait(struct gfs2_sbd *sdp)
        }
 }
 
-static int bd_cmp(void *priv, struct list_head *a, struct list_head *b)
+static int ip_cmp(void *priv, struct list_head *a, struct list_head *b)
 {
-       struct gfs2_bufdata *bda, *bdb;
+       struct gfs2_inode *ipa, *ipb;
 
-       bda = list_entry(a, struct gfs2_bufdata, bd_list);
-       bdb = list_entry(b, struct gfs2_bufdata, bd_list);
+       ipa = list_entry(a, struct gfs2_inode, i_ordered);
+       ipb = list_entry(b, struct gfs2_inode, i_ordered);
 
-       if (bda->bd_bh->b_blocknr < bdb->bd_bh->b_blocknr)
+       if (ipa->i_no_addr < ipb->i_no_addr)
                return -1;
-       if (bda->bd_bh->b_blocknr > bdb->bd_bh->b_blocknr)
+       if (ipa->i_no_addr > ipb->i_no_addr)
                return 1;
        return 0;
 }
 
 static void gfs2_ordered_write(struct gfs2_sbd *sdp)
 {
-       struct gfs2_bufdata *bd;
-       struct buffer_head *bh;
+       struct gfs2_inode *ip;
        LIST_HEAD(written);
 
-       gfs2_log_lock(sdp);
-       list_sort(NULL, &sdp->sd_log_le_ordered, &bd_cmp);
+       spin_lock(&sdp->sd_ordered_lock);
+       list_sort(NULL, &sdp->sd_log_le_ordered, &ip_cmp);
        while (!list_empty(&sdp->sd_log_le_ordered)) {
-               bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_list);
-               list_move(&bd->bd_list, &written);
-               bh = bd->bd_bh;
-               if (!buffer_dirty(bh))
+               ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, i_ordered);
+               list_move(&ip->i_ordered, &written);
+               if (ip->i_inode.i_mapping->nrpages == 0)
                        continue;
-               get_bh(bh);
-               gfs2_log_unlock(sdp);
-               lock_buffer(bh);
-               if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) {
-                       bh->b_end_io = end_buffer_write_sync;
-                       submit_bh(WRITE_SYNC, bh);
-               } else {
-                       unlock_buffer(bh);
-                       brelse(bh);
-               }
-               gfs2_log_lock(sdp);
+               spin_unlock(&sdp->sd_ordered_lock);
+               filemap_fdatawrite(ip->i_inode.i_mapping);
+               spin_lock(&sdp->sd_ordered_lock);
        }
        list_splice(&written, &sdp->sd_log_le_ordered);
-       gfs2_log_unlock(sdp);
+       spin_unlock(&sdp->sd_ordered_lock);
 }
 
 static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
 {
-       struct gfs2_bufdata *bd;
-       struct buffer_head *bh;
+       struct gfs2_inode *ip;
 
-       gfs2_log_lock(sdp);
+       spin_lock(&sdp->sd_ordered_lock);
        while (!list_empty(&sdp->sd_log_le_ordered)) {
-               bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_list);
-               bh = bd->bd_bh;
-               if (buffer_locked(bh)) {
-                       get_bh(bh);
-                       gfs2_log_unlock(sdp);
-                       wait_on_buffer(bh);
-                       brelse(bh);
-                       gfs2_log_lock(sdp);
+               ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, i_ordered);
+               list_del(&ip->i_ordered);
+               WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags));
+               if (ip->i_inode.i_mapping->nrpages == 0)
                        continue;
-               }
-               list_del_init(&bd->bd_list);
+               spin_unlock(&sdp->sd_ordered_lock);
+               filemap_fdatawait(ip->i_inode.i_mapping);
+               spin_lock(&sdp->sd_ordered_lock);
        }
-       gfs2_log_unlock(sdp);
+       spin_unlock(&sdp->sd_ordered_lock);
+}
+
+void gfs2_ordered_del_inode(struct gfs2_inode *ip)
+{
+       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+
+       spin_lock(&sdp->sd_ordered_lock);
+       if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags))
+               list_del(&ip->i_ordered);
+       spin_unlock(&sdp->sd_ordered_lock);
 }
 
 /**
index 3fd5215ea25fbba01971683bff9b347dbe129084..3566f35915e06f4abb9ecda802f5b55cc37d8dd9 100644 (file)
@@ -48,6 +48,18 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
        sdp->sd_log_head = sdp->sd_log_tail = value;
 }
 
+static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
+{
+       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+
+       if (!test_bit(GIF_ORDERED, &ip->i_flags)) {
+               spin_lock(&sdp->sd_ordered_lock);
+               if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags))
+                       list_add(&ip->i_ordered, &sdp->sd_log_le_ordered);
+               spin_unlock(&sdp->sd_ordered_lock);
+       }
+}
+extern void gfs2_ordered_del_inode(struct gfs2_inode *ip);
 extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
                            unsigned int ssize);
 
index 9ceccb1595a3d6f454dd0818eaea92cc8593114f..a5055977a214a1c99bff6e7f099a9fb4825e4f5f 100644 (file)
@@ -37,7 +37,7 @@
  *
  * The log lock must be held when calling this function
  */
-static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh)
+void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh)
 {
        struct gfs2_bufdata *bd;
 
@@ -388,32 +388,6 @@ static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type,
        return page;
 }
 
-static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
-{
-       struct gfs2_meta_header *mh;
-       struct gfs2_trans *tr;
-
-       tr = current->journal_info;
-       tr->tr_touched = 1;
-       if (!list_empty(&bd->bd_list))
-               return;
-       set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
-       set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
-       mh = (struct gfs2_meta_header *)bd->bd_bh->b_data;
-       if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) {
-               printk(KERN_ERR
-                      "Attempting to add uninitialised block to journal (inplace block=%lld)\n",
-                      (unsigned long long)bd->bd_bh->b_blocknr);
-               BUG();
-       }
-       gfs2_pin(sdp, bd->bd_bh);
-       mh->__pad0 = cpu_to_be64(0);
-       mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
-       sdp->sd_log_num_buf++;
-       list_add(&bd->bd_list, &sdp->sd_log_le_buf);
-       tr->tr_num_buf_new++;
-}
-
 static void gfs2_check_magic(struct buffer_head *bh)
 {
        void *kaddr;
@@ -600,20 +574,6 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
                jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
 }
 
-static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
-{
-       struct gfs2_glock *gl = bd->bd_gl;
-       struct gfs2_trans *tr;
-
-       tr = current->journal_info;
-       tr->tr_touched = 1;
-       tr->tr_num_revoke++;
-       sdp->sd_log_num_revoke++;
-       atomic_inc(&gl->gl_revokes);
-       set_bit(GLF_LFLUSH, &gl->gl_flags);
-       list_add(&bd->bd_list, &sdp->sd_log_le_revoke);
-}
-
 static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 {
        struct gfs2_meta_header *mh;
@@ -748,44 +708,6 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
        gfs2_revoke_clean(sdp);
 }
 
-/**
- * databuf_lo_add - Add a databuf to the transaction.
- *
- * This is used in two distinct cases:
- * i) In ordered write mode
- *    We put the data buffer on a list so that we can ensure that its
- *    synced to disk at the right time
- * ii) In journaled data mode
- *    We need to journal the data block in the same way as metadata in
- *    the functions above. The difference is that here we have a tag
- *    which is two __be64's being the block number (as per meta data)
- *    and a flag which says whether the data block needs escaping or
- *    not. This means we need a new log entry for each 251 or so data
- *    blocks, which isn't an enormous overhead but twice as much as
- *    for normal metadata blocks.
- */
-static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
-{
-       struct gfs2_trans *tr = current->journal_info;
-       struct address_space *mapping = bd->bd_bh->b_page->mapping;
-       struct gfs2_inode *ip = GFS2_I(mapping->host);
-
-       if (tr)
-               tr->tr_touched = 1;
-       if (!list_empty(&bd->bd_list))
-               return;
-       set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
-       set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
-       if (gfs2_is_jdata(ip)) {
-               gfs2_pin(sdp, bd->bd_bh);
-               tr->tr_num_databuf_new++;
-               sdp->sd_log_num_databuf++;
-               list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf);
-       } else {
-               list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);
-       }
-}
-
 /**
  * databuf_lo_before_commit - Scan the data buffers, writing as we go
  *
@@ -885,7 +807,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
 
 
 const struct gfs2_log_operations gfs2_buf_lops = {
-       .lo_add = buf_lo_add,
        .lo_before_commit = buf_lo_before_commit,
        .lo_after_commit = buf_lo_after_commit,
        .lo_before_scan = buf_lo_before_scan,
@@ -895,7 +816,6 @@ const struct gfs2_log_operations gfs2_buf_lops = {
 };
 
 const struct gfs2_log_operations gfs2_revoke_lops = {
-       .lo_add = revoke_lo_add,
        .lo_before_commit = revoke_lo_before_commit,
        .lo_after_commit = revoke_lo_after_commit,
        .lo_before_scan = revoke_lo_before_scan,
@@ -909,7 +829,6 @@ const struct gfs2_log_operations gfs2_rg_lops = {
 };
 
 const struct gfs2_log_operations gfs2_databuf_lops = {
-       .lo_add = databuf_lo_add,
        .lo_before_commit = databuf_lo_before_commit,
        .lo_after_commit = databuf_lo_after_commit,
        .lo_scan_elements = databuf_lo_scan_elements,
index 954a330585f4dcb69373e3cefcafa1d29c131d84..ba77b7da83251dd7c6f3b010a8fdd3682bc3874f 100644 (file)
@@ -29,6 +29,7 @@ extern const struct gfs2_log_operations gfs2_databuf_lops;
 extern const struct gfs2_log_operations *gfs2_log_ops[];
 extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page);
 extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int rw);
+extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
 
 static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
 {
@@ -46,19 +47,6 @@ static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
        return limit;
 }
 
-static inline void lops_init_le(struct gfs2_bufdata *bd,
-                               const struct gfs2_log_operations *lops)
-{
-       INIT_LIST_HEAD(&bd->bd_list);
-       bd->bd_ops = lops;
-}
-
-static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
-{
-       if (bd->bd_ops->lo_add)
-               bd->bd_ops->lo_add(sdp, bd);
-}
-
 static inline void lops_before_commit(struct gfs2_sbd *sdp)
 {
        int x;
index 22255d96b27efbb9c3a93e6db8678a147d99548b..b059bbb5059ec3a03efc5b5d7907f1cd66a2be01 100644 (file)
@@ -271,41 +271,6 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
        return 0;
 }
 
-/**
- * gfs2_attach_bufdata - attach a struct gfs2_bufdata structure to a buffer
- * @gl: the glock the buffer belongs to
- * @bh: The buffer to be attached to
- * @meta: Flag to indicate whether its metadata or not
- */
-
-void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
-                        int meta)
-{
-       struct gfs2_bufdata *bd;
-
-       if (meta)
-               lock_page(bh->b_page);
-
-       if (bh->b_private) {
-               if (meta)
-                       unlock_page(bh->b_page);
-               return;
-       }
-
-       bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL);
-       bd->bd_bh = bh;
-       bd->bd_gl = gl;
-
-       if (meta)
-               lops_init_le(bd, &gfs2_buf_lops);
-       else
-               lops_init_le(bd, &gfs2_databuf_lops);
-       bh->b_private = bd;
-
-       if (meta)
-               unlock_page(bh->b_page);
-}
-
 void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta)
 {
        struct address_space *mapping = bh->b_page->mapping;
index c30973b07a7caf54ae5c04e80be2cc6706aeb57e..0d4c843b6f8e59aec3f143a80417d0e4e6de43e0 100644 (file)
@@ -56,9 +56,6 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno,
 int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
 struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create);
 
-void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
-                        int meta);
-
 void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr,
                              int meta);
 
index 0e3554edb8f25d2f5d82932294eca6b5b4d54020..1b612be4b873c663640cbd1338d9ff2d5aaa5d8e 100644 (file)
@@ -81,6 +81,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
        init_waitqueue_head(&sdp->sd_glock_wait);
        atomic_set(&sdp->sd_glock_disposal, 0);
        init_completion(&sdp->sd_locking_init);
+       init_completion(&sdp->sd_wdack);
        spin_lock_init(&sdp->sd_statfs_spin);
 
        spin_lock_init(&sdp->sd_rindex_spin);
@@ -102,6 +103,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
        INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
        INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
        INIT_LIST_HEAD(&sdp->sd_log_le_ordered);
+       spin_lock_init(&sdp->sd_ordered_lock);
 
        init_waitqueue_head(&sdp->sd_log_waitq);
        init_waitqueue_head(&sdp->sd_logd_waitq);
@@ -115,8 +117,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
 
        INIT_LIST_HEAD(&sdp->sd_revoke_list);
 
-       mutex_init(&sdp->sd_freeze_lock);
-
        return sdp;
 }
 
index ae55e248c3b75054bd2ade8438eb9cd09f88ec5c..06122d09c0d1d88d37143ebf0178f13b98042481 100644 (file)
@@ -590,7 +590,7 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
        s64 x;
 
        mutex_lock(&sdp->sd_quota_mutex);
-       gfs2_trans_add_bh(ip->i_gl, qd->qd_bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, qd->qd_bh);
 
        if (!test_bit(QDF_CHANGE, &qd->qd_flags)) {
                qc->qc_change = 0;
@@ -726,7 +726,7 @@ get_a_page:
                        goto unlock_out;
        }
 
-       gfs2_trans_add_bh(ip->i_gl, bh, 0);
+       gfs2_trans_add_meta(ip->i_gl, bh);
 
        kaddr = kmap_atomic(page);
        if (offset + sizeof(struct gfs2_quota) > PAGE_CACHE_SIZE)
index b7eff078fe90f88f6561978b1917e50658482011..52c2aeaf45cef89cb5535b832ecc5fc9663fb328 100644 (file)
@@ -1323,7 +1323,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
                        if (ret == 0) {
                                bh = rgd->rd_bits[0].bi_bh;
                                rgd->rd_flags |= GFS2_RGF_TRIMMED;
-                               gfs2_trans_add_bh(rgd->rd_gl, bh, 1);
+                               gfs2_trans_add_meta(rgd->rd_gl, bh);
                                gfs2_rgrp_out(rgd, bh->b_data);
                                gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, bh->b_data);
                                gfs2_trans_end(sdp);
@@ -1968,14 +1968,14 @@ static void gfs2_alloc_extent(const struct gfs2_rbm *rbm, bool dinode,
 
        *n = 1;
        block = gfs2_rbm_to_block(rbm);
-       gfs2_trans_add_bh(rbm->rgd->rd_gl, rbm->bi->bi_bh, 1);
+       gfs2_trans_add_meta(rbm->rgd->rd_gl, rbm->bi->bi_bh);
        gfs2_setbit(rbm, true, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
        block++;
        while (*n < elen) {
                ret = gfs2_rbm_from_block(&pos, block);
                if (ret || gfs2_testbit(&pos) != GFS2_BLKST_FREE)
                        break;
-               gfs2_trans_add_bh(pos.rgd->rd_gl, pos.bi->bi_bh, 1);
+               gfs2_trans_add_meta(pos.rgd->rd_gl, pos.bi->bi_bh);
                gfs2_setbit(&pos, true, GFS2_BLKST_USED);
                (*n)++;
                block++;
@@ -2014,7 +2014,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
                               rbm.bi->bi_bh->b_data + rbm.bi->bi_offset,
                               rbm.bi->bi_len);
                }
-               gfs2_trans_add_bh(rbm.rgd->rd_gl, rbm.bi->bi_bh, 1);
+               gfs2_trans_add_meta(rbm.rgd->rd_gl, rbm.bi->bi_bh);
                gfs2_setbit(&rbm, false, new_state);
        }
 
@@ -2157,7 +2157,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
                if (error == 0) {
                        struct gfs2_dinode *di =
                                (struct gfs2_dinode *)dibh->b_data;
-                       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+                       gfs2_trans_add_meta(ip->i_gl, dibh);
                        di->di_goal_meta = di->di_goal_data =
                                cpu_to_be64(ip->i_goal);
                        brelse(dibh);
@@ -2176,7 +2176,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
                        *generation = rbm.rgd->rd_igeneration++;
        }
 
-       gfs2_trans_add_bh(rbm.rgd->rd_gl, rbm.rgd->rd_bits[0].bi_bh, 1);
+       gfs2_trans_add_meta(rbm.rgd->rd_gl, rbm.rgd->rd_bits[0].bi_bh);
        gfs2_rgrp_out(rbm.rgd, rbm.rgd->rd_bits[0].bi_bh->b_data);
        gfs2_rgrp_ondisk2lvb(rbm.rgd->rd_rgl, rbm.rgd->rd_bits[0].bi_bh->b_data);
 
@@ -2223,7 +2223,7 @@ void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta)
        trace_gfs2_block_alloc(ip, rgd, bstart, blen, GFS2_BLKST_FREE);
        rgd->rd_free += blen;
        rgd->rd_flags &= ~GFS2_RGF_TRIMMED;
-       gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+       gfs2_trans_add_meta(rgd->rd_gl, rgd->rd_bits[0].bi_bh);
        gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
        gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
 
@@ -2260,7 +2260,7 @@ void gfs2_unlink_di(struct inode *inode)
        if (!rgd)
                return;
        trace_gfs2_block_alloc(ip, rgd, blkno, 1, GFS2_BLKST_UNLINKED);
-       gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+       gfs2_trans_add_meta(rgd->rd_gl, rgd->rd_bits[0].bi_bh);
        gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
        gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
        update_rgrp_lvb_unlinked(rgd, 1);
@@ -2281,7 +2281,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
        rgd->rd_dinodes--;
        rgd->rd_free++;
 
-       gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+       gfs2_trans_add_meta(rgd->rd_gl, rgd->rd_bits[0].bi_bh);
        gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
        gfs2_rgrp_ondisk2lvb(rgd->rd_rgl, rgd->rd_bits[0].bi_bh->b_data);
        update_rgrp_lvb_unlinked(rgd, -1);
index d6488674d916273398b0bf8bd9cd3b2328c8a1fb..a3b40eeaa6e231860fb796f0c27a7677c5adffca 100644 (file)
@@ -500,7 +500,7 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
        if (error)
                return;
 
-       gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
+       gfs2_trans_add_meta(l_ip->i_gl, l_bh);
 
        spin_lock(&sdp->sd_statfs_spin);
        l_sc->sc_total += total;
@@ -528,7 +528,7 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
        struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
        struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
 
-       gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
+       gfs2_trans_add_meta(l_ip->i_gl, l_bh);
 
        spin_lock(&sdp->sd_statfs_spin);
        m_sc->sc_total += l_sc->sc_total;
@@ -539,7 +539,7 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
               0, sizeof(struct gfs2_statfs_change));
        spin_unlock(&sdp->sd_statfs_spin);
 
-       gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1);
+       gfs2_trans_add_meta(m_ip->i_gl, m_bh);
        gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode));
 }
 
@@ -663,54 +663,6 @@ out:
        return error;
 }
 
-/**
- * gfs2_freeze_fs - freezes the file system
- * @sdp: the file system
- *
- * This function flushes data and meta data for all machines by
- * acquiring the transaction log exclusively.  All journals are
- * ensured to be in a clean state as well.
- *
- * Returns: errno
- */
-
-int gfs2_freeze_fs(struct gfs2_sbd *sdp)
-{
-       int error = 0;
-
-       mutex_lock(&sdp->sd_freeze_lock);
-
-       if (!sdp->sd_freeze_count++) {
-               error = gfs2_lock_fs_check_clean(sdp, &sdp->sd_freeze_gh);
-               if (error)
-                       sdp->sd_freeze_count--;
-       }
-
-       mutex_unlock(&sdp->sd_freeze_lock);
-
-       return error;
-}
-
-/**
- * gfs2_unfreeze_fs - unfreezes the file system
- * @sdp: the file system
- *
- * This function allows the file system to proceed by unlocking
- * the exclusively held transaction lock.  Other GFS2 nodes are
- * now free to acquire the lock shared and go on with their lives.
- *
- */
-
-void gfs2_unfreeze_fs(struct gfs2_sbd *sdp)
-{
-       mutex_lock(&sdp->sd_freeze_lock);
-
-       if (sdp->sd_freeze_count && !--sdp->sd_freeze_count)
-               gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
-
-       mutex_unlock(&sdp->sd_freeze_lock);
-}
-
 void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
 {
        struct gfs2_dinode *str = buf;
@@ -824,7 +776,7 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
 
        ret = gfs2_meta_inode_buffer(ip, &bh);
        if (ret == 0) {
-               gfs2_trans_add_bh(ip->i_gl, bh, 1);
+               gfs2_trans_add_meta(ip->i_gl, bh);
                gfs2_dinode_out(ip, bh->b_data);
                brelse(bh);
        }
@@ -888,13 +840,6 @@ static void gfs2_put_super(struct super_block *sb)
        int error;
        struct gfs2_jdesc *jd;
 
-       /*  Unfreeze the filesystem, if we need to  */
-
-       mutex_lock(&sdp->sd_freeze_lock);
-       if (sdp->sd_freeze_count)
-               gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
-       mutex_unlock(&sdp->sd_freeze_lock);
-
        /* No more recovery requests */
        set_bit(SDF_NORECOVERY, &sdp->sd_flags);
        smp_mb();
@@ -985,7 +930,7 @@ static int gfs2_freeze(struct super_block *sb)
                return -EINVAL;
 
        for (;;) {
-               error = gfs2_freeze_fs(sdp);
+               error = gfs2_lock_fs_check_clean(sdp, &sdp->sd_freeze_gh);
                if (!error)
                        break;
 
@@ -1013,7 +958,9 @@ static int gfs2_freeze(struct super_block *sb)
 
 static int gfs2_unfreeze(struct super_block *sb)
 {
-       gfs2_unfreeze_fs(sb->s_fs_info);
+       struct gfs2_sbd *sdp = sb->s_fs_info;
+
+       gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
        return 0;
 }
 
@@ -1577,6 +1524,7 @@ out:
        /* Case 3 starts here */
        truncate_inode_pages(&inode->i_data, 0);
        gfs2_rs_delete(ip);
+       gfs2_ordered_del_inode(ip);
        clear_inode(inode);
        gfs2_dir_hash_inval(ip);
        ip->i_gl->gl_object = NULL;
index a0464680af0b8cec6b7fdf2c69099ba740933dce..90e3322ffa10ab4564195aa22ba156262dc304ff 100644 (file)
@@ -46,9 +46,6 @@ extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
                          struct buffer_head *l_bh);
 extern int gfs2_statfs_sync(struct super_block *sb, int type);
 
-extern int gfs2_freeze_fs(struct gfs2_sbd *sdp);
-extern void gfs2_unfreeze_fs(struct gfs2_sbd *sdp);
-
 extern struct file_system_type gfs2_fs_type;
 extern struct file_system_type gfs2meta_fs_type;
 extern const struct export_operations gfs2_export_ops;
index 8056b7b7238e9ee7770b21fd7cd5e77835c3062c..4fb9ad80d2600ac5ac53ddd399ff29ec1cb61f89 100644 (file)
@@ -91,19 +91,15 @@ static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf)
 
 static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf)
 {
-       unsigned int count;
-
-       mutex_lock(&sdp->sd_freeze_lock);
-       count = sdp->sd_freeze_count;
-       mutex_unlock(&sdp->sd_freeze_lock);
+       struct super_block *sb = sdp->sd_vfs;
+       int frozen = (sb->s_writers.frozen == SB_UNFROZEN) ? 0 : 1;
 
-       return snprintf(buf, PAGE_SIZE, "%u\n", count);
+       return snprintf(buf, PAGE_SIZE, "%u\n", frozen);
 }
 
 static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
 {
-       ssize_t ret = len;
-       int error = 0;
+       int error;
        int n = simple_strtol(buf, NULL, 0);
 
        if (!capable(CAP_SYS_ADMIN))
@@ -111,19 +107,21 @@ static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
 
        switch (n) {
        case 0:
-               gfs2_unfreeze_fs(sdp);
+               error = thaw_super(sdp->sd_vfs);
                break;
        case 1:
-               error = gfs2_freeze_fs(sdp);
+               error = freeze_super(sdp->sd_vfs);
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
        }
 
-       if (error)
+       if (error) {
                fs_warn(sdp, "freeze %d error %d", n, error);
+               return error;
+       }
 
-       return ret;
+       return len;
 }
 
 static ssize_t withdraw_show(struct gfs2_sbd *sdp, char *buf)
@@ -332,6 +330,28 @@ static ssize_t block_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
        return ret;
 }
 
+static ssize_t wdack_show(struct gfs2_sbd *sdp, char *buf)
+{
+       int val = completion_done(&sdp->sd_wdack) ? 1 : 0;
+
+       return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t wdack_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
+{
+       ssize_t ret = len;
+       int val;
+
+       val = simple_strtol(buf, NULL, 0);
+
+       if ((val == 1) &&
+           !strcmp(sdp->sd_lockstruct.ls_ops->lm_proto_name, "lock_dlm"))
+               complete(&sdp->sd_wdack);
+       else
+               ret = -EINVAL;
+       return ret;
+}
+
 static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf)
 {
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
@@ -463,7 +483,7 @@ static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
 GDLM_ATTR(proto_name,          0444, proto_name_show,          NULL);
 GDLM_ATTR(block,               0644, block_show,               block_store);
-GDLM_ATTR(withdraw,            0644, withdraw_show,            withdraw_store);
+GDLM_ATTR(withdraw,            0644, wdack_show,               wdack_store);
 GDLM_ATTR(jid,                 0644, jid_show,                 jid_store);
 GDLM_ATTR(first,               0644, lkfirst_show,             lkfirst_store);
 GDLM_ATTR(first_done,          0444, first_done_show,          NULL);
index 413627072f368168814f0df6ba340103c45f9e10..88162fae27a547ffe9a88364fd15fc90e79dad43 100644 (file)
@@ -18,6 +18,7 @@
 #include "gfs2.h"
 #include "incore.h"
 #include "glock.h"
+#include "inode.h"
 #include "log.h"
 #include "lops.h"
 #include "meta_io.h"
@@ -142,44 +143,143 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
        sb_end_intwrite(sdp->sd_vfs);
 }
 
+static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
+                                              struct buffer_head *bh,
+                                              const struct gfs2_log_operations *lops)
+{
+       struct gfs2_bufdata *bd;
+
+       bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL);
+       bd->bd_bh = bh;
+       bd->bd_gl = gl;
+       bd->bd_ops = lops;
+       INIT_LIST_HEAD(&bd->bd_list);
+       bh->b_private = bd;
+       return bd;
+}
+
 /**
- * gfs2_trans_add_bh - Add a to-be-modified buffer to the current transaction
- * @gl: the glock the buffer belongs to
+ * gfs2_trans_add_data - Add a databuf to the transaction.
+ * @gl: The inode glock associated with the buffer
  * @bh: The buffer to add
- * @meta: True in the case of adding metadata
  *
+ * This is used in two distinct cases:
+ * i) In ordered write mode
+ *    We put the data buffer on a list so that we can ensure that its
+ *    synced to disk at the right time
+ * ii) In journaled data mode
+ *    We need to journal the data block in the same way as metadata in
+ *    the functions above. The difference is that here we have a tag
+ *    which is two __be64's being the block number (as per meta data)
+ *    and a flag which says whether the data block needs escaping or
+ *    not. This means we need a new log entry for each 251 or so data
+ *    blocks, which isn't an enormous overhead but twice as much as
+ *    for normal metadata blocks.
  */
+void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
+{
+       struct gfs2_trans *tr = current->journal_info;
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+       struct address_space *mapping = bh->b_page->mapping;
+       struct gfs2_inode *ip = GFS2_I(mapping->host);
+       struct gfs2_bufdata *bd;
 
-void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)
+       if (!gfs2_is_jdata(ip)) {
+               gfs2_ordered_add_inode(ip);
+               return;
+       }
+
+       lock_buffer(bh);
+       gfs2_log_lock(sdp);
+       bd = bh->b_private;
+       if (bd == NULL) {
+               gfs2_log_unlock(sdp);
+               unlock_buffer(bh);
+               if (bh->b_private == NULL)
+                       bd = gfs2_alloc_bufdata(gl, bh, &gfs2_databuf_lops);
+               lock_buffer(bh);
+               gfs2_log_lock(sdp);
+       }
+       gfs2_assert(sdp, bd->bd_gl == gl);
+       tr->tr_touched = 1;
+       if (list_empty(&bd->bd_list)) {
+               set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+               set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
+               gfs2_pin(sdp, bd->bd_bh);
+               tr->tr_num_databuf_new++;
+               sdp->sd_log_num_databuf++;
+               list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf);
+       }
+       gfs2_log_unlock(sdp);
+       unlock_buffer(bh);
+}
+
+static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 {
+       struct gfs2_meta_header *mh;
+       struct gfs2_trans *tr;
+
+       tr = current->journal_info;
+       tr->tr_touched = 1;
+       if (!list_empty(&bd->bd_list))
+               return;
+       set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+       set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
+       mh = (struct gfs2_meta_header *)bd->bd_bh->b_data;
+       if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) {
+               printk(KERN_ERR
+                      "Attempting to add uninitialised block to journal (inplace block=%lld)\n",
+                      (unsigned long long)bd->bd_bh->b_blocknr);
+               BUG();
+       }
+       gfs2_pin(sdp, bd->bd_bh);
+       mh->__pad0 = cpu_to_be64(0);
+       mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
+       sdp->sd_log_num_buf++;
+       list_add(&bd->bd_list, &sdp->sd_log_le_buf);
+       tr->tr_num_buf_new++;
+}
+
+void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
+{
+
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct gfs2_bufdata *bd;
 
        lock_buffer(bh);
        gfs2_log_lock(sdp);
        bd = bh->b_private;
-       if (bd)
-               gfs2_assert(sdp, bd->bd_gl == gl);
-       else {
+       if (bd == NULL) {
                gfs2_log_unlock(sdp);
                unlock_buffer(bh);
-               gfs2_attach_bufdata(gl, bh, meta);
-               bd = bh->b_private;
+               lock_page(bh->b_page);
+               if (bh->b_private == NULL)
+                       bd = gfs2_alloc_bufdata(gl, bh, &gfs2_buf_lops);
+               unlock_page(bh->b_page);
                lock_buffer(bh);
                gfs2_log_lock(sdp);
        }
-       lops_add(sdp, bd);
+       gfs2_assert(sdp, bd->bd_gl == gl);
+       meta_lo_add(sdp, bd);
        gfs2_log_unlock(sdp);
        unlock_buffer(bh);
 }
 
 void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 {
+       struct gfs2_glock *gl = bd->bd_gl;
+       struct gfs2_trans *tr = current->journal_info;
+
        BUG_ON(!list_empty(&bd->bd_list));
        BUG_ON(!list_empty(&bd->bd_ail_st_list));
        BUG_ON(!list_empty(&bd->bd_ail_gl_list));
-       lops_init_le(bd, &gfs2_revoke_lops);
-       lops_add(sdp, bd);
+       bd->bd_ops = &gfs2_revoke_lops;
+       tr->tr_touched = 1;
+       tr->tr_num_revoke++;
+       sdp->sd_log_num_revoke++;
+       atomic_inc(&gl->gl_revokes);
+       set_bit(GLF_LFLUSH, &gl->gl_flags);
+       list_add(&bd->bd_list, &sdp->sd_log_le_revoke);
 }
 
 void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
index bf2ae9aeee7ab1208f42cea980e382fa5d183b7f..1e6e7da25a1725a797826e33cb46a629acad8394 100644 (file)
@@ -39,7 +39,8 @@ extern int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
                            unsigned int revokes);
 
 extern void gfs2_trans_end(struct gfs2_sbd *sdp);
-extern void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta);
+extern void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh);
+extern void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh);
 extern void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
 extern void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len);
 
index f00d7c5744f66585333f25f7b324d2549f2ebe8a..6402fb69d71bd838d943c4d60d1a8879d15f6217 100644 (file)
@@ -54,6 +54,9 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
 
                kobject_uevent(&sdp->sd_kobj, KOBJ_OFFLINE);
 
+               if (!strcmp(sdp->sd_lockstruct.ls_ops->lm_proto_name, "lock_dlm"))
+                       wait_for_completion(&sdp->sd_wdack);
+
                if (lm->lm_unmount) {
                        fs_err(sdp, "telling LM to unmount\n");
                        lm->lm_unmount(sdp);
index 76c144b3c9bbdc4fe98d018ebf7303cebf423816..cbb46c2baa69416f1f5771fc11f82aad5bd1fa17 100644 (file)
@@ -270,7 +270,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
        if (error)
                goto out_gunlock;
 
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, bh);
 
        dataptrs = GFS2_EA2DATAPTRS(ea);
        for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++) {
@@ -309,7 +309,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
                ip->i_inode.i_ctime = CURRENT_TIME;
-               gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+               gfs2_trans_add_meta(ip->i_gl, dibh);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
@@ -509,7 +509,7 @@ static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
                }
 
                if (din) {
-                       gfs2_trans_add_bh(ip->i_gl, bh[x], 1);
+                       gfs2_trans_add_meta(ip->i_gl, bh[x]);
                        memcpy(pos, din, cp_size);
                        din += sdp->sd_jbsize;
                }
@@ -629,7 +629,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
                return error;
        gfs2_trans_add_unrevoke(sdp, block, 1);
        *bhp = gfs2_meta_new(ip->i_gl, block);
-       gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
+       gfs2_trans_add_meta(ip->i_gl, *bhp);
        gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
        gfs2_buffer_clear_tail(*bhp, sizeof(struct gfs2_meta_header));
 
@@ -691,7 +691,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
                                return error;
                        gfs2_trans_add_unrevoke(sdp, block, 1);
                        bh = gfs2_meta_new(ip->i_gl, block);
-                       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+                       gfs2_trans_add_meta(ip->i_gl, bh);
                        gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);
 
                        gfs2_add_inode_blocks(&ip->i_inode, 1);
@@ -751,7 +751,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
                ip->i_inode.i_ctime = CURRENT_TIME;
-               gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+               gfs2_trans_add_meta(ip->i_gl, dibh);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
@@ -834,7 +834,7 @@ static void ea_set_remove_stuffed(struct gfs2_inode *ip,
        struct gfs2_ea_header *prev = el->el_prev;
        u32 len;
 
-       gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, el->el_bh);
 
        if (!prev || !GFS2_EA_IS_STUFFED(ea)) {
                ea->ea_type = GFS2_EATYPE_UNUSED;
@@ -872,7 +872,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
        if (error)
                return error;
 
-       gfs2_trans_add_bh(ip->i_gl, bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, bh);
 
        if (es->ea_split)
                ea = ea_split_ea(ea);
@@ -886,7 +886,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
        if (error)
                goto out;
        ip->i_inode.i_ctime = CURRENT_TIME;
-       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_trans_add_meta(ip->i_gl, dibh);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
 out:
@@ -901,7 +901,7 @@ static int ea_set_simple_alloc(struct gfs2_inode *ip,
        struct gfs2_ea_header *ea = es->es_ea;
        int error;
 
-       gfs2_trans_add_bh(ip->i_gl, es->es_bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, es->es_bh);
 
        if (es->ea_split)
                ea = ea_split_ea(ea);
@@ -997,7 +997,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
                        goto out;
                }
 
-               gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+               gfs2_trans_add_meta(ip->i_gl, indbh);
        } else {
                u64 blk;
                unsigned int n = 1;
@@ -1006,7 +1006,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
                        return error;
                gfs2_trans_add_unrevoke(sdp, blk, 1);
                indbh = gfs2_meta_new(ip->i_gl, blk);
-               gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+               gfs2_trans_add_meta(ip->i_gl, indbh);
                gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
                gfs2_buffer_clear_tail(indbh, mh_size);
 
@@ -1092,7 +1092,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
        if (error)
                return error;
 
-       gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1);
+       gfs2_trans_add_meta(ip->i_gl, el->el_bh);
 
        if (prev) {
                u32 len;
@@ -1109,7 +1109,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
                ip->i_inode.i_ctime = CURRENT_TIME;
-               gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+               gfs2_trans_add_meta(ip->i_gl, dibh);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
@@ -1265,7 +1265,7 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
        if (GFS2_EA_IS_STUFFED(el.el_ea)) {
                error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0);
                if (error == 0) {
-                       gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1);
+                       gfs2_trans_add_meta(ip->i_gl, el.el_bh);
                        memcpy(GFS2_EA2DATA(el.el_ea), data,
                               GFS2_EA_DATA_LEN(el.el_ea));
                }
@@ -1352,7 +1352,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
        if (error)
                goto out_gunlock;
 
-       gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+       gfs2_trans_add_meta(ip->i_gl, indbh);
 
        eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header));
        bstart = 0;
@@ -1384,7 +1384,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
-               gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+               gfs2_trans_add_meta(ip->i_gl, dibh);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }
@@ -1434,7 +1434,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
-               gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+               gfs2_trans_add_meta(ip->i_gl, dibh);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
        }