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) }