diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-08-04 23:17:27 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:06 -0400 |
commit | ea8c281947950fac5f78818b767821d696c9512a (patch) | |
tree | a30e9da5371d9a694a8f73d450231107ccad1dcb /fs/btrfs | |
parent | d7a029a89ef370e74b63f18b81498d90d1ee3cc1 (diff) |
Btrfs: Maintain a list of inodes that are delalloc and a way to wait on them
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 2 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 12 | ||||
-rw-r--r-- | fs/btrfs/file.c | 3 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 47 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 4 |
7 files changed, 60 insertions, 13 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index df624fd735c1..534ac4153ddd 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -42,6 +42,8 @@ struct btrfs_inode { | |||
42 | /* for keeping track of orphaned inodes */ | 42 | /* for keeping track of orphaned inodes */ |
43 | struct list_head i_orphan; | 43 | struct list_head i_orphan; |
44 | 44 | ||
45 | struct list_head delalloc_inodes; | ||
46 | |||
45 | /* | 47 | /* |
46 | * transid of the trans_handle that last modified this inode | 48 | * transid of the trans_handle that last modified this inode |
47 | */ | 49 | */ |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 62499dd761b7..116aee21bf77 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -551,6 +551,7 @@ struct btrfs_fs_info { | |||
551 | */ | 551 | */ |
552 | spinlock_t ordered_extent_lock; | 552 | spinlock_t ordered_extent_lock; |
553 | struct list_head ordered_extents; | 553 | struct list_head ordered_extents; |
554 | struct list_head delalloc_inodes; | ||
554 | 555 | ||
555 | /* | 556 | /* |
556 | * there is a pool of worker threads for checksumming during writes | 557 | * there is a pool of worker threads for checksumming during writes |
@@ -637,6 +638,7 @@ struct btrfs_root { | |||
637 | struct kobject root_kobj; | 638 | struct kobject root_kobj; |
638 | struct completion kobj_unregister; | 639 | struct completion kobj_unregister; |
639 | struct mutex objectid_mutex; | 640 | struct mutex objectid_mutex; |
641 | |||
640 | u64 objectid; | 642 | u64 objectid; |
641 | u64 last_trans; | 643 | u64 last_trans; |
642 | 644 | ||
@@ -1651,6 +1653,8 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | |||
1651 | #define PageChecked PageFsMisc | 1653 | #define PageChecked PageFsMisc |
1652 | #endif | 1654 | #endif |
1653 | 1655 | ||
1656 | int btrfs_start_delalloc_inodes(struct btrfs_root *root); | ||
1657 | int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end); | ||
1654 | int btrfs_writepages(struct address_space *mapping, | 1658 | int btrfs_writepages(struct address_space *mapping, |
1655 | struct writeback_control *wbc); | 1659 | struct writeback_control *wbc); |
1656 | int btrfs_create_subvol_root(struct btrfs_root *new_root, | 1660 | int btrfs_create_subvol_root(struct btrfs_root *new_root, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index da9dda4338a3..76543683f3b9 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1234,6 +1234,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1234 | INIT_LIST_HEAD(&fs_info->trans_list); | 1234 | INIT_LIST_HEAD(&fs_info->trans_list); |
1235 | INIT_LIST_HEAD(&fs_info->dead_roots); | 1235 | INIT_LIST_HEAD(&fs_info->dead_roots); |
1236 | INIT_LIST_HEAD(&fs_info->hashers); | 1236 | INIT_LIST_HEAD(&fs_info->hashers); |
1237 | INIT_LIST_HEAD(&fs_info->delalloc_inodes); | ||
1237 | spin_lock_init(&fs_info->hash_lock); | 1238 | spin_lock_init(&fs_info->hash_lock); |
1238 | spin_lock_init(&fs_info->delalloc_lock); | 1239 | spin_lock_init(&fs_info->delalloc_lock); |
1239 | spin_lock_init(&fs_info->new_trans_lock); | 1240 | spin_lock_init(&fs_info->new_trans_lock); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index dbde12881244..33cb2ac4cb28 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1230,7 +1230,6 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1230 | found->total_bytes += total_bytes; | 1230 | found->total_bytes += total_bytes; |
1231 | found->bytes_used += bytes_used; | 1231 | found->bytes_used += bytes_used; |
1232 | found->full = 0; | 1232 | found->full = 0; |
1233 | WARN_ON(found->total_bytes < found->bytes_used); | ||
1234 | *space_info = found; | 1233 | *space_info = found; |
1235 | return 0; | 1234 | return 0; |
1236 | } | 1235 | } |
@@ -2841,8 +2840,7 @@ again: | |||
2841 | */ | 2840 | */ |
2842 | clear_page_dirty_for_io(page); | 2841 | clear_page_dirty_for_io(page); |
2843 | 2842 | ||
2844 | set_extent_delalloc(io_tree, page_start, | 2843 | btrfs_set_extent_delalloc(inode, page_start, page_end); |
2845 | page_end, GFP_NOFS); | ||
2846 | set_page_dirty(page); | 2844 | set_page_dirty(page); |
2847 | 2845 | ||
2848 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | 2846 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); |
@@ -3319,6 +3317,13 @@ again: | |||
3319 | key.type = 0; | 3317 | key.type = 0; |
3320 | cur_byte = key.objectid; | 3318 | cur_byte = key.objectid; |
3321 | 3319 | ||
3320 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
3321 | |||
3322 | btrfs_start_delalloc_inodes(root); | ||
3323 | btrfs_wait_ordered_extents(tree_root); | ||
3324 | |||
3325 | mutex_lock(&root->fs_info->alloc_mutex); | ||
3326 | |||
3322 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 3327 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
3323 | if (ret < 0) | 3328 | if (ret < 0) |
3324 | goto out; | 3329 | goto out; |
@@ -3401,6 +3406,7 @@ next: | |||
3401 | 3406 | ||
3402 | btrfs_clean_old_snapshots(tree_root); | 3407 | btrfs_clean_old_snapshots(tree_root); |
3403 | 3408 | ||
3409 | btrfs_start_delalloc_inodes(root); | ||
3404 | btrfs_wait_ordered_extents(tree_root); | 3410 | btrfs_wait_ordered_extents(tree_root); |
3405 | 3411 | ||
3406 | trans = btrfs_start_transaction(tree_root, 1); | 3412 | trans = btrfs_start_transaction(tree_root, 1); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 8915f2dc1bce..eb8e4556fa71 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -312,8 +312,7 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
312 | * to reset the delalloc bit on things that already have | 312 | * to reset the delalloc bit on things that already have |
313 | * extents reserved. | 313 | * extents reserved. |
314 | */ | 314 | */ |
315 | set_extent_delalloc(io_tree, start_pos, | 315 | btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block); |
316 | end_of_last_block, GFP_NOFS); | ||
317 | for (i = 0; i < num_pages; i++) { | 316 | for (i = 0; i < num_pages; i++) { |
318 | struct page *p = pages[i]; | 317 | struct page *p = pages[i]; |
319 | SetPageUptodate(p); | 318 | SetPageUptodate(p); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 640648c66b22..8a405a5fa6a3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -303,6 +303,10 @@ int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, | |||
303 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); | 303 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); |
304 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; | 304 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; |
305 | root->fs_info->delalloc_bytes += end - start + 1; | 305 | root->fs_info->delalloc_bytes += end - start + 1; |
306 | if (list_empty(&BTRFS_I(inode)->delalloc_inodes)) { | ||
307 | list_add_tail(&BTRFS_I(inode)->delalloc_inodes, | ||
308 | &root->fs_info->delalloc_inodes); | ||
309 | } | ||
306 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | 310 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); |
307 | } | 311 | } |
308 | return 0; | 312 | return 0; |
@@ -325,6 +329,10 @@ int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end, | |||
325 | root->fs_info->delalloc_bytes -= end - start + 1; | 329 | root->fs_info->delalloc_bytes -= end - start + 1; |
326 | BTRFS_I(inode)->delalloc_bytes -= end - start + 1; | 330 | BTRFS_I(inode)->delalloc_bytes -= end - start + 1; |
327 | } | 331 | } |
332 | if (BTRFS_I(inode)->delalloc_bytes == 0 && | ||
333 | !list_empty(&BTRFS_I(inode)->delalloc_inodes)) { | ||
334 | list_del_init(&BTRFS_I(inode)->delalloc_inodes); | ||
335 | } | ||
328 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | 336 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); |
329 | } | 337 | } |
330 | return 0; | 338 | return 0; |
@@ -408,6 +416,12 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans, | |||
408 | return 0; | 416 | return 0; |
409 | } | 417 | } |
410 | 418 | ||
419 | int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end) | ||
420 | { | ||
421 | return set_extent_delalloc(&BTRFS_I(inode)->io_tree, start, end, | ||
422 | GFP_NOFS); | ||
423 | } | ||
424 | |||
411 | struct btrfs_writepage_fixup { | 425 | struct btrfs_writepage_fixup { |
412 | struct page *page; | 426 | struct page *page; |
413 | struct btrfs_work work; | 427 | struct btrfs_work work; |
@@ -453,8 +467,7 @@ again: | |||
453 | goto again; | 467 | goto again; |
454 | } | 468 | } |
455 | 469 | ||
456 | set_extent_delalloc(&BTRFS_I(inode)->io_tree, page_start, page_end, | 470 | btrfs_set_extent_delalloc(inode, page_start, page_end); |
457 | GFP_NOFS); | ||
458 | ClearPageChecked(page); | 471 | ClearPageChecked(page); |
459 | out: | 472 | out: |
460 | unlock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end, GFP_NOFS); | 473 | unlock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end, GFP_NOFS); |
@@ -1530,8 +1543,7 @@ again: | |||
1530 | goto again; | 1543 | goto again; |
1531 | } | 1544 | } |
1532 | 1545 | ||
1533 | set_extent_delalloc(&BTRFS_I(inode)->io_tree, page_start, | 1546 | btrfs_set_extent_delalloc(inode, page_start, page_end); |
1534 | page_end, GFP_NOFS); | ||
1535 | ret = 0; | 1547 | ret = 0; |
1536 | if (offset != PAGE_CACHE_SIZE) { | 1548 | if (offset != PAGE_CACHE_SIZE) { |
1537 | kaddr = kmap(page); | 1549 | kaddr = kmap(page); |
@@ -1766,6 +1778,7 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p) | |||
1766 | inode->i_mapping, GFP_NOFS); | 1778 | inode->i_mapping, GFP_NOFS); |
1767 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 1779 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
1768 | inode->i_mapping, GFP_NOFS); | 1780 | inode->i_mapping, GFP_NOFS); |
1781 | INIT_LIST_HEAD(&BTRFS_I(inode)->delalloc_inodes); | ||
1769 | btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree); | 1782 | btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree); |
1770 | mutex_init(&BTRFS_I(inode)->csum_mutex); | 1783 | mutex_init(&BTRFS_I(inode)->csum_mutex); |
1771 | mutex_init(&BTRFS_I(inode)->extent_mutex); | 1784 | mutex_init(&BTRFS_I(inode)->extent_mutex); |
@@ -2158,6 +2171,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
2158 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 2171 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
2159 | inode->i_mapping, GFP_NOFS); | 2172 | inode->i_mapping, GFP_NOFS); |
2160 | btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree); | 2173 | btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree); |
2174 | INIT_LIST_HEAD(&BTRFS_I(inode)->delalloc_inodes); | ||
2161 | mutex_init(&BTRFS_I(inode)->csum_mutex); | 2175 | mutex_init(&BTRFS_I(inode)->csum_mutex); |
2162 | mutex_init(&BTRFS_I(inode)->extent_mutex); | 2176 | mutex_init(&BTRFS_I(inode)->extent_mutex); |
2163 | BTRFS_I(inode)->delalloc_bytes = 0; | 2177 | BTRFS_I(inode)->delalloc_bytes = 0; |
@@ -2400,6 +2414,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
2400 | inode->i_mapping, GFP_NOFS); | 2414 | inode->i_mapping, GFP_NOFS); |
2401 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 2415 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
2402 | inode->i_mapping, GFP_NOFS); | 2416 | inode->i_mapping, GFP_NOFS); |
2417 | INIT_LIST_HEAD(&BTRFS_I(inode)->delalloc_inodes); | ||
2403 | mutex_init(&BTRFS_I(inode)->csum_mutex); | 2418 | mutex_init(&BTRFS_I(inode)->csum_mutex); |
2404 | mutex_init(&BTRFS_I(inode)->extent_mutex); | 2419 | mutex_init(&BTRFS_I(inode)->extent_mutex); |
2405 | BTRFS_I(inode)->delalloc_bytes = 0; | 2420 | BTRFS_I(inode)->delalloc_bytes = 0; |
@@ -3049,8 +3064,7 @@ again: | |||
3049 | goto again; | 3064 | goto again; |
3050 | } | 3065 | } |
3051 | 3066 | ||
3052 | set_extent_delalloc(&BTRFS_I(inode)->io_tree, page_start, | 3067 | btrfs_set_extent_delalloc(inode, page_start, page_end); |
3053 | page_end, GFP_NOFS); | ||
3054 | ret = 0; | 3068 | ret = 0; |
3055 | 3069 | ||
3056 | /* page is wholly or partially inside EOF */ | 3070 | /* page is wholly or partially inside EOF */ |
@@ -3373,6 +3387,26 @@ out_unlock: | |||
3373 | return ret; | 3387 | return ret; |
3374 | } | 3388 | } |
3375 | 3389 | ||
3390 | int btrfs_start_delalloc_inodes(struct btrfs_root *root) | ||
3391 | { | ||
3392 | struct list_head *head = &root->fs_info->delalloc_inodes; | ||
3393 | struct btrfs_inode *binode; | ||
3394 | unsigned long flags; | ||
3395 | |||
3396 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); | ||
3397 | while(!list_empty(head)) { | ||
3398 | binode = list_entry(head->next, struct btrfs_inode, | ||
3399 | delalloc_inodes); | ||
3400 | atomic_inc(&binode->vfs_inode.i_count); | ||
3401 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | ||
3402 | filemap_write_and_wait(binode->vfs_inode.i_mapping); | ||
3403 | iput(&binode->vfs_inode); | ||
3404 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); | ||
3405 | } | ||
3406 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | ||
3407 | return 0; | ||
3408 | } | ||
3409 | |||
3376 | static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | 3410 | static int btrfs_symlink(struct inode *dir, struct dentry *dentry, |
3377 | const char *symname) | 3411 | const char *symname) |
3378 | { | 3412 | { |
@@ -3436,6 +3470,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
3436 | inode->i_mapping, GFP_NOFS); | 3470 | inode->i_mapping, GFP_NOFS); |
3437 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 3471 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
3438 | inode->i_mapping, GFP_NOFS); | 3472 | inode->i_mapping, GFP_NOFS); |
3473 | INIT_LIST_HEAD(&BTRFS_I(inode)->delalloc_inodes); | ||
3439 | mutex_init(&BTRFS_I(inode)->csum_mutex); | 3474 | mutex_init(&BTRFS_I(inode)->csum_mutex); |
3440 | mutex_init(&BTRFS_I(inode)->extent_mutex); | 3475 | mutex_init(&BTRFS_I(inode)->extent_mutex); |
3441 | BTRFS_I(inode)->delalloc_bytes = 0; | 3476 | BTRFS_I(inode)->delalloc_bytes = 0; |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0b63c3c77cfd..e1046a54b1c5 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -274,8 +274,7 @@ again: | |||
274 | */ | 274 | */ |
275 | clear_page_dirty_for_io(page); | 275 | clear_page_dirty_for_io(page); |
276 | 276 | ||
277 | set_extent_delalloc(io_tree, page_start, | 277 | btrfs_set_extent_delalloc(inode, page_start, page_end); |
278 | page_end, GFP_NOFS); | ||
279 | 278 | ||
280 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); | 279 | unlock_extent(io_tree, page_start, page_end, GFP_NOFS); |
281 | set_page_dirty(page); | 280 | set_page_dirty(page); |
@@ -784,6 +783,7 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
784 | case BTRFS_IOC_TRANS_END: | 783 | case BTRFS_IOC_TRANS_END: |
785 | return btrfs_ioctl_trans_end(file); | 784 | return btrfs_ioctl_trans_end(file); |
786 | case BTRFS_IOC_SYNC: | 785 | case BTRFS_IOC_SYNC: |
786 | btrfs_start_delalloc_inodes(root); | ||
787 | btrfs_sync_fs(file->f_dentry->d_sb, 1); | 787 | btrfs_sync_fs(file->f_dentry->d_sb, 1); |
788 | return 0; | 788 | return 0; |
789 | } | 789 | } |