|
@@ -219,13 +219,32 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc)
|
|
|
|
|
|
static int nilfs_set_page_dirty(struct page *page)
|
|
|
{
|
|
|
- int ret = __set_page_dirty_buffers(page);
|
|
|
+ int ret = __set_page_dirty_nobuffers(page);
|
|
|
|
|
|
- if (ret) {
|
|
|
+ if (page_has_buffers(page)) {
|
|
|
struct inode *inode = page->mapping->host;
|
|
|
- unsigned nr_dirty = 1 << (PAGE_SHIFT - inode->i_blkbits);
|
|
|
+ unsigned nr_dirty = 0;
|
|
|
+ struct buffer_head *bh, *head;
|
|
|
|
|
|
- nilfs_set_file_dirty(inode, nr_dirty);
|
|
|
+ /*
|
|
|
+ * This page is locked by callers, and no other thread
|
|
|
+ * concurrently marks its buffers dirty since they are
|
|
|
+ * only dirtied through routines in fs/buffer.c in
|
|
|
+ * which call sites of mark_buffer_dirty are protected
|
|
|
+ * by page lock.
|
|
|
+ */
|
|
|
+ bh = head = page_buffers(page);
|
|
|
+ do {
|
|
|
+ /* Do not mark hole blocks dirty */
|
|
|
+ if (buffer_dirty(bh) || !buffer_mapped(bh))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ set_buffer_dirty(bh);
|
|
|
+ nr_dirty++;
|
|
|
+ } while (bh = bh->b_this_page, bh != head);
|
|
|
+
|
|
|
+ if (nr_dirty)
|
|
|
+ nilfs_set_file_dirty(inode, nr_dirty);
|
|
|
}
|
|
|
return ret;
|
|
|
}
|