aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 76c4f9d1b80a..66f87156882f 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4117,6 +4117,86 @@ static int logged_inode_size(struct btrfs_root *log, struct inode *inode,
4117 return 0; 4117 return 0;
4118} 4118}
4119 4119
4120/*
4121 * At the moment we always log all xattrs. This is to figure out at log replay
4122 * time which xattrs must have their deletion replayed. If a xattr is missing
4123 * in the log tree and exists in the fs/subvol tree, we delete it. This is
4124 * because if a xattr is deleted, the inode is fsynced and a power failure
4125 * happens, causing the log to be replayed the next time the fs is mounted,
4126 * we want the xattr to not exist anymore (same behaviour as other filesystems
4127 * with a journal, ext3/4, xfs, f2fs, etc).
4128 */
4129static int btrfs_log_all_xattrs(struct btrfs_trans_handle *trans,
4130 struct btrfs_root *root,
4131 struct inode *inode,
4132 struct btrfs_path *path,
4133 struct btrfs_path *dst_path)
4134{
4135 int ret;
4136 struct btrfs_key key;
4137 const u64 ino = btrfs_ino(inode);
4138 int ins_nr = 0;
4139 int start_slot = 0;
4140
4141 key.objectid = ino;
4142 key.type = BTRFS_XATTR_ITEM_KEY;
4143 key.offset = 0;
4144
4145 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
4146 if (ret < 0)
4147 return ret;
4148
4149 while (true) {
4150 int slot = path->slots[0];
4151 struct extent_buffer *leaf = path->nodes[0];
4152 int nritems = btrfs_header_nritems(leaf);
4153
4154 if (slot >= nritems) {
4155 if (ins_nr > 0) {
4156 u64 last_extent = 0;
4157
4158 ret = copy_items(trans, inode, dst_path, path,
4159 &last_extent, start_slot,
4160 ins_nr, 1, 0);
4161 /* can't be 1, extent items aren't processed */
4162 ASSERT(ret <= 0);
4163 if (ret < 0)
4164 return ret;
4165 ins_nr = 0;
4166 }
4167 ret = btrfs_next_leaf(root, path);
4168 if (ret < 0)
4169 return ret;
4170 else if (ret > 0)
4171 break;
4172 continue;
4173 }
4174
4175 btrfs_item_key_to_cpu(leaf, &key, slot);
4176 if (key.objectid != ino || key.type != BTRFS_XATTR_ITEM_KEY)
4177 break;
4178
4179 if (ins_nr == 0)
4180 start_slot = slot;
4181 ins_nr++;
4182 path->slots[0]++;
4183 cond_resched();
4184 }
4185 if (ins_nr > 0) {
4186 u64 last_extent = 0;
4187
4188 ret = copy_items(trans, inode, dst_path, path,
4189 &last_extent, start_slot,
4190 ins_nr, 1, 0);
4191 /* can't be 1, extent items aren't processed */
4192 ASSERT(ret <= 0);
4193 if (ret < 0)
4194 return ret;
4195 }
4196
4197 return 0;
4198}
4199
4120/* log a single inode in the tree log. 4200/* log a single inode in the tree log.
4121 * At least one parent directory for this inode must exist in the tree 4201 * At least one parent directory for this inode must exist in the tree
4122 * or be logged already. 4202 * or be logged already.
@@ -4289,6 +4369,25 @@ again:
4289 if (min_key.type == BTRFS_INODE_ITEM_KEY) 4369 if (min_key.type == BTRFS_INODE_ITEM_KEY)
4290 need_log_inode_item = false; 4370 need_log_inode_item = false;
4291 4371
4372 /* Skip xattrs, we log them later with btrfs_log_all_xattrs() */
4373 if (min_key.type == BTRFS_XATTR_ITEM_KEY) {
4374 if (ins_nr == 0)
4375 goto next_slot;
4376 ret = copy_items(trans, inode, dst_path, path,
4377 &last_extent, ins_start_slot,
4378 ins_nr, inode_only, logged_isize);
4379 if (ret < 0) {
4380 err = ret;
4381 goto out_unlock;
4382 }
4383 ins_nr = 0;
4384 if (ret) {
4385 btrfs_release_path(path);
4386 continue;
4387 }
4388 goto next_slot;
4389 }
4390
4292 src = path->nodes[0]; 4391 src = path->nodes[0];
4293 if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) { 4392 if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) {
4294 ins_nr++; 4393 ins_nr++;
@@ -4356,6 +4455,11 @@ next_slot:
4356 ins_nr = 0; 4455 ins_nr = 0;
4357 } 4456 }
4358 4457
4458 btrfs_release_path(path);
4459 btrfs_release_path(dst_path);
4460 err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path);
4461 if (err)
4462 goto out_unlock;
4359log_extents: 4463log_extents:
4360 btrfs_release_path(path); 4464 btrfs_release_path(path);
4361 btrfs_release_path(dst_path); 4465 btrfs_release_path(dst_path);