Commit f792e3ac authored by David Howells's avatar David Howells
Browse files

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
Loading
Loading
Loading
Loading
+26 −15
Original line number Diff line number Diff line
@@ -135,23 +135,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
		if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) &&
		    (to < f || from > t))
			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;
	_leave(" = 0");
	return 0;
@@ -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 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;
	int ret;

@@ -216,6 +204,29 @@ int afs_write_end(struct file *file, struct address_space *mapping,
		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);
	if (PageDirty(page))
		_debug("dirtied");