aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2011-12-02 08:56:41 -0500
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-01-05 04:49:43 -0500
commit4692cf58aa7b81f721c1653d48db99ea41421d58 (patch)
tree0a5bf889142252d91bcc8df33a9c63c18024fe70 /fs/btrfs
parent8da6d5815c592b713ecaf4f4f8b631f8359c96c4 (diff)
Btrfs: new backref walking code
The old backref iteration code could only safely be used on commit roots. Besides this limitation, it had bugs in finding the roots for these references. This commit replaces large parts of it by btrfs_find_all_roots() which a) really finds all roots and the correct roots, b) works correctly under heavy file system load, c) considers delayed refs. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/backref.c354
-rw-r--r--fs/btrfs/ioctl.c8
-rw-r--r--fs/btrfs/scrub.c7
3 files changed, 107 insertions, 262 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 03c30a1836f4..b9a843226de8 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -23,18 +23,6 @@
23#include "transaction.h" 23#include "transaction.h"
24#include "delayed-ref.h" 24#include "delayed-ref.h"
25 25
26struct __data_ref {
27 struct list_head list;
28 u64 inum;
29 u64 root;
30 u64 extent_data_item_offset;
31};
32
33struct __shared_ref {
34 struct list_head list;
35 u64 disk_byte;
36};
37
38/* 26/*
39 * this structure records all encountered refs on the way up to the root 27 * this structure records all encountered refs on the way up to the root
40 */ 28 */
@@ -964,8 +952,11 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
964 btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]); 952 btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]);
965 if (found_key->type != BTRFS_EXTENT_ITEM_KEY || 953 if (found_key->type != BTRFS_EXTENT_ITEM_KEY ||
966 found_key->objectid > logical || 954 found_key->objectid > logical ||
967 found_key->objectid + found_key->offset <= logical) 955 found_key->objectid + found_key->offset <= logical) {
956 pr_debug("logical %llu is not within any extent\n",
957 (unsigned long long)logical);
968 return -ENOENT; 958 return -ENOENT;
959 }
969 960
970 eb = path->nodes[0]; 961 eb = path->nodes[0];
971 item_size = btrfs_item_size_nr(eb, path->slots[0]); 962 item_size = btrfs_item_size_nr(eb, path->slots[0]);
@@ -974,6 +965,13 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
974 ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item); 965 ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
975 flags = btrfs_extent_flags(eb, ei); 966 flags = btrfs_extent_flags(eb, ei);
976 967
968 pr_debug("logical %llu is at position %llu within the extent (%llu "
969 "EXTENT_ITEM %llu) flags %#llx size %u\n",
970 (unsigned long long)logical,
971 (unsigned long long)(logical - found_key->objectid),
972 (unsigned long long)found_key->objectid,
973 (unsigned long long)found_key->offset,
974 (unsigned long long)flags, item_size);
977 if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) 975 if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
978 return BTRFS_EXTENT_FLAG_TREE_BLOCK; 976 return BTRFS_EXTENT_FLAG_TREE_BLOCK;
979 if (flags & BTRFS_EXTENT_FLAG_DATA) 977 if (flags & BTRFS_EXTENT_FLAG_DATA)
@@ -1070,128 +1068,11 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb,
1070 return 0; 1068 return 0;
1071} 1069}
1072 1070
1073static int __data_list_add(struct list_head *head, u64 inum, 1071static int iterate_leaf_refs(struct btrfs_fs_info *fs_info,
1074 u64 extent_data_item_offset, u64 root) 1072 struct btrfs_path *path, u64 logical,
1075{ 1073 u64 orig_extent_item_objectid,
1076 struct __data_ref *ref; 1074 u64 extent_item_pos, u64 root,
1077 1075 iterate_extent_inodes_t *iterate, void *ctx)
1078 ref = kmalloc(sizeof(*ref), GFP_NOFS);
1079 if (!ref)
1080 return -ENOMEM;
1081
1082 ref->inum = inum;
1083 ref->extent_data_item_offset = extent_data_item_offset;
1084 ref->root = root;
1085 list_add_tail(&ref->list, head);
1086
1087 return 0;
1088}
1089
1090static int __data_list_add_eb(struct list_head *head, struct extent_buffer *eb,
1091 struct btrfs_extent_data_ref *dref)
1092{
1093 return __data_list_add(head, btrfs_extent_data_ref_objectid(eb, dref),
1094 btrfs_extent_data_ref_offset(eb, dref),
1095 btrfs_extent_data_ref_root(eb, dref));
1096}
1097
1098static int __shared_list_add(struct list_head *head, u64 disk_byte)
1099{
1100 struct __shared_ref *ref;
1101
1102 ref = kmalloc(sizeof(*ref), GFP_NOFS);
1103 if (!ref)
1104 return -ENOMEM;
1105
1106 ref->disk_byte = disk_byte;
1107 list_add_tail(&ref->list, head);
1108
1109 return 0;
1110}
1111
1112static int __iter_shared_inline_ref_inodes(struct btrfs_fs_info *fs_info,
1113 u64 logical, u64 inum,
1114 u64 extent_data_item_offset,
1115 u64 extent_offset,
1116 struct btrfs_path *path,
1117 struct list_head *data_refs,
1118 iterate_extent_inodes_t *iterate,
1119 void *ctx)
1120{
1121 u64 ref_root;
1122 u32 item_size;
1123 struct btrfs_key key;
1124 struct extent_buffer *eb;
1125 struct btrfs_extent_item *ei;
1126 struct btrfs_extent_inline_ref *eiref;
1127 struct __data_ref *ref;
1128 int ret;
1129 int type;
1130 int last;
1131 unsigned long ptr = 0;
1132
1133 WARN_ON(!list_empty(data_refs));
1134 ret = extent_from_logical(fs_info, logical, path, &key);
1135 if (ret & BTRFS_EXTENT_FLAG_DATA)
1136 ret = -EIO;
1137 if (ret < 0)
1138 goto out;
1139
1140 eb = path->nodes[0];
1141 ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
1142 item_size = btrfs_item_size_nr(eb, path->slots[0]);
1143
1144 ret = 0;
1145 ref_root = 0;
1146 /*
1147 * as done in iterate_extent_inodes, we first build a list of refs to
1148 * iterate, then free the path and then iterate them to avoid deadlocks.
1149 */
1150 do {
1151 last = __get_extent_inline_ref(&ptr, eb, ei, item_size,
1152 &eiref, &type);
1153 if (last < 0) {
1154 ret = last;
1155 goto out;
1156 }
1157 if (type == BTRFS_TREE_BLOCK_REF_KEY ||
1158 type == BTRFS_SHARED_BLOCK_REF_KEY) {
1159 ref_root = btrfs_extent_inline_ref_offset(eb, eiref);
1160 ret = __data_list_add(data_refs, inum,
1161 extent_data_item_offset,
1162 ref_root);
1163 }
1164 } while (!ret && !last);
1165
1166 btrfs_release_path(path);
1167
1168 if (ref_root == 0) {
1169 printk(KERN_ERR "btrfs: failed to find tree block ref "
1170 "for shared data backref %llu\n", logical);
1171 WARN_ON(1);
1172 ret = -EIO;
1173 }
1174
1175out:
1176 while (!list_empty(data_refs)) {
1177 ref = list_first_entry(data_refs, struct __data_ref, list);
1178 list_del(&ref->list);
1179 if (!ret)
1180 ret = iterate(ref->inum, extent_offset +
1181 ref->extent_data_item_offset,
1182 ref->root, ctx);
1183 kfree(ref);
1184 }
1185
1186 return ret;
1187}
1188
1189static int __iter_shared_inline_ref(struct btrfs_fs_info *fs_info,
1190 u64 logical, u64 orig_extent_item_objectid,
1191 u64 extent_offset, struct btrfs_path *path,
1192 struct list_head *data_refs,
1193 iterate_extent_inodes_t *iterate,
1194 void *ctx)
1195{ 1076{
1196 u64 disk_byte; 1077 u64 disk_byte;
1197 struct btrfs_key key; 1078 struct btrfs_key key;
@@ -1199,8 +1080,10 @@ static int __iter_shared_inline_ref(struct btrfs_fs_info *fs_info,
1199 struct extent_buffer *eb; 1080 struct extent_buffer *eb;
1200 int slot; 1081 int slot;
1201 int nritems; 1082 int nritems;
1202 int ret; 1083 int ret = 0;
1203 int found = 0; 1084 int extent_type;
1085 u64 data_offset;
1086 u64 data_len;
1204 1087
1205 eb = read_tree_block(fs_info->tree_root, logical, 1088 eb = read_tree_block(fs_info->tree_root, logical,
1206 fs_info->tree_root->leafsize, 0); 1089 fs_info->tree_root->leafsize, 0);
@@ -1218,149 +1101,99 @@ static int __iter_shared_inline_ref(struct btrfs_fs_info *fs_info,
1218 if (key.type != BTRFS_EXTENT_DATA_KEY) 1101 if (key.type != BTRFS_EXTENT_DATA_KEY)
1219 continue; 1102 continue;
1220 fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); 1103 fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
1221 if (!fi) { 1104 extent_type = btrfs_file_extent_type(eb, fi);
1222 free_extent_buffer(eb); 1105 if (extent_type == BTRFS_FILE_EXTENT_INLINE)
1223 return -EIO; 1106 continue;
1224 } 1107 /* don't skip BTRFS_FILE_EXTENT_PREALLOC, we can handle that */
1225 disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); 1108 disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
1226 if (disk_byte != orig_extent_item_objectid) { 1109 if (disk_byte != orig_extent_item_objectid)
1227 if (found) 1110 continue;
1228 break;
1229 else
1230 continue;
1231 }
1232 ++found;
1233 ret = __iter_shared_inline_ref_inodes(fs_info, logical,
1234 key.objectid,
1235 key.offset,
1236 extent_offset, path,
1237 data_refs,
1238 iterate, ctx);
1239 if (ret)
1240 break;
1241 }
1242 1111
1243 if (!found) { 1112 data_offset = btrfs_file_extent_offset(eb, fi);
1244 printk(KERN_ERR "btrfs: failed to follow shared data backref " 1113 data_len = btrfs_file_extent_num_bytes(eb, fi);
1245 "to parent %llu\n", logical); 1114
1246 WARN_ON(1); 1115 if (extent_item_pos < data_offset ||
1247 ret = -EIO; 1116 extent_item_pos >= data_offset + data_len)
1117 continue;
1118
1119 pr_debug("ref for %llu resolved, key (%llu EXTEND_DATA %llu), "
1120 "root %llu\n", orig_extent_item_objectid,
1121 key.objectid, key.offset, root);
1122 ret = iterate(key.objectid,
1123 key.offset + (extent_item_pos - data_offset),
1124 root, ctx);
1125 if (ret) {
1126 pr_debug("stopping iteration because ret=%d\n", ret);
1127 break;
1128 }
1248 } 1129 }
1249 1130
1250 free_extent_buffer(eb); 1131 free_extent_buffer(eb);
1132
1251 return ret; 1133 return ret;
1252} 1134}
1253 1135
1254/* 1136/*
1255 * calls iterate() for every inode that references the extent identified by 1137 * calls iterate() for every inode that references the extent identified by
1256 * the given parameters. will use the path given as a parameter and return it 1138 * the given parameters.
1257 * released.
1258 * when the iterator function returns a non-zero value, iteration stops. 1139 * when the iterator function returns a non-zero value, iteration stops.
1140 * path is guaranteed to be in released state when iterate() is called.
1259 */ 1141 */
1260int iterate_extent_inodes(struct btrfs_fs_info *fs_info, 1142int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
1261 struct btrfs_path *path, 1143 struct btrfs_path *path,
1262 u64 extent_item_objectid, 1144 u64 extent_item_objectid, u64 extent_item_pos,
1263 u64 extent_offset,
1264 iterate_extent_inodes_t *iterate, void *ctx) 1145 iterate_extent_inodes_t *iterate, void *ctx)
1265{ 1146{
1266 unsigned long ptr = 0;
1267 int last;
1268 int ret; 1147 int ret;
1269 int type;
1270 u64 logical;
1271 u32 item_size;
1272 struct btrfs_extent_inline_ref *eiref;
1273 struct btrfs_extent_data_ref *dref;
1274 struct extent_buffer *eb;
1275 struct btrfs_extent_item *ei;
1276 struct btrfs_key key;
1277 struct list_head data_refs = LIST_HEAD_INIT(data_refs); 1148 struct list_head data_refs = LIST_HEAD_INIT(data_refs);
1278 struct list_head shared_refs = LIST_HEAD_INIT(shared_refs); 1149 struct list_head shared_refs = LIST_HEAD_INIT(shared_refs);
1279 struct __data_ref *ref_d; 1150 struct btrfs_trans_handle *trans;
1280 struct __shared_ref *ref_s; 1151 struct ulist *refs;
1152 struct ulist *roots;
1153 struct ulist_node *ref_node = NULL;
1154 struct ulist_node *root_node = NULL;
1155 struct seq_list seq_elem;
1156 struct btrfs_delayed_ref_root *delayed_refs;
1281 1157
1282 eb = path->nodes[0]; 1158 trans = btrfs_join_transaction(fs_info->extent_root);
1283 ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item); 1159 if (IS_ERR(trans))
1284 item_size = btrfs_item_size_nr(eb, path->slots[0]); 1160 return PTR_ERR(trans);
1285
1286 /* first we iterate the inline refs, ... */
1287 do {
1288 last = __get_extent_inline_ref(&ptr, eb, ei, item_size,
1289 &eiref, &type);
1290 if (last == -ENOENT) {
1291 ret = 0;
1292 break;
1293 }
1294 if (last < 0) {
1295 ret = last;
1296 break;
1297 }
1298 1161
1299 if (type == BTRFS_EXTENT_DATA_REF_KEY) { 1162 pr_debug("resolving all inodes for extent %llu\n",
1300 dref = (struct btrfs_extent_data_ref *)(&eiref->offset); 1163 extent_item_objectid);
1301 ret = __data_list_add_eb(&data_refs, eb, dref);
1302 } else if (type == BTRFS_SHARED_DATA_REF_KEY) {
1303 logical = btrfs_extent_inline_ref_offset(eb, eiref);
1304 ret = __shared_list_add(&shared_refs, logical);
1305 }
1306 } while (!ret && !last);
1307 1164
1308 /* ... then we proceed to in-tree references and ... */ 1165 delayed_refs = &trans->transaction->delayed_refs;
1309 while (!ret) { 1166 spin_lock(&delayed_refs->lock);
1310 ++path->slots[0]; 1167 btrfs_get_delayed_seq(delayed_refs, &seq_elem);
1311 if (path->slots[0] > btrfs_header_nritems(eb)) { 1168 spin_unlock(&delayed_refs->lock);
1312 ret = btrfs_next_leaf(fs_info->extent_root, path);
1313 if (ret) {
1314 if (ret == 1)
1315 ret = 0; /* we're done */
1316 break;
1317 }
1318 eb = path->nodes[0];
1319 }
1320 btrfs_item_key_to_cpu(eb, &key, path->slots[0]);
1321 if (key.objectid != extent_item_objectid)
1322 break;
1323 if (key.type == BTRFS_EXTENT_DATA_REF_KEY) {
1324 dref = btrfs_item_ptr(eb, path->slots[0],
1325 struct btrfs_extent_data_ref);
1326 ret = __data_list_add_eb(&data_refs, eb, dref);
1327 } else if (key.type == BTRFS_SHARED_DATA_REF_KEY) {
1328 ret = __shared_list_add(&shared_refs, key.offset);
1329 }
1330 }
1331 1169
1332 btrfs_release_path(path); 1170 ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid,
1171 extent_item_pos, seq_elem.seq,
1172 &refs);
1333 1173
1334 /* 1174 if (ret)
1335 * ... only at the very end we can process the refs we found. this is 1175 goto out;
1336 * because the iterator function we call is allowed to make tree lookups
1337 * and we have to avoid deadlocks. additionally, we need more tree
1338 * lookups ourselves for shared data refs.
1339 */
1340 while (!list_empty(&data_refs)) {
1341 ref_d = list_first_entry(&data_refs, struct __data_ref, list);
1342 list_del(&ref_d->list);
1343 if (!ret)
1344 ret = iterate(ref_d->inum, extent_offset +
1345 ref_d->extent_data_item_offset,
1346 ref_d->root, ctx);
1347 kfree(ref_d);
1348 }
1349 1176
1350 while (!list_empty(&shared_refs)) { 1177 while (!ret && (ref_node = ulist_next(refs, ref_node))) {
1351 ref_s = list_first_entry(&shared_refs, struct __shared_ref, 1178 ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, -1,
1352 list); 1179 seq_elem.seq, &roots);
1353 list_del(&ref_s->list); 1180 if (ret)
1354 if (!ret) 1181 break;
1355 ret = __iter_shared_inline_ref(fs_info, 1182 while (!ret && (root_node = ulist_next(roots, root_node))) {
1356 ref_s->disk_byte, 1183 pr_debug("root %llu references leaf %llu\n",
1357 extent_item_objectid, 1184 root_node->val, ref_node->val);
1358 extent_offset, path, 1185 ret = iterate_leaf_refs(fs_info, path, ref_node->val,
1359 &data_refs, 1186 extent_item_objectid,
1360 iterate, ctx); 1187 extent_item_pos, root_node->val,
1361 kfree(ref_s); 1188 iterate, ctx);
1189 }
1362 } 1190 }
1363 1191
1192 ulist_free(refs);
1193 ulist_free(roots);
1194out:
1195 btrfs_put_delayed_seq(delayed_refs, &seq_elem);
1196 btrfs_end_transaction(trans, fs_info->extent_root);
1364 return ret; 1197 return ret;
1365} 1198}
1366 1199
@@ -1369,19 +1202,20 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
1369 iterate_extent_inodes_t *iterate, void *ctx) 1202 iterate_extent_inodes_t *iterate, void *ctx)
1370{ 1203{
1371 int ret; 1204 int ret;
1372 u64 offset; 1205 u64 extent_item_pos;
1373 struct btrfs_key found_key; 1206 struct btrfs_key found_key;
1374 1207
1375 ret = extent_from_logical(fs_info, logical, path, 1208 ret = extent_from_logical(fs_info, logical, path,
1376 &found_key); 1209 &found_key);
1210 btrfs_release_path(path);
1377 if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) 1211 if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
1378 ret = -EINVAL; 1212 ret = -EINVAL;
1379 if (ret < 0) 1213 if (ret < 0)
1380 return ret; 1214 return ret;
1381 1215
1382 offset = logical - found_key.objectid; 1216 extent_item_pos = logical - found_key.objectid;
1383 ret = iterate_extent_inodes(fs_info, path, found_key.objectid, 1217 ret = iterate_extent_inodes(fs_info, path, found_key.objectid,
1384 offset, iterate, ctx); 1218 extent_item_pos, iterate, ctx);
1385 1219
1386 return ret; 1220 return ret;
1387} 1221}
@@ -1426,6 +1260,10 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
1426 for (cur = 0; cur < btrfs_item_size(eb, item); cur += len) { 1260 for (cur = 0; cur < btrfs_item_size(eb, item); cur += len) {
1427 name_len = btrfs_inode_ref_name_len(eb, iref); 1261 name_len = btrfs_inode_ref_name_len(eb, iref);
1428 /* path must be released before calling iterate()! */ 1262 /* path must be released before calling iterate()! */
1263 pr_debug("following ref at offset %u for inode %llu in "
1264 "tree %llu\n", cur,
1265 (unsigned long long)found_key.objectid,
1266 (unsigned long long)fs_root->objectid);
1429 ret = iterate(parent, iref, eb, ctx); 1267 ret = iterate(parent, iref, eb, ctx);
1430 if (ret) { 1268 if (ret) {
1431 free_extent_buffer(eb); 1269 free_extent_buffer(eb);
@@ -1466,10 +1304,14 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
1466 return PTR_ERR(fspath); 1304 return PTR_ERR(fspath);
1467 1305
1468 if (fspath > fspath_min) { 1306 if (fspath > fspath_min) {
1307 pr_debug("path resolved: %s\n", fspath);
1469 ipath->fspath->val[i] = (u64)(unsigned long)fspath; 1308 ipath->fspath->val[i] = (u64)(unsigned long)fspath;
1470 ++ipath->fspath->elem_cnt; 1309 ++ipath->fspath->elem_cnt;
1471 ipath->fspath->bytes_left = fspath - fspath_min; 1310 ipath->fspath->bytes_left = fspath - fspath_min;
1472 } else { 1311 } else {
1312 pr_debug("missed path, not enough space. missing bytes: %lu, "
1313 "constructed so far: %s\n",
1314 (unsigned long)(fspath_min - fspath), fspath_min);
1473 ++ipath->fspath->elem_missed; 1315 ++ipath->fspath->elem_missed;
1474 ipath->fspath->bytes_missing += fspath_min - fspath; 1316 ipath->fspath->bytes_missing += fspath_min - fspath;
1475 ipath->fspath->bytes_left = 0; 1317 ipath->fspath->bytes_left = 0;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c48f2e931ea0..9b0526872b7b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2976,7 +2976,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
2976{ 2976{
2977 int ret = 0; 2977 int ret = 0;
2978 int size; 2978 int size;
2979 u64 extent_offset; 2979 u64 extent_item_pos;
2980 struct btrfs_ioctl_logical_ino_args *loi; 2980 struct btrfs_ioctl_logical_ino_args *loi;
2981 struct btrfs_data_container *inodes = NULL; 2981 struct btrfs_data_container *inodes = NULL;
2982 struct btrfs_path *path = NULL; 2982 struct btrfs_path *path = NULL;
@@ -3007,15 +3007,17 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
3007 } 3007 }
3008 3008
3009 ret = extent_from_logical(root->fs_info, loi->logical, path, &key); 3009 ret = extent_from_logical(root->fs_info, loi->logical, path, &key);
3010 btrfs_release_path(path);
3010 3011
3011 if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) 3012 if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
3012 ret = -ENOENT; 3013 ret = -ENOENT;
3013 if (ret < 0) 3014 if (ret < 0)
3014 goto out; 3015 goto out;
3015 3016
3016 extent_offset = loi->logical - key.objectid; 3017 extent_item_pos = loi->logical - key.objectid;
3017 ret = iterate_extent_inodes(root->fs_info, path, key.objectid, 3018 ret = iterate_extent_inodes(root->fs_info, path, key.objectid,
3018 extent_offset, build_ino_list, inodes); 3019 extent_item_pos, build_ino_list,
3020 inodes);
3019 3021
3020 if (ret < 0) 3022 if (ret < 0)
3021 goto out; 3023 goto out;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index c27bcb67f330..b5edff25a53f 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -309,7 +309,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_bio *sbio,
309 u8 ref_level; 309 u8 ref_level;
310 unsigned long ptr = 0; 310 unsigned long ptr = 0;
311 const int bufsize = 4096; 311 const int bufsize = 4096;
312 u64 extent_offset; 312 u64 extent_item_pos;
313 313
314 path = btrfs_alloc_path(); 314 path = btrfs_alloc_path();
315 315
@@ -329,12 +329,13 @@ static void scrub_print_warning(const char *errstr, struct scrub_bio *sbio,
329 if (ret < 0) 329 if (ret < 0)
330 goto out; 330 goto out;
331 331
332 extent_offset = swarn.logical - found_key.objectid; 332 extent_item_pos = swarn.logical - found_key.objectid;
333 swarn.extent_item_size = found_key.offset; 333 swarn.extent_item_size = found_key.offset;
334 334
335 eb = path->nodes[0]; 335 eb = path->nodes[0];
336 ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item); 336 ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
337 item_size = btrfs_item_size_nr(eb, path->slots[0]); 337 item_size = btrfs_item_size_nr(eb, path->slots[0]);
338 btrfs_release_path(path);
338 339
339 if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) { 340 if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
340 do { 341 do {
@@ -351,7 +352,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_bio *sbio,
351 } else { 352 } else {
352 swarn.path = path; 353 swarn.path = path;
353 iterate_extent_inodes(fs_info, path, found_key.objectid, 354 iterate_extent_inodes(fs_info, path, found_key.objectid,
354 extent_offset, 355 extent_item_pos,
355 scrub_print_warning_inode, &swarn); 356 scrub_print_warning_inode, &swarn);
356 } 357 }
357 358