VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
2874c5fd28426 (Thomas Gleixner         2019-05-27 08:55:01 +0200   1) // SPDX-License-Identifier: GPL-2.0-or-later
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700   2) /* handling of writes to regular files and writing back to the server
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700   3)  *
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700   4)  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700   5)  * Written by David Howells (dhowells@redhat.com)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700   6)  */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000   7) 
4af3c9cc4fad5 (Alexey Dobriyan         2007-10-16 23:29:23 -0700   8) #include <linux/backing-dev.h>
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700   9) #include <linux/slab.h>
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  10) #include <linux/fs.h>
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  11) #include <linux/pagemap.h>
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  12) #include <linux/writeback.h>
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  13) #include <linux/pagevec.h>
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  14) #include <linux/netfs.h>
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  15) #include <linux/fscache.h>
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  16) #include "internal.h"
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  17) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  18) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  19)  * mark a page as having been made dirty and thus needing writeback
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  20)  */
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  21) int afs_set_page_dirty(struct page *page)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  22) {
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  23) 	_enter("");
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  24) 	return __set_page_dirty_nobuffers(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  25) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  26) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  27) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  28)  * prepare to perform part of a write to a page
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  29)  */
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700  30) int afs_write_begin(struct file *file, struct address_space *mapping,
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700  31) 		    loff_t pos, unsigned len, unsigned flags,
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  32) 		    struct page **_page, void **fsdata)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  33) {
496ad9aa8ef44 (Al Viro                 2013-01-23 17:07:38 -0500  34) 	struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700  35) 	struct page *page;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  36) 	unsigned long priv;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  37) 	unsigned f, from;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  38) 	unsigned t, to;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  39) 	pgoff_t index;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  40) 	int ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  41) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  42) 	_enter("{%llx:%llu},%llx,%x",
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  43) 	       vnode->fid.vid, vnode->fid.vnode, pos, len);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  44) 
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  45) 	/* Prefetch area to be written into the cache if we're caching this
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  46) 	 * file.  We need to do this before we get a lock on the page in case
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  47) 	 * there's more than one writer competing for the same cache block.
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  48) 	 */
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  49) 	ret = netfs_write_begin(file, mapping, pos, len, flags, &page, fsdata,
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  50) 				&afs_req_ops, NULL);
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  51) 	if (ret < 0)
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000  52) 		return ret;
630f5dda8442c (David Howells           2020-02-06 14:22:28 +0000  53) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  54) 	index = page->index;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  55) 	from = pos - index * PAGE_SIZE;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  56) 	to = from + len;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100  57) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  58) try_again:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  59) 	/* See if this page is already partially written in a way that we can
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  60) 	 * merge the new write with.
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  61) 	 */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  62) 	if (PagePrivate(page)) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  63) 		priv = page_private(page);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000  64) 		f = afs_page_dirty_from(page, priv);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000  65) 		t = afs_page_dirty_to(page, priv);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  66) 		ASSERTCMP(f, <=, t);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  67) 
5a039c32271b9 (David Howells           2017-11-18 00:13:30 +0000  68) 		if (PageWriteback(page)) {
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000  69) 			trace_afs_page_dirty(vnode, tracepoint_string("alrdy"), page);
5a039c32271b9 (David Howells           2017-11-18 00:13:30 +0000  70) 			goto flush_conflicting_write;
5a039c32271b9 (David Howells           2017-11-18 00:13:30 +0000  71) 		}
5a8132761609b (David Howells           2018-04-06 14:17:26 +0100  72) 		/* If the file is being filled locally, allow inter-write
5a8132761609b (David Howells           2018-04-06 14:17:26 +0100  73) 		 * spaces to be merged into writes.  If it's not, only write
5a8132761609b (David Howells           2018-04-06 14:17:26 +0100  74) 		 * back what the user gives us.
5a8132761609b (David Howells           2018-04-06 14:17:26 +0100  75) 		 */
5a8132761609b (David Howells           2018-04-06 14:17:26 +0100  76) 		if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) &&
5a8132761609b (David Howells           2018-04-06 14:17:26 +0100  77) 		    (to < f || from > t))
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  78) 			goto flush_conflicting_write;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  79) 	}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  80) 
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  81) 	*_page = page;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  82) 	_leave(" = 0");
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  83) 	return 0;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  84) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  85) 	/* The previous write and this write aren't adjacent or overlapping, so
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  86) 	 * flush the page out.
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  87) 	 */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  88) flush_conflicting_write:
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  89) 	_debug("flush conflict");
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  90) 	ret = write_one_page(page);
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  91) 	if (ret < 0)
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  92) 		goto error;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  93) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000  94) 	ret = lock_page_killable(page);
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  95) 	if (ret < 0)
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  96) 		goto error;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700  97) 	goto try_again;
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  98) 
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100  99) error:
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100 100) 	put_page(page);
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100 101) 	_leave(" = %d", ret);
21db2cdc667f7 (David Howells           2020-10-22 14:03:03 +0100 102) 	return ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 103) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 104) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 105) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 106)  * finalise part of a write to a page
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 107)  */
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700 108) int afs_write_end(struct file *file, struct address_space *mapping,
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700 109) 		  loff_t pos, unsigned len, unsigned copied,
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700 110) 		  struct page *page, void *fsdata)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 111) {
496ad9aa8ef44 (Al Viro                 2013-01-23 17:07:38 -0500 112) 	struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 113) 	unsigned long priv;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 114) 	unsigned int f, from = pos & (thp_size(page) - 1);
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 115) 	unsigned int t, to = from + copied;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 116) 	loff_t i_size, maybe_i_size;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 117) 
3b6492df4153b (David Howells           2018-10-20 00:57:57 +0100 118) 	_enter("{%llx:%llu},{%lx}",
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700 119) 	       vnode->fid.vid, vnode->fid.vnode, page->index);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 120) 
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 121) 	if (!PageUptodate(page)) {
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 122) 		if (copied < len) {
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 123) 			copied = 0;
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 124) 			goto out;
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 125) 		}
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 126) 
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 127) 		SetPageUptodate(page);
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 128) 	}
66e9c6a86b800 (David Howells           2021-06-14 14:13:41 +0100 129) 
3ad216ee73abc (David Howells           2020-11-14 17:27:57 +0000 130) 	if (copied == 0)
3ad216ee73abc (David Howells           2020-11-14 17:27:57 +0000 131) 		goto out;
3ad216ee73abc (David Howells           2020-11-14 17:27:57 +0000 132) 
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700 133) 	maybe_i_size = pos + copied;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 134) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 135) 	i_size = i_size_read(&vnode->vfs_inode);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 136) 	if (maybe_i_size > i_size) {
1f32ef7989705 (David Howells           2020-06-12 23:58:51 +0100 137) 		write_seqlock(&vnode->cb_lock);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 138) 		i_size = i_size_read(&vnode->vfs_inode);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 139) 		if (maybe_i_size > i_size)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 140) 			i_size_write(&vnode->vfs_inode, maybe_i_size);
1f32ef7989705 (David Howells           2020-06-12 23:58:51 +0100 141) 		write_sequnlock(&vnode->cb_lock);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 142) 	}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 143) 
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 144) 	if (PagePrivate(page)) {
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 145) 		priv = page_private(page);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 146) 		f = afs_page_dirty_from(page, priv);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 147) 		t = afs_page_dirty_to(page, priv);
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 148) 		if (from < f)
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 149) 			f = from;
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 150) 		if (to > t)
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 151) 			t = to;
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 152) 		priv = afs_page_dirty(page, f, t);
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 153) 		set_page_private(page, priv);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 154) 		trace_afs_page_dirty(vnode, tracepoint_string("dirty+"), page);
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 155) 	} else {
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 156) 		priv = afs_page_dirty(page, from, to);
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 157) 		attach_page_private(page, (void *)priv);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 158) 		trace_afs_page_dirty(vnode, tracepoint_string("dirty"), page);
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 159) 	}
f792e3ac82fe2 (David Howells           2020-10-26 14:05:33 +0000 160) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 161) 	if (set_page_dirty(page))
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 162) 		_debug("dirtied %lx", page->index);
afae457d87486 (David Howells           2018-01-02 10:02:19 +0000 163) 
afae457d87486 (David Howells           2018-01-02 10:02:19 +0000 164) out:
15b4650e55e06 (Nicholas Piggin         2008-10-15 22:04:32 -0700 165) 	unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov      2016-04-01 15:29:47 +0300 166) 	put_page(page);
3003bbd0697b6 (David Howells           2020-02-06 14:22:29 +0000 167) 	return copied;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 168) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 169) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 170) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 171)  * kill all the pages in the given range
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 172)  */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 173) static void afs_kill_pages(struct address_space *mapping,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 174) 			   loff_t start, loff_t len)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 175) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 176) 	struct afs_vnode *vnode = AFS_FS_I(mapping->host);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 177) 	struct pagevec pv;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 178) 	unsigned int loop, psize;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 179) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 180) 	_enter("{%llx:%llu},%llx @%llx",
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 181) 	       vnode->fid.vid, vnode->fid.vnode, len, start);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 182) 
8667982014d60 (Mel Gorman              2017-11-15 17:37:52 -0800 183) 	pagevec_init(&pv);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 184) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 185) 	do {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 186) 		_debug("kill %llx @%llx", len, start);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 187) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 188) 		pv.nr = find_get_pages_contig(mapping, start / PAGE_SIZE,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 189) 					      PAGEVEC_SIZE, pv.pages);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 190) 		if (pv.nr == 0)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 191) 			break;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 192) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 193) 		for (loop = 0; loop < pv.nr; loop++) {
7286a35e89317 (David Howells           2017-03-16 16:27:48 +0000 194) 			struct page *page = pv.pages[loop];
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 195) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 196) 			if (page->index * PAGE_SIZE >= start + len)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 197) 				break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 198) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 199) 			psize = thp_size(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 200) 			start += psize;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 201) 			len -= psize;
7286a35e89317 (David Howells           2017-03-16 16:27:48 +0000 202) 			ClearPageUptodate(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 203) 			end_page_writeback(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 204) 			lock_page(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 205) 			generic_error_remove_page(mapping, page);
21bd68f196ca9 (Marc Dionne             2019-04-13 08:37:37 +0100 206) 			unlock_page(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 207) 		}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 208) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 209) 		__pagevec_release(&pv);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 210) 	} while (len > 0);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 211) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 212) 	_leave("");
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 213) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 214) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 215) /*
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 216)  * Redirty all the pages in a given range.
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 217)  */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 218) static void afs_redirty_pages(struct writeback_control *wbc,
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 219) 			      struct address_space *mapping,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 220) 			      loff_t start, loff_t len)
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 221) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 222) 	struct afs_vnode *vnode = AFS_FS_I(mapping->host);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 223) 	struct pagevec pv;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 224) 	unsigned int loop, psize;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 225) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 226) 	_enter("{%llx:%llu},%llx @%llx",
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 227) 	       vnode->fid.vid, vnode->fid.vnode, len, start);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 228) 
487e2c9f44c4b (Linus Torvalds          2017-11-16 11:41:22 -0800 229) 	pagevec_init(&pv);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 230) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 231) 	do {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 232) 		_debug("redirty %llx @%llx", len, start);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 233) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 234) 		pv.nr = find_get_pages_contig(mapping, start / PAGE_SIZE,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 235) 					      PAGEVEC_SIZE, pv.pages);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 236) 		if (pv.nr == 0)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 237) 			break;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 238) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 239) 		for (loop = 0; loop < pv.nr; loop++) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 240) 			struct page *page = pv.pages[loop];
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 241) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 242) 			if (page->index * PAGE_SIZE >= start + len)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 243) 				break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 244) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 245) 			psize = thp_size(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 246) 			start += psize;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 247) 			len -= psize;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 248) 			redirty_page_for_writepage(wbc, page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 249) 			end_page_writeback(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 250) 		}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 251) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 252) 		__pagevec_release(&pv);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 253) 	} while (len > 0);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 254) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 255) 	_leave("");
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 256) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 257) 
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 258) /*
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 259)  * completion of write to server
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 260)  */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 261) static void afs_pages_written_back(struct afs_vnode *vnode, loff_t start, unsigned int len)
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 262) {
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 263) 	struct address_space *mapping = vnode->vfs_inode.i_mapping;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 264) 	struct page *page;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 265) 	pgoff_t end;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 266) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 267) 	XA_STATE(xas, &mapping->i_pages, start / PAGE_SIZE);
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 268) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 269) 	_enter("{%llx:%llu},{%x @%llx}",
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 270) 	       vnode->fid.vid, vnode->fid.vnode, len, start);
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 271) 
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 272) 	rcu_read_lock();
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 273) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 274) 	end = (start + len - 1) / PAGE_SIZE;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 275) 	xas_for_each(&xas, page, end) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 276) 		if (!PageWriteback(page)) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 277) 			kdebug("bad %x @%llx page %lx %lx", len, start, page->index, end);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 278) 			ASSERT(PageWriteback(page));
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 279) 		}
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 280) 
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 281) 		trace_afs_page_dirty(vnode, tracepoint_string("clear"), page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 282) 		detach_page_private(page);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 283) 		page_endio(page, true, 0);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 284) 	}
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 285) 
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 286) 	rcu_read_unlock();
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 287) 
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 288) 	afs_prune_wb_keys(vnode);
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 289) 	_leave("");
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 290) }
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 291) 
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 292) /*
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 293)  * Find a key to use for the writeback.  We cached the keys used to author the
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 294)  * writes on the vnode.  *_wbk will contain the last writeback key used or NULL
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 295)  * and we need to start from there if it's set.
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 296)  */
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 297) static int afs_get_writeback_key(struct afs_vnode *vnode,
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 298) 				 struct afs_wb_key **_wbk)
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 299) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 300) 	struct afs_wb_key *wbk = NULL;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 301) 	struct list_head *p;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 302) 	int ret = -ENOKEY, ret2;
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 303) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 304) 	spin_lock(&vnode->wb_lock);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 305) 	if (*_wbk)
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 306) 		p = (*_wbk)->vnode_link.next;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 307) 	else
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 308) 		p = vnode->wb_keys.next;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 309) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 310) 	while (p != &vnode->wb_keys) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 311) 		wbk = list_entry(p, struct afs_wb_key, vnode_link);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 312) 		_debug("wbk %u", key_serial(wbk->key));
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 313) 		ret2 = key_validate(wbk->key);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 314) 		if (ret2 == 0) {
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 315) 			refcount_inc(&wbk->usage);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 316) 			_debug("USE WB KEY %u", key_serial(wbk->key));
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 317) 			break;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 318) 		}
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 319) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 320) 		wbk = NULL;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 321) 		if (ret == -ENOKEY)
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 322) 			ret = ret2;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 323) 		p = p->next;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 324) 	}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 325) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 326) 	spin_unlock(&vnode->wb_lock);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 327) 	if (*_wbk)
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 328) 		afs_put_wb_key(*_wbk);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 329) 	*_wbk = wbk;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 330) 	return 0;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 331) }
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 332) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 333) static void afs_store_data_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 334) {
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 335) 	struct afs_vnode *vnode = op->file[0].vnode;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 336) 
da8d07551275a (David Howells           2020-06-13 19:34:59 +0100 337) 	op->ctime = op->file[0].scb.status.mtime_client;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 338) 	afs_vnode_commit_status(op, &op->file[0]);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 339) 	if (op->error == 0) {
d383e346f97d6 (David Howells           2020-10-22 14:40:31 +0100 340) 		if (!op->store.laundering)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 341) 			afs_pages_written_back(vnode, op->store.pos, op->store.size);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 342) 		afs_stat_v(vnode, n_stores);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 343) 		atomic_long_add(op->store.size, &afs_v2net(vnode)->n_store_bytes);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 344) 	}
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 345) }
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 346) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 347) static const struct afs_operation_ops afs_store_data_operation = {
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 348) 	.issue_afs_rpc	= afs_fs_store_data,
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 349) 	.issue_yfs_rpc	= yfs_fs_store_data,
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 350) 	.success	= afs_store_data_success,
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 351) };
a58823ac45896 (David Howells           2019-05-09 15:16:10 +0100 352) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 353) /*
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 354)  * write to a file
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 355)  */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 356) static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t pos,
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 357) 			  bool laundering)
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 358) {
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 359) 	struct afs_operation *op;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 360) 	struct afs_wb_key *wbk = NULL;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 361) 	loff_t size = iov_iter_count(iter), i_size;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 362) 	int ret = -ENOKEY;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 363) 
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 364) 	_enter("%s{%llx:%llu.%u},%llx,%llx",
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 365) 	       vnode->volume->name,
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 366) 	       vnode->fid.vid,
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 367) 	       vnode->fid.vnode,
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 368) 	       vnode->fid.unique,
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 369) 	       size, pos);
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 370) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 371) 	ret = afs_get_writeback_key(vnode, &wbk);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 372) 	if (ret) {
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 373) 		_leave(" = %d [no keys]", ret);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 374) 		return ret;
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 375) 	}
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 376) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 377) 	op = afs_alloc_operation(wbk->key, vnode->volume);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 378) 	if (IS_ERR(op)) {
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 379) 		afs_put_wb_key(wbk);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 380) 		return -ENOMEM;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 381) 	}
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 382) 
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 383) 	i_size = i_size_read(&vnode->vfs_inode);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 384) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 385) 	afs_op_set_vnode(op, 0, vnode);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 386) 	op->file[0].dv_delta = 1;
22650f1481265 (David Howells           2021-04-30 13:47:08 +0100 387) 	op->file[0].modification = true;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 388) 	op->store.write_iter = iter;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 389) 	op->store.pos = pos;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 390) 	op->store.size = size;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 391) 	op->store.i_size = max(pos + size, i_size);
d383e346f97d6 (David Howells           2020-10-22 14:40:31 +0100 392) 	op->store.laundering = laundering;
b3597945c8a78 (David Howells           2020-06-11 21:50:24 +0100 393) 	op->mtime = vnode->vfs_inode.i_mtime;
811f04bac1518 (David Howells           2020-07-08 09:27:07 +0100 394) 	op->flags |= AFS_OPERATION_UNINTR;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 395) 	op->ops = &afs_store_data_operation;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 396) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 397) try_next_key:
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 398) 	afs_begin_vnode_operation(op);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 399) 	afs_wait_for_operation(op);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 400) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 401) 	switch (op->error) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 402) 	case -EACCES:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 403) 	case -EPERM:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 404) 	case -ENOKEY:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 405) 	case -EKEYEXPIRED:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 406) 	case -EKEYREJECTED:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 407) 	case -EKEYREVOKED:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 408) 		_debug("next");
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 409) 
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 410) 		ret = afs_get_writeback_key(vnode, &wbk);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 411) 		if (ret == 0) {
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 412) 			key_put(op->key);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 413) 			op->key = key_get(wbk->key);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 414) 			goto try_next_key;
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 415) 		}
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 416) 		break;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 417) 	}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 418) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 419) 	afs_put_wb_key(wbk);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 420) 	_leave(" = %d", op->error);
e49c7b2f6de7f (David Howells           2020-04-10 20:51:51 +0100 421) 	return afs_put_operation(op);
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 422) }
d2ddc776a4581 (David Howells           2017-11-02 15:27:50 +0000 423) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 424) /*
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 425)  * Extend the region to be written back to include subsequent contiguously
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 426)  * dirty pages if possible, but don't sleep while doing so.
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 427)  *
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 428)  * If this page holds new content, then we can include filler zeros in the
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 429)  * writeback.
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 430)  */
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 431) static void afs_extend_writeback(struct address_space *mapping,
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 432) 				 struct afs_vnode *vnode,
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 433) 				 long *_count,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 434) 				 loff_t start,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 435) 				 loff_t max_len,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 436) 				 bool new_content,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 437) 				 unsigned int *_len)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 438) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 439) 	struct pagevec pvec;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 440) 	struct page *page;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 441) 	unsigned long priv;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 442) 	unsigned int psize, filler = 0;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 443) 	unsigned int f, t;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 444) 	loff_t len = *_len;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 445) 	pgoff_t index = (start + len) / PAGE_SIZE;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 446) 	bool stop = true;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 447) 	unsigned int i;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 448) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 449) 	XA_STATE(xas, &mapping->i_pages, index);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 450) 	pagevec_init(&pvec);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 451) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 452) 	do {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 453) 		/* Firstly, we gather up a batch of contiguous dirty pages
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 454) 		 * under the RCU read lock - but we can't clear the dirty flags
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 455) 		 * there if any of those pages are mapped.
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 456) 		 */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 457) 		rcu_read_lock();
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 458) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 459) 		xas_for_each(&xas, page, ULONG_MAX) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 460) 			stop = true;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 461) 			if (xas_retry(&xas, page))
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 462) 				continue;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 463) 			if (xa_is_value(page))
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 464) 				break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 465) 			if (page->index != index)
5a8132761609b (David Howells           2018-04-06 14:17:26 +0100 466) 				break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 467) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 468) 			if (!page_cache_get_speculative(page)) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 469) 				xas_reset(&xas);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 470) 				continue;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 471) 			}
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 472) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 473) 			/* Has the page moved or been split? */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 474) 			if (unlikely(page != xas_reload(&xas)))
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 475) 				break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 476) 
529ae9aaa0837 (Nicholas Piggin         2008-08-02 12:01:03 +0200 477) 			if (!trylock_page(page))
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 478) 				break;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 479) 			if (!PageDirty(page) || PageWriteback(page)) {
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 480) 				unlock_page(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 481) 				break;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 482) 			}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 483) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 484) 			psize = thp_size(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 485) 			priv = page_private(page);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 486) 			f = afs_page_dirty_from(page, priv);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 487) 			t = afs_page_dirty_to(page, priv);
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 488) 			if (f != 0 && !new_content) {
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 489) 				unlock_page(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 490) 				break;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 491) 			}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 492) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 493) 			len += filler + t;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 494) 			filler = psize - t;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 495) 			if (len >= max_len || *_count <= 0)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 496) 				stop = true;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 497) 			else if (t == psize || new_content)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 498) 				stop = false;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 499) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 500) 			index += thp_nr_pages(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 501) 			if (!pagevec_add(&pvec, page))
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 502) 				break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 503) 			if (stop)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 504) 				break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 505) 		}
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 506) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 507) 		if (!stop)
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 508) 			xas_pause(&xas);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 509) 		rcu_read_unlock();
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 510) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 511) 		/* Now, if we obtained any pages, we can shift them to being
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 512) 		 * writable and mark them for caching.
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 513) 		 */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 514) 		if (!pagevec_count(&pvec))
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 515) 			break;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 516) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 517) 		for (i = 0; i < pagevec_count(&pvec); i++) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 518) 			page = pvec.pages[i];
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 519) 			trace_afs_page_dirty(vnode, tracepoint_string("store+"), page);
13524ab3c6f41 (David Howells           2017-11-02 15:27:53 +0000 520) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 521) 			if (!clear_page_dirty_for_io(page))
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 522) 				BUG();
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 523) 			if (test_set_page_writeback(page))
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 524) 				BUG();
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 525) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 526) 			*_count -= thp_nr_pages(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 527) 			unlock_page(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 528) 		}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 529) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 530) 		pagevec_release(&pvec);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 531) 		cond_resched();
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 532) 	} while (!stop);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 533) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 534) 	*_len = len;
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 535) }
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 536) 
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 537) /*
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 538)  * Synchronously write back the locked page and any subsequent non-locked dirty
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 539)  * pages.
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 540)  */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 541) static ssize_t afs_write_back_from_locked_page(struct address_space *mapping,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 542) 					       struct writeback_control *wbc,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 543) 					       struct page *page,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 544) 					       loff_t start, loff_t end)
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 545) {
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 546) 	struct afs_vnode *vnode = AFS_FS_I(mapping->host);
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 547) 	struct iov_iter iter;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 548) 	unsigned long priv;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 549) 	unsigned int offset, to, len, max_len;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 550) 	loff_t i_size = i_size_read(&vnode->vfs_inode);
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 551) 	bool new_content = test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 552) 	long count = wbc->nr_to_write;
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 553) 	int ret;
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 554) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 555) 	_enter(",%lx,%llx-%llx", page->index, start, end);
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 556) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 557) 	if (test_set_page_writeback(page))
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 558) 		BUG();
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 559) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 560) 	count -= thp_nr_pages(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 561) 
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 562) 	/* Find all consecutive lockable dirty pages that have contiguous
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 563) 	 * written regions, stopping when we find a page that is not
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 564) 	 * immediately lockable, is not dirty or is missing, or we reach the
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 565) 	 * end of the range.
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 566) 	 */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 567) 	priv = page_private(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 568) 	offset = afs_page_dirty_from(page, priv);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 569) 	to = afs_page_dirty_to(page, priv);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 570) 	trace_afs_page_dirty(vnode, tracepoint_string("store"), page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 571) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 572) 	len = to - offset;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 573) 	start += offset;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 574) 	if (start < i_size) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 575) 		/* Trim the write to the EOF; the extra data is ignored.  Also
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 576) 		 * put an upper limit on the size of a single storedata op.
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 577) 		 */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 578) 		max_len = 65536 * 4096;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 579) 		max_len = min_t(unsigned long long, max_len, end - start + 1);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 580) 		max_len = min_t(unsigned long long, max_len, i_size - start);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 581) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 582) 		if (len < max_len &&
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 583) 		    (to == thp_size(page) || new_content))
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 584) 			afs_extend_writeback(mapping, vnode, &count,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 585) 					     start, max_len, new_content, &len);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 586) 		len = min_t(loff_t, len, max_len);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 587) 	}
810caa3e6708b (David Howells           2020-10-30 10:01:09 +0000 588) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 589) 	/* We now have a contiguous set of dirty pages, each with writeback
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 590) 	 * set; the first page is still locked at this point, but all the rest
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 591) 	 * have been unlocked.
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 592) 	 */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 593) 	unlock_page(page);
793fe82ee33aa (David Howells           2020-06-12 16:13:52 +0100 594) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 595) 	if (start < i_size) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 596) 		_debug("write back %x @%llx [%llx]", len, start, i_size);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 597) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 598) 		iov_iter_xarray(&iter, WRITE, &mapping->i_pages, start, len);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 599) 		ret = afs_store_data(vnode, &iter, start, false);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 600) 	} else {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 601) 		_debug("write discard %x @%llx [%llx]", len, start, i_size);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 602) 
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 603) 		/* The dirty region was entirely beyond the EOF. */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 604) 		afs_pages_written_back(vnode, start, len);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 605) 		ret = 0;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 606) 	}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 607) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 608) 	switch (ret) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 609) 	case 0:
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 610) 		wbc->nr_to_write = count;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 611) 		ret = len;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 612) 		break;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 613) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 614) 	default:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 615) 		pr_notice("kAFS: Unexpected error from FS.StoreData %d\n", ret);
df561f6688fef (Gustavo A. R. Silva     2020-08-23 17:36:59 -0500 616) 		fallthrough;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 617) 	case -EACCES:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 618) 	case -EPERM:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 619) 	case -ENOKEY:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 620) 	case -EKEYEXPIRED:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 621) 	case -EKEYREJECTED:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 622) 	case -EKEYREVOKED:
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 623) 		afs_redirty_pages(wbc, mapping, start, len);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 624) 		mapping_set_error(mapping, ret);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 625) 		break;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 626) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 627) 	case -EDQUOT:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 628) 	case -ENOSPC:
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 629) 		afs_redirty_pages(wbc, mapping, start, len);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 630) 		mapping_set_error(mapping, -ENOSPC);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 631) 		break;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 632) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 633) 	case -EROFS:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 634) 	case -EIO:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 635) 	case -EREMOTEIO:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 636) 	case -EFBIG:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 637) 	case -ENOENT:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 638) 	case -ENOMEDIUM:
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 639) 	case -ENXIO:
f51375cd9e1ad (David Howells           2018-10-20 00:57:57 +0100 640) 		trace_afs_file_error(vnode, ret, afs_file_error_writeback_fail);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 641) 		afs_kill_pages(mapping, start, len);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 642) 		mapping_set_error(mapping, ret);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 643) 		break;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 644) 	}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 645) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 646) 	_leave(" = %d", ret);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 647) 	return ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 648) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 649) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 650) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 651)  * write a page back to the server
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 652)  * - the caller locked the page for us
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 653)  */
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 654) int afs_writepage(struct page *page, struct writeback_control *wbc)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 655) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 656) 	ssize_t ret;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 657) 	loff_t start;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 658) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 659) 	_enter("{%lx},", page->index);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 660) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 661) 	start = page->index * PAGE_SIZE;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 662) 	ret = afs_write_back_from_locked_page(page->mapping, wbc, page,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 663) 					      start, LLONG_MAX - start);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 664) 	if (ret < 0) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 665) 		_leave(" = %zd", ret);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 666) 		return ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 667) 	}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 668) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 669) 	_leave(" = 0");
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 670) 	return 0;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 671) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 672) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 673) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 674)  * write a region of pages back to the server
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 675)  */
c1206a2c6d87d (Adrian Bunk             2007-10-16 23:26:41 -0700 676) static int afs_writepages_region(struct address_space *mapping,
c1206a2c6d87d (Adrian Bunk             2007-10-16 23:26:41 -0700 677) 				 struct writeback_control *wbc,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 678) 				 loff_t start, loff_t end, loff_t *_next)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 679) {
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 680) 	struct page *page;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 681) 	ssize_t ret;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 682) 	int n;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 683) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 684) 	_enter("%llx,%llx,", start, end);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 685) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 686) 	do {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 687) 		pgoff_t index = start / PAGE_SIZE;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 688) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 689) 		n = find_get_pages_range_tag(mapping, &index, end / PAGE_SIZE,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 690) 					     PAGECACHE_TAG_DIRTY, 1, &page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 691) 		if (!n)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 692) 			break;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 693) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 694) 		start = (loff_t)page->index * PAGE_SIZE; /* May regress with THPs */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 695) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 696) 		_debug("wback %lx", page->index);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 697) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 698) 		/* At this point we hold neither the i_pages lock nor the
b93b016313b3b (Matthew Wilcox          2018-04-10 16:36:56 -0700 699) 		 * page lock: the page may be truncated or invalidated
b93b016313b3b (Matthew Wilcox          2018-04-10 16:36:56 -0700 700) 		 * (changing page->mapping to NULL), or even swizzled
b93b016313b3b (Matthew Wilcox          2018-04-10 16:36:56 -0700 701) 		 * back from swapper_space to tmpfs file mapping
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 702) 		 */
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 703) 		if (wbc->sync_mode != WB_SYNC_NONE) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 704) 			ret = lock_page_killable(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 705) 			if (ret < 0) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 706) 				put_page(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 707) 				return ret;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 708) 			}
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 709) 		} else {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 710) 			if (!trylock_page(page)) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 711) 				put_page(page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 712) 				return 0;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 713) 			}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 714) 		}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 715) 
c5051c7bc777d (David Howells           2017-03-16 16:27:49 +0000 716) 		if (page->mapping != mapping || !PageDirty(page)) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 717) 			start += thp_size(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 718) 			unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov      2016-04-01 15:29:47 +0300 719) 			put_page(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 720) 			continue;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 721) 		}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 722) 
c5051c7bc777d (David Howells           2017-03-16 16:27:49 +0000 723) 		if (PageWriteback(page)) {
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 724) 			unlock_page(page);
c5051c7bc777d (David Howells           2017-03-16 16:27:49 +0000 725) 			if (wbc->sync_mode != WB_SYNC_NONE)
c5051c7bc777d (David Howells           2017-03-16 16:27:49 +0000 726) 				wait_on_page_writeback(page);
29c8bbbd6e21d (David Howells           2017-03-16 16:27:43 +0000 727) 			put_page(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 728) 			continue;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 729) 		}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 730) 
65a151094edeb (David Howells           2017-03-16 16:27:49 +0000 731) 		if (!clear_page_dirty_for_io(page))
65a151094edeb (David Howells           2017-03-16 16:27:49 +0000 732) 			BUG();
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 733) 		ret = afs_write_back_from_locked_page(mapping, wbc, page, start, end);
09cbfeaf1a5a6 (Kirill A. Shutemov      2016-04-01 15:29:47 +0300 734) 		put_page(page);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 735) 		if (ret < 0) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 736) 			_leave(" = %zd", ret);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 737) 			return ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 738) 		}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 739) 
dc2557308ede6 (Marc Dionne             2021-06-06 21:21:27 +0100 740) 		start += ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 741) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 742) 		cond_resched();
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 743) 	} while (wbc->nr_to_write > 0);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 744) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 745) 	*_next = start;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 746) 	_leave(" = 0 [%llx]", *_next);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 747) 	return 0;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 748) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 749) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 750) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 751)  * write some of the pending data back to the server
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 752)  */
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 753) int afs_writepages(struct address_space *mapping,
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 754) 		   struct writeback_control *wbc)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 755) {
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 756) 	struct afs_vnode *vnode = AFS_FS_I(mapping->host);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 757) 	loff_t start, next;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 758) 	int ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 759) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 760) 	_enter("");
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 761) 
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 762) 	/* We have to be careful as we can end up racing with setattr()
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 763) 	 * truncating the pagecache since the caller doesn't take a lock here
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 764) 	 * to prevent it.
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 765) 	 */
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 766) 	if (wbc->sync_mode == WB_SYNC_ALL)
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 767) 		down_read(&vnode->validate_lock);
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 768) 	else if (!down_read_trylock(&vnode->validate_lock))
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 769) 		return 0;
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 770) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 771) 	if (wbc->range_cyclic) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 772) 		start = mapping->writeback_index * PAGE_SIZE;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 773) 		ret = afs_writepages_region(mapping, wbc, start, LLONG_MAX, &next);
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 774) 		if (ret == 0) {
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 775) 			mapping->writeback_index = next / PAGE_SIZE;
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 776) 			if (start > 0 && wbc->nr_to_write > 0) {
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 777) 				ret = afs_writepages_region(mapping, wbc, 0,
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 778) 							    start, &next);
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 779) 				if (ret == 0)
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 780) 					mapping->writeback_index =
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 781) 						next / PAGE_SIZE;
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 782) 			}
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 783) 		}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 784) 	} else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 785) 		ret = afs_writepages_region(mapping, wbc, 0, LLONG_MAX, &next);
8dda575c89125 (Tom Rix                 2021-04-30 08:50:31 -0700 786) 		if (wbc->nr_to_write > 0 && ret == 0)
2131ea6126924 (David Howells           2021-07-12 17:04:47 +0100 787) 			mapping->writeback_index = next / PAGE_SIZE;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 788) 	} else {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 789) 		ret = afs_writepages_region(mapping, wbc,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 790) 					    wbc->range_start, wbc->range_end, &next);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 791) 	}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 792) 
ec0fa0b659144 (David Howells           2020-10-07 14:22:12 +0100 793) 	up_read(&vnode->validate_lock);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 794) 	_leave(" = %d", ret);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 795) 	return ret;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 796) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 797) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 798) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 799)  * write to an AFS file
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 800)  */
50b5551d1719c (Al Viro                 2014-04-03 14:13:46 -0400 801) ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 802) {
496ad9aa8ef44 (Al Viro                 2013-01-23 17:07:38 -0500 803) 	struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp));
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 804) 	ssize_t result;
50b5551d1719c (Al Viro                 2014-04-03 14:13:46 -0400 805) 	size_t count = iov_iter_count(from);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 806) 
3b6492df4153b (David Howells           2018-10-20 00:57:57 +0100 807) 	_enter("{%llx:%llu},{%zu},",
50b5551d1719c (Al Viro                 2014-04-03 14:13:46 -0400 808) 	       vnode->fid.vid, vnode->fid.vnode, count);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 809) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 810) 	if (IS_SWAPFILE(&vnode->vfs_inode)) {
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 811) 		printk(KERN_INFO
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 812) 		       "AFS: Attempt to write to active swap file!\n");
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 813) 		return -EBUSY;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 814) 	}
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 815) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 816) 	if (!count)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 817) 		return 0;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 818) 
50b5551d1719c (Al Viro                 2014-04-03 14:13:46 -0400 819) 	result = generic_file_write_iter(iocb, from);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 820) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 821) 	_leave(" = %zd", result);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 822) 	return result;
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 823) }
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 824) 
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 825) /*
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 826)  * flush any dirty pages for this process, and check for write errors.
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 827)  * - the return status from this call provides a reliable indication of
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 828)  *   whether any write errors occurred for this process.
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 829)  */
02c24a82187d5 (Josef Bacik             2011-07-16 20:44:56 -0400 830) int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 831) {
3c981bfc57040 (Al Viro                 2013-09-03 13:37:45 -0400 832) 	struct inode *inode = file_inode(file);
3c981bfc57040 (Al Viro                 2013-09-03 13:37:45 -0400 833) 	struct afs_vnode *vnode = AFS_FS_I(inode);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 834) 
3b6492df4153b (David Howells           2018-10-20 00:57:57 +0100 835) 	_enter("{%llx:%llu},{n=%pD},%d",
3c981bfc57040 (Al Viro                 2013-09-03 13:37:45 -0400 836) 	       vnode->fid.vid, vnode->fid.vnode, file,
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 837) 	       datasync);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 838) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 839) 	return file_write_and_wait_range(file, start, end);
31143d5d515ec (David Howells           2007-05-09 02:33:46 -0700 840) }
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 841) 
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 842) /*
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 843)  * notification that a previously read-only page is about to become writable
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 844)  * - if it returns an error, the caller will deliver a bus error signal
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 845)  */
0722f18620597 (Souptick Joarder        2018-08-23 17:00:48 -0700 846) vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 847) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 848) 	struct page *page = thp_head(vmf->page);
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 849) 	struct file *file = vmf->vma->vm_file;
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 850) 	struct inode *inode = file_inode(file);
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 851) 	struct afs_vnode *vnode = AFS_FS_I(inode);
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 852) 	unsigned long priv;
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 853) 	vm_fault_t ret = VM_FAULT_RETRY;
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 854) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 855) 	_enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, page->index);
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 856) 
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 857) 	sb_start_pagefault(inode->i_sb);
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 858) 
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 859) 	/* Wait for the page to be written to the cache before we allow it to
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 860) 	 * be modified.  We then assume the entire page will need writing back.
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 861) 	 */
630f5dda8442c (David Howells           2020-02-06 14:22:28 +0000 862) #ifdef CONFIG_AFS_FSCACHE
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 863) 	if (PageFsCache(page) &&
5cbf03985c67c (David Howells           2020-02-06 14:22:29 +0000 864) 	    wait_on_page_fscache_killable(page) < 0)
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 865) 		goto out;
630f5dda8442c (David Howells           2020-02-06 14:22:28 +0000 866) #endif
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 867) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 868) 	if (wait_on_page_writeback_killable(page))
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 869) 		goto out;
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 870) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 871) 	if (lock_page_killable(page) < 0)
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 872) 		goto out;
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 873) 
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 874) 	/* We mustn't change page->private until writeback is complete as that
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 875) 	 * details the portion of the page we need to write back and we might
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 876) 	 * need to redirty the page if there's a problem.
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 877) 	 */
5cbf03985c67c (David Howells           2020-02-06 14:22:29 +0000 878) 	if (wait_on_page_writeback_killable(page) < 0) {
5cbf03985c67c (David Howells           2020-02-06 14:22:29 +0000 879) 		unlock_page(page);
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 880) 		goto out;
5cbf03985c67c (David Howells           2020-02-06 14:22:29 +0000 881) 	}
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 882) 
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 883) 	priv = afs_page_dirty(page, 0, thp_size(page));
f86726a69dec5 (David Howells           2020-10-22 14:08:23 +0100 884) 	priv = afs_page_dirty_mmapped(priv);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 885) 	if (PagePrivate(page)) {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 886) 		set_page_private(page, priv);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 887) 		trace_afs_page_dirty(vnode, tracepoint_string("mkwrite+"), page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 888) 	} else {
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 889) 		attach_page_private(page, (void *)priv);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 890) 		trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 891) 	}
bb413489288e4 (David Howells           2020-06-12 00:15:13 +0100 892) 	file_update_time(file);
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 893) 
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 894) 	ret = VM_FAULT_LOCKED;
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 895) out:
1cf7a1518aefa (David Howells           2017-11-02 15:27:52 +0000 896) 	sb_end_pagefault(inode->i_sb);
9620ad86d0e3e (Matthew Wilcox (Oracle) 2021-06-16 22:22:28 +0100 897) 	return ret;
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 898) }
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 899) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 900) /*
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 901)  * Prune the keys cached for writeback.  The caller must hold vnode->wb_lock.
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 902)  */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 903) void afs_prune_wb_keys(struct afs_vnode *vnode)
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 904) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 905) 	LIST_HEAD(graveyard);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 906) 	struct afs_wb_key *wbk, *tmp;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 907) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 908) 	/* Discard unused keys */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 909) 	spin_lock(&vnode->wb_lock);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 910) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 911) 	if (!mapping_tagged(&vnode->vfs_inode.i_data, PAGECACHE_TAG_WRITEBACK) &&
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 912) 	    !mapping_tagged(&vnode->vfs_inode.i_data, PAGECACHE_TAG_DIRTY)) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 913) 		list_for_each_entry_safe(wbk, tmp, &vnode->wb_keys, vnode_link) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 914) 			if (refcount_read(&wbk->usage) == 1)
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 915) 				list_move(&wbk->vnode_link, &graveyard);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 916) 		}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 917) 	}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 918) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 919) 	spin_unlock(&vnode->wb_lock);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 920) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 921) 	while (!list_empty(&graveyard)) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 922) 		wbk = list_entry(graveyard.next, struct afs_wb_key, vnode_link);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 923) 		list_del(&wbk->vnode_link);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 924) 		afs_put_wb_key(wbk);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 925) 	}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 926) }
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 927) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 928) /*
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 929)  * Clean up a page during invalidation.
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 930)  */
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 931) int afs_launder_page(struct page *page)
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 932) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 933) 	struct address_space *mapping = page->mapping;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 934) 	struct afs_vnode *vnode = AFS_FS_I(mapping->host);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 935) 	struct iov_iter iter;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 936) 	struct bio_vec bv[1];
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 937) 	unsigned long priv;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 938) 	unsigned int f, t;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 939) 	int ret = 0;
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 940) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 941) 	_enter("{%lx}", page->index);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 942) 
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 943) 	priv = page_private(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 944) 	if (clear_page_dirty_for_io(page)) {
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 945) 		f = 0;
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 946) 		t = thp_size(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 947) 		if (PagePrivate(page)) {
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 948) 			f = afs_page_dirty_from(page, priv);
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 949) 			t = afs_page_dirty_to(page, priv);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 950) 		}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 951) 
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 952) 		bv[0].bv_page = page;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 953) 		bv[0].bv_offset = f;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 954) 		bv[0].bv_len = t - f;
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 955) 		iov_iter_bvec(&iter, WRITE, bv, 1, bv[0].bv_len);
bd80d8a80e128 (David Howells           2020-02-06 14:22:28 +0000 956) 
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 957) 		trace_afs_page_dirty(vnode, tracepoint_string("launder"), page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 958) 		ret = afs_store_data(vnode, &iter, (loff_t)page->index * PAGE_SIZE,
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 959) 				     true);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 960) 	}
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 961) 
67d78a6f6e7b3 (David Howells           2020-10-28 14:23:46 +0000 962) 	trace_afs_page_dirty(vnode, tracepoint_string("laundered"), page);
e87b03f5830ec (David Howells           2020-10-20 09:33:45 +0100 963) 	detach_page_private(page);
630f5dda8442c (David Howells           2020-02-06 14:22:28 +0000 964) 	wait_on_page_fscache(page);
4343d00872e1d (David Howells           2017-11-02 15:27:52 +0000 965) 	return ret;
9b3f26c9110dc (David Howells           2009-04-03 16:42:41 +0100 966) }