diff options
| -rw-r--r-- | fs/btrfs/inode-map.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 000970512624..3262cd17a12f 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
| @@ -60,12 +60,12 @@ again: | |||
| 60 | 60 | ||
| 61 | while (1) { | 61 | while (1) { |
| 62 | smp_mb(); | 62 | smp_mb(); |
| 63 | if (fs_info->closing > 1) | 63 | if (fs_info->closing) |
| 64 | goto out; | 64 | goto out; |
| 65 | 65 | ||
| 66 | leaf = path->nodes[0]; | 66 | leaf = path->nodes[0]; |
| 67 | slot = path->slots[0]; | 67 | slot = path->slots[0]; |
| 68 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | 68 | if (slot >= btrfs_header_nritems(leaf)) { |
| 69 | ret = btrfs_next_leaf(root, path); | 69 | ret = btrfs_next_leaf(root, path); |
| 70 | if (ret < 0) | 70 | if (ret < 0) |
| 71 | goto out; | 71 | goto out; |
| @@ -100,7 +100,7 @@ again: | |||
| 100 | if (key.type != BTRFS_INODE_ITEM_KEY) | 100 | if (key.type != BTRFS_INODE_ITEM_KEY) |
| 101 | goto next; | 101 | goto next; |
| 102 | 102 | ||
| 103 | if (key.objectid >= BTRFS_LAST_FREE_OBJECTID) | 103 | if (key.objectid >= root->highest_objectid) |
| 104 | break; | 104 | break; |
| 105 | 105 | ||
| 106 | if (last != (u64)-1 && last + 1 != key.objectid) { | 106 | if (last != (u64)-1 && last + 1 != key.objectid) { |
| @@ -114,9 +114,9 @@ next: | |||
| 114 | path->slots[0]++; | 114 | path->slots[0]++; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | if (last < BTRFS_LAST_FREE_OBJECTID - 1) { | 117 | if (last < root->highest_objectid - 1) { |
| 118 | __btrfs_add_free_space(ctl, last + 1, | 118 | __btrfs_add_free_space(ctl, last + 1, |
| 119 | BTRFS_LAST_FREE_OBJECTID - last - 1); | 119 | root->highest_objectid - last - 1); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | spin_lock(&root->cache_lock); | 122 | spin_lock(&root->cache_lock); |
| @@ -136,8 +136,10 @@ out: | |||
| 136 | 136 | ||
| 137 | static void start_caching(struct btrfs_root *root) | 137 | static void start_caching(struct btrfs_root *root) |
| 138 | { | 138 | { |
| 139 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; | ||
| 139 | struct task_struct *tsk; | 140 | struct task_struct *tsk; |
| 140 | int ret; | 141 | int ret; |
| 142 | u64 objectid; | ||
| 141 | 143 | ||
| 142 | spin_lock(&root->cache_lock); | 144 | spin_lock(&root->cache_lock); |
| 143 | if (root->cached != BTRFS_CACHE_NO) { | 145 | if (root->cached != BTRFS_CACHE_NO) { |
| @@ -156,6 +158,19 @@ static void start_caching(struct btrfs_root *root) | |||
| 156 | return; | 158 | return; |
| 157 | } | 159 | } |
| 158 | 160 | ||
| 161 | /* | ||
| 162 | * It can be quite time-consuming to fill the cache by searching | ||
| 163 | * through the extent tree, and this can keep ino allocation path | ||
| 164 | * waiting. Therefore at start we quickly find out the highest | ||
| 165 | * inode number and we know we can use inode numbers which fall in | ||
| 166 | * [highest_ino + 1, BTRFS_LAST_FREE_OBJECTID]. | ||
| 167 | */ | ||
| 168 | ret = btrfs_find_free_objectid(root, &objectid); | ||
| 169 | if (!ret && objectid <= BTRFS_LAST_FREE_OBJECTID) { | ||
| 170 | __btrfs_add_free_space(ctl, objectid, | ||
| 171 | BTRFS_LAST_FREE_OBJECTID - objectid + 1); | ||
| 172 | } | ||
| 173 | |||
| 159 | tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n", | 174 | tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n", |
| 160 | root->root_key.objectid); | 175 | root->root_key.objectid); |
| 161 | BUG_ON(IS_ERR(tsk)); | 176 | BUG_ON(IS_ERR(tsk)); |
| @@ -209,7 +224,8 @@ again: | |||
| 209 | 224 | ||
| 210 | start_caching(root); | 225 | start_caching(root); |
| 211 | 226 | ||
| 212 | if (objectid <= root->cache_progress) | 227 | if (objectid <= root->cache_progress || |
| 228 | objectid > root->highest_objectid) | ||
| 213 | __btrfs_add_free_space(ctl, objectid, 1); | 229 | __btrfs_add_free_space(ctl, objectid, 1); |
| 214 | else | 230 | else |
| 215 | __btrfs_add_free_space(pinned, objectid, 1); | 231 | __btrfs_add_free_space(pinned, objectid, 1); |
