aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-08-04 23:17:27 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:06 -0400
commitea8c281947950fac5f78818b767821d696c9512a (patch)
treea30e9da5371d9a694a8f73d450231107ccad1dcb /fs
parentd7a029a89ef370e74b63f18b81498d90d1ee3cc1 (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')
-rw-r--r--fs/btrfs/btrfs_inode.h2
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c1
-rw-r--r--fs/btrfs/extent-tree.c12
-rw-r--r--fs/btrfs/file.c3
-rw-r--r--fs/btrfs/inode.c47
-rw-r--r--fs/btrfs/ioctl.c4
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
1656int btrfs_start_delalloc_inodes(struct btrfs_root *root);
1657int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end);
1654int btrfs_writepages(struct address_space *mapping, 1658int btrfs_writepages(struct address_space *mapping,
1655 struct writeback_control *wbc); 1659 struct writeback_control *wbc);
1656int btrfs_create_subvol_root(struct btrfs_root *new_root, 1660int 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
419int 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
411struct btrfs_writepage_fixup { 425struct 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);
459out: 472out:
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
3390int 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
3376static int btrfs_symlink(struct inode *dir, struct dentry *dentry, 3410static 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 }