aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-30 15:44:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-30 15:44:29 -0400
commit9613bebb223dea3179c265dc31e1bb41ae39f321 (patch)
tree39bf883573d23775a53be3172323c0237fef5630 /fs/btrfs/backref.c
parent40380f1c7841a5dcbf0b20f0b6da11969211ef77 (diff)
parentbc3f116fec194f1d7329b160c266fe16b9266a1e (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes and features from Chris Mason: "We've merged in the error handling patches from SuSE. These are already shipping in the sles kernel, and they give btrfs the ability to abort transactions and go readonly on errors. It involves a lot of churn as they clarify BUG_ONs, and remove the ones we now properly deal with. Josef reworked the way our metadata interacts with the page cache. page->private now points to the btrfs extent_buffer object, which makes everything faster. He changed it so we write an whole extent buffer at a time instead of allowing individual pages to go down,, which will be important for the raid5/6 code (for the 3.5 merge window ;) Josef also made us more aggressive about dropping pages for metadata blocks that were freed due to COW. Overall, our metadata caching is much faster now. We've integrated my patch for metadata bigger than the page size. This allows metadata blocks up to 64KB in size. In practice 16K and 32K seem to work best. For workloads with lots of metadata, this cuts down the size of the extent allocation tree dramatically and fragments much less. Scrub was updated to support the larger block sizes, which ended up being a fairly large change (thanks Stefan Behrens). We also have an assortment of fixes and updates, especially to the balancing code (Ilya Dryomov), the back ref walker (Jan Schmidt) and the defragging code (Liu Bo)." Fixed up trivial conflicts in fs/btrfs/scrub.c that were just due to removal of the second argument to k[un]map_atomic() in commit 7ac687d9e047. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (75 commits) Btrfs: update the checks for mixed block groups with big metadata blocks Btrfs: update to the right index of defragment Btrfs: do not bother to defrag an extent if it is a big real extent Btrfs: add a check to decide if we should defrag the range Btrfs: fix recursive defragment with autodefrag option Btrfs: fix the mismatch of page->mapping Btrfs: fix race between direct io and autodefrag Btrfs: fix deadlock during allocating chunks Btrfs: show useful info in space reservation tracepoint Btrfs: don't use crc items bigger than 4KB Btrfs: flush out and clean up any block device pages during mount btrfs: disallow unequal data/metadata blocksize for mixed block groups Btrfs: enhance superblock sanity checks Btrfs: change scrub to support big blocks Btrfs: minor cleanup in scrub Btrfs: introduce common define for max number of mirrors Btrfs: fix infinite loop in btrfs_shrink_device() Btrfs: fix memory leak in resolver code Btrfs: allow dup for data chunks in mixed mode Btrfs: validate target profiles only if we are going to use them ...
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c122
1 files changed, 67 insertions, 55 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 0436c12da8c2..f4e90748940a 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -116,6 +116,7 @@ add_parent:
116 * to a logical address 116 * to a logical address
117 */ 117 */
118static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, 118static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
119 int search_commit_root,
119 struct __prelim_ref *ref, 120 struct __prelim_ref *ref,
120 struct ulist *parents) 121 struct ulist *parents)
121{ 122{
@@ -131,6 +132,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
131 path = btrfs_alloc_path(); 132 path = btrfs_alloc_path();
132 if (!path) 133 if (!path)
133 return -ENOMEM; 134 return -ENOMEM;
135 path->search_commit_root = !!search_commit_root;
134 136
135 root_key.objectid = ref->root_id; 137 root_key.objectid = ref->root_id;
136 root_key.type = BTRFS_ROOT_ITEM_KEY; 138 root_key.type = BTRFS_ROOT_ITEM_KEY;
@@ -188,6 +190,7 @@ out:
188 * resolve all indirect backrefs from the list 190 * resolve all indirect backrefs from the list
189 */ 191 */
190static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, 192static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
193 int search_commit_root,
191 struct list_head *head) 194 struct list_head *head)
192{ 195{
193 int err; 196 int err;
@@ -212,7 +215,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
212 continue; 215 continue;
213 if (ref->count == 0) 216 if (ref->count == 0)
214 continue; 217 continue;
215 err = __resolve_indirect_ref(fs_info, ref, parents); 218 err = __resolve_indirect_ref(fs_info, search_commit_root,
219 ref, parents);
216 if (err) { 220 if (err) {
217 if (ret == 0) 221 if (ret == 0)
218 ret = err; 222 ret = err;
@@ -586,6 +590,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
586 struct btrfs_delayed_ref_head *head; 590 struct btrfs_delayed_ref_head *head;
587 int info_level = 0; 591 int info_level = 0;
588 int ret; 592 int ret;
593 int search_commit_root = (trans == BTRFS_BACKREF_SEARCH_COMMIT_ROOT);
589 struct list_head prefs_delayed; 594 struct list_head prefs_delayed;
590 struct list_head prefs; 595 struct list_head prefs;
591 struct __prelim_ref *ref; 596 struct __prelim_ref *ref;
@@ -600,6 +605,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
600 path = btrfs_alloc_path(); 605 path = btrfs_alloc_path();
601 if (!path) 606 if (!path)
602 return -ENOMEM; 607 return -ENOMEM;
608 path->search_commit_root = !!search_commit_root;
603 609
604 /* 610 /*
605 * grab both a lock on the path and a lock on the delayed ref head. 611 * grab both a lock on the path and a lock on the delayed ref head.
@@ -614,35 +620,39 @@ again:
614 goto out; 620 goto out;
615 BUG_ON(ret == 0); 621 BUG_ON(ret == 0);
616 622
617 /* 623 if (trans != BTRFS_BACKREF_SEARCH_COMMIT_ROOT) {
618 * look if there are updates for this ref queued and lock the head 624 /*
619 */ 625 * look if there are updates for this ref queued and lock the
620 delayed_refs = &trans->transaction->delayed_refs; 626 * head
621 spin_lock(&delayed_refs->lock); 627 */
622 head = btrfs_find_delayed_ref_head(trans, bytenr); 628 delayed_refs = &trans->transaction->delayed_refs;
623 if (head) { 629 spin_lock(&delayed_refs->lock);
624 if (!mutex_trylock(&head->mutex)) { 630 head = btrfs_find_delayed_ref_head(trans, bytenr);
625 atomic_inc(&head->node.refs); 631 if (head) {
626 spin_unlock(&delayed_refs->lock); 632 if (!mutex_trylock(&head->mutex)) {
627 633 atomic_inc(&head->node.refs);
628 btrfs_release_path(path); 634 spin_unlock(&delayed_refs->lock);
629 635
630 /* 636 btrfs_release_path(path);
631 * Mutex was contended, block until it's 637
632 * released and try again 638 /*
633 */ 639 * Mutex was contended, block until it's
634 mutex_lock(&head->mutex); 640 * released and try again
635 mutex_unlock(&head->mutex); 641 */
636 btrfs_put_delayed_ref(&head->node); 642 mutex_lock(&head->mutex);
637 goto again; 643 mutex_unlock(&head->mutex);
638 } 644 btrfs_put_delayed_ref(&head->node);
639 ret = __add_delayed_refs(head, seq, &info_key, &prefs_delayed); 645 goto again;
640 if (ret) { 646 }
641 spin_unlock(&delayed_refs->lock); 647 ret = __add_delayed_refs(head, seq, &info_key,
642 goto out; 648 &prefs_delayed);
649 if (ret) {
650 spin_unlock(&delayed_refs->lock);
651 goto out;
652 }
643 } 653 }
654 spin_unlock(&delayed_refs->lock);
644 } 655 }
645 spin_unlock(&delayed_refs->lock);
646 656
647 if (path->slots[0]) { 657 if (path->slots[0]) {
648 struct extent_buffer *leaf; 658 struct extent_buffer *leaf;
@@ -679,7 +689,7 @@ again:
679 if (ret) 689 if (ret)
680 goto out; 690 goto out;
681 691
682 ret = __resolve_indirect_refs(fs_info, &prefs); 692 ret = __resolve_indirect_refs(fs_info, search_commit_root, &prefs);
683 if (ret) 693 if (ret)
684 goto out; 694 goto out;
685 695
@@ -1074,8 +1084,7 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb,
1074 return 0; 1084 return 0;
1075} 1085}
1076 1086
1077static int iterate_leaf_refs(struct btrfs_fs_info *fs_info, 1087static int iterate_leaf_refs(struct btrfs_fs_info *fs_info, u64 logical,
1078 struct btrfs_path *path, u64 logical,
1079 u64 orig_extent_item_objectid, 1088 u64 orig_extent_item_objectid,
1080 u64 extent_item_pos, u64 root, 1089 u64 extent_item_pos, u64 root,
1081 iterate_extent_inodes_t *iterate, void *ctx) 1090 iterate_extent_inodes_t *iterate, void *ctx)
@@ -1143,35 +1152,38 @@ static int iterate_leaf_refs(struct btrfs_fs_info *fs_info,
1143 * calls iterate() for every inode that references the extent identified by 1152 * calls iterate() for every inode that references the extent identified by
1144 * the given parameters. 1153 * the given parameters.
1145 * when the iterator function returns a non-zero value, iteration stops. 1154 * when the iterator function returns a non-zero value, iteration stops.
1146 * path is guaranteed to be in released state when iterate() is called.
1147 */ 1155 */
1148int iterate_extent_inodes(struct btrfs_fs_info *fs_info, 1156int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
1149 struct btrfs_path *path,
1150 u64 extent_item_objectid, u64 extent_item_pos, 1157 u64 extent_item_objectid, u64 extent_item_pos,
1158 int search_commit_root,
1151 iterate_extent_inodes_t *iterate, void *ctx) 1159 iterate_extent_inodes_t *iterate, void *ctx)
1152{ 1160{
1153 int ret; 1161 int ret;
1154 struct list_head data_refs = LIST_HEAD_INIT(data_refs); 1162 struct list_head data_refs = LIST_HEAD_INIT(data_refs);
1155 struct list_head shared_refs = LIST_HEAD_INIT(shared_refs); 1163 struct list_head shared_refs = LIST_HEAD_INIT(shared_refs);
1156 struct btrfs_trans_handle *trans; 1164 struct btrfs_trans_handle *trans;
1157 struct ulist *refs; 1165 struct ulist *refs = NULL;
1158 struct ulist *roots; 1166 struct ulist *roots = NULL;
1159 struct ulist_node *ref_node = NULL; 1167 struct ulist_node *ref_node = NULL;
1160 struct ulist_node *root_node = NULL; 1168 struct ulist_node *root_node = NULL;
1161 struct seq_list seq_elem; 1169 struct seq_list seq_elem;
1162 struct btrfs_delayed_ref_root *delayed_refs; 1170 struct btrfs_delayed_ref_root *delayed_refs = NULL;
1163
1164 trans = btrfs_join_transaction(fs_info->extent_root);
1165 if (IS_ERR(trans))
1166 return PTR_ERR(trans);
1167 1171
1168 pr_debug("resolving all inodes for extent %llu\n", 1172 pr_debug("resolving all inodes for extent %llu\n",
1169 extent_item_objectid); 1173 extent_item_objectid);
1170 1174
1171 delayed_refs = &trans->transaction->delayed_refs; 1175 if (search_commit_root) {
1172 spin_lock(&delayed_refs->lock); 1176 trans = BTRFS_BACKREF_SEARCH_COMMIT_ROOT;
1173 btrfs_get_delayed_seq(delayed_refs, &seq_elem); 1177 } else {
1174 spin_unlock(&delayed_refs->lock); 1178 trans = btrfs_join_transaction(fs_info->extent_root);
1179 if (IS_ERR(trans))
1180 return PTR_ERR(trans);
1181
1182 delayed_refs = &trans->transaction->delayed_refs;
1183 spin_lock(&delayed_refs->lock);
1184 btrfs_get_delayed_seq(delayed_refs, &seq_elem);
1185 spin_unlock(&delayed_refs->lock);
1186 }
1175 1187
1176 ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, 1188 ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid,
1177 extent_item_pos, seq_elem.seq, 1189 extent_item_pos, seq_elem.seq,
@@ -1188,7 +1200,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
1188 while (!ret && (root_node = ulist_next(roots, root_node))) { 1200 while (!ret && (root_node = ulist_next(roots, root_node))) {
1189 pr_debug("root %llu references leaf %llu\n", 1201 pr_debug("root %llu references leaf %llu\n",
1190 root_node->val, ref_node->val); 1202 root_node->val, ref_node->val);
1191 ret = iterate_leaf_refs(fs_info, path, ref_node->val, 1203 ret = iterate_leaf_refs(fs_info, ref_node->val,
1192 extent_item_objectid, 1204 extent_item_objectid,
1193 extent_item_pos, root_node->val, 1205 extent_item_pos, root_node->val,
1194 iterate, ctx); 1206 iterate, ctx);
@@ -1198,8 +1210,11 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
1198 ulist_free(refs); 1210 ulist_free(refs);
1199 ulist_free(roots); 1211 ulist_free(roots);
1200out: 1212out:
1201 btrfs_put_delayed_seq(delayed_refs, &seq_elem); 1213 if (!search_commit_root) {
1202 btrfs_end_transaction(trans, fs_info->extent_root); 1214 btrfs_put_delayed_seq(delayed_refs, &seq_elem);
1215 btrfs_end_transaction(trans, fs_info->extent_root);
1216 }
1217
1203 return ret; 1218 return ret;
1204} 1219}
1205 1220
@@ -1210,6 +1225,7 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
1210 int ret; 1225 int ret;
1211 u64 extent_item_pos; 1226 u64 extent_item_pos;
1212 struct btrfs_key found_key; 1227 struct btrfs_key found_key;
1228 int search_commit_root = path->search_commit_root;
1213 1229
1214 ret = extent_from_logical(fs_info, logical, path, 1230 ret = extent_from_logical(fs_info, logical, path,
1215 &found_key); 1231 &found_key);
@@ -1220,8 +1236,9 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
1220 return ret; 1236 return ret;
1221 1237
1222 extent_item_pos = logical - found_key.objectid; 1238 extent_item_pos = logical - found_key.objectid;
1223 ret = iterate_extent_inodes(fs_info, path, found_key.objectid, 1239 ret = iterate_extent_inodes(fs_info, found_key.objectid,
1224 extent_item_pos, iterate, ctx); 1240 extent_item_pos, search_commit_root,
1241 iterate, ctx);
1225 1242
1226 return ret; 1243 return ret;
1227} 1244}
@@ -1342,12 +1359,6 @@ int paths_from_inode(u64 inum, struct inode_fs_paths *ipath)
1342 inode_to_path, ipath); 1359 inode_to_path, ipath);
1343} 1360}
1344 1361
1345/*
1346 * allocates space to return multiple file system paths for an inode.
1347 * total_bytes to allocate are passed, note that space usable for actual path
1348 * information will be total_bytes - sizeof(struct inode_fs_paths).
1349 * the returned pointer must be freed with free_ipath() in the end.
1350 */
1351struct btrfs_data_container *init_data_container(u32 total_bytes) 1362struct btrfs_data_container *init_data_container(u32 total_bytes)
1352{ 1363{
1353 struct btrfs_data_container *data; 1364 struct btrfs_data_container *data;
@@ -1403,5 +1414,6 @@ struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
1403 1414
1404void free_ipath(struct inode_fs_paths *ipath) 1415void free_ipath(struct inode_fs_paths *ipath)
1405{ 1416{
1417 kfree(ipath->fspath);
1406 kfree(ipath); 1418 kfree(ipath);
1407} 1419}