Skip to content

Commit 1d1d1a7

Browse files
djwongtorvalds
authored andcommitted
mm: only enforce stable page writes if the backing device requires it
Create a helper function to check if a backing device requires stable page writes and, if so, performs the necessary wait. Then, make it so that all points in the memory manager that handle making pages writable use the helper function. This should provide stable page write support to most filesystems, while eliminating unnecessary waiting for devices that don't require the feature. Before this patchset, all filesystems would block, regardless of whether or not it was necessary. ext3 would wait, but still generate occasional checksum errors. The network filesystems were left to do their own thing, so they'd wait too. After this patchset, all the disk filesystems except ext3 and btrfs will wait only if the hardware requires it. ext3 (if necessary) snapshots pages instead of blocking, and btrfs provides its own bdi so the mm will never wait. Network filesystems haven't been touched, so either they provide their own stable page guarantees or they don't block at all. The blocking behavior is back to what it was before 3.0 if you don't have a disk requiring stable page writes. Here's the result of using dbench to test latency on ext2: 3.8.0-rc3: Operation Count AvgLat MaxLat ---------------------------------------- WriteX 109347 0.028 59.817 ReadX 347180 0.004 3.391 Flush 15514 29.828 287.283 Throughput 57.429 MB/sec 4 clients 4 procs max_latency=287.290 ms 3.8.0-rc3 + patches: WriteX 105556 0.029 4.273 ReadX 335004 0.005 4.112 Flush 14982 30.540 298.634 Throughput 55.4496 MB/sec 4 clients 4 procs max_latency=298.650 ms As you can see, the maximum write latency drops considerably with this patch enabled. The other filesystems (ext3/ext4/xfs/btrfs) behave similarly, but see the cover letter for those results. Signed-off-by: Darrick J. Wong <[email protected]> Acked-by: Steven Whitehouse <[email protected]> Reviewed-by: Jan Kara <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Artem Bityutskiy <[email protected]> Cc: Joel Becker <[email protected]> Cc: Mark Fasheh <[email protected]> Cc: Jens Axboe <[email protected]> Cc: Eric Van Hensbergen <[email protected]> Cc: Ron Minnich <[email protected]> Cc: Latchesar Ionkov <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 7d311cd commit 1d1d1a7

File tree

7 files changed

+27
-5
lines changed

7 files changed

+27
-5
lines changed

fs/buffer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2359,7 +2359,7 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
23592359
if (unlikely(ret < 0))
23602360
goto out_unlock;
23612361
set_page_dirty(page);
2362-
wait_on_page_writeback(page);
2362+
wait_for_stable_page(page);
23632363
return 0;
23642364
out_unlock:
23652365
unlock_page(page);

fs/ext4/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4968,7 +4968,7 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
49684968
0, len, NULL,
49694969
ext4_bh_unmapped)) {
49704970
/* Wait so that we don't change page under IO */
4971-
wait_on_page_writeback(page);
4971+
wait_for_stable_page(page);
49724972
ret = VM_FAULT_LOCKED;
49734973
goto out;
49744974
}

fs/gfs2/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
483483
gfs2_holder_uninit(&gh);
484484
if (ret == 0) {
485485
set_page_dirty(page);
486-
wait_on_page_writeback(page);
486+
wait_for_stable_page(page);
487487
}
488488
sb_end_pagefault(inode->i_sb);
489489
return block_page_mkwrite_return(ret);

fs/nilfs2/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
126126
nilfs_transaction_commit(inode->i_sb);
127127

128128
mapped:
129-
wait_on_page_writeback(page);
129+
wait_for_stable_page(page);
130130
out:
131131
sb_end_pagefault(inode->i_sb);
132132
return block_page_mkwrite_return(ret);

include/linux/pagemap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ static inline void wait_on_page_writeback(struct page *page)
414414
}
415415

416416
extern void end_page_writeback(struct page *page);
417+
void wait_for_stable_page(struct page *page);
417418

418419
/*
419420
* Add an arbitrary waiter to a page's wait queue

mm/filemap.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,6 +1728,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
17281728
* see the dirty page and writeprotect it again.
17291729
*/
17301730
set_page_dirty(page);
1731+
wait_for_stable_page(page);
17311732
out:
17321733
sb_end_pagefault(inode->i_sb);
17331734
return ret;
@@ -2274,7 +2275,7 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping,
22742275
return NULL;
22752276
}
22762277
found:
2277-
wait_on_page_writeback(page);
2278+
wait_for_stable_page(page);
22782279
return page;
22792280
}
22802281
EXPORT_SYMBOL(grab_cache_page_write_begin);

mm/page-writeback.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,3 +2290,23 @@ int mapping_tagged(struct address_space *mapping, int tag)
22902290
return radix_tree_tagged(&mapping->page_tree, tag);
22912291
}
22922292
EXPORT_SYMBOL(mapping_tagged);
2293+
2294+
/**
2295+
* wait_for_stable_page() - wait for writeback to finish, if necessary.
2296+
* @page: The page to wait on.
2297+
*
2298+
* This function determines if the given page is related to a backing device
2299+
* that requires page contents to be held stable during writeback. If so, then
2300+
* it will wait for any pending writeback to complete.
2301+
*/
2302+
void wait_for_stable_page(struct page *page)
2303+
{
2304+
struct address_space *mapping = page_mapping(page);
2305+
struct backing_dev_info *bdi = mapping->backing_dev_info;
2306+
2307+
if (!bdi_cap_stable_pages_required(bdi))
2308+
return;
2309+
2310+
wait_on_page_writeback(page);
2311+
}
2312+
EXPORT_SYMBOL_GPL(wait_for_stable_page);

0 commit comments

Comments
 (0)