diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index e42fd233e04c..676e4bd65c52 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -167,20 +167,28 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
167 | entry->file_offset = file_offset; | 167 | entry->file_offset = file_offset; |
168 | entry->start = start; | 168 | entry->start = start; |
169 | entry->len = len; | 169 | entry->len = len; |
170 | entry->inode = inode; | ||
171 | |||
170 | /* one ref for the tree */ | 172 | /* one ref for the tree */ |
171 | atomic_set(&entry->refs, 1); | 173 | atomic_set(&entry->refs, 1); |
172 | init_waitqueue_head(&entry->wait); | 174 | init_waitqueue_head(&entry->wait); |
173 | INIT_LIST_HEAD(&entry->list); | 175 | INIT_LIST_HEAD(&entry->list); |
176 | INIT_LIST_HEAD(&entry->root_extent_list); | ||
174 | 177 | ||
175 | node = tree_insert(&tree->tree, file_offset, | 178 | node = tree_insert(&tree->tree, file_offset, |
176 | &entry->rb_node); | 179 | &entry->rb_node); |
177 | if (node) { | 180 | if (node) { |
178 | entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); | 181 | printk("warning dup entry from add_ordered_extent\n"); |
179 | atomic_inc(&entry->refs); | 182 | BUG(); |
180 | } | 183 | } |
181 | set_extent_ordered(&BTRFS_I(inode)->io_tree, file_offset, | 184 | set_extent_ordered(&BTRFS_I(inode)->io_tree, file_offset, |
182 | entry_end(entry) - 1, GFP_NOFS); | 185 | entry_end(entry) - 1, GFP_NOFS); |
183 | 186 | ||
187 | spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | ||
188 | list_add_tail(&entry->root_extent_list, | ||
189 | &BTRFS_I(inode)->root->fs_info->ordered_extents); | ||
190 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | ||
191 | |||
184 | mutex_unlock(&tree->mutex); | 192 | mutex_unlock(&tree->mutex); |
185 | BUG_ON(node); | 193 | BUG_ON(node); |
186 | return 0; | 194 | return 0; |
@@ -285,11 +293,55 @@ int btrfs_remove_ordered_extent(struct inode *inode, | |||
285 | rb_erase(node, &tree->tree); | 293 | rb_erase(node, &tree->tree); |
286 | tree->last = NULL; | 294 | tree->last = NULL; |
287 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); | 295 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); |
296 | |||
297 | spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | ||
298 | list_del_init(&entry->root_extent_list); | ||
299 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | ||
300 | |||
288 | mutex_unlock(&tree->mutex); | 301 | mutex_unlock(&tree->mutex); |
289 | wake_up(&entry->wait); | 302 | wake_up(&entry->wait); |
290 | return 0; | 303 | return 0; |
291 | } | 304 | } |
292 | 305 | ||
306 | int btrfs_wait_ordered_extents(struct btrfs_root *root) | ||
307 | { | ||
308 | struct list_head splice; | ||
309 | struct list_head *cur; | ||
310 | struct btrfs_ordered_extent *ordered; | ||
311 | struct inode *inode; | ||
312 | |||
313 | INIT_LIST_HEAD(&splice); | ||
314 | |||
315 | spin_lock(&root->fs_info->ordered_extent_lock); | ||
316 | list_splice_init(&root->fs_info->ordered_extents, &splice); | ||
317 | while(!list_empty(&splice)) { | ||
318 | cur = splice.next; | ||
319 | ordered = list_entry(cur, struct btrfs_ordered_extent, | ||
320 | root_extent_list); | ||
321 | list_del_init(&ordered->root_extent_list); | ||
322 | atomic_inc(&ordered->refs); | ||
323 | inode = ordered->inode; | ||
324 | |||
325 | /* | ||
326 | * the inode can't go away until all the pages are gone | ||
327 | * and the pages won't go away while there is still | ||
328 | * an ordered extent and the ordered extent won't go | ||
329 | * away until it is off this list. So, we can safely | ||
330 | * increment i_count here and call iput later | ||
331 | */ | ||
332 | atomic_inc(&inode->i_count); | ||
333 | spin_unlock(&root->fs_info->ordered_extent_lock); | ||
334 | |||
335 | btrfs_start_ordered_extent(inode, ordered, 1); | ||
336 | btrfs_put_ordered_extent(ordered); | ||
337 | iput(inode); | ||
338 | |||
339 | spin_lock(&root->fs_info->ordered_extent_lock); | ||
340 | } | ||
341 | spin_unlock(&root->fs_info->ordered_extent_lock); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
293 | /* | 345 | /* |
294 | * Used to start IO or wait for a given ordered extent to finish. | 346 | * Used to start IO or wait for a given ordered extent to finish. |
295 | * | 347 | * |