#include "locking.h"
#include "print-tree.h"
#include "compat.h"
+#include "tree-log.h"
/* magic values for the inode_only field in btrfs_log_inode:
*
static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode,
int inode_only);
+static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct btrfs_path *path, u64 objectid);
/*
* tree logging is a special write ahead log used to make sure that
* tree of log tree roots. This must be called with a tree log transaction
* running (see start_log_trans).
*/
-int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
+static int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
struct btrfs_key key;
int ret;
u64 objectid = root->root_key.objectid;
- leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
+ leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
BTRFS_TREE_LOG_OBJECTID,
- 0, 0, 0, 0, 0);
+ trans->transid, 0, 0, 0);
if (IS_ERR(leaf)) {
ret = PTR_ERR(leaf);
return ret;
inode_item->generation = cpu_to_le64(1);
inode_item->size = cpu_to_le64(3);
inode_item->nlink = cpu_to_le32(1);
- inode_item->nblocks = cpu_to_le64(1);
+ inode_item->nbytes = cpu_to_le64(root->leafsize);
inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
btrfs_set_root_bytenr(&root_item, leaf->start);
+ btrfs_set_root_generation(&root_item, trans->transid);
btrfs_set_root_level(&root_item, 0);
btrfs_set_root_refs(&root_item, 0);
btrfs_set_root_used(&root_item, 0);
*/
new_root->ref_cows = 0;
new_root->last_trans = trans->transid;
+
+ /*
+ * we need to make sure the root block for this new tree
+ * is marked as dirty in the dirty_log_pages tree. This
+ * is how it gets flushed down to disk at tree log commit time.
+ *
+ * the tree logging mutex keeps others from coming in and changing
+ * the new_root->node, so we can safely access it here
+ */
+ set_extent_dirty(&new_root->dirty_log_pages, new_root->node->start,
+ new_root->node->start + new_root->node->len - 1,
+ GFP_NOFS);
+
fail:
return ret;
}
struct walk_control *wc, u64 gen)
{
if (wc->pin) {
- mutex_lock(&log->fs_info->alloc_mutex);
+ mutex_lock(&log->fs_info->pinned_mutex);
btrfs_update_pinned_extents(log->fs_info->extent_root,
eb->start, eb->len, 1);
- mutex_unlock(&log->fs_info->alloc_mutex);
+ mutex_unlock(&log->fs_info->pinned_mutex);
}
if (btrfs_buffer_uptodate(eb, gen)) {
if (found_size > item_size) {
btrfs_truncate_item(trans, root, path, item_size, 1);
} else if (found_size < item_size) {
- ret = btrfs_del_item(trans, root,
- path);
- BUG_ON(ret);
-
- btrfs_release_path(root, path);
- ret = btrfs_insert_empty_item(trans,
- root, path, key, item_size);
+ ret = btrfs_extend_item(trans, root, path,
+ item_size - found_size);
BUG_ON(ret);
}
} else if (ret) {
u64 extent_end;
u64 alloc_hint;
u64 start = key->offset;
+ u64 saved_nbytes;
struct btrfs_file_extent_item *item;
struct inode *inode = NULL;
unsigned long size;
item = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
found_type = btrfs_file_extent_type(eb, item);
- if (found_type == BTRFS_FILE_EXTENT_REG)
+ if (found_type == BTRFS_FILE_EXTENT_REG ||
+ found_type == BTRFS_FILE_EXTENT_PREALLOC)
extent_end = start + btrfs_file_extent_num_bytes(eb, item);
else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
- size = btrfs_file_extent_inline_len(eb,
- btrfs_item_nr(eb, slot));
+ size = btrfs_file_extent_inline_len(eb, item);
extent_end = (start + size + mask) & ~mask;
} else {
ret = 0;
ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
start, 0);
- if (ret == 0 && found_type == BTRFS_FILE_EXTENT_REG) {
+ if (ret == 0 &&
+ (found_type == BTRFS_FILE_EXTENT_REG ||
+ found_type == BTRFS_FILE_EXTENT_PREALLOC)) {
struct btrfs_file_extent_item cmp1;
struct btrfs_file_extent_item cmp2;
struct btrfs_file_extent_item *existing;
}
btrfs_release_path(root, path);
+ saved_nbytes = inode_get_bytes(inode);
/* drop any overlapping extents */
ret = btrfs_drop_extents(trans, root, inode,
start, extent_end, start, &alloc_hint);
BUG_ON(ret);
- BUG_ON(ret);
- if (found_type == BTRFS_FILE_EXTENT_REG) {
+ if (found_type == BTRFS_FILE_EXTENT_REG ||
+ found_type == BTRFS_FILE_EXTENT_PREALLOC) {
+ unsigned long dest_offset;
struct btrfs_key ins;
+ ret = btrfs_insert_empty_item(trans, root, path, key,
+ sizeof(*item));
+ BUG_ON(ret);
+ dest_offset = btrfs_item_ptr_offset(path->nodes[0],
+ path->slots[0]);
+ copy_extent_buffer(path->nodes[0], eb, dest_offset,
+ (unsigned long)item, sizeof(*item));
+
ins.objectid = btrfs_file_extent_disk_bytenr(eb, item);
ins.offset = btrfs_file_extent_disk_num_bytes(eb, item);
ins.type = BTRFS_EXTENT_ITEM_KEY;
- /* insert the extent pointer in the file */
- ret = overwrite_item(trans, root, path, eb, slot, key);
- BUG_ON(ret);
-
- /*
- * is this extent already allocated in the extent
- * allocation tree? If so, just add a reference
- */
- ret = btrfs_lookup_extent(root, path, ins.objectid, ins.offset);
- btrfs_release_path(root, path);
- if (ret == 0) {
- ret = btrfs_inc_extent_ref(trans, root,
- ins.objectid, ins.offset,
- root->root_key.objectid,
- trans->transid, key->objectid, start);
- } else {
+ if (ins.objectid > 0) {
+ u64 csum_start;
+ u64 csum_end;
+ LIST_HEAD(ordered_sums);
/*
- * insert the extent pointer in the extent
- * allocation tree
+ * is this extent already allocated in the extent
+ * allocation tree? If so, just add a reference
*/
- ret = btrfs_alloc_logged_extent(trans, root,
+ ret = btrfs_lookup_extent(root, ins.objectid,
+ ins.offset);
+ if (ret == 0) {
+ ret = btrfs_inc_extent_ref(trans, root,
+ ins.objectid, ins.offset,
+ path->nodes[0]->start,
+ root->root_key.objectid,
+ trans->transid, key->objectid);
+ } else {
+ /*
+ * insert the extent pointer in the extent
+ * allocation tree
+ */
+ ret = btrfs_alloc_logged_extent(trans, root,
+ path->nodes[0]->start,
root->root_key.objectid,
trans->transid, key->objectid,
- start, &ins);
+ &ins);
+ BUG_ON(ret);
+ }
+ btrfs_release_path(root, path);
+
+ if (btrfs_file_extent_compression(eb, item)) {
+ csum_start = ins.objectid;
+ csum_end = csum_start + ins.offset;
+ } else {
+ csum_start = ins.objectid +
+ btrfs_file_extent_offset(eb, item);
+ csum_end = csum_start +
+ btrfs_file_extent_num_bytes(eb, item);
+ }
+
+ ret = btrfs_lookup_csums_range(root->log_root,
+ csum_start, csum_end - 1,
+ &ordered_sums);
BUG_ON(ret);
+ while (!list_empty(&ordered_sums)) {
+ struct btrfs_ordered_sum *sums;
+ sums = list_entry(ordered_sums.next,
+ struct btrfs_ordered_sum,
+ list);
+ ret = btrfs_csum_file_blocks(trans,
+ root->fs_info->csum_root,
+ sums);
+ BUG_ON(ret);
+ list_del(&sums->list);
+ kfree(sums);
+ }
+ } else {
+ btrfs_release_path(root, path);
}
} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
/* inline extents are easy, we just overwrite them */
ret = overwrite_item(trans, root, path, eb, slot, key);
BUG_ON(ret);
}
- /* btrfs_drop_extents changes i_blocks, update it here */
- inode->i_blocks += (extent_end - start) >> 9;
+
+ inode_set_bytes(inode, saved_nbytes);
btrfs_update_inode(trans, root, inode);
out:
if (inode)
inode = read_one_inode(root, location.objectid);
BUG_ON(!inode);
- btrfs_inc_nlink(inode);
+ ret = link_to_fixup_dir(trans, root, path, location.objectid);
+ BUG_ON(ret);
ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len);
+ BUG_ON(ret);
kfree(name);
iput(inode);
*/
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
ptr_end = ptr + btrfs_item_size_nr(leaf, path->slots[0]);
- while(ptr < ptr_end) {
+ while (ptr < ptr_end) {
victim_ref = (struct btrfs_inode_ref *)ptr;
victim_name_len = btrfs_inode_ref_name_len(leaf,
victim_ref);
return 0;
}
-/*
- * replay one csum item from the log tree into the subvolume 'root'
- * eb, slot and key all refer to the log tree
- * path is for temp use by this function and should be released on return
- *
- * This copies the checksums out of the log tree and inserts them into
- * the subvolume. Any existing checksums for this range in the file
- * are overwritten, and new items are added where required.
- *
- * We keep this simple by reusing the btrfs_ordered_sum code from
- * the data=ordered mode. This basically means making a copy
- * of all the checksums in ram, which we have to do anyway for kmap
- * rules.
- *
- * The copy is then sent down to btrfs_csum_file_blocks, which
- * does all the hard work of finding existing items in the file
- * or adding new ones.
- */
-static noinline int replay_one_csum(struct btrfs_trans_handle *trans,
- struct btrfs_root *root,
- struct btrfs_path *path,
- struct extent_buffer *eb, int slot,
- struct btrfs_key *key)
-{
- int ret;
- u32 item_size = btrfs_item_size_nr(eb, slot);
- u64 cur_offset;
- unsigned long file_bytes;
- struct btrfs_ordered_sum *sums;
- struct btrfs_sector_sum *sector_sum;
- struct inode *inode;
- unsigned long ptr;
-
- file_bytes = (item_size / BTRFS_CRC32_SIZE) * root->sectorsize;
- inode = read_one_inode(root, key->objectid);
- if (!inode) {
- return -EIO;
- }
-
- sums = kzalloc(btrfs_ordered_sum_size(root, file_bytes), GFP_NOFS);
- if (!sums) {
- iput(inode);
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&sums->list);
- sums->len = file_bytes;
- sums->file_offset = key->offset;
-
- /*
- * copy all the sums into the ordered sum struct
- */
- sector_sum = sums->sums;
- cur_offset = key->offset;
- ptr = btrfs_item_ptr_offset(eb, slot);
- while(item_size > 0) {
- sector_sum->offset = cur_offset;
- read_extent_buffer(eb, §or_sum->sum, ptr, BTRFS_CRC32_SIZE);
- sector_sum++;
- item_size -= BTRFS_CRC32_SIZE;
- ptr += BTRFS_CRC32_SIZE;
- cur_offset += root->sectorsize;
- }
-
- /* let btrfs_csum_file_blocks add them into the file */
- ret = btrfs_csum_file_blocks(trans, root, inode, sums);
- BUG_ON(ret);
- kfree(sums);
- iput(inode);
-
- return 0;
-}
/*
* There are a few corners where the link count of the file can't
* be properly maintained during replay. So, instead of adding
path = btrfs_alloc_path();
- while(1) {
+ while (1) {
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0)
break;
ptr = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]);
ptr_end = ptr + btrfs_item_size_nr(path->nodes[0],
path->slots[0]);
- while(ptr < ptr_end) {
+ while (ptr < ptr_end) {
struct btrfs_inode_ref *ref;
ref = (struct btrfs_inode_ref *)ptr;
key.objectid = BTRFS_TREE_LOG_FIXUP_OBJECTID;
key.type = BTRFS_ORPHAN_ITEM_KEY;
key.offset = (u64)-1;
- while(1) {
+ while (1) {
ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
if (ret < 0)
break;
if (key->type == BTRFS_DIR_ITEM_KEY) {
dst_di = btrfs_lookup_dir_item(trans, root, path, key->objectid,
name, name_len, 1);
- }
- else if (key->type == BTRFS_DIR_INDEX_KEY) {
+ } else if (key->type == BTRFS_DIR_INDEX_KEY) {
dst_di = btrfs_lookup_dir_index_item(trans, root, path,
key->objectid,
key->offset, name,
ptr = btrfs_item_ptr_offset(eb, slot);
ptr_end = ptr + item_size;
- while(ptr < ptr_end) {
+ while (ptr < ptr_end) {
di = (struct btrfs_dir_item *)ptr;
name_len = btrfs_dir_name_len(eb, di);
ret = replay_one_name(trans, root, path, eb, di, key);
item_size = btrfs_item_size_nr(eb, slot);
ptr = btrfs_item_ptr_offset(eb, slot);
ptr_end = ptr + item_size;
- while(ptr < ptr_end) {
+ while (ptr < ptr_end) {
di = (struct btrfs_dir_item *)ptr;
name_len = btrfs_dir_name_len(eb, di);
name = kmalloc(name_len, GFP_NOFS);
again:
range_start = 0;
range_end = 0;
- while(1) {
+ while (1) {
ret = find_dir_range(log, path, dirid, key_type,
&range_start, &range_end);
if (ret != 0)
break;
dir_key.offset = range_start;
- while(1) {
+ while (1) {
int nritems;
ret = btrfs_search_slot(NULL, root, &dir_key, path,
0, 0);
ret = replay_one_extent(wc->trans, root, path,
eb, i, &key);
BUG_ON(ret);
- } else if (key.type == BTRFS_CSUM_ITEM_KEY) {
- ret = replay_one_csum(wc->trans, root, path,
- eb, i, &key);
- BUG_ON(ret);
} else if (key.type == BTRFS_DIR_ITEM_KEY ||
key.type == BTRFS_DIR_INDEX_KEY) {
ret = replay_one_dir_item(wc->trans, root, path,
return 0;
}
-static int noinline walk_down_log_tree(struct btrfs_trans_handle *trans,
+static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path, int *level,
struct walk_control *wc)
WARN_ON(*level < 0);
WARN_ON(*level >= BTRFS_MAX_LEVEL);
- while(*level > 0) {
+ while (*level > 0) {
WARN_ON(*level < 0);
WARN_ON(*level >= BTRFS_MAX_LEVEL);
cur = path->nodes[*level];
WARN_ON(*level < 0);
WARN_ON(*level >= BTRFS_MAX_LEVEL);
- if (path->nodes[*level] == root->node) {
+ if (path->nodes[*level] == root->node)
parent = path->nodes[*level];
- } else {
+ else
parent = path->nodes[*level + 1];
- }
+
bytenr = path->nodes[*level]->start;
blocksize = btrfs_level_size(root, *level);
return 0;
}
-static int noinline walk_up_log_tree(struct btrfs_trans_handle *trans,
+static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path, int *level,
struct walk_control *wc)
int slot;
int ret;
- for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
+ for (i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
slot = path->slots[i];
if (slot < btrfs_header_nritems(path->nodes[i]) - 1) {
struct extent_buffer *node;
WARN_ON(*level == 0);
return 0;
} else {
- if (path->nodes[*level] == root->node) {
- root_owner = root->root_key.objectid;
- root_gen =
- btrfs_header_generation(path->nodes[*level]);
- } else {
- struct extent_buffer *node;
- node = path->nodes[*level + 1];
- root_owner = btrfs_header_owner(node);
- root_gen = btrfs_header_generation(node);
- }
+ struct extent_buffer *parent;
+ if (path->nodes[*level] == root->node)
+ parent = path->nodes[*level];
+ else
+ parent = path->nodes[*level + 1];
+
+ root_owner = btrfs_header_owner(parent);
+ root_gen = btrfs_header_generation(parent);
wc->process_func(root, path->nodes[*level], wc,
btrfs_header_generation(path->nodes[*level]));
if (wc->free) {
extent_buffer_get(log->node);
path->slots[level] = 0;
- while(1) {
+ while (1) {
wret = walk_down_log_tree(trans, log, path, &level, wc);
if (wret > 0)
break;
return ret;
}
-int wait_log_commit(struct btrfs_root *log)
+static int wait_log_commit(struct btrfs_root *log)
{
DEFINE_WAIT(wait);
u64 transid = log->fs_info->tree_log_transid;
schedule();
finish_wait(&log->fs_info->tree_log_wait, &wait);
mutex_lock(&log->fs_info->tree_log_mutex);
- } while(transid == log->fs_info->tree_log_transid &&
+ } while (transid == log->fs_info->tree_log_transid &&
atomic_read(&log->fs_info->tree_log_commit));
return 0;
}
int ret;
unsigned long batch;
struct btrfs_root *log = root->log_root;
- struct walk_control wc = {
- .write = 1,
- .process_func = process_one_buffer
- };
mutex_lock(&log->fs_info->tree_log_mutex);
if (atomic_read(&log->fs_info->tree_log_commit)) {
}
atomic_set(&log->fs_info->tree_log_commit, 1);
- while(1) {
+ while (1) {
batch = log->fs_info->tree_log_batch;
mutex_unlock(&log->fs_info->tree_log_mutex);
schedule_timeout_uninterruptible(1);
mutex_lock(&log->fs_info->tree_log_mutex);
- while(atomic_read(&log->fs_info->tree_log_writers)) {
+ while (atomic_read(&log->fs_info->tree_log_writers)) {
DEFINE_WAIT(wait);
prepare_to_wait(&log->fs_info->tree_log_wait, &wait,
TASK_UNINTERRUPTIBLE);
if (batch == log->fs_info->tree_log_batch)
break;
}
- ret = walk_log_tree(trans, log, &wc);
- BUG_ON(ret);
-
- ret = walk_log_tree(trans, log->fs_info->log_root_tree, &wc);
- BUG_ON(ret);
- wc.wait = 1;
-
- ret = walk_log_tree(trans, log, &wc);
+ ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages);
BUG_ON(ret);
-
- ret = walk_log_tree(trans, log->fs_info->log_root_tree, &wc);
+ ret = btrfs_write_and_wait_marked_extents(root->fs_info->log_root_tree,
+ &root->fs_info->log_root_tree->dirty_log_pages);
BUG_ON(ret);
btrfs_set_super_log_root(&root->fs_info->super_for_commit,
btrfs_set_super_log_root_level(&root->fs_info->super_for_commit,
btrfs_header_level(log->fs_info->log_root_tree->node));
- write_ctree_super(trans, log->fs_info->tree_root);
+ write_ctree_super(trans, log->fs_info->tree_root, 2);
log->fs_info->tree_log_transid++;
log->fs_info->tree_log_batch = 0;
atomic_set(&log->fs_info->tree_log_commit, 0);
out:
mutex_unlock(&log->fs_info->tree_log_mutex);
return 0;
-
}
/* * free all the extents used by the tree log. This should be called
int ret;
struct btrfs_root *log;
struct key;
+ u64 start;
+ u64 end;
struct walk_control wc = {
.free = 1,
.process_func = process_one_buffer
};
- if (!root->log_root)
+ if (!root->log_root || root->fs_info->log_root_recovering)
return 0;
log = root->log_root;
ret = walk_log_tree(trans, log, &wc);
BUG_ON(ret);
+ while (1) {
+ ret = find_first_extent_bit(&log->dirty_log_pages,
+ 0, &start, &end, EXTENT_DIRTY);
+ if (ret)
+ break;
+
+ clear_extent_dirty(&log->dirty_log_pages,
+ start, end, GFP_NOFS);
+ }
+
log = root->log_root;
ret = btrfs_del_root(trans, root->fs_info->log_root_tree,
&log->root_key);
return 0;
btrfs_set_root_bytenr(&log->root_item, log->node->start);
+ btrfs_set_root_generation(&log->root_item, trans->transid);
btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node));
ret = btrfs_update_root(trans, log->fs_info->log_root_tree,
&log->root_key, &log->root_item);
struct btrfs_key tmp;
btrfs_item_key_to_cpu(path->nodes[0], &tmp,
path->slots[0]);
- if (key_type == tmp.type) {
+ if (key_type == tmp.type)
first_offset = max(min_offset, tmp.offset) + 1;
- }
}
goto done;
}
* we have a block from this transaction, log every item in it
* from our directory
*/
- while(1) {
+ while (1) {
struct btrfs_key tmp;
src = path->nodes[0];
nritems = btrfs_header_nritems(src);
again:
min_key = 0;
max_key = 0;
- while(1) {
+ while (1) {
ret = log_dir_items(trans, root, inode, path,
dst_path, key_type, min_key,
&max_key);
key.type = max_key_type;
key.offset = (u64)-1;
- while(1) {
+ while (1) {
ret = btrfs_search_slot(trans, log, &key, path, -1, 1);
if (ret != 1)
u32 *ins_sizes;
char *ins_data;
int i;
+ struct list_head ordered_sums;
+
+ INIT_LIST_HEAD(&ordered_sums);
ins_data = kmalloc(nr * sizeof(struct btrfs_key) +
nr * sizeof(u32), GFP_NOFS);
struct btrfs_file_extent_item);
found_type = btrfs_file_extent_type(src, extent);
- if (found_type == BTRFS_FILE_EXTENT_REG) {
+ if (found_type == BTRFS_FILE_EXTENT_REG ||
+ found_type == BTRFS_FILE_EXTENT_PREALLOC) {
u64 ds = btrfs_file_extent_disk_bytenr(src,
extent);
u64 dl = btrfs_file_extent_disk_num_bytes(src,
extent);
+ u64 cs = btrfs_file_extent_offset(src, extent);
+ u64 cl = btrfs_file_extent_num_bytes(src,
+ extent);;
+ if (btrfs_file_extent_compression(src,
+ extent)) {
+ cs = 0;
+ cl = dl;
+ }
/* ds == 0 is a hole */
if (ds != 0) {
ret = btrfs_inc_extent_ref(trans, log,
ds, dl,
+ dst_path->nodes[0]->start,
BTRFS_TREE_LOG_OBJECTID,
- 0, ins_keys[i].objectid,
- ins_keys[i].offset);
+ trans->transid,
+ ins_keys[i].objectid);
+ BUG_ON(ret);
+ ret = btrfs_lookup_csums_range(
+ log->fs_info->csum_root,
+ ds + cs, ds + cs + cl - 1,
+ &ordered_sums);
BUG_ON(ret);
}
}
btrfs_mark_buffer_dirty(dst_path->nodes[0]);
btrfs_release_path(log, dst_path);
kfree(ins_data);
+
+ /*
+ * we have to do this after the loop above to avoid changing the
+ * log tree while trying to change the log tree.
+ */
+ while (!list_empty(&ordered_sums)) {
+ struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next,
+ struct btrfs_ordered_sum,
+ list);
+ ret = btrfs_csum_file_blocks(trans, log, sums);
+ BUG_ON(ret);
+ list_del(&sums->list);
+ kfree(sums);
+ }
return 0;
}
BUG_ON(ret);
path->keep_locks = 1;
- while(1) {
+ while (1) {
ins_nr = 0;
ret = btrfs_search_forward(root, &min_key, &max_key,
path, 0, trans->transid);
ins_nr = 0;
}
WARN_ON(ins_nr);
- if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode) &&
- BTRFS_I(inode)->log_dirty_trans >= trans->transid) {
+ if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
btrfs_release_path(root, path);
btrfs_release_path(log, dst_path);
BTRFS_I(inode)->log_dirty_trans = 0;
start_log_trans(trans, root);
sb = dentry->d_inode->i_sb;
- while(1) {
+ while (1) {
ret = __btrfs_log_inode(trans, root, dentry->d_inode,
inode_only);
BUG_ON(ret);
key.offset = (u64)-1;
btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
- while(1) {
+ while (1) {
ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0);
if (ret < 0)
break;
tmp_key.offset = (u64)-1;
wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key);
-
BUG_ON(!wc.replay_dest);
+ wc.replay_dest->log_root = log;
btrfs_record_root_in_trans(wc.replay_dest);
ret = walk_log_tree(trans, log, &wc);
BUG_ON(ret);
}
key.offset = found_key.offset - 1;
+ wc.replay_dest->log_root = NULL;
free_extent_buffer(log->node);
kfree(log);