diff options
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 7ba58386beee..39ff14403d13 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -1181,7 +1181,20 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) | |||
1181 | void mark_buffer_dirty(struct buffer_head *bh) | 1181 | void mark_buffer_dirty(struct buffer_head *bh) |
1182 | { | 1182 | { |
1183 | WARN_ON_ONCE(!buffer_uptodate(bh)); | 1183 | WARN_ON_ONCE(!buffer_uptodate(bh)); |
1184 | if (!buffer_dirty(bh) && !test_set_buffer_dirty(bh)) | 1184 | |
1185 | /* | ||
1186 | * Very *carefully* optimize the it-is-already-dirty case. | ||
1187 | * | ||
1188 | * Don't let the final "is it dirty" escape to before we | ||
1189 | * perhaps modified the buffer. | ||
1190 | */ | ||
1191 | if (buffer_dirty(bh)) { | ||
1192 | smp_mb(); | ||
1193 | if (buffer_dirty(bh)) | ||
1194 | return; | ||
1195 | } | ||
1196 | |||
1197 | if (!test_set_buffer_dirty(bh)) | ||
1185 | __set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0); | 1198 | __set_page_dirty(bh->b_page, page_mapping(bh->b_page), 0); |
1186 | } | 1199 | } |
1187 | 1200 | ||
@@ -2564,14 +2577,13 @@ int nobh_write_end(struct file *file, struct address_space *mapping, | |||
2564 | struct inode *inode = page->mapping->host; | 2577 | struct inode *inode = page->mapping->host; |
2565 | struct buffer_head *head = fsdata; | 2578 | struct buffer_head *head = fsdata; |
2566 | struct buffer_head *bh; | 2579 | struct buffer_head *bh; |
2580 | BUG_ON(fsdata != NULL && page_has_buffers(page)); | ||
2567 | 2581 | ||
2568 | if (!PageMappedToDisk(page)) { | 2582 | if (unlikely(copied < len) && !page_has_buffers(page)) |
2569 | if (unlikely(copied < len) && !page_has_buffers(page)) | 2583 | attach_nobh_buffers(page, head); |
2570 | attach_nobh_buffers(page, head); | 2584 | if (page_has_buffers(page)) |
2571 | if (page_has_buffers(page)) | 2585 | return generic_write_end(file, mapping, pos, len, |
2572 | return generic_write_end(file, mapping, pos, len, | 2586 | copied, page, fsdata); |
2573 | copied, page, fsdata); | ||
2574 | } | ||
2575 | 2587 | ||
2576 | SetPageUptodate(page); | 2588 | SetPageUptodate(page); |
2577 | set_page_dirty(page); | 2589 | set_page_dirty(page); |