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); |
