static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, int num_blocks, int wait) { struct btrfs_trans_handle *h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); int ret; mutex_lock(&root->fs_info->trans_mutex); if (!root->fs_info->log_root_recovering && ((wait == 1 && !root->fs_info->open_ioctl_trans) || wait == 2)) wait_current_trans(root); ret = join_transaction(root); BUG_ON(ret); h->transid = root->fs_info->running_transaction->transid; h->transaction = root->fs_info->running_transaction; h->blocks_reserved = num_blocks; h->blocks_used = 0; h->block_group = 0; h->alloc_exclude_nr = 0; h->alloc_exclude_start = 0; h->delayed_ref_updates = 0; if (!current->journal_info) current->journal_info = h; root->fs_info->running_transaction->use_count++; record_root_in_trans(h, root); mutex_unlock(&root->fs_info->trans_mutex); return h; }
static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, u64 num_items, int type) { struct btrfs_trans_handle *h; struct btrfs_transaction *cur_trans; int retries = 0; int ret; again: h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); if (!h) return ERR_PTR(-ENOMEM); mutex_lock(&root->fs_info->trans_mutex); if (may_wait_transaction(root, type)) wait_current_trans(root); ret = join_transaction(root); BUG_ON(ret); cur_trans = root->fs_info->running_transaction; cur_trans->use_count++; mutex_unlock(&root->fs_info->trans_mutex); h->transid = cur_trans->transid; h->transaction = cur_trans; h->blocks_used = 0; h->block_group = 0; h->bytes_reserved = 0; h->delayed_ref_updates = 0; h->block_rsv = NULL; smp_mb(); if (cur_trans->blocked && may_wait_transaction(root, type)) { btrfs_commit_transaction(h, root); goto again; } if (num_items > 0) { ret = btrfs_trans_reserve_metadata(h, root, num_items, &retries); if (ret == -EAGAIN) { btrfs_commit_transaction(h, root); goto again; } if (ret < 0) { btrfs_end_transaction(h, root); return ERR_PTR(ret); } } mutex_lock(&root->fs_info->trans_mutex); record_root_in_trans(h, root); mutex_unlock(&root->fs_info->trans_mutex); if (!current->journal_info && type != TRANS_USERSPACE) current->journal_info = h; return h; }