diff options
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r-- | fs/btrfs/backref.c | 299 |
1 files changed, 240 insertions, 59 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index ff6475f409d6..f3187938e081 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/vmalloc.h> | ||
19 | #include "ctree.h" | 20 | #include "ctree.h" |
20 | #include "disk-io.h" | 21 | #include "disk-io.h" |
21 | #include "backref.h" | 22 | #include "backref.h" |
@@ -231,7 +232,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
231 | } | 232 | } |
232 | if (!ret) { | 233 | if (!ret) { |
233 | ret = ulist_add(parents, eb->start, | 234 | ret = ulist_add(parents, eb->start, |
234 | (unsigned long)eie, GFP_NOFS); | 235 | (uintptr_t)eie, GFP_NOFS); |
235 | if (ret < 0) | 236 | if (ret < 0) |
236 | break; | 237 | break; |
237 | if (!extent_item_pos) { | 238 | if (!extent_item_pos) { |
@@ -363,8 +364,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
363 | ULIST_ITER_INIT(&uiter); | 364 | ULIST_ITER_INIT(&uiter); |
364 | node = ulist_next(parents, &uiter); | 365 | node = ulist_next(parents, &uiter); |
365 | ref->parent = node ? node->val : 0; | 366 | ref->parent = node ? node->val : 0; |
366 | ref->inode_list = | 367 | ref->inode_list = node ? |
367 | node ? (struct extent_inode_elem *)node->aux : 0; | 368 | (struct extent_inode_elem *)(uintptr_t)node->aux : 0; |
368 | 369 | ||
369 | /* additional parents require new refs being added here */ | 370 | /* additional parents require new refs being added here */ |
370 | while ((node = ulist_next(parents, &uiter))) { | 371 | while ((node = ulist_next(parents, &uiter))) { |
@@ -375,8 +376,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
375 | } | 376 | } |
376 | memcpy(new_ref, ref, sizeof(*ref)); | 377 | memcpy(new_ref, ref, sizeof(*ref)); |
377 | new_ref->parent = node->val; | 378 | new_ref->parent = node->val; |
378 | new_ref->inode_list = | 379 | new_ref->inode_list = (struct extent_inode_elem *) |
379 | (struct extent_inode_elem *)node->aux; | 380 | (uintptr_t)node->aux; |
380 | list_add(&new_ref->list, &ref->list); | 381 | list_add(&new_ref->list, &ref->list); |
381 | } | 382 | } |
382 | ulist_reinit(parents); | 383 | ulist_reinit(parents); |
@@ -914,8 +915,8 @@ again: | |||
914 | free_extent_buffer(eb); | 915 | free_extent_buffer(eb); |
915 | } | 916 | } |
916 | ret = ulist_add_merge(refs, ref->parent, | 917 | ret = ulist_add_merge(refs, ref->parent, |
917 | (unsigned long)ref->inode_list, | 918 | (uintptr_t)ref->inode_list, |
918 | (unsigned long *)&eie, GFP_NOFS); | 919 | (u64 *)&eie, GFP_NOFS); |
919 | if (!ret && extent_item_pos) { | 920 | if (!ret && extent_item_pos) { |
920 | /* | 921 | /* |
921 | * we've recorded that parent, so we must extend | 922 | * we've recorded that parent, so we must extend |
@@ -959,7 +960,7 @@ static void free_leaf_list(struct ulist *blocks) | |||
959 | while ((node = ulist_next(blocks, &uiter))) { | 960 | while ((node = ulist_next(blocks, &uiter))) { |
960 | if (!node->aux) | 961 | if (!node->aux) |
961 | continue; | 962 | continue; |
962 | eie = (struct extent_inode_elem *)node->aux; | 963 | eie = (struct extent_inode_elem *)(uintptr_t)node->aux; |
963 | for (; eie; eie = eie_next) { | 964 | for (; eie; eie = eie_next) { |
964 | eie_next = eie->next; | 965 | eie_next = eie->next; |
965 | kfree(eie); | 966 | kfree(eie); |
@@ -1108,26 +1109,80 @@ static int inode_ref_info(u64 inum, u64 ioff, struct btrfs_root *fs_root, | |||
1108 | found_key); | 1109 | found_key); |
1109 | } | 1110 | } |
1110 | 1111 | ||
1111 | /* | 1112 | int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, |
1112 | * this iterates to turn a btrfs_inode_ref into a full filesystem path. elements | 1113 | u64 start_off, struct btrfs_path *path, |
1113 | * of the path are separated by '/' and the path is guaranteed to be | 1114 | struct btrfs_inode_extref **ret_extref, |
1114 | * 0-terminated. the path is only given within the current file system. | 1115 | u64 *found_off) |
1115 | * Therefore, it never starts with a '/'. the caller is responsible to provide | 1116 | { |
1116 | * "size" bytes in "dest". the dest buffer will be filled backwards. finally, | 1117 | int ret, slot; |
1117 | * the start point of the resulting string is returned. this pointer is within | 1118 | struct btrfs_key key; |
1118 | * dest, normally. | 1119 | struct btrfs_key found_key; |
1119 | * in case the path buffer would overflow, the pointer is decremented further | 1120 | struct btrfs_inode_extref *extref; |
1120 | * as if output was written to the buffer, though no more output is actually | 1121 | struct extent_buffer *leaf; |
1121 | * generated. that way, the caller can determine how much space would be | 1122 | unsigned long ptr; |
1122 | * required for the path to fit into the buffer. in that case, the returned | 1123 | |
1123 | * value will be smaller than dest. callers must check this! | 1124 | key.objectid = inode_objectid; |
1124 | */ | 1125 | btrfs_set_key_type(&key, BTRFS_INODE_EXTREF_KEY); |
1125 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | 1126 | key.offset = start_off; |
1126 | struct btrfs_inode_ref *iref, | 1127 | |
1128 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
1129 | if (ret < 0) | ||
1130 | return ret; | ||
1131 | |||
1132 | while (1) { | ||
1133 | leaf = path->nodes[0]; | ||
1134 | slot = path->slots[0]; | ||
1135 | if (slot >= btrfs_header_nritems(leaf)) { | ||
1136 | /* | ||
1137 | * If the item at offset is not found, | ||
1138 | * btrfs_search_slot will point us to the slot | ||
1139 | * where it should be inserted. In our case | ||
1140 | * that will be the slot directly before the | ||
1141 | * next INODE_REF_KEY_V2 item. In the case | ||
1142 | * that we're pointing to the last slot in a | ||
1143 | * leaf, we must move one leaf over. | ||
1144 | */ | ||
1145 | ret = btrfs_next_leaf(root, path); | ||
1146 | if (ret) { | ||
1147 | if (ret >= 1) | ||
1148 | ret = -ENOENT; | ||
1149 | break; | ||
1150 | } | ||
1151 | continue; | ||
1152 | } | ||
1153 | |||
1154 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
1155 | |||
1156 | /* | ||
1157 | * Check that we're still looking at an extended ref key for | ||
1158 | * this particular objectid. If we have different | ||
1159 | * objectid or type then there are no more to be found | ||
1160 | * in the tree and we can exit. | ||
1161 | */ | ||
1162 | ret = -ENOENT; | ||
1163 | if (found_key.objectid != inode_objectid) | ||
1164 | break; | ||
1165 | if (btrfs_key_type(&found_key) != BTRFS_INODE_EXTREF_KEY) | ||
1166 | break; | ||
1167 | |||
1168 | ret = 0; | ||
1169 | ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); | ||
1170 | extref = (struct btrfs_inode_extref *)ptr; | ||
1171 | *ret_extref = extref; | ||
1172 | if (found_off) | ||
1173 | *found_off = found_key.offset; | ||
1174 | break; | ||
1175 | } | ||
1176 | |||
1177 | return ret; | ||
1178 | } | ||
1179 | |||
1180 | static char *ref_to_path(struct btrfs_root *fs_root, | ||
1181 | struct btrfs_path *path, | ||
1182 | u32 name_len, unsigned long name_off, | ||
1127 | struct extent_buffer *eb_in, u64 parent, | 1183 | struct extent_buffer *eb_in, u64 parent, |
1128 | char *dest, u32 size) | 1184 | char *dest, u32 size) |
1129 | { | 1185 | { |
1130 | u32 len; | ||
1131 | int slot; | 1186 | int slot; |
1132 | u64 next_inum; | 1187 | u64 next_inum; |
1133 | int ret; | 1188 | int ret; |
@@ -1135,17 +1190,17 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
1135 | struct extent_buffer *eb = eb_in; | 1190 | struct extent_buffer *eb = eb_in; |
1136 | struct btrfs_key found_key; | 1191 | struct btrfs_key found_key; |
1137 | int leave_spinning = path->leave_spinning; | 1192 | int leave_spinning = path->leave_spinning; |
1193 | struct btrfs_inode_ref *iref; | ||
1138 | 1194 | ||
1139 | if (bytes_left >= 0) | 1195 | if (bytes_left >= 0) |
1140 | dest[bytes_left] = '\0'; | 1196 | dest[bytes_left] = '\0'; |
1141 | 1197 | ||
1142 | path->leave_spinning = 1; | 1198 | path->leave_spinning = 1; |
1143 | while (1) { | 1199 | while (1) { |
1144 | len = btrfs_inode_ref_name_len(eb, iref); | 1200 | bytes_left -= name_len; |
1145 | bytes_left -= len; | ||
1146 | if (bytes_left >= 0) | 1201 | if (bytes_left >= 0) |
1147 | read_extent_buffer(eb, dest + bytes_left, | 1202 | read_extent_buffer(eb, dest + bytes_left, |
1148 | (unsigned long)(iref + 1), len); | 1203 | name_off, name_len); |
1149 | if (eb != eb_in) { | 1204 | if (eb != eb_in) { |
1150 | btrfs_tree_read_unlock_blocking(eb); | 1205 | btrfs_tree_read_unlock_blocking(eb); |
1151 | free_extent_buffer(eb); | 1206 | free_extent_buffer(eb); |
@@ -1155,6 +1210,7 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
1155 | ret = -ENOENT; | 1210 | ret = -ENOENT; |
1156 | if (ret) | 1211 | if (ret) |
1157 | break; | 1212 | break; |
1213 | |||
1158 | next_inum = found_key.offset; | 1214 | next_inum = found_key.offset; |
1159 | 1215 | ||
1160 | /* regular exit ahead */ | 1216 | /* regular exit ahead */ |
@@ -1170,8 +1226,11 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
1170 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | 1226 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); |
1171 | } | 1227 | } |
1172 | btrfs_release_path(path); | 1228 | btrfs_release_path(path); |
1173 | |||
1174 | iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); | 1229 | iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); |
1230 | |||
1231 | name_len = btrfs_inode_ref_name_len(eb, iref); | ||
1232 | name_off = (unsigned long)(iref + 1); | ||
1233 | |||
1175 | parent = next_inum; | 1234 | parent = next_inum; |
1176 | --bytes_left; | 1235 | --bytes_left; |
1177 | if (bytes_left >= 0) | 1236 | if (bytes_left >= 0) |
@@ -1188,12 +1247,39 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
1188 | } | 1247 | } |
1189 | 1248 | ||
1190 | /* | 1249 | /* |
1250 | * this iterates to turn a btrfs_inode_ref into a full filesystem path. elements | ||
1251 | * of the path are separated by '/' and the path is guaranteed to be | ||
1252 | * 0-terminated. the path is only given within the current file system. | ||
1253 | * Therefore, it never starts with a '/'. the caller is responsible to provide | ||
1254 | * "size" bytes in "dest". the dest buffer will be filled backwards. finally, | ||
1255 | * the start point of the resulting string is returned. this pointer is within | ||
1256 | * dest, normally. | ||
1257 | * in case the path buffer would overflow, the pointer is decremented further | ||
1258 | * as if output was written to the buffer, though no more output is actually | ||
1259 | * generated. that way, the caller can determine how much space would be | ||
1260 | * required for the path to fit into the buffer. in that case, the returned | ||
1261 | * value will be smaller than dest. callers must check this! | ||
1262 | */ | ||
1263 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, | ||
1264 | struct btrfs_path *path, | ||
1265 | struct btrfs_inode_ref *iref, | ||
1266 | struct extent_buffer *eb_in, u64 parent, | ||
1267 | char *dest, u32 size) | ||
1268 | { | ||
1269 | return ref_to_path(fs_root, path, | ||
1270 | btrfs_inode_ref_name_len(eb_in, iref), | ||
1271 | (unsigned long)(iref + 1), | ||
1272 | eb_in, parent, dest, size); | ||
1273 | } | ||
1274 | |||
1275 | /* | ||
1191 | * this makes the path point to (logical EXTENT_ITEM *) | 1276 | * this makes the path point to (logical EXTENT_ITEM *) |
1192 | * returns BTRFS_EXTENT_FLAG_DATA for data, BTRFS_EXTENT_FLAG_TREE_BLOCK for | 1277 | * returns BTRFS_EXTENT_FLAG_DATA for data, BTRFS_EXTENT_FLAG_TREE_BLOCK for |
1193 | * tree blocks and <0 on error. | 1278 | * tree blocks and <0 on error. |
1194 | */ | 1279 | */ |
1195 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | 1280 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, |
1196 | struct btrfs_path *path, struct btrfs_key *found_key) | 1281 | struct btrfs_path *path, struct btrfs_key *found_key, |
1282 | u64 *flags_ret) | ||
1197 | { | 1283 | { |
1198 | int ret; | 1284 | int ret; |
1199 | u64 flags; | 1285 | u64 flags; |
@@ -1237,10 +1323,17 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | |||
1237 | (unsigned long long)found_key->objectid, | 1323 | (unsigned long long)found_key->objectid, |
1238 | (unsigned long long)found_key->offset, | 1324 | (unsigned long long)found_key->offset, |
1239 | (unsigned long long)flags, item_size); | 1325 | (unsigned long long)flags, item_size); |
1240 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) | 1326 | |
1241 | return BTRFS_EXTENT_FLAG_TREE_BLOCK; | 1327 | WARN_ON(!flags_ret); |
1242 | if (flags & BTRFS_EXTENT_FLAG_DATA) | 1328 | if (flags_ret) { |
1243 | return BTRFS_EXTENT_FLAG_DATA; | 1329 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) |
1330 | *flags_ret = BTRFS_EXTENT_FLAG_TREE_BLOCK; | ||
1331 | else if (flags & BTRFS_EXTENT_FLAG_DATA) | ||
1332 | *flags_ret = BTRFS_EXTENT_FLAG_DATA; | ||
1333 | else | ||
1334 | BUG_ON(1); | ||
1335 | return 0; | ||
1336 | } | ||
1244 | 1337 | ||
1245 | return -EIO; | 1338 | return -EIO; |
1246 | } | 1339 | } |
@@ -1404,12 +1497,13 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1404 | ULIST_ITER_INIT(&root_uiter); | 1497 | ULIST_ITER_INIT(&root_uiter); |
1405 | while (!ret && (root_node = ulist_next(roots, &root_uiter))) { | 1498 | while (!ret && (root_node = ulist_next(roots, &root_uiter))) { |
1406 | pr_debug("root %llu references leaf %llu, data list " | 1499 | pr_debug("root %llu references leaf %llu, data list " |
1407 | "%#lx\n", root_node->val, ref_node->val, | 1500 | "%#llx\n", root_node->val, ref_node->val, |
1408 | ref_node->aux); | 1501 | (long long)ref_node->aux); |
1409 | ret = iterate_leaf_refs( | 1502 | ret = iterate_leaf_refs((struct extent_inode_elem *) |
1410 | (struct extent_inode_elem *)ref_node->aux, | 1503 | (uintptr_t)ref_node->aux, |
1411 | root_node->val, extent_item_objectid, | 1504 | root_node->val, |
1412 | iterate, ctx); | 1505 | extent_item_objectid, |
1506 | iterate, ctx); | ||
1413 | } | 1507 | } |
1414 | ulist_free(roots); | 1508 | ulist_free(roots); |
1415 | roots = NULL; | 1509 | roots = NULL; |
@@ -1432,15 +1526,15 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |||
1432 | { | 1526 | { |
1433 | int ret; | 1527 | int ret; |
1434 | u64 extent_item_pos; | 1528 | u64 extent_item_pos; |
1529 | u64 flags = 0; | ||
1435 | struct btrfs_key found_key; | 1530 | struct btrfs_key found_key; |
1436 | int search_commit_root = path->search_commit_root; | 1531 | int search_commit_root = path->search_commit_root; |
1437 | 1532 | ||
1438 | ret = extent_from_logical(fs_info, logical, path, | 1533 | ret = extent_from_logical(fs_info, logical, path, &found_key, &flags); |
1439 | &found_key); | ||
1440 | btrfs_release_path(path); | 1534 | btrfs_release_path(path); |
1441 | if (ret < 0) | 1535 | if (ret < 0) |
1442 | return ret; | 1536 | return ret; |
1443 | if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) | 1537 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) |
1444 | return -EINVAL; | 1538 | return -EINVAL; |
1445 | 1539 | ||
1446 | extent_item_pos = logical - found_key.objectid; | 1540 | extent_item_pos = logical - found_key.objectid; |
@@ -1451,9 +1545,12 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |||
1451 | return ret; | 1545 | return ret; |
1452 | } | 1546 | } |
1453 | 1547 | ||
1454 | static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | 1548 | typedef int (iterate_irefs_t)(u64 parent, u32 name_len, unsigned long name_off, |
1455 | struct btrfs_path *path, | 1549 | struct extent_buffer *eb, void *ctx); |
1456 | iterate_irefs_t *iterate, void *ctx) | 1550 | |
1551 | static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root, | ||
1552 | struct btrfs_path *path, | ||
1553 | iterate_irefs_t *iterate, void *ctx) | ||
1457 | { | 1554 | { |
1458 | int ret = 0; | 1555 | int ret = 0; |
1459 | int slot; | 1556 | int slot; |
@@ -1470,7 +1567,7 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | |||
1470 | while (!ret) { | 1567 | while (!ret) { |
1471 | path->leave_spinning = 1; | 1568 | path->leave_spinning = 1; |
1472 | ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path, | 1569 | ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path, |
1473 | &found_key); | 1570 | &found_key); |
1474 | if (ret < 0) | 1571 | if (ret < 0) |
1475 | break; | 1572 | break; |
1476 | if (ret) { | 1573 | if (ret) { |
@@ -1498,7 +1595,8 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | |||
1498 | "tree %llu\n", cur, | 1595 | "tree %llu\n", cur, |
1499 | (unsigned long long)found_key.objectid, | 1596 | (unsigned long long)found_key.objectid, |
1500 | (unsigned long long)fs_root->objectid); | 1597 | (unsigned long long)fs_root->objectid); |
1501 | ret = iterate(parent, iref, eb, ctx); | 1598 | ret = iterate(parent, name_len, |
1599 | (unsigned long)(iref + 1), eb, ctx); | ||
1502 | if (ret) | 1600 | if (ret) |
1503 | break; | 1601 | break; |
1504 | len = sizeof(*iref) + name_len; | 1602 | len = sizeof(*iref) + name_len; |
@@ -1513,12 +1611,98 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | |||
1513 | return ret; | 1611 | return ret; |
1514 | } | 1612 | } |
1515 | 1613 | ||
1614 | static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root, | ||
1615 | struct btrfs_path *path, | ||
1616 | iterate_irefs_t *iterate, void *ctx) | ||
1617 | { | ||
1618 | int ret; | ||
1619 | int slot; | ||
1620 | u64 offset = 0; | ||
1621 | u64 parent; | ||
1622 | int found = 0; | ||
1623 | struct extent_buffer *eb; | ||
1624 | struct btrfs_inode_extref *extref; | ||
1625 | struct extent_buffer *leaf; | ||
1626 | u32 item_size; | ||
1627 | u32 cur_offset; | ||
1628 | unsigned long ptr; | ||
1629 | |||
1630 | while (1) { | ||
1631 | ret = btrfs_find_one_extref(fs_root, inum, offset, path, &extref, | ||
1632 | &offset); | ||
1633 | if (ret < 0) | ||
1634 | break; | ||
1635 | if (ret) { | ||
1636 | ret = found ? 0 : -ENOENT; | ||
1637 | break; | ||
1638 | } | ||
1639 | ++found; | ||
1640 | |||
1641 | slot = path->slots[0]; | ||
1642 | eb = path->nodes[0]; | ||
1643 | /* make sure we can use eb after releasing the path */ | ||
1644 | atomic_inc(&eb->refs); | ||
1645 | |||
1646 | btrfs_tree_read_lock(eb); | ||
1647 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
1648 | btrfs_release_path(path); | ||
1649 | |||
1650 | leaf = path->nodes[0]; | ||
1651 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); | ||
1652 | ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); | ||
1653 | cur_offset = 0; | ||
1654 | |||
1655 | while (cur_offset < item_size) { | ||
1656 | u32 name_len; | ||
1657 | |||
1658 | extref = (struct btrfs_inode_extref *)(ptr + cur_offset); | ||
1659 | parent = btrfs_inode_extref_parent(eb, extref); | ||
1660 | name_len = btrfs_inode_extref_name_len(eb, extref); | ||
1661 | ret = iterate(parent, name_len, | ||
1662 | (unsigned long)&extref->name, eb, ctx); | ||
1663 | if (ret) | ||
1664 | break; | ||
1665 | |||
1666 | cur_offset += btrfs_inode_extref_name_len(leaf, extref); | ||
1667 | cur_offset += sizeof(*extref); | ||
1668 | } | ||
1669 | btrfs_tree_read_unlock_blocking(eb); | ||
1670 | free_extent_buffer(eb); | ||
1671 | |||
1672 | offset++; | ||
1673 | } | ||
1674 | |||
1675 | btrfs_release_path(path); | ||
1676 | |||
1677 | return ret; | ||
1678 | } | ||
1679 | |||
1680 | static int iterate_irefs(u64 inum, struct btrfs_root *fs_root, | ||
1681 | struct btrfs_path *path, iterate_irefs_t *iterate, | ||
1682 | void *ctx) | ||
1683 | { | ||
1684 | int ret; | ||
1685 | int found_refs = 0; | ||
1686 | |||
1687 | ret = iterate_inode_refs(inum, fs_root, path, iterate, ctx); | ||
1688 | if (!ret) | ||
1689 | ++found_refs; | ||
1690 | else if (ret != -ENOENT) | ||
1691 | return ret; | ||
1692 | |||
1693 | ret = iterate_inode_extrefs(inum, fs_root, path, iterate, ctx); | ||
1694 | if (ret == -ENOENT && found_refs) | ||
1695 | return 0; | ||
1696 | |||
1697 | return ret; | ||
1698 | } | ||
1699 | |||
1516 | /* | 1700 | /* |
1517 | * returns 0 if the path could be dumped (probably truncated) | 1701 | * returns 0 if the path could be dumped (probably truncated) |
1518 | * returns <0 in case of an error | 1702 | * returns <0 in case of an error |
1519 | */ | 1703 | */ |
1520 | static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref, | 1704 | static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off, |
1521 | struct extent_buffer *eb, void *ctx) | 1705 | struct extent_buffer *eb, void *ctx) |
1522 | { | 1706 | { |
1523 | struct inode_fs_paths *ipath = ctx; | 1707 | struct inode_fs_paths *ipath = ctx; |
1524 | char *fspath; | 1708 | char *fspath; |
@@ -1531,20 +1715,17 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref, | |||
1531 | ipath->fspath->bytes_left - s_ptr : 0; | 1715 | ipath->fspath->bytes_left - s_ptr : 0; |
1532 | 1716 | ||
1533 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; | 1717 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; |
1534 | fspath = btrfs_iref_to_path(ipath->fs_root, ipath->btrfs_path, iref, eb, | 1718 | fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, |
1535 | inum, fspath_min, bytes_left); | 1719 | name_off, eb, inum, fspath_min, |
1720 | bytes_left); | ||
1536 | if (IS_ERR(fspath)) | 1721 | if (IS_ERR(fspath)) |
1537 | return PTR_ERR(fspath); | 1722 | return PTR_ERR(fspath); |
1538 | 1723 | ||
1539 | if (fspath > fspath_min) { | 1724 | if (fspath > fspath_min) { |
1540 | pr_debug("path resolved: %s\n", fspath); | ||
1541 | ipath->fspath->val[i] = (u64)(unsigned long)fspath; | 1725 | ipath->fspath->val[i] = (u64)(unsigned long)fspath; |
1542 | ++ipath->fspath->elem_cnt; | 1726 | ++ipath->fspath->elem_cnt; |
1543 | ipath->fspath->bytes_left = fspath - fspath_min; | 1727 | ipath->fspath->bytes_left = fspath - fspath_min; |
1544 | } else { | 1728 | } else { |
1545 | pr_debug("missed path, not enough space. missing bytes: %lu, " | ||
1546 | "constructed so far: %s\n", | ||
1547 | (unsigned long)(fspath_min - fspath), fspath_min); | ||
1548 | ++ipath->fspath->elem_missed; | 1729 | ++ipath->fspath->elem_missed; |
1549 | ipath->fspath->bytes_missing += fspath_min - fspath; | 1730 | ipath->fspath->bytes_missing += fspath_min - fspath; |
1550 | ipath->fspath->bytes_left = 0; | 1731 | ipath->fspath->bytes_left = 0; |
@@ -1566,7 +1747,7 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref, | |||
1566 | int paths_from_inode(u64 inum, struct inode_fs_paths *ipath) | 1747 | int paths_from_inode(u64 inum, struct inode_fs_paths *ipath) |
1567 | { | 1748 | { |
1568 | return iterate_irefs(inum, ipath->fs_root, ipath->btrfs_path, | 1749 | return iterate_irefs(inum, ipath->fs_root, ipath->btrfs_path, |
1569 | inode_to_path, ipath); | 1750 | inode_to_path, ipath); |
1570 | } | 1751 | } |
1571 | 1752 | ||
1572 | struct btrfs_data_container *init_data_container(u32 total_bytes) | 1753 | struct btrfs_data_container *init_data_container(u32 total_bytes) |
@@ -1575,7 +1756,7 @@ struct btrfs_data_container *init_data_container(u32 total_bytes) | |||
1575 | size_t alloc_bytes; | 1756 | size_t alloc_bytes; |
1576 | 1757 | ||
1577 | alloc_bytes = max_t(size_t, total_bytes, sizeof(*data)); | 1758 | alloc_bytes = max_t(size_t, total_bytes, sizeof(*data)); |
1578 | data = kmalloc(alloc_bytes, GFP_NOFS); | 1759 | data = vmalloc(alloc_bytes); |
1579 | if (!data) | 1760 | if (!data) |
1580 | return ERR_PTR(-ENOMEM); | 1761 | return ERR_PTR(-ENOMEM); |
1581 | 1762 | ||
@@ -1626,6 +1807,6 @@ void free_ipath(struct inode_fs_paths *ipath) | |||
1626 | { | 1807 | { |
1627 | if (!ipath) | 1808 | if (!ipath) |
1628 | return; | 1809 | return; |
1629 | kfree(ipath->fspath); | 1810 | vfree(ipath->fspath); |
1630 | kfree(ipath); | 1811 | kfree(ipath); |
1631 | } | 1812 | } |