2874c5fd28426 (Thomas Gleixner 2019-05-27 08:55:01 +0200 1) // SPDX-License-Identifier: GPL-2.0-or-later
08e0e7c82eead (David Howells 2007-04-26 15:55:03 -0700 2) /* AFS filesystem file handling
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) *
08e0e7c82eead (David Howells 2007-04-26 15:55:03 -0700 4) * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Written by David Howells (dhowells@redhat.com)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) #include <linux/module.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) #include <linux/init.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/pagemap.h>
31143d5d515ec (David Howells 2007-05-09 02:33:46 -0700 13) #include <linux/writeback.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 14) #include <linux/gfp.h>
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 15) #include <linux/task_io_accounting_ops.h>
f86196ea8737c (Nikolay Borisov 2019-01-03 15:29:02 -0800 16) #include <linux/mm.h>
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 17) #include <linux/netfs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) #include "internal.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19)
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 20) static int afs_file_mmap(struct file *file, struct vm_area_struct *vma);
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 21) static int afs_readpage(struct file *file, struct page *page);
d47992f86b307 (Lukas Czerner 2013-05-21 23:17:23 -0400 22) static void afs_invalidatepage(struct page *page, unsigned int offset,
d47992f86b307 (Lukas Czerner 2013-05-21 23:17:23 -0400 23) unsigned int length);
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 24) static int afs_releasepage(struct page *page, gfp_t gfp_flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 26) static void afs_readahead(struct readahead_control *ractl);
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 27)
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 28) const struct file_operations afs_file_operations = {
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 29) .open = afs_open,
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 30) .release = afs_release,
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 31) .llseek = generic_file_llseek,
aad4f8bb42af0 (Al Viro 2014-04-02 14:33:16 -0400 32) .read_iter = generic_file_read_iter,
50b5551d1719c (Al Viro 2014-04-03 14:13:46 -0400 33) .write_iter = afs_file_write,
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 34) .mmap = afs_file_mmap,
5ffc4ef45b3b0 (Jens Axboe 2007-06-01 11:49:19 +0200 35) .splice_read = generic_file_splice_read,
06a17bbe1d47f (David Howells 2020-10-27 09:39:04 +0000 36) .splice_write = iter_file_splice_write,
31143d5d515ec (David Howells 2007-05-09 02:33:46 -0700 37) .fsync = afs_fsync,
e8d6c554126b8 (David Howells 2007-07-15 23:40:12 -0700 38) .lock = afs_lock,
e8d6c554126b8 (David Howells 2007-07-15 23:40:12 -0700 39) .flock = afs_flock,
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 40) };
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 41)
754661f143e70 (Arjan van de Ven 2007-02-12 00:55:38 -0800 42) const struct inode_operations afs_file_inode_operations = {
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 43) .getattr = afs_getattr,
31143d5d515ec (David Howells 2007-05-09 02:33:46 -0700 44) .setattr = afs_setattr,
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 45) .permission = afs_permission,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 48) const struct address_space_operations afs_fs_aops = {
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 49) .readpage = afs_readpage,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 50) .readahead = afs_readahead,
31143d5d515ec (David Howells 2007-05-09 02:33:46 -0700 51) .set_page_dirty = afs_set_page_dirty,
31143d5d515ec (David Howells 2007-05-09 02:33:46 -0700 52) .launder_page = afs_launder_page,
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 53) .releasepage = afs_releasepage,
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 54) .invalidatepage = afs_invalidatepage,
15b4650e55e06 (Nicholas Piggin 2008-10-15 22:04:32 -0700 55) .write_begin = afs_write_begin,
15b4650e55e06 (Nicholas Piggin 2008-10-15 22:04:32 -0700 56) .write_end = afs_write_end,
31143d5d515ec (David Howells 2007-05-09 02:33:46 -0700 57) .writepage = afs_writepage,
31143d5d515ec (David Howells 2007-05-09 02:33:46 -0700 58) .writepages = afs_writepages,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 59) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60)
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 61) static const struct vm_operations_struct afs_vm_ops = {
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 62) .fault = filemap_fault,
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 63) .map_pages = filemap_map_pages,
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 64) .page_mkwrite = afs_page_mkwrite,
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 65) };
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 66)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 67) /*
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 68) * Discard a pin on a writeback key.
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 69) */
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 70) void afs_put_wb_key(struct afs_wb_key *wbk)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 71) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 72) if (wbk && refcount_dec_and_test(&wbk->usage)) {
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 73) key_put(wbk->key);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 74) kfree(wbk);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 75) }
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 76) }
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 77)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 78) /*
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 79) * Cache key for writeback.
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 80) */
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 81) int afs_cache_wb_key(struct afs_vnode *vnode, struct afs_file *af)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 82) {
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 83) struct afs_wb_key *wbk, *p;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 84)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 85) wbk = kzalloc(sizeof(struct afs_wb_key), GFP_KERNEL);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 86) if (!wbk)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 87) return -ENOMEM;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 88) refcount_set(&wbk->usage, 2);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 89) wbk->key = af->key;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 90)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 91) spin_lock(&vnode->wb_lock);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 92) list_for_each_entry(p, &vnode->wb_keys, vnode_link) {
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 93) if (p->key == wbk->key)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 94) goto found;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 95) }
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 96)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 97) key_get(wbk->key);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 98) list_add_tail(&wbk->vnode_link, &vnode->wb_keys);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 99) spin_unlock(&vnode->wb_lock);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 100) af->wb = wbk;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 101) return 0;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 102)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 103) found:
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 104) refcount_inc(&p->usage);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 105) spin_unlock(&vnode->wb_lock);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 106) af->wb = p;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 107) kfree(wbk);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 108) return 0;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 109) }
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 110)
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 111) /*
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 112) * open an AFS file or directory and attach a key to it
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 113) */
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 114) int afs_open(struct inode *inode, struct file *file)
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 115) {
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 116) struct afs_vnode *vnode = AFS_FS_I(inode);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 117) struct afs_file *af;
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 118) struct key *key;
260a980317dac (David Howells 2007-04-26 15:59:35 -0700 119) int ret;
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 120)
3b6492df4153b (David Howells 2018-10-20 00:57:57 +0100 121) _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode);
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 122)
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 123) key = afs_request_key(vnode->volume->cell);
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 124) if (IS_ERR(key)) {
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 125) ret = PTR_ERR(key);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 126) goto error;
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 127) }
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 128)
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 129) af = kzalloc(sizeof(*af), GFP_KERNEL);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 130) if (!af) {
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 131) ret = -ENOMEM;
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 132) goto error_key;
260a980317dac (David Howells 2007-04-26 15:59:35 -0700 133) }
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 134) af->key = key;
260a980317dac (David Howells 2007-04-26 15:59:35 -0700 135)
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 136) ret = afs_validate(vnode, key);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 137) if (ret < 0)
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 138) goto error_af;
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 139)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 140) if (file->f_mode & FMODE_WRITE) {
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 141) ret = afs_cache_wb_key(vnode, af);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 142) if (ret < 0)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 143) goto error_af;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 144) }
5a8132761609b (David Howells 2018-04-06 14:17:26 +0100 145)
5a8132761609b (David Howells 2018-04-06 14:17:26 +0100 146) if (file->f_flags & O_TRUNC)
5a8132761609b (David Howells 2018-04-06 14:17:26 +0100 147) set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 148)
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 149) file->private_data = af;
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 150) _leave(" = 0");
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 151) return 0;
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 152)
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 153) error_af:
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 154) kfree(af);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 155) error_key:
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 156) key_put(key);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 157) error:
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 158) _leave(" = %d", ret);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 159) return ret;
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 160) }
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 161)
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 162) /*
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 163) * release an AFS file or directory and discard its key
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 164) */
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 165) int afs_release(struct inode *inode, struct file *file)
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 166) {
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 167) struct afs_vnode *vnode = AFS_FS_I(inode);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 168) struct afs_file *af = file->private_data;
a1b879eefc2b3 (David Howells 2019-05-15 12:09:17 +0100 169) int ret = 0;
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 170)
3b6492df4153b (David Howells 2018-10-20 00:57:57 +0100 171) _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode);
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 172)
5a8132761609b (David Howells 2018-04-06 14:17:26 +0100 173) if ((file->f_mode & FMODE_WRITE))
a1b879eefc2b3 (David Howells 2019-05-15 12:09:17 +0100 174) ret = vfs_fsync(file, 0);
5a8132761609b (David Howells 2018-04-06 14:17:26 +0100 175)
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 176) file->private_data = NULL;
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 177) if (af->wb)
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 178) afs_put_wb_key(af->wb);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 179) key_put(af->key);
215804a99283c (David Howells 2017-11-02 15:27:52 +0000 180) kfree(af);
4343d00872e1d (David Howells 2017-11-02 15:27:52 +0000 181) afs_prune_wb_keys(vnode);
a1b879eefc2b3 (David Howells 2019-05-15 12:09:17 +0100 182) _leave(" = %d", ret);
a1b879eefc2b3 (David Howells 2019-05-15 12:09:17 +0100 183) return ret;
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 184) }
00d3b7a4533e3 (David Howells 2007-04-26 15:57:07 -0700 185)
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 186) /*
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 187) * Allocate a new read record.
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 188) */
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 189) struct afs_read *afs_alloc_read(gfp_t gfp)
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 190) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 191) struct afs_read *req;
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 192)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 193) req = kzalloc(sizeof(struct afs_read), gfp);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 194) if (req)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 195) refcount_set(&req->usage, 1);
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 196)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 197) return req;
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 198) }
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 199)
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 200) /*
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 201) * Dispose of a ref to a read record.
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 202) */
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 203) void afs_put_read(struct afs_read *req)
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 204) {
f3ddee8dc4e2c (David Howells 2018-04-06 14:17:25 +0100 205) if (refcount_dec_and_test(&req->usage)) {
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 206) if (req->cleanup)
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 207) req->cleanup(req);
c69bf479baa61 (David Howells 2020-02-06 14:22:27 +0000 208) key_put(req->key);
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 209) kfree(req);
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 210) }
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 211) }
196ee9cd2d047 (David Howells 2017-01-05 10:38:34 +0000 212)
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 213) static void afs_fetch_data_notify(struct afs_operation *op)
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 214) {
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 215) struct afs_read *req = op->fetch.req;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 216) struct netfs_read_subrequest *subreq = req->subreq;
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 217) int error = op->error;
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 218)
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 219) if (error == -ECONNABORTED)
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 220) error = afs_abort_to_error(op->ac.abort_code);
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 221) req->error = error;
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 222)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 223) if (subreq) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 224) __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 225) netfs_subreq_terminated(subreq, error ?: req->actual_len, false);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 226) req->subreq = NULL;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 227) } else if (req->done) {
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 228) req->done(req);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 229) }
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 230) }
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 231)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 232) static void afs_fetch_data_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 233) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 234) struct afs_vnode *vnode = op->file[0].vnode;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 235)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 236) _enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 237) afs_vnode_commit_status(op, &op->file[0]);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 238) afs_stat_v(vnode, n_fetches);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 239) atomic_long_add(op->fetch.req->actual_len, &op->net->n_fetch_bytes);
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 240) afs_fetch_data_notify(op);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 241) }
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 242)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 243) static void afs_fetch_data_put(struct afs_operation *op)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 244) {
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 245) op->fetch.req->error = op->error;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 246) afs_put_read(op->fetch.req);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 247) }
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 248)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 249) static const struct afs_operation_ops afs_fetch_data_operation = {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 250) .issue_afs_rpc = afs_fs_fetch_data,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 251) .issue_yfs_rpc = yfs_fs_fetch_data,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 252) .success = afs_fetch_data_success,
728279a5a1fd9 (David Howells 2020-06-16 00:34:09 +0100 253) .aborted = afs_check_for_remote_deletion,
dc4191841d099 (David Howells 2020-09-18 09:11:15 +0100 254) .failed = afs_fetch_data_notify,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 255) .put = afs_fetch_data_put,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 256) };
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 257)
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 258) /*
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 259) * Fetch file data from the volume.
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 260) */
c69bf479baa61 (David Howells 2020-02-06 14:22:27 +0000 261) int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req)
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 262) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 263) struct afs_operation *op;
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 264)
3b6492df4153b (David Howells 2018-10-20 00:57:57 +0100 265) _enter("%s{%llx:%llu.%u},%x,,,",
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 266) vnode->volume->name,
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 267) vnode->fid.vid,
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 268) vnode->fid.vnode,
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 269) vnode->fid.unique,
c69bf479baa61 (David Howells 2020-02-06 14:22:27 +0000 270) key_serial(req->key));
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 271)
c69bf479baa61 (David Howells 2020-02-06 14:22:27 +0000 272) op = afs_alloc_operation(req->key, vnode->volume);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 273) if (IS_ERR(op)) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 274) if (req->subreq)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 275) netfs_subreq_terminated(req->subreq, PTR_ERR(op), false);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 276) return PTR_ERR(op);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 277) }
a58823ac45896 (David Howells 2019-05-09 15:16:10 +0100 278)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 279) afs_op_set_vnode(op, 0, vnode);
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 280)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 281) op->fetch.req = afs_get_read(req);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 282) op->ops = &afs_fetch_data_operation;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 283) return afs_do_sync_operation(op);
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 284) }
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 285)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 286) static void afs_req_issue_op(struct netfs_read_subrequest *subreq)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 287) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 288) struct afs_vnode *vnode = AFS_FS_I(subreq->rreq->inode);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 289) struct afs_read *fsreq;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 290)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 291) fsreq = afs_alloc_read(GFP_NOFS);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 292) if (!fsreq)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 293) return netfs_subreq_terminated(subreq, -ENOMEM, false);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 295) fsreq->subreq = subreq;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 296) fsreq->pos = subreq->start + subreq->transferred;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 297) fsreq->len = subreq->len - subreq->transferred;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 298) fsreq->key = subreq->rreq->netfs_priv;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 299) fsreq->vnode = vnode;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 300) fsreq->iter = &fsreq->def_iter;
03ffae909278b (David Howells 2020-02-10 10:00:22 +0000 301)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 302) iov_iter_xarray(&fsreq->def_iter, READ,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 303) &fsreq->vnode->vfs_inode.i_mapping->i_pages,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 304) fsreq->pos, fsreq->len);
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 305)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 306) afs_fetch_data(fsreq->vnode, fsreq);
ec26815ad847d (David Howells 2007-04-26 15:49:28 -0700 307) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 309) static int afs_symlink_readpage(struct page *page)
f6d335c08df48 (Al Viro 2010-05-21 15:27:09 +0100 310) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 311) struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 312) struct afs_read *fsreq;
f6d335c08df48 (Al Viro 2010-05-21 15:27:09 +0100 313) int ret;
f6d335c08df48 (Al Viro 2010-05-21 15:27:09 +0100 314)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 315) fsreq = afs_alloc_read(GFP_NOFS);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 316) if (!fsreq)
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 317) return -ENOMEM;
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 318)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 319) fsreq->pos = page->index * PAGE_SIZE;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 320) fsreq->len = PAGE_SIZE;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 321) fsreq->vnode = vnode;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 322) fsreq->iter = &fsreq->def_iter;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 323) iov_iter_xarray(&fsreq->def_iter, READ, &page->mapping->i_pages,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 324) fsreq->pos, fsreq->len);
c450846461f88 (David Howells 2020-02-06 14:22:28 +0000 325)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 326) ret = afs_fetch_data(fsreq->vnode, fsreq);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 327) page_endio(page, false, ret);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 328) return ret;
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 329) }
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 330)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 331) static void afs_init_rreq(struct netfs_read_request *rreq, struct file *file)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 332) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 333) rreq->netfs_priv = key_get(afs_file_key(file));
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 334) }
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 335)
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 336) static bool afs_is_cache_enabled(struct inode *inode)
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 337) {
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 338) struct fscache_cookie *cookie = afs_vnode_cache(AFS_FS_I(inode));
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 339)
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 340) return fscache_cookie_enabled(cookie) && !hlist_empty(&cookie->backing_objects);
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 341) }
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 342)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 343) static int afs_begin_cache_operation(struct netfs_read_request *rreq)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 344) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 345) struct afs_vnode *vnode = AFS_FS_I(rreq->inode);
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 346)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 347) return fscache_begin_read_operation(rreq, afs_vnode_cache(vnode));
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 348) }
91b467e0a3f5f (David Howells 2017-01-05 10:38:35 +0000 349)
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 350) static int afs_check_write_begin(struct file *file, loff_t pos, unsigned len,
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 351) struct page *page, void **_fsdata)
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 352) {
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 353) struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 354)
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 355) return test_bit(AFS_VNODE_DELETED, &vnode->flags) ? -ESTALE : 0;
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 356) }
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 357)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 358) static void afs_priv_cleanup(struct address_space *mapping, void *netfs_priv)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 359) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 360) key_put(netfs_priv);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 361) }
f6d335c08df48 (Al Viro 2010-05-21 15:27:09 +0100 362)
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 363) const struct netfs_read_request_ops afs_req_ops = {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 364) .init_rreq = afs_init_rreq,
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 365) .is_cache_enabled = afs_is_cache_enabled,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 366) .begin_cache_operation = afs_begin_cache_operation,
3003bbd0697b6 (David Howells 2020-02-06 14:22:29 +0000 367) .check_write_begin = afs_check_write_begin,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 368) .issue_op = afs_req_issue_op,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 369) .cleanup = afs_priv_cleanup,
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 370) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 371)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 372) static int afs_readpage(struct file *file, struct page *page)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 373) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 374) if (!file)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 375) return afs_symlink_readpage(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 376)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 377) return netfs_readpage(file, page, &afs_req_ops, NULL);
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 378) }
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 379)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 380) static void afs_readahead(struct readahead_control *ractl)
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 381) {
5cbf03985c67c (David Howells 2020-02-06 14:22:29 +0000 382) netfs_readahead(ractl, &afs_req_ops, NULL);
ec26815ad847d (David Howells 2007-04-26 15:49:28 -0700 383) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 384)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 385) /*
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 386) * Adjust the dirty region of the page on truncation or full invalidation,
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 387) * getting rid of the markers altogether if the region is entirely invalidated.
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 388) */
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 389) static void afs_invalidate_dirty(struct page *page, unsigned int offset,
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 390) unsigned int length)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 391) {
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 392) struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 393) unsigned long priv;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 394) unsigned int f, t, end = offset + length;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 395)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 396) priv = page_private(page);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 397)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 398) /* we clean up only if the entire page is being invalidated */
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 399) if (offset == 0 && length == thp_size(page))
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 400) goto full_invalidate;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 401)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 402) /* If the page was dirtied by page_mkwrite(), the PTE stays writable
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 403) * and we don't get another notification to tell us to expand it
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 404) * again.
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 405) */
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 406) if (afs_is_page_dirty_mmapped(priv))
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 407) return;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 408)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 409) /* We may need to shorten the dirty region */
67d78a6f6e7b3 (David Howells 2020-10-28 14:23:46 +0000 410) f = afs_page_dirty_from(page, priv);
67d78a6f6e7b3 (David Howells 2020-10-28 14:23:46 +0000 411) t = afs_page_dirty_to(page, priv);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 412)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 413) if (t <= offset || f >= end)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 414) return; /* Doesn't overlap */
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 415)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 416) if (f < offset && t > end)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 417) return; /* Splits the dirty region - just absorb it */
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 418)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 419) if (f >= offset && t <= end)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 420) goto undirty;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 421)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 422) if (f < offset)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 423) t = offset;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 424) else
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 425) f = end;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 426) if (f == t)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 427) goto undirty;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 428)
67d78a6f6e7b3 (David Howells 2020-10-28 14:23:46 +0000 429) priv = afs_page_dirty(page, f, t);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 430) set_page_private(page, priv);
67d78a6f6e7b3 (David Howells 2020-10-28 14:23:46 +0000 431) trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 432) return;
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 433)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 434) undirty:
67d78a6f6e7b3 (David Howells 2020-10-28 14:23:46 +0000 435) trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 436) clear_page_dirty_for_io(page);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 437) full_invalidate:
67d78a6f6e7b3 (David Howells 2020-10-28 14:23:46 +0000 438) trace_afs_page_dirty(vnode, tracepoint_string("inval"), page);
e87b03f5830ec (David Howells 2020-10-20 09:33:45 +0100 439) detach_page_private(page);
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 440) }
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 441)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 442) /*
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 443) * invalidate part or all of a page
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 444) * - release a page and clean up its private data if offset is 0 (indicating
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 445) * the entire page)
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 446) */
d47992f86b307 (Lukas Czerner 2013-05-21 23:17:23 -0400 447) static void afs_invalidatepage(struct page *page, unsigned int offset,
d47992f86b307 (Lukas Czerner 2013-05-21 23:17:23 -0400 448) unsigned int length)
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 449) {
d47992f86b307 (Lukas Czerner 2013-05-21 23:17:23 -0400 450) _enter("{%lu},%u,%u", page->index, offset, length);
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 451)
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 452) BUG_ON(!PageLocked(page));
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 453)
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 454) if (PagePrivate(page))
f86726a69dec5 (David Howells 2020-10-22 14:08:23 +0100 455) afs_invalidate_dirty(page, offset, length);
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 456)
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 457) wait_on_page_fscache(page);
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 458) _leave("");
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 459) }
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 460)
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 461) /*
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 462) * release a page and clean up its private state if it's not busy
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 463) * - return true if the page can now be released, false if not
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 464) */
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 465) static int afs_releasepage(struct page *page, gfp_t gfp_flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 466) {
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 467) struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 468)
3b6492df4153b (David Howells 2018-10-20 00:57:57 +0100 469) _enter("{{%llx:%llu}[%lu],%lx},%x",
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 470) vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
416351f28d2b3 (David Howells 2007-05-09 02:33:45 -0700 471) gfp_flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 472)
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 473) /* deny if page is being written to the cache and the caller hasn't
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 474) * elected to wait */
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 475) #ifdef CONFIG_AFS_FSCACHE
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 476) if (PageFsCache(page)) {
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 477) if (!(gfp_flags & __GFP_DIRECT_RECLAIM) || !(gfp_flags & __GFP_FS))
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 478) return false;
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 479) wait_on_page_fscache(page);
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 480) }
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 481) #endif
630f5dda8442c (David Howells 2020-02-06 14:22:28 +0000 482)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 483) if (PagePrivate(page)) {
67d78a6f6e7b3 (David Howells 2020-10-28 14:23:46 +0000 484) trace_afs_page_dirty(vnode, tracepoint_string("rel"), page);
e87b03f5830ec (David Howells 2020-10-20 09:33:45 +0100 485) detach_page_private(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 486) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 487)
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 488) /* indicate that the page can be released */
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 489) _leave(" = T");
9b3f26c9110dc (David Howells 2009-04-03 16:42:41 +0100 490) return 1;
ec26815ad847d (David Howells 2007-04-26 15:49:28 -0700 491) }
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 492)
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 493) /*
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 494) * Handle setting up a memory mapping on an AFS file.
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 495) */
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 496) static int afs_file_mmap(struct file *file, struct vm_area_struct *vma)
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 497) {
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 498) int ret;
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 499)
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 500) ret = generic_file_mmap(file, vma);
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 501) if (ret == 0)
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 502) vma->vm_ops = &afs_vm_ops;
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 503) return ret;
1cf7a1518aefa (David Howells 2017-11-02 15:27:52 +0000 504) }