aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/inode.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 7875a2dd54b9..b1a6a7373f07 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2458,6 +2458,33 @@ out_writepages:
2458 return ret; 2458 return ret;
2459} 2459}
2460 2460
2461#define FALL_BACK_TO_NONDELALLOC 1
2462static int ext4_nonda_switch(struct super_block *sb)
2463{
2464 s64 free_blocks, dirty_blocks;
2465 struct ext4_sb_info *sbi = EXT4_SB(sb);
2466
2467 /*
2468 * switch to non delalloc mode if we are running low
2469 * on free block. The free block accounting via percpu
2470 * counters can get slightly wrong with FBC_BATCH getting
2471 * accumulated on each CPU without updating global counters
2472 * Delalloc need an accurate free block accounting. So switch
2473 * to non delalloc when we are near to error range.
2474 */
2475 free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
2476 dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyblocks_counter);
2477 if (2 * free_blocks < 3 * dirty_blocks ||
2478 free_blocks < (dirty_blocks + EXT4_FREEBLOCKS_WATERMARK)) {
2479 /*
2480 * free block count is less that 150% of dirty blocks
2481 * or free blocks is less that watermark
2482 */
2483 return 1;
2484 }
2485 return 0;
2486}
2487
2461static int ext4_da_write_begin(struct file *file, struct address_space *mapping, 2488static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
2462 loff_t pos, unsigned len, unsigned flags, 2489 loff_t pos, unsigned len, unsigned flags,
2463 struct page **pagep, void **fsdata) 2490 struct page **pagep, void **fsdata)
@@ -2472,6 +2499,13 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
2472 index = pos >> PAGE_CACHE_SHIFT; 2499 index = pos >> PAGE_CACHE_SHIFT;
2473 from = pos & (PAGE_CACHE_SIZE - 1); 2500 from = pos & (PAGE_CACHE_SIZE - 1);
2474 to = from + len; 2501 to = from + len;
2502
2503 if (ext4_nonda_switch(inode->i_sb)) {
2504 *fsdata = (void *)FALL_BACK_TO_NONDELALLOC;
2505 return ext4_write_begin(file, mapping, pos,
2506 len, flags, pagep, fsdata);
2507 }
2508 *fsdata = (void *)0;
2475retry: 2509retry:
2476 /* 2510 /*
2477 * With delayed allocation, we don't log the i_disksize update 2511 * With delayed allocation, we don't log the i_disksize update
@@ -2540,6 +2574,19 @@ static int ext4_da_write_end(struct file *file,
2540 handle_t *handle = ext4_journal_current_handle(); 2574 handle_t *handle = ext4_journal_current_handle();
2541 loff_t new_i_size; 2575 loff_t new_i_size;
2542 unsigned long start, end; 2576 unsigned long start, end;
2577 int write_mode = (int)(unsigned long)fsdata;
2578
2579 if (write_mode == FALL_BACK_TO_NONDELALLOC) {
2580 if (ext4_should_order_data(inode)) {
2581 return ext4_ordered_write_end(file, mapping, pos,
2582 len, copied, page, fsdata);
2583 } else if (ext4_should_writeback_data(inode)) {
2584 return ext4_writeback_write_end(file, mapping, pos,
2585 len, copied, page, fsdata);
2586 } else {
2587 BUG();
2588 }
2589 }
2543 2590
2544 start = pos & (PAGE_CACHE_SIZE - 1); 2591 start = pos & (PAGE_CACHE_SIZE - 1);
2545 end = start + copied - 1; 2592 end = start + copied - 1;
@@ -4877,6 +4924,7 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page)
4877 loff_t size; 4924 loff_t size;
4878 unsigned long len; 4925 unsigned long len;
4879 int ret = -EINVAL; 4926 int ret = -EINVAL;
4927 void *fsdata;
4880 struct file *file = vma->vm_file; 4928 struct file *file = vma->vm_file;
4881 struct inode *inode = file->f_path.dentry->d_inode; 4929 struct inode *inode = file->f_path.dentry->d_inode;
4882 struct address_space *mapping = inode->i_mapping; 4930 struct address_space *mapping = inode->i_mapping;
@@ -4915,11 +4963,11 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page)
4915 * on the same page though 4963 * on the same page though
4916 */ 4964 */
4917 ret = mapping->a_ops->write_begin(file, mapping, page_offset(page), 4965 ret = mapping->a_ops->write_begin(file, mapping, page_offset(page),
4918 len, AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); 4966 len, AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
4919 if (ret < 0) 4967 if (ret < 0)
4920 goto out_unlock; 4968 goto out_unlock;
4921 ret = mapping->a_ops->write_end(file, mapping, page_offset(page), 4969 ret = mapping->a_ops->write_end(file, mapping, page_offset(page),
4922 len, len, page, NULL); 4970 len, len, page, fsdata);
4923 if (ret < 0) 4971 if (ret < 0)
4924 goto out_unlock; 4972 goto out_unlock;
4925 ret = 0; 4973 ret = 0;