diff mbox

[02/12,v5] Btrfs: introduce sub transaction stuff

Message ID 1312623467-31487-3-git-send-email-liubo2009@cn.fujitsu.com (mailing list archive)
State New, archived
Headers show

Commit Message

liubo Aug. 6, 2011, 9:37 a.m. UTC
Introduce a new concept "sub transaction",
the relation between transaction and sub transaction is

transaction A       ---> transid = x
   sub trans a(1)   ---> sub_transid = x+1
   sub trans a(2)   ---> sub_transid = x+2
     ... ...
   sub trans a(n-1) ---> sub_transid = x+n-1
   sub trans a(n)   ---> sub_transid = x+n
transaction B       ---> transid = x+n+1
     ... ...

And the most important is
a) a trans handler's transid now gets value from sub transid instead of transid.
b) when a transaction commits, transid may not added by 1, but depend on the
   biggest sub_transaction of the last neighbour transaction,
   i.e.
        B->transid = a(n)->transid + 1,
        (B->transid - A->transid) >= 1
c) we start a new sub transaction after a fsync.

We also ship some 'trans->transid' to 'trans->transaction->transid' to
ensure btrfs works well and to get rid of WARNings.

These are used for the new log code.

Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
---
 fs/btrfs/ctree.c       |   35 ++++++++++++++++++-----------------
 fs/btrfs/ctree.h       |    1 +
 fs/btrfs/disk-io.c     |    7 ++++---
 fs/btrfs/extent-tree.c |   10 ++++++----
 fs/btrfs/inode.c       |    4 ++--
 fs/btrfs/ioctl.c       |    2 +-
 fs/btrfs/relocation.c  |    6 +++---
 fs/btrfs/transaction.c |   13 ++++++++-----
 fs/btrfs/transaction.h |    1 +
 fs/btrfs/tree-defrag.c |    2 +-
 fs/btrfs/tree-log.c    |   16 ++++++++++++++--
 11 files changed, 59 insertions(+), 38 deletions(-)

Comments

Mitch Harder Aug. 9, 2011, 5:25 p.m. UTC | #1
On Sat, Aug 6, 2011 at 4:37 AM, Liu Bo <liubo2009@cn.fujitsu.com> wrote:
> Introduce a new concept "sub transaction",
> the relation between transaction and sub transaction is
>
> transaction A       ---> transid = x
>   sub trans a(1)   ---> sub_transid = x+1
>   sub trans a(2)   ---> sub_transid = x+2
>     ... ...
>   sub trans a(n-1) ---> sub_transid = x+n-1
>   sub trans a(n)   ---> sub_transid = x+n
> transaction B       ---> transid = x+n+1
>     ... ...
>
> And the most important is
> a) a trans handler's transid now gets value from sub transid instead of transid.
> b) when a transaction commits, transid may not added by 1, but depend on the
>   biggest sub_transaction of the last neighbour transaction,
>   i.e.
>        B->transid = a(n)->transid + 1,
>        (B->transid - A->transid) >= 1
> c) we start a new sub transaction after a fsync.
>
> We also ship some 'trans->transid' to 'trans->transaction->transid' to
> ensure btrfs works well and to get rid of WARNings.
>
> These are used for the new log code.
>
> Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
> ---
>  fs/btrfs/ctree.c       |   35 ++++++++++++++++++-----------------
>  fs/btrfs/ctree.h       |    1 +
>  fs/btrfs/disk-io.c     |    7 ++++---
>  fs/btrfs/extent-tree.c |   10 ++++++----
>  fs/btrfs/inode.c       |    4 ++--
>  fs/btrfs/ioctl.c       |    2 +-
>  fs/btrfs/relocation.c  |    6 +++---
>  fs/btrfs/transaction.c |   13 ++++++++-----
>  fs/btrfs/transaction.h |    1 +
>  fs/btrfs/tree-defrag.c |    2 +-
>  fs/btrfs/tree-log.c    |   16 ++++++++++++++--
>  11 files changed, 59 insertions(+), 38 deletions(-)
>
> diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
> index 011cab3..41d1d17 100644
> --- a/fs/btrfs/ctree.c
> +++ b/fs/btrfs/ctree.c
> @@ -228,9 +228,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
>        int level;
>        struct btrfs_disk_key disk_key;
>
> -       WARN_ON(root->ref_cows && trans->transid !=
> +       WARN_ON(root->ref_cows && trans->transaction->transid !=
>                root->fs_info->running_transaction->transid);
> -       WARN_ON(root->ref_cows && trans->transid != root->last_trans);
> +       WARN_ON(root->ref_cows && trans->transid < root->last_trans);
>
>        level = btrfs_header_level(buf);
>        if (level == 0)
> @@ -425,9 +425,9 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
>
>        btrfs_assert_tree_locked(buf);
>
> -       WARN_ON(root->ref_cows && trans->transid !=
> +       WARN_ON(root->ref_cows && trans->transaction->transid !=
>                root->fs_info->running_transaction->transid);
> -       WARN_ON(root->ref_cows && trans->transid != root->last_trans);
> +       WARN_ON(root->ref_cows && trans->transid < root->last_trans);
>
>        level = btrfs_header_level(buf);
>
> @@ -493,7 +493,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
>                else
>                        parent_start = 0;
>
> -               WARN_ON(trans->transid != btrfs_header_generation(parent));
> +               WARN_ON(btrfs_header_generation(parent) <
> +                                               trans->transaction->transid);
>                btrfs_set_node_blockptr(parent, parent_slot,
>                                        cow->start);
>                btrfs_set_node_ptr_generation(parent, parent_slot,
> @@ -514,7 +515,7 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans,
>                                   struct btrfs_root *root,
>                                   struct extent_buffer *buf)
>  {
> -       if (btrfs_header_generation(buf) == trans->transid &&
> +       if (btrfs_header_generation(buf) >= trans->transaction->transid &&
>            !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN) &&
>            !(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID &&
>              btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)))
> @@ -542,7 +543,7 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
>                       root->fs_info->running_transaction->transid);
>                WARN_ON(1);
>        }
> -       if (trans->transid != root->fs_info->generation) {
> +       if (trans->transaction->transid != root->fs_info->generation) {
>                printk(KERN_CRIT "trans %llu running %llu\n",
>                       (unsigned long long)trans->transid,
>                       (unsigned long long)root->fs_info->generation);
> @@ -645,7 +646,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
>
>        if (trans->transaction != root->fs_info->running_transaction)
>                WARN_ON(1);
> -       if (trans->transid != root->fs_info->generation)
> +       if (trans->transaction->transid != root->fs_info->generation)
>                WARN_ON(1);
>
>        parent_nritems = btrfs_header_nritems(parent);
> @@ -898,7 +899,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
>
>        WARN_ON(path->locks[level] != BTRFS_WRITE_LOCK &&
>                path->locks[level] != BTRFS_WRITE_LOCK_BLOCKING);
> -       WARN_ON(btrfs_header_generation(mid) != trans->transid);
> +       WARN_ON(btrfs_header_generation(mid) < trans->transaction->transid);
>
>        orig_ptr = btrfs_node_blockptr(mid, orig_slot);
>
> @@ -1105,7 +1106,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
>                return 1;
>
>        mid = path->nodes[level];
> -       WARN_ON(btrfs_header_generation(mid) != trans->transid);
> +       WARN_ON(btrfs_header_generation(mid) < trans->transaction->transid);
>
>        if (level < BTRFS_MAX_LEVEL - 1)
>                parent = path->nodes[level + 1];
> @@ -1942,8 +1943,8 @@ static int push_node_left(struct btrfs_trans_handle *trans,
>        src_nritems = btrfs_header_nritems(src);
>        dst_nritems = btrfs_header_nritems(dst);
>        push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
> -       WARN_ON(btrfs_header_generation(src) != trans->transid);
> -       WARN_ON(btrfs_header_generation(dst) != trans->transid);
> +       WARN_ON(btrfs_header_generation(src) < trans->transaction->transid);
> +       WARN_ON(btrfs_header_generation(dst) < trans->transaction->transid);
>
>        if (!empty && src_nritems <= 8)
>                return 1;
> @@ -2005,8 +2006,8 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
>        int dst_nritems;
>        int ret = 0;
>
> -       WARN_ON(btrfs_header_generation(src) != trans->transid);
> -       WARN_ON(btrfs_header_generation(dst) != trans->transid);
> +       WARN_ON(btrfs_header_generation(src) < trans->transaction->transid);
> +       WARN_ON(btrfs_header_generation(dst) < trans->transaction->transid);
>
>        src_nritems = btrfs_header_nritems(src);
>        dst_nritems = btrfs_header_nritems(dst);
> @@ -2097,7 +2098,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
>        btrfs_set_node_key(c, &lower_key, 0);
>        btrfs_set_node_blockptr(c, 0, lower->start);
>        lower_gen = btrfs_header_generation(lower);
> -       WARN_ON(lower_gen != trans->transid);
> +       WARN_ON(lower_gen < trans->transaction->transid);
>
>        btrfs_set_node_ptr_generation(c, 0, lower_gen);
>
> @@ -2177,7 +2178,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
>        u32 c_nritems;
>
>        c = path->nodes[level];
> -       WARN_ON(btrfs_header_generation(c) != trans->transid);
> +       WARN_ON(btrfs_header_generation(c) < trans->transaction->transid);
>        if (c == root->node) {
>                /* trying to split the root, lets make a new one */
>                ret = insert_new_root(trans, root, path, level + 1);
> @@ -3751,7 +3752,7 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
>  {
>        int ret;
>
> -       WARN_ON(btrfs_header_generation(leaf) != trans->transid);
> +       WARN_ON(btrfs_header_generation(leaf) < trans->transaction->transid);
>        ret = del_ptr(trans, root, path, 1, path->slots[1]);
>        if (ret)
>                return ret;
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index a6263bd..310f586 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -925,6 +925,7 @@ struct btrfs_fs_info {
>        struct mutex durable_block_rsv_mutex;
>
>        u64 generation;
> +       u64 sub_generation;
>        u64 last_trans_committed;
>
>        /*
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 94ecac3..50e74b1 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -1035,7 +1035,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>                     struct extent_buffer *buf)
>  {
>        struct inode *btree_inode = root->fs_info->btree_inode;
> -       if (btrfs_header_generation(buf) ==
> +       if (btrfs_header_generation(buf) >=
>            root->fs_info->running_transaction->transid) {
>                btrfs_assert_tree_locked(buf);
>
> @@ -1559,7 +1559,7 @@ static int transaction_kthread(void *arg)
>
>                trans = btrfs_join_transaction(root);
>                BUG_ON(IS_ERR(trans));
> -               if (transid == trans->transid) {
> +               if (transid == trans->transaction->transid) {
>                        ret = btrfs_commit_transaction(trans, root);
>                        BUG_ON(ret);
>                } else {
> @@ -2001,6 +2001,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
>        csum_root->track_dirty = 1;
>
>        fs_info->generation = generation;
> +       fs_info->sub_generation = generation;
>        fs_info->last_trans_committed = generation;
>        fs_info->data_alloc_profile = (u64)-1;
>        fs_info->metadata_alloc_profile = (u64)-1;
> @@ -2671,7 +2672,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
>        int was_dirty;
>
>        btrfs_assert_tree_locked(buf);
> -       if (transid != root->fs_info->generation) {
> +       if (transid < root->fs_info->generation) {
>                printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
>                       "found %llu running %llu\n",
>                        (unsigned long long)buf->start,
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index 66bac22..fa101ab 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -4363,7 +4363,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
>        list_for_each_entry_safe(block_rsv, next_rsv,
>                                 &fs_info->durable_block_rsv_list, list) {
>
> -               idx = trans->transid & 0x1;
> +               idx = trans->transaction->transid & 0x1;
>                if (block_rsv->freed[idx] > 0) {
>                        block_rsv_add_bytes(block_rsv,
>                                            block_rsv->freed[idx], 0);
> @@ -4680,7 +4680,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
>        if (block_rsv->space_info != cache->space_info)
>                goto out;
>
> -       if (btrfs_header_generation(buf) == trans->transid) {
> +       if (btrfs_header_generation(buf) >= trans->transaction->transid) {
>                if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
>                        ret = check_ref_cleanup(trans, root, buf->start);
>                        if (!ret)
> @@ -4730,7 +4730,8 @@ pin:
>
>                if (ret) {
>                        spin_lock(&block_rsv->lock);
> -                       block_rsv->freed[trans->transid & 0x1] += buf->len;
> +                       block_rsv->freed[trans->transaction->transid & 0x1] +=
> +                                                                      buf->len;
>                        spin_unlock(&block_rsv->lock);
>                }
>        }
> @@ -6164,7 +6165,8 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
>                }
>                /* make block locked assertion in clean_tree_block happy */
>                if (!path->locks[level] &&
> -                   btrfs_header_generation(eb) == trans->transid) {
> +                   btrfs_header_generation(eb) >=
> +                                                trans->transaction->transid) {
>                        btrfs_tree_lock(eb);
>                        btrfs_set_lock_blocking(eb);
>                        path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 34195f9..99eb0b3 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -2106,7 +2106,7 @@ void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans,
>         * space than it frees. So we should make sure there is enough
>         * reserved space.
>         */
> -       index = trans->transid & 0x1;
> +       index = trans->transaction->transid & 0x1;
>        if (block_rsv->reserved + block_rsv->freed[index] < block_rsv->size) {
>                num_bytes += block_rsv->size -
>                             (block_rsv->reserved + block_rsv->freed[index]);
> @@ -2130,7 +2130,7 @@ void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans,
>
>        /* refill source subvolume's orphan block reservation */
>        block_rsv = root->orphan_block_rsv;
> -       index = trans->transid & 0x1;
> +       index = trans->transaction->transid & 0x1;
>        if (block_rsv->reserved + block_rsv->freed[index] < block_rsv->size) {
>                num_bytes = block_rsv->size -
>                            (block_rsv->reserved + block_rsv->freed[index]);
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 2bb0886..bc9a2ad 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -2758,7 +2758,7 @@ static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp
>        trans = btrfs_start_transaction(root, 0);
>        if (IS_ERR(trans))
>                return PTR_ERR(trans);
> -       transid = trans->transid;
> +       transid = trans->transaction->transid;
>        ret = btrfs_commit_transaction_async(trans, root, 0);
>        if (ret) {
>                btrfs_end_transaction(trans, root);
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index 59bb176..3063be1 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -469,7 +469,7 @@ static int update_backref_cache(struct btrfs_trans_handle *trans,
>                return 0;
>        }
>
> -       if (cache->last_trans == trans->transid)
> +       if (cache->last_trans >= trans->transaction->transid)
>                return 0;
>
>        /*
> @@ -1281,7 +1281,7 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
>                BUG_ON(ret);
>
>                btrfs_set_root_last_snapshot(&root->root_item,
> -                                            trans->transid - 1);
> +                                            trans->transaction->transid - 1);
>        } else {
>                /*
>                 * called by btrfs_reloc_post_snapshot_hook.
> @@ -2271,7 +2271,7 @@ static int record_reloc_root_in_trans(struct btrfs_trans_handle *trans,
>  {
>        struct btrfs_root *root;
>
> -       if (reloc_root->last_trans == trans->transid)
> +       if (reloc_root->last_trans >= trans->transaction->transid)
>                return 0;
>
>        root = read_fs_root(reloc_root->fs_info, reloc_root->root_key.offset);
> diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
> index 7dc36fa..531b0dc 100644
> --- a/fs/btrfs/transaction.c
> +++ b/fs/btrfs/transaction.c
> @@ -113,7 +113,9 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail)
>        extent_io_tree_init(&cur_trans->dirty_pages,
>                             root->fs_info->btree_inode->i_mapping);
>        root->fs_info->generation++;
> +       root->fs_info->sub_generation = root->fs_info->generation;
>        cur_trans->transid = root->fs_info->generation;
> +       cur_trans->sub_transid = cur_trans->transid;
>        root->fs_info->running_transaction = cur_trans;
>        spin_unlock(&root->fs_info->trans_lock);
>
> @@ -129,7 +131,7 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail)
>  static int record_root_in_trans(struct btrfs_trans_handle *trans,
>                               struct btrfs_root *root)
>  {
> -       if (root->ref_cows && root->last_trans < trans->transid) {
> +       if (root->ref_cows && root->last_trans < trans->transaction->transid) {
>                WARN_ON(root == root->fs_info->extent_root);
>                WARN_ON(root->commit_root != root->node);
>
> @@ -146,7 +148,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
>                smp_wmb();
>
>                spin_lock(&root->fs_info->fs_roots_radix_lock);
> -               if (root->last_trans == trans->transid) {
> +               if (root->last_trans >= trans->transaction->transid) {
>                        spin_unlock(&root->fs_info->fs_roots_radix_lock);
>                        return 0;
>                }
> @@ -194,7 +196,7 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
>         * and barriers
>         */
>        smp_rmb();
> -       if (root->last_trans == trans->transid &&
> +       if (root->last_trans >= trans->transaction->transid &&
>            !root->in_trans_setup)
>                return 0;
>
> @@ -302,7 +304,7 @@ again:
>
>        cur_trans = root->fs_info->running_transaction;
>
> -       h->transid = cur_trans->transid;
> +       h->transid = cur_trans->sub_transid;
>        h->transaction = cur_trans;
>        h->blocks_used = 0;
>        h->bytes_reserved = 0;
> @@ -1346,6 +1348,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
>
>        trans->transaction->blocked = 0;
>        spin_lock(&root->fs_info->trans_lock);
> +       root->fs_info->generation = cur_trans->sub_transid;
>        root->fs_info->running_transaction = NULL;
>        root->fs_info->trans_no_join = 0;
>        spin_unlock(&root->fs_info->trans_lock);
> @@ -1367,7 +1370,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
>
>        cur_trans->commit_done = 1;
>
> -       root->fs_info->last_trans_committed = cur_trans->transid;
> +       root->fs_info->last_trans_committed = cur_trans->sub_transid;
>
>        wake_up(&cur_trans->commit_wait);
>
> diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
> index 02564e6..45876b0 100644
> --- a/fs/btrfs/transaction.h
> +++ b/fs/btrfs/transaction.h
> @@ -23,6 +23,7 @@
>
>  struct btrfs_transaction {
>        u64 transid;
> +       u64 sub_transid;
>        /*
>         * total writers in this transaction, it must be zero before the
>         * transaction can end
> diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
> index 3b580ee..a2569af 100644
> --- a/fs/btrfs/tree-defrag.c
> +++ b/fs/btrfs/tree-defrag.c
> @@ -139,7 +139,7 @@ done:
>        if (ret != -EAGAIN) {
>                memset(&root->defrag_progress, 0,
>                       sizeof(root->defrag_progress));
> -               root->defrag_trans_start = trans->transid;
> +               root->defrag_trans_start = trans->transaction->transid;
>        }
>        return ret;
>  }
> diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
> index f320641..5a026d2 100644
> --- a/fs/btrfs/tree-log.c
> +++ b/fs/btrfs/tree-log.c
> @@ -134,9 +134,19 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
>  static int start_log_trans(struct btrfs_trans_handle *trans,
>                           struct btrfs_root *root)
>  {
> +       struct btrfs_transaction *cur_trans;
>        int ret;
>        int err = 0;
>
> +       /* start a new sub transaction */
> +       spin_lock(&root->fs_info->trans_lock);
> +
> +       cur_trans = root->fs_info->running_transaction;
> +       cur_trans->sub_transid++;
> +       root->fs_info->sub_generation = cur_trans->sub_transid;
> +
> +       spin_unlock(&root->fs_info->trans_lock);
> +
>        mutex_lock(&root->log_mutex);
>        if (root->log_root) {
>                if (!root->log_start_pid) {
> @@ -2007,7 +2017,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
>        }
>
>        /* bail out if we need to do a full commit */
> -       if (root->fs_info->last_trans_log_full_commit == trans->transid) {
> +       if (root->fs_info->last_trans_log_full_commit >=
> +                                               trans->transaction->transid) {
>                ret = -EAGAIN;
>                mutex_unlock(&root->log_mutex);
>                goto out;
> @@ -2084,7 +2095,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
>         * now that we've moved on to the tree of log tree roots,
>         * check the full commit flag again
>         */
> -       if (root->fs_info->last_trans_log_full_commit == trans->transid) {
> +       if (root->fs_info->last_trans_log_full_commit >=
> +                                               trans->transaction->transid) {
>                btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
>                mutex_unlock(&log_root_tree->log_mutex);
>                ret = -EAGAIN;
> --
> 1.6.5.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Portions of this patch conflict with another patch recently posted to
the Mailing List by Josef.

http://www.mail-archive.com/linux-btrfs@vger.kernel.org/msg11657.html

"[PATCH] Btrfs: kill the durable block rsv stuff" removes portions of
the functions btrfs_finish_extent_commit() and btrfs_free_tree_block()
in fs/btrfs/extent-tree.c that are modified in this patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 011cab3..41d1d17 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -228,9 +228,9 @@  int btrfs_copy_root(struct btrfs_trans_handle *trans,
 	int level;
 	struct btrfs_disk_key disk_key;
 
-	WARN_ON(root->ref_cows && trans->transid !=
+	WARN_ON(root->ref_cows && trans->transaction->transid !=
 		root->fs_info->running_transaction->transid);
-	WARN_ON(root->ref_cows && trans->transid != root->last_trans);
+	WARN_ON(root->ref_cows && trans->transid < root->last_trans);
 
 	level = btrfs_header_level(buf);
 	if (level == 0)
@@ -425,9 +425,9 @@  static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
 
 	btrfs_assert_tree_locked(buf);
 
-	WARN_ON(root->ref_cows && trans->transid !=
+	WARN_ON(root->ref_cows && trans->transaction->transid !=
 		root->fs_info->running_transaction->transid);
-	WARN_ON(root->ref_cows && trans->transid != root->last_trans);
+	WARN_ON(root->ref_cows && trans->transid < root->last_trans);
 
 	level = btrfs_header_level(buf);
 
@@ -493,7 +493,8 @@  static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
 		else
 			parent_start = 0;
 
-		WARN_ON(trans->transid != btrfs_header_generation(parent));
+		WARN_ON(btrfs_header_generation(parent) <
+						trans->transaction->transid);
 		btrfs_set_node_blockptr(parent, parent_slot,
 					cow->start);
 		btrfs_set_node_ptr_generation(parent, parent_slot,
@@ -514,7 +515,7 @@  static inline int should_cow_block(struct btrfs_trans_handle *trans,
 				   struct btrfs_root *root,
 				   struct extent_buffer *buf)
 {
-	if (btrfs_header_generation(buf) == trans->transid &&
+	if (btrfs_header_generation(buf) >= trans->transaction->transid &&
 	    !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN) &&
 	    !(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID &&
 	      btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)))
@@ -542,7 +543,7 @@  noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
 		       root->fs_info->running_transaction->transid);
 		WARN_ON(1);
 	}
-	if (trans->transid != root->fs_info->generation) {
+	if (trans->transaction->transid != root->fs_info->generation) {
 		printk(KERN_CRIT "trans %llu running %llu\n",
 		       (unsigned long long)trans->transid,
 		       (unsigned long long)root->fs_info->generation);
@@ -645,7 +646,7 @@  int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 
 	if (trans->transaction != root->fs_info->running_transaction)
 		WARN_ON(1);
-	if (trans->transid != root->fs_info->generation)
+	if (trans->transaction->transid != root->fs_info->generation)
 		WARN_ON(1);
 
 	parent_nritems = btrfs_header_nritems(parent);
@@ -898,7 +899,7 @@  static noinline int balance_level(struct btrfs_trans_handle *trans,
 
 	WARN_ON(path->locks[level] != BTRFS_WRITE_LOCK &&
 		path->locks[level] != BTRFS_WRITE_LOCK_BLOCKING);
-	WARN_ON(btrfs_header_generation(mid) != trans->transid);
+	WARN_ON(btrfs_header_generation(mid) < trans->transaction->transid);
 
 	orig_ptr = btrfs_node_blockptr(mid, orig_slot);
 
@@ -1105,7 +1106,7 @@  static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
 		return 1;
 
 	mid = path->nodes[level];
-	WARN_ON(btrfs_header_generation(mid) != trans->transid);
+	WARN_ON(btrfs_header_generation(mid) < trans->transaction->transid);
 
 	if (level < BTRFS_MAX_LEVEL - 1)
 		parent = path->nodes[level + 1];
@@ -1942,8 +1943,8 @@  static int push_node_left(struct btrfs_trans_handle *trans,
 	src_nritems = btrfs_header_nritems(src);
 	dst_nritems = btrfs_header_nritems(dst);
 	push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
-	WARN_ON(btrfs_header_generation(src) != trans->transid);
-	WARN_ON(btrfs_header_generation(dst) != trans->transid);
+	WARN_ON(btrfs_header_generation(src) < trans->transaction->transid);
+	WARN_ON(btrfs_header_generation(dst) < trans->transaction->transid);
 
 	if (!empty && src_nritems <= 8)
 		return 1;
@@ -2005,8 +2006,8 @@  static int balance_node_right(struct btrfs_trans_handle *trans,
 	int dst_nritems;
 	int ret = 0;
 
-	WARN_ON(btrfs_header_generation(src) != trans->transid);
-	WARN_ON(btrfs_header_generation(dst) != trans->transid);
+	WARN_ON(btrfs_header_generation(src) < trans->transaction->transid);
+	WARN_ON(btrfs_header_generation(dst) < trans->transaction->transid);
 
 	src_nritems = btrfs_header_nritems(src);
 	dst_nritems = btrfs_header_nritems(dst);
@@ -2097,7 +2098,7 @@  static noinline int insert_new_root(struct btrfs_trans_handle *trans,
 	btrfs_set_node_key(c, &lower_key, 0);
 	btrfs_set_node_blockptr(c, 0, lower->start);
 	lower_gen = btrfs_header_generation(lower);
-	WARN_ON(lower_gen != trans->transid);
+	WARN_ON(lower_gen < trans->transaction->transid);
 
 	btrfs_set_node_ptr_generation(c, 0, lower_gen);
 
@@ -2177,7 +2178,7 @@  static noinline int split_node(struct btrfs_trans_handle *trans,
 	u32 c_nritems;
 
 	c = path->nodes[level];
-	WARN_ON(btrfs_header_generation(c) != trans->transid);
+	WARN_ON(btrfs_header_generation(c) < trans->transaction->transid);
 	if (c == root->node) {
 		/* trying to split the root, lets make a new one */
 		ret = insert_new_root(trans, root, path, level + 1);
@@ -3751,7 +3752,7 @@  static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
 {
 	int ret;
 
-	WARN_ON(btrfs_header_generation(leaf) != trans->transid);
+	WARN_ON(btrfs_header_generation(leaf) < trans->transaction->transid);
 	ret = del_ptr(trans, root, path, 1, path->slots[1]);
 	if (ret)
 		return ret;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index a6263bd..310f586 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -925,6 +925,7 @@  struct btrfs_fs_info {
 	struct mutex durable_block_rsv_mutex;
 
 	u64 generation;
+	u64 sub_generation;
 	u64 last_trans_committed;
 
 	/*
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 94ecac3..50e74b1 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1035,7 +1035,7 @@  int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		     struct extent_buffer *buf)
 {
 	struct inode *btree_inode = root->fs_info->btree_inode;
-	if (btrfs_header_generation(buf) ==
+	if (btrfs_header_generation(buf) >=
 	    root->fs_info->running_transaction->transid) {
 		btrfs_assert_tree_locked(buf);
 
@@ -1559,7 +1559,7 @@  static int transaction_kthread(void *arg)
 
 		trans = btrfs_join_transaction(root);
 		BUG_ON(IS_ERR(trans));
-		if (transid == trans->transid) {
+		if (transid == trans->transaction->transid) {
 			ret = btrfs_commit_transaction(trans, root);
 			BUG_ON(ret);
 		} else {
@@ -2001,6 +2001,7 @@  struct btrfs_root *open_ctree(struct super_block *sb,
 	csum_root->track_dirty = 1;
 
 	fs_info->generation = generation;
+	fs_info->sub_generation = generation;
 	fs_info->last_trans_committed = generation;
 	fs_info->data_alloc_profile = (u64)-1;
 	fs_info->metadata_alloc_profile = (u64)-1;
@@ -2671,7 +2672,7 @@  void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
 	int was_dirty;
 
 	btrfs_assert_tree_locked(buf);
-	if (transid != root->fs_info->generation) {
+	if (transid < root->fs_info->generation) {
 		printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
 		       "found %llu running %llu\n",
 			(unsigned long long)buf->start,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 66bac22..fa101ab 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4363,7 +4363,7 @@  int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 	list_for_each_entry_safe(block_rsv, next_rsv,
 				 &fs_info->durable_block_rsv_list, list) {
 
-		idx = trans->transid & 0x1;
+		idx = trans->transaction->transid & 0x1;
 		if (block_rsv->freed[idx] > 0) {
 			block_rsv_add_bytes(block_rsv,
 					    block_rsv->freed[idx], 0);
@@ -4680,7 +4680,7 @@  void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
 	if (block_rsv->space_info != cache->space_info)
 		goto out;
 
-	if (btrfs_header_generation(buf) == trans->transid) {
+	if (btrfs_header_generation(buf) >= trans->transaction->transid) {
 		if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
 			ret = check_ref_cleanup(trans, root, buf->start);
 			if (!ret)
@@ -4730,7 +4730,8 @@  pin:
 
 		if (ret) {
 			spin_lock(&block_rsv->lock);
-			block_rsv->freed[trans->transid & 0x1] += buf->len;
+			block_rsv->freed[trans->transaction->transid & 0x1] +=
+								       buf->len;
 			spin_unlock(&block_rsv->lock);
 		}
 	}
@@ -6164,7 +6165,8 @@  static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
 		}
 		/* make block locked assertion in clean_tree_block happy */
 		if (!path->locks[level] &&
-		    btrfs_header_generation(eb) == trans->transid) {
+		    btrfs_header_generation(eb) >=
+						 trans->transaction->transid) {
 			btrfs_tree_lock(eb);
 			btrfs_set_lock_blocking(eb);
 			path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 34195f9..99eb0b3 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2106,7 +2106,7 @@  void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans,
 	 * space than it frees. So we should make sure there is enough
 	 * reserved space.
 	 */
-	index = trans->transid & 0x1;
+	index = trans->transaction->transid & 0x1;
 	if (block_rsv->reserved + block_rsv->freed[index] < block_rsv->size) {
 		num_bytes += block_rsv->size -
 			     (block_rsv->reserved + block_rsv->freed[index]);
@@ -2130,7 +2130,7 @@  void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans,
 
 	/* refill source subvolume's orphan block reservation */
 	block_rsv = root->orphan_block_rsv;
-	index = trans->transid & 0x1;
+	index = trans->transaction->transid & 0x1;
 	if (block_rsv->reserved + block_rsv->freed[index] < block_rsv->size) {
 		num_bytes = block_rsv->size -
 			    (block_rsv->reserved + block_rsv->freed[index]);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 2bb0886..bc9a2ad 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2758,7 +2758,7 @@  static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp
 	trans = btrfs_start_transaction(root, 0);
 	if (IS_ERR(trans))
 		return PTR_ERR(trans);
-	transid = trans->transid;
+	transid = trans->transaction->transid;
 	ret = btrfs_commit_transaction_async(trans, root, 0);
 	if (ret) {
 		btrfs_end_transaction(trans, root);
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 59bb176..3063be1 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -469,7 +469,7 @@  static int update_backref_cache(struct btrfs_trans_handle *trans,
 		return 0;
 	}
 
-	if (cache->last_trans == trans->transid)
+	if (cache->last_trans >= trans->transaction->transid)
 		return 0;
 
 	/*
@@ -1281,7 +1281,7 @@  static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
 		BUG_ON(ret);
 
 		btrfs_set_root_last_snapshot(&root->root_item,
-					     trans->transid - 1);
+					     trans->transaction->transid - 1);
 	} else {
 		/*
 		 * called by btrfs_reloc_post_snapshot_hook.
@@ -2271,7 +2271,7 @@  static int record_reloc_root_in_trans(struct btrfs_trans_handle *trans,
 {
 	struct btrfs_root *root;
 
-	if (reloc_root->last_trans == trans->transid)
+	if (reloc_root->last_trans >= trans->transaction->transid)
 		return 0;
 
 	root = read_fs_root(reloc_root->fs_info, reloc_root->root_key.offset);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 7dc36fa..531b0dc 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -113,7 +113,9 @@  static noinline int join_transaction(struct btrfs_root *root, int nofail)
 	extent_io_tree_init(&cur_trans->dirty_pages,
 			     root->fs_info->btree_inode->i_mapping);
 	root->fs_info->generation++;
+	root->fs_info->sub_generation = root->fs_info->generation;
 	cur_trans->transid = root->fs_info->generation;
+	cur_trans->sub_transid = cur_trans->transid;
 	root->fs_info->running_transaction = cur_trans;
 	spin_unlock(&root->fs_info->trans_lock);
 
@@ -129,7 +131,7 @@  static noinline int join_transaction(struct btrfs_root *root, int nofail)
 static int record_root_in_trans(struct btrfs_trans_handle *trans,
 			       struct btrfs_root *root)
 {
-	if (root->ref_cows && root->last_trans < trans->transid) {
+	if (root->ref_cows && root->last_trans < trans->transaction->transid) {
 		WARN_ON(root == root->fs_info->extent_root);
 		WARN_ON(root->commit_root != root->node);
 
@@ -146,7 +148,7 @@  static int record_root_in_trans(struct btrfs_trans_handle *trans,
 		smp_wmb();
 
 		spin_lock(&root->fs_info->fs_roots_radix_lock);
-		if (root->last_trans == trans->transid) {
+		if (root->last_trans >= trans->transaction->transid) {
 			spin_unlock(&root->fs_info->fs_roots_radix_lock);
 			return 0;
 		}
@@ -194,7 +196,7 @@  int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
 	 * and barriers
 	 */
 	smp_rmb();
-	if (root->last_trans == trans->transid &&
+	if (root->last_trans >= trans->transaction->transid &&
 	    !root->in_trans_setup)
 		return 0;
 
@@ -302,7 +304,7 @@  again:
 
 	cur_trans = root->fs_info->running_transaction;
 
-	h->transid = cur_trans->transid;
+	h->transid = cur_trans->sub_transid;
 	h->transaction = cur_trans;
 	h->blocks_used = 0;
 	h->bytes_reserved = 0;
@@ -1346,6 +1348,7 @@  int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
 	trans->transaction->blocked = 0;
 	spin_lock(&root->fs_info->trans_lock);
+	root->fs_info->generation = cur_trans->sub_transid;
 	root->fs_info->running_transaction = NULL;
 	root->fs_info->trans_no_join = 0;
 	spin_unlock(&root->fs_info->trans_lock);
@@ -1367,7 +1370,7 @@  int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
 	cur_trans->commit_done = 1;
 
-	root->fs_info->last_trans_committed = cur_trans->transid;
+	root->fs_info->last_trans_committed = cur_trans->sub_transid;
 
 	wake_up(&cur_trans->commit_wait);
 
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 02564e6..45876b0 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -23,6 +23,7 @@ 
 
 struct btrfs_transaction {
 	u64 transid;
+	u64 sub_transid;
 	/*
 	 * total writers in this transaction, it must be zero before the
 	 * transaction can end
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 3b580ee..a2569af 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -139,7 +139,7 @@  done:
 	if (ret != -EAGAIN) {
 		memset(&root->defrag_progress, 0,
 		       sizeof(root->defrag_progress));
-		root->defrag_trans_start = trans->transid;
+		root->defrag_trans_start = trans->transaction->transid;
 	}
 	return ret;
 }
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index f320641..5a026d2 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -134,9 +134,19 @@  static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
 static int start_log_trans(struct btrfs_trans_handle *trans,
 			   struct btrfs_root *root)
 {
+	struct btrfs_transaction *cur_trans;
 	int ret;
 	int err = 0;
 
+	/* start a new sub transaction */
+	spin_lock(&root->fs_info->trans_lock);
+
+	cur_trans = root->fs_info->running_transaction;
+	cur_trans->sub_transid++;
+	root->fs_info->sub_generation = cur_trans->sub_transid;
+
+	spin_unlock(&root->fs_info->trans_lock);
+
 	mutex_lock(&root->log_mutex);
 	if (root->log_root) {
 		if (!root->log_start_pid) {
@@ -2007,7 +2017,8 @@  int btrfs_sync_log(struct btrfs_trans_handle *trans,
 	}
 
 	/* bail out if we need to do a full commit */
-	if (root->fs_info->last_trans_log_full_commit == trans->transid) {
+	if (root->fs_info->last_trans_log_full_commit >=
+						trans->transaction->transid) {
 		ret = -EAGAIN;
 		mutex_unlock(&root->log_mutex);
 		goto out;
@@ -2084,7 +2095,8 @@  int btrfs_sync_log(struct btrfs_trans_handle *trans,
 	 * now that we've moved on to the tree of log tree roots,
 	 * check the full commit flag again
 	 */
-	if (root->fs_info->last_trans_log_full_commit == trans->transid) {
+	if (root->fs_info->last_trans_log_full_commit >=
+						trans->transaction->transid) {
 		btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 		mutex_unlock(&log_root_tree->log_mutex);
 		ret = -EAGAIN;