Commit f792e3ac authored by David Howells's avatar David Howells

afs: Fix where page->private is set during write

In afs, page->private is set to indicate the dirty region of a page.  This
is done in afs_write_begin(), but that can't take account of whether the
copy into the page actually worked.

Fix this by moving the change of page->private into afs_write_end().

Fixes: 4343d008 ("afs: Get rid of the afs_writeback record")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 21db2cdc
...@@ -135,23 +135,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping, ...@@ -135,23 +135,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) && if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) &&
(to < f || from > t)) (to < f || from > t))
goto flush_conflicting_write; goto flush_conflicting_write;
if (from < f)
f = from;
if (to > t)
t = to;
} else {
f = from;
t = to;
} }
priv = (unsigned long)t << AFS_PRIV_SHIFT;
priv |= f;
trace_afs_page_dirty(vnode, tracepoint_string("begin"),
page->index, priv);
if (PagePrivate(page))
set_page_private(page, priv);
else
attach_page_private(page, (void *)priv);
*_page = page; *_page = page;
_leave(" = 0"); _leave(" = 0");
return 0; return 0;
...@@ -185,6 +170,9 @@ int afs_write_end(struct file *file, struct address_space *mapping, ...@@ -185,6 +170,9 @@ int afs_write_end(struct file *file, struct address_space *mapping,
{ {
struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
struct key *key = afs_file_key(file); struct key *key = afs_file_key(file);
unsigned long priv;
unsigned int f, from = pos & (PAGE_SIZE - 1);
unsigned int t, to = from + copied;
loff_t i_size, maybe_i_size; loff_t i_size, maybe_i_size;
int ret; int ret;
...@@ -216,6 +204,29 @@ int afs_write_end(struct file *file, struct address_space *mapping, ...@@ -216,6 +204,29 @@ int afs_write_end(struct file *file, struct address_space *mapping,
SetPageUptodate(page); SetPageUptodate(page);
} }
if (PagePrivate(page)) {
priv = page_private(page);
f = priv & AFS_PRIV_MAX;
t = priv >> AFS_PRIV_SHIFT;
if (from < f)
f = from;
if (to > t)
t = to;
priv = (unsigned long)t << AFS_PRIV_SHIFT;
priv |= f;
set_page_private(page, priv);
trace_afs_page_dirty(vnode, tracepoint_string("dirty+"),
page->index, priv);
} else {
f = from;
t = to;
priv = (unsigned long)t << AFS_PRIV_SHIFT;
priv |= f;
attach_page_private(page, (void *)priv);
trace_afs_page_dirty(vnode, tracepoint_string("dirty"),
page->index, priv);
}
set_page_dirty(page); set_page_dirty(page);
if (PageDirty(page)) if (PageDirty(page))
_debug("dirtied"); _debug("dirtied");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment