aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/write.c')
-rw-r--r--fs/afs/write.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 9370e2feb999..8b39e6ebb40b 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -42,10 +42,11 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
if (!req)
return -ENOMEM;
- atomic_set(&req->usage, 1);
+ refcount_set(&req->usage, 1);
req->pos = pos;
req->len = len;
req->nr_pages = 1;
+ req->pages = req->array;
req->pages[0] = page;
get_page(page);
@@ -124,7 +125,12 @@ try_again:
page->index, priv);
goto flush_conflicting_write;
}
- if (to < f || from > t)
+ /* If the file is being filled locally, allow inter-write
+ * spaces to be merged into writes. If it's not, only write
+ * back what the user gives us.
+ */
+ if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) &&
+ (to < f || from > t))
goto flush_conflicting_write;
if (from < f)
f = from;
@@ -345,7 +351,7 @@ found_key:
ret = -ERESTARTSYS;
if (afs_begin_vnode_operation(&fc, vnode, wbk->key)) {
while (afs_select_fileserver(&fc)) {
- fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+ fc.cb_break = afs_calc_vnode_cb_break(vnode);
afs_fs_store_data(&fc, mapping, first, last, offset, to);
}
@@ -355,6 +361,12 @@ found_key:
}
switch (ret) {
+ case 0:
+ afs_stat_v(vnode, n_stores);
+ atomic_long_add((last * PAGE_SIZE + to) -
+ (first * PAGE_SIZE + offset),
+ &afs_v2net(vnode)->n_store_bytes);
+ break;
case -EACCES:
case -EPERM:
case -ENOKEY:
@@ -412,7 +424,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
trace_afs_page_dirty(vnode, tracepoint_string("WARN"),
primary_page->index, priv);
- if (start >= final_page || to < PAGE_SIZE)
+ if (start >= final_page ||
+ (to < PAGE_SIZE && !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)))
goto no_more;
start++;
@@ -433,9 +446,10 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
}
for (loop = 0; loop < n; loop++) {
- if (to != PAGE_SIZE)
- break;
page = pages[loop];
+ if (to != PAGE_SIZE &&
+ !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags))
+ break;
if (page->index > final_page)
break;
if (!trylock_page(page))
@@ -448,7 +462,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
priv = page_private(page);
f = priv & AFS_PRIV_MAX;
t = priv >> AFS_PRIV_SHIFT;
- if (f != 0) {
+ if (f != 0 &&
+ !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)) {
unlock_page(page);
break;
}
@@ -570,10 +585,11 @@ static int afs_writepages_region(struct address_space *mapping,
_debug("wback %lx", page->index);
- /* at this point we hold neither mapping->tree_lock nor lock on
- * the page itself: the page may be truncated or invalidated
- * (changing page->mapping to NULL), or even swizzled back from
- * swapper_space to tmpfs file mapping
+ /*
+ * at this point we hold neither the i_pages lock nor the
+ * page lock: the page may be truncated or invalidated
+ * (changing page->mapping to NULL), or even swizzled
+ * back from swapper_space to tmpfs file mapping
*/
ret = lock_page_killable(page);
if (ret < 0) {
@@ -734,20 +750,6 @@ int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
}
/*
- * Flush out all outstanding writes on a file opened for writing when it is
- * closed.
- */
-int afs_flush(struct file *file, fl_owner_t id)
-{
- _enter("");
-
- if ((file->f_mode & FMODE_WRITE) == 0)
- return 0;
-
- return vfs_fsync(file, 0);
-}
-
-/*
* notification that a previously read-only page is about to become writable
* - if it returns an error, the caller will deliver a bus error signal
*/