aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2014-01-23 16:03:45 -0500
committerChris Mason <clm@fb.com>2014-01-28 16:20:27 -0500
commit580f0a678ebeba85d30b6a7f22ce32c472263c72 (patch)
treeae906912beacd74e676f685f769c0c5ea56007bd /fs/btrfs/backref.c
parent0a2b2a844af616addc87cac3cc18dcaba2a9d0fb (diff)
Btrfs: fix extent_from_logical to deal with skinny metadata
I don't think this is an issue and I've not seen it in practice but extent_from_logical will fail to find a skinny extent because it uses btrfs_previous_item and gives it the normal extent item type. This is just not a place to use btrfs_previous_item since we care about either normal extents or skinny extents, so open code btrfs_previous_item to properly check. This would only affect metadata and the only place this is used for metadata is scrub and I'm pretty sure it's just for printing stuff out, not actually doing any work so hopefully it was never a problem other than a cosmetic one. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 34a8952de8dd..dcf2448c16f1 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1302,20 +1302,45 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
1302 ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); 1302 ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
1303 if (ret < 0) 1303 if (ret < 0)
1304 return ret; 1304 return ret;
1305 ret = btrfs_previous_item(fs_info->extent_root, path,
1306 0, BTRFS_EXTENT_ITEM_KEY);
1307 if (ret < 0)
1308 return ret;
1309 1305
1310 btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]); 1306 while (1) {
1307 u32 nritems;
1308 if (path->slots[0] == 0) {
1309 btrfs_set_path_blocking(path);
1310 ret = btrfs_prev_leaf(fs_info->extent_root, path);
1311 if (ret != 0) {
1312 if (ret > 0) {
1313 pr_debug("logical %llu is not within "
1314 "any extent\n", logical);
1315 ret = -ENOENT;
1316 }
1317 return ret;
1318 }
1319 } else {
1320 path->slots[0]--;
1321 }
1322 nritems = btrfs_header_nritems(path->nodes[0]);
1323 if (nritems == 0) {
1324 pr_debug("logical %llu is not within any extent\n",
1325 logical);
1326 return -ENOENT;
1327 }
1328 if (path->slots[0] == nritems)
1329 path->slots[0]--;
1330
1331 btrfs_item_key_to_cpu(path->nodes[0], found_key,
1332 path->slots[0]);
1333 if (found_key->type == BTRFS_EXTENT_ITEM_KEY ||
1334 found_key->type == BTRFS_METADATA_ITEM_KEY)
1335 break;
1336 }
1337
1311 if (found_key->type == BTRFS_METADATA_ITEM_KEY) 1338 if (found_key->type == BTRFS_METADATA_ITEM_KEY)
1312 size = fs_info->extent_root->leafsize; 1339 size = fs_info->extent_root->leafsize;
1313 else if (found_key->type == BTRFS_EXTENT_ITEM_KEY) 1340 else if (found_key->type == BTRFS_EXTENT_ITEM_KEY)
1314 size = found_key->offset; 1341 size = found_key->offset;
1315 1342
1316 if ((found_key->type != BTRFS_EXTENT_ITEM_KEY && 1343 if (found_key->objectid > logical ||
1317 found_key->type != BTRFS_METADATA_ITEM_KEY) ||
1318 found_key->objectid > logical ||
1319 found_key->objectid + size <= logical) { 1344 found_key->objectid + size <= logical) {
1320 pr_debug("logical %llu is not within any extent\n", logical); 1345 pr_debug("logical %llu is not within any extent\n", logical);
1321 return -ENOENT; 1346 return -ENOENT;