|
@@ -1181,6 +1181,38 @@ errout:
|
|
|
return ret ? ret : copied;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * This is a private version of page_zero_new_buffers() which doesn't
|
|
|
+ * set the buffer to be dirty, since in data=journalled mode we need
|
|
|
+ * to call ext4_handle_dirty_metadata() instead.
|
|
|
+ */
|
|
|
+static void zero_new_buffers(struct page *page, unsigned from, unsigned to)
|
|
|
+{
|
|
|
+ unsigned int block_start = 0, block_end;
|
|
|
+ struct buffer_head *head, *bh;
|
|
|
+
|
|
|
+ bh = head = page_buffers(page);
|
|
|
+ do {
|
|
|
+ block_end = block_start + bh->b_size;
|
|
|
+ if (buffer_new(bh)) {
|
|
|
+ if (block_end > from && block_start < to) {
|
|
|
+ if (!PageUptodate(page)) {
|
|
|
+ unsigned start, size;
|
|
|
+
|
|
|
+ start = max(from, block_start);
|
|
|
+ size = min(to, block_end) - start;
|
|
|
+
|
|
|
+ zero_user(page, start, size);
|
|
|
+ set_buffer_uptodate(bh);
|
|
|
+ }
|
|
|
+ clear_buffer_new(bh);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ block_start = block_end;
|
|
|
+ bh = bh->b_this_page;
|
|
|
+ } while (bh != head);
|
|
|
+}
|
|
|
+
|
|
|
static int ext4_journalled_write_end(struct file *file,
|
|
|
struct address_space *mapping,
|
|
|
loff_t pos, unsigned len, unsigned copied,
|
|
@@ -1207,7 +1239,7 @@ static int ext4_journalled_write_end(struct file *file,
|
|
|
if (copied < len) {
|
|
|
if (!PageUptodate(page))
|
|
|
copied = 0;
|
|
|
- page_zero_new_buffers(page, from+copied, to);
|
|
|
+ zero_new_buffers(page, from+copied, to);
|
|
|
}
|
|
|
|
|
|
ret = ext4_walk_page_buffers(handle, page_buffers(page), from,
|