12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 208e0e7c8SDavid Howells /* AFS filesystem file handling 31da177e4SLinus Torvalds * 408e0e7c8SDavid Howells * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved. 51da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds #include <linux/kernel.h> 91da177e4SLinus Torvalds #include <linux/module.h> 101da177e4SLinus Torvalds #include <linux/init.h> 111da177e4SLinus Torvalds #include <linux/fs.h> 121da177e4SLinus Torvalds #include <linux/pagemap.h> 1331143d5dSDavid Howells #include <linux/writeback.h> 145a0e3ad6STejun Heo #include <linux/gfp.h> 1591b467e0SDavid Howells #include <linux/task_io_accounting_ops.h> 16f86196eaSNikolay Borisov #include <linux/mm.h> 171da177e4SLinus Torvalds #include "internal.h" 181da177e4SLinus Torvalds 191cf7a151SDavid Howells static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); 20416351f2SDavid Howells static int afs_readpage(struct file *file, struct page *page); 21d47992f8SLukas Czerner static void afs_invalidatepage(struct page *page, unsigned int offset, 22d47992f8SLukas Czerner unsigned int length); 23416351f2SDavid Howells static int afs_releasepage(struct page *page, gfp_t gfp_flags); 241da177e4SLinus Torvalds 259b3f26c9SDavid Howells static int afs_readpages(struct file *filp, struct address_space *mapping, 269b3f26c9SDavid Howells struct list_head *pages, unsigned nr_pages); 279b3f26c9SDavid Howells 2800d3b7a4SDavid Howells const struct file_operations afs_file_operations = { 2900d3b7a4SDavid Howells .open = afs_open, 3000d3b7a4SDavid Howells .release = afs_release, 3100d3b7a4SDavid Howells .llseek = generic_file_llseek, 32aad4f8bbSAl Viro .read_iter = generic_file_read_iter, 3350b5551dSAl Viro .write_iter = afs_file_write, 341cf7a151SDavid Howells .mmap = afs_file_mmap, 355ffc4ef4SJens Axboe .splice_read = generic_file_splice_read, 3606a17bbeSDavid Howells .splice_write = iter_file_splice_write, 3731143d5dSDavid Howells .fsync = afs_fsync, 38e8d6c554SDavid Howells .lock = afs_lock, 39e8d6c554SDavid Howells .flock = afs_flock, 4000d3b7a4SDavid Howells }; 4100d3b7a4SDavid Howells 42754661f1SArjan van de Ven const struct inode_operations afs_file_inode_operations = { 43416351f2SDavid Howells .getattr = afs_getattr, 4431143d5dSDavid Howells .setattr = afs_setattr, 4500d3b7a4SDavid Howells .permission = afs_permission, 461da177e4SLinus Torvalds }; 471da177e4SLinus Torvalds 48f5e54d6eSChristoph Hellwig const struct address_space_operations afs_fs_aops = { 49416351f2SDavid Howells .readpage = afs_readpage, 509b3f26c9SDavid Howells .readpages = afs_readpages, 5131143d5dSDavid Howells .set_page_dirty = afs_set_page_dirty, 5231143d5dSDavid Howells .launder_page = afs_launder_page, 53416351f2SDavid Howells .releasepage = afs_releasepage, 54416351f2SDavid Howells .invalidatepage = afs_invalidatepage, 5515b4650eSNick Piggin .write_begin = afs_write_begin, 5615b4650eSNick Piggin .write_end = afs_write_end, 5731143d5dSDavid Howells .writepage = afs_writepage, 5831143d5dSDavid Howells .writepages = afs_writepages, 591da177e4SLinus Torvalds }; 601da177e4SLinus Torvalds 611cf7a151SDavid Howells static const struct vm_operations_struct afs_vm_ops = { 621cf7a151SDavid Howells .fault = filemap_fault, 631cf7a151SDavid Howells .map_pages = filemap_map_pages, 641cf7a151SDavid Howells .page_mkwrite = afs_page_mkwrite, 651cf7a151SDavid Howells }; 661cf7a151SDavid Howells 671da177e4SLinus Torvalds /* 684343d008SDavid Howells * Discard a pin on a writeback key. 694343d008SDavid Howells */ 704343d008SDavid Howells void afs_put_wb_key(struct afs_wb_key *wbk) 714343d008SDavid Howells { 72e49c7b2fSDavid Howells if (wbk && refcount_dec_and_test(&wbk->usage)) { 734343d008SDavid Howells key_put(wbk->key); 744343d008SDavid Howells kfree(wbk); 754343d008SDavid Howells } 764343d008SDavid Howells } 774343d008SDavid Howells 784343d008SDavid Howells /* 794343d008SDavid Howells * Cache key for writeback. 804343d008SDavid Howells */ 814343d008SDavid Howells int afs_cache_wb_key(struct afs_vnode *vnode, struct afs_file *af) 824343d008SDavid Howells { 834343d008SDavid Howells struct afs_wb_key *wbk, *p; 844343d008SDavid Howells 854343d008SDavid Howells wbk = kzalloc(sizeof(struct afs_wb_key), GFP_KERNEL); 864343d008SDavid Howells if (!wbk) 874343d008SDavid Howells return -ENOMEM; 884343d008SDavid Howells refcount_set(&wbk->usage, 2); 894343d008SDavid Howells wbk->key = af->key; 904343d008SDavid Howells 914343d008SDavid Howells spin_lock(&vnode->wb_lock); 924343d008SDavid Howells list_for_each_entry(p, &vnode->wb_keys, vnode_link) { 934343d008SDavid Howells if (p->key == wbk->key) 944343d008SDavid Howells goto found; 954343d008SDavid Howells } 964343d008SDavid Howells 974343d008SDavid Howells key_get(wbk->key); 984343d008SDavid Howells list_add_tail(&wbk->vnode_link, &vnode->wb_keys); 994343d008SDavid Howells spin_unlock(&vnode->wb_lock); 1004343d008SDavid Howells af->wb = wbk; 1014343d008SDavid Howells return 0; 1024343d008SDavid Howells 1034343d008SDavid Howells found: 1044343d008SDavid Howells refcount_inc(&p->usage); 1054343d008SDavid Howells spin_unlock(&vnode->wb_lock); 1064343d008SDavid Howells af->wb = p; 1074343d008SDavid Howells kfree(wbk); 1084343d008SDavid Howells return 0; 1094343d008SDavid Howells } 1104343d008SDavid Howells 1114343d008SDavid Howells /* 11200d3b7a4SDavid Howells * open an AFS file or directory and attach a key to it 11300d3b7a4SDavid Howells */ 11400d3b7a4SDavid Howells int afs_open(struct inode *inode, struct file *file) 11500d3b7a4SDavid Howells { 11600d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 117215804a9SDavid Howells struct afs_file *af; 11800d3b7a4SDavid Howells struct key *key; 119260a9803SDavid Howells int ret; 12000d3b7a4SDavid Howells 1213b6492dfSDavid Howells _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode); 12200d3b7a4SDavid Howells 12300d3b7a4SDavid Howells key = afs_request_key(vnode->volume->cell); 12400d3b7a4SDavid Howells if (IS_ERR(key)) { 125215804a9SDavid Howells ret = PTR_ERR(key); 126215804a9SDavid Howells goto error; 127215804a9SDavid Howells } 128215804a9SDavid Howells 129215804a9SDavid Howells af = kzalloc(sizeof(*af), GFP_KERNEL); 130215804a9SDavid Howells if (!af) { 131215804a9SDavid Howells ret = -ENOMEM; 132215804a9SDavid Howells goto error_key; 13300d3b7a4SDavid Howells } 1344343d008SDavid Howells af->key = key; 13500d3b7a4SDavid Howells 136260a9803SDavid Howells ret = afs_validate(vnode, key); 137215804a9SDavid Howells if (ret < 0) 138215804a9SDavid Howells goto error_af; 139260a9803SDavid Howells 1404343d008SDavid Howells if (file->f_mode & FMODE_WRITE) { 1414343d008SDavid Howells ret = afs_cache_wb_key(vnode, af); 1424343d008SDavid Howells if (ret < 0) 1434343d008SDavid Howells goto error_af; 1444343d008SDavid Howells } 1454343d008SDavid Howells 1465a813276SDavid Howells if (file->f_flags & O_TRUNC) 1475a813276SDavid Howells set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); 1485a813276SDavid Howells 149215804a9SDavid Howells file->private_data = af; 15000d3b7a4SDavid Howells _leave(" = 0"); 15100d3b7a4SDavid Howells return 0; 152215804a9SDavid Howells 153215804a9SDavid Howells error_af: 154215804a9SDavid Howells kfree(af); 155215804a9SDavid Howells error_key: 156215804a9SDavid Howells key_put(key); 157215804a9SDavid Howells error: 158215804a9SDavid Howells _leave(" = %d", ret); 159215804a9SDavid Howells return ret; 16000d3b7a4SDavid Howells } 16100d3b7a4SDavid Howells 16200d3b7a4SDavid Howells /* 16300d3b7a4SDavid Howells * release an AFS file or directory and discard its key 16400d3b7a4SDavid Howells */ 16500d3b7a4SDavid Howells int afs_release(struct inode *inode, struct file *file) 16600d3b7a4SDavid Howells { 16700d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 168215804a9SDavid Howells struct afs_file *af = file->private_data; 169a1b879eeSDavid Howells int ret = 0; 17000d3b7a4SDavid Howells 1713b6492dfSDavid Howells _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode); 17200d3b7a4SDavid Howells 1735a813276SDavid Howells if ((file->f_mode & FMODE_WRITE)) 174a1b879eeSDavid Howells ret = vfs_fsync(file, 0); 1755a813276SDavid Howells 176215804a9SDavid Howells file->private_data = NULL; 1774343d008SDavid Howells if (af->wb) 1784343d008SDavid Howells afs_put_wb_key(af->wb); 179215804a9SDavid Howells key_put(af->key); 180215804a9SDavid Howells kfree(af); 1814343d008SDavid Howells afs_prune_wb_keys(vnode); 182a1b879eeSDavid Howells _leave(" = %d", ret); 183a1b879eeSDavid Howells return ret; 18400d3b7a4SDavid Howells } 18500d3b7a4SDavid Howells 186196ee9cdSDavid Howells /* 187c4508464SDavid Howells * Handle completion of a read operation. 188c4508464SDavid Howells */ 189c4508464SDavid Howells static void afs_file_read_done(struct afs_read *req) 190c4508464SDavid Howells { 191c4508464SDavid Howells struct afs_vnode *vnode = req->vnode; 192c4508464SDavid Howells struct page *page; 193c4508464SDavid Howells pgoff_t index = req->pos >> PAGE_SHIFT; 194c4508464SDavid Howells pgoff_t last = index + req->nr_pages - 1; 195c4508464SDavid Howells 196c4508464SDavid Howells XA_STATE(xas, &vnode->vfs_inode.i_mapping->i_pages, index); 197c4508464SDavid Howells 198c4508464SDavid Howells if (iov_iter_count(req->iter) > 0) { 199c4508464SDavid Howells /* The read was short - clear the excess buffer. */ 200c4508464SDavid Howells _debug("afterclear %zx %zx %llx/%llx", 201c4508464SDavid Howells req->iter->iov_offset, 202c4508464SDavid Howells iov_iter_count(req->iter), 203c4508464SDavid Howells req->actual_len, req->len); 204c4508464SDavid Howells iov_iter_zero(iov_iter_count(req->iter), req->iter); 205c4508464SDavid Howells } 206c4508464SDavid Howells 207c4508464SDavid Howells rcu_read_lock(); 208c4508464SDavid Howells xas_for_each(&xas, page, last) { 209c4508464SDavid Howells page_endio(page, false, 0); 210c4508464SDavid Howells put_page(page); 211c4508464SDavid Howells } 212c4508464SDavid Howells rcu_read_unlock(); 213c4508464SDavid Howells 214c4508464SDavid Howells task_io_account_read(req->len); 215c4508464SDavid Howells req->cleanup = NULL; 216c4508464SDavid Howells } 217c4508464SDavid Howells 218c4508464SDavid Howells /* 219c4508464SDavid Howells * Dispose of our locks and refs on the pages if the read failed. 220c4508464SDavid Howells */ 221c4508464SDavid Howells static void afs_file_read_cleanup(struct afs_read *req) 222c4508464SDavid Howells { 223c4508464SDavid Howells struct page *page; 224c4508464SDavid Howells pgoff_t index = req->pos >> PAGE_SHIFT; 225c4508464SDavid Howells pgoff_t last = index + req->nr_pages - 1; 226c4508464SDavid Howells 227c4508464SDavid Howells if (req->iter) { 228c4508464SDavid Howells XA_STATE(xas, &req->vnode->vfs_inode.i_mapping->i_pages, index); 229c4508464SDavid Howells 230c4508464SDavid Howells _enter("%lu,%u,%zu", index, req->nr_pages, iov_iter_count(req->iter)); 231c4508464SDavid Howells 232c4508464SDavid Howells rcu_read_lock(); 233c4508464SDavid Howells xas_for_each(&xas, page, last) { 234c4508464SDavid Howells BUG_ON(xa_is_value(page)); 235c4508464SDavid Howells BUG_ON(PageCompound(page)); 236c4508464SDavid Howells 237c4508464SDavid Howells page_endio(page, false, req->error); 238c4508464SDavid Howells put_page(page); 239c4508464SDavid Howells } 240c4508464SDavid Howells rcu_read_unlock(); 241c4508464SDavid Howells } 242c4508464SDavid Howells } 243c4508464SDavid Howells 244c4508464SDavid Howells /* 245196ee9cdSDavid Howells * Dispose of a ref to a read record. 246196ee9cdSDavid Howells */ 247196ee9cdSDavid Howells void afs_put_read(struct afs_read *req) 248196ee9cdSDavid Howells { 249f3ddee8dSDavid Howells if (refcount_dec_and_test(&req->usage)) { 250c4508464SDavid Howells if (req->cleanup) 251c4508464SDavid Howells req->cleanup(req); 252c69bf479SDavid Howells key_put(req->key); 253196ee9cdSDavid Howells kfree(req); 254196ee9cdSDavid Howells } 255196ee9cdSDavid Howells } 256196ee9cdSDavid Howells 257*dc419184SDavid Howells static void afs_fetch_data_notify(struct afs_operation *op) 258*dc419184SDavid Howells { 259*dc419184SDavid Howells struct afs_read *req = op->fetch.req; 260*dc419184SDavid Howells int error = op->error; 261*dc419184SDavid Howells 262*dc419184SDavid Howells if (error == -ECONNABORTED) 263*dc419184SDavid Howells error = afs_abort_to_error(op->ac.abort_code); 264*dc419184SDavid Howells req->error = error; 265*dc419184SDavid Howells 266*dc419184SDavid Howells if (req->done) 267*dc419184SDavid Howells req->done(req); 268*dc419184SDavid Howells } 269*dc419184SDavid Howells 270e49c7b2fSDavid Howells static void afs_fetch_data_success(struct afs_operation *op) 271e49c7b2fSDavid Howells { 272e49c7b2fSDavid Howells struct afs_vnode *vnode = op->file[0].vnode; 273e49c7b2fSDavid Howells 274e49c7b2fSDavid Howells _enter("op=%08x", op->debug_id); 275e49c7b2fSDavid Howells afs_vnode_commit_status(op, &op->file[0]); 276e49c7b2fSDavid Howells afs_stat_v(vnode, n_fetches); 277e49c7b2fSDavid Howells atomic_long_add(op->fetch.req->actual_len, &op->net->n_fetch_bytes); 278*dc419184SDavid Howells afs_fetch_data_notify(op); 279e49c7b2fSDavid Howells } 280e49c7b2fSDavid Howells 281e49c7b2fSDavid Howells static void afs_fetch_data_put(struct afs_operation *op) 282e49c7b2fSDavid Howells { 283c4508464SDavid Howells op->fetch.req->error = op->error; 284e49c7b2fSDavid Howells afs_put_read(op->fetch.req); 285e49c7b2fSDavid Howells } 286e49c7b2fSDavid Howells 287e49c7b2fSDavid Howells static const struct afs_operation_ops afs_fetch_data_operation = { 288e49c7b2fSDavid Howells .issue_afs_rpc = afs_fs_fetch_data, 289e49c7b2fSDavid Howells .issue_yfs_rpc = yfs_fs_fetch_data, 290e49c7b2fSDavid Howells .success = afs_fetch_data_success, 291728279a5SDavid Howells .aborted = afs_check_for_remote_deletion, 292*dc419184SDavid Howells .failed = afs_fetch_data_notify, 293e49c7b2fSDavid Howells .put = afs_fetch_data_put, 294e49c7b2fSDavid Howells }; 295e49c7b2fSDavid Howells 2961da177e4SLinus Torvalds /* 297d2ddc776SDavid Howells * Fetch file data from the volume. 298d2ddc776SDavid Howells */ 299c69bf479SDavid Howells int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req) 300d2ddc776SDavid Howells { 301e49c7b2fSDavid Howells struct afs_operation *op; 302d2ddc776SDavid Howells 3033b6492dfSDavid Howells _enter("%s{%llx:%llu.%u},%x,,,", 304d2ddc776SDavid Howells vnode->volume->name, 305d2ddc776SDavid Howells vnode->fid.vid, 306d2ddc776SDavid Howells vnode->fid.vnode, 307d2ddc776SDavid Howells vnode->fid.unique, 308c69bf479SDavid Howells key_serial(req->key)); 309d2ddc776SDavid Howells 310c69bf479SDavid Howells op = afs_alloc_operation(req->key, vnode->volume); 311e49c7b2fSDavid Howells if (IS_ERR(op)) 312e49c7b2fSDavid Howells return PTR_ERR(op); 313a58823acSDavid Howells 314e49c7b2fSDavid Howells afs_op_set_vnode(op, 0, vnode); 315a58823acSDavid Howells 316e49c7b2fSDavid Howells op->fetch.req = afs_get_read(req); 317e49c7b2fSDavid Howells op->ops = &afs_fetch_data_operation; 318e49c7b2fSDavid Howells return afs_do_sync_operation(op); 319d2ddc776SDavid Howells } 320d2ddc776SDavid Howells 321d2ddc776SDavid Howells /* 322f6d335c0SAl Viro * read page from file, directory or symlink, given a key to use 3231da177e4SLinus Torvalds */ 324c4508464SDavid Howells static int afs_page_filler(struct key *key, struct page *page) 3251da177e4SLinus Torvalds { 326f6d335c0SAl Viro struct inode *inode = page->mapping->host; 327f6d335c0SAl Viro struct afs_vnode *vnode = AFS_FS_I(inode); 328196ee9cdSDavid Howells struct afs_read *req; 3291da177e4SLinus Torvalds int ret; 3301da177e4SLinus Torvalds 33100d3b7a4SDavid Howells _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); 3321da177e4SLinus Torvalds 333cd7619d6SMatt Mackall BUG_ON(!PageLocked(page)); 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds ret = -ESTALE; 33608e0e7c8SDavid Howells if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 3371da177e4SLinus Torvalds goto error; 3381da177e4SLinus Torvalds 339c4508464SDavid Howells req = kzalloc(sizeof(struct afs_read), GFP_KERNEL); 340196ee9cdSDavid Howells if (!req) 341196ee9cdSDavid Howells goto enomem; 342196ee9cdSDavid Howells 343f3ddee8dSDavid Howells refcount_set(&req->usage, 1); 344c4508464SDavid Howells req->vnode = vnode; 345c69bf479SDavid Howells req->key = key_get(key); 346196ee9cdSDavid Howells req->pos = (loff_t)page->index << PAGE_SHIFT; 347e87b03f5SDavid Howells req->len = thp_size(page); 348e87b03f5SDavid Howells req->nr_pages = thp_nr_pages(page); 349c4508464SDavid Howells req->done = afs_file_read_done; 350c4508464SDavid Howells req->cleanup = afs_file_read_cleanup; 351c4508464SDavid Howells 352196ee9cdSDavid Howells get_page(page); 353c4508464SDavid Howells iov_iter_xarray(&req->def_iter, READ, &page->mapping->i_pages, 354c4508464SDavid Howells req->pos, req->len); 355c4508464SDavid Howells req->iter = &req->def_iter; 3561da177e4SLinus Torvalds 357c69bf479SDavid Howells ret = afs_fetch_data(vnode, req); 358c4508464SDavid Howells if (ret < 0) 359c4508464SDavid Howells goto fetch_error; 360c4508464SDavid Howells 361196ee9cdSDavid Howells afs_put_read(req); 3621da177e4SLinus Torvalds _leave(" = 0"); 3631da177e4SLinus Torvalds return 0; 3641da177e4SLinus Torvalds 365c4508464SDavid Howells fetch_error: 366c4508464SDavid Howells switch (ret) { 367c4508464SDavid Howells case -EINTR: 368c4508464SDavid Howells case -ENOMEM: 369c4508464SDavid Howells case -ERESTARTSYS: 370c4508464SDavid Howells case -EAGAIN: 371c4508464SDavid Howells afs_put_read(req); 37268ae849dSDavid Howells goto error; 373c4508464SDavid Howells case -ENOENT: 374c4508464SDavid Howells _debug("got NOENT from server - marking file deleted and stale"); 375c4508464SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 376c4508464SDavid Howells ret = -ESTALE; 377c4508464SDavid Howells /* Fall through */ 378c4508464SDavid Howells default: 379c4508464SDavid Howells page_endio(page, false, ret); 380c4508464SDavid Howells afs_put_read(req); 381c4508464SDavid Howells _leave(" = %d", ret); 382c4508464SDavid Howells return ret; 383c4508464SDavid Howells } 384c4508464SDavid Howells 385196ee9cdSDavid Howells enomem: 386196ee9cdSDavid Howells ret = -ENOMEM; 3871da177e4SLinus Torvalds error: 3881da177e4SLinus Torvalds unlock_page(page); 3891da177e4SLinus Torvalds _leave(" = %d", ret); 3901da177e4SLinus Torvalds return ret; 391ec26815aSDavid Howells } 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds /* 394f6d335c0SAl Viro * read page from file, directory or symlink, given a file to nominate the key 395f6d335c0SAl Viro * to be used 396f6d335c0SAl Viro */ 397f6d335c0SAl Viro static int afs_readpage(struct file *file, struct page *page) 398f6d335c0SAl Viro { 399f6d335c0SAl Viro struct key *key; 400f6d335c0SAl Viro int ret; 401f6d335c0SAl Viro 402f6d335c0SAl Viro if (file) { 403215804a9SDavid Howells key = afs_file_key(file); 404f6d335c0SAl Viro ASSERT(key != NULL); 405f6d335c0SAl Viro ret = afs_page_filler(key, page); 406f6d335c0SAl Viro } else { 407f6d335c0SAl Viro struct inode *inode = page->mapping->host; 408d2ddc776SDavid Howells key = afs_request_key(AFS_FS_S(inode->i_sb)->cell); 409f6d335c0SAl Viro if (IS_ERR(key)) { 410f6d335c0SAl Viro ret = PTR_ERR(key); 411f6d335c0SAl Viro } else { 412f6d335c0SAl Viro ret = afs_page_filler(key, page); 413f6d335c0SAl Viro key_put(key); 414f6d335c0SAl Viro } 415f6d335c0SAl Viro } 416f6d335c0SAl Viro return ret; 417f6d335c0SAl Viro } 418f6d335c0SAl Viro 419f6d335c0SAl Viro /* 42091b467e0SDavid Howells * Read a contiguous set of pages. 42191b467e0SDavid Howells */ 42291b467e0SDavid Howells static int afs_readpages_one(struct file *file, struct address_space *mapping, 42391b467e0SDavid Howells struct list_head *pages) 42491b467e0SDavid Howells { 42591b467e0SDavid Howells struct afs_vnode *vnode = AFS_FS_I(mapping->host); 42691b467e0SDavid Howells struct afs_read *req; 42791b467e0SDavid Howells struct list_head *p; 42891b467e0SDavid Howells struct page *first, *page; 42991b467e0SDavid Howells pgoff_t index; 430c4508464SDavid Howells int ret, n; 43191b467e0SDavid Howells 43291b467e0SDavid Howells /* Count the number of contiguous pages at the front of the list. Note 43391b467e0SDavid Howells * that the list goes prev-wards rather than next-wards. 43491b467e0SDavid Howells */ 435f86196eaSNikolay Borisov first = lru_to_page(pages); 43691b467e0SDavid Howells index = first->index + 1; 43791b467e0SDavid Howells n = 1; 43891b467e0SDavid Howells for (p = first->lru.prev; p != pages; p = p->prev) { 43991b467e0SDavid Howells page = list_entry(p, struct page, lru); 44091b467e0SDavid Howells if (page->index != index) 44191b467e0SDavid Howells break; 44291b467e0SDavid Howells index++; 44391b467e0SDavid Howells n++; 44491b467e0SDavid Howells } 44591b467e0SDavid Howells 446c4508464SDavid Howells req = kzalloc(sizeof(struct afs_read), GFP_NOFS); 44791b467e0SDavid Howells if (!req) 44891b467e0SDavid Howells return -ENOMEM; 44991b467e0SDavid Howells 450f3ddee8dSDavid Howells refcount_set(&req->usage, 1); 451a58823acSDavid Howells req->vnode = vnode; 452c69bf479SDavid Howells req->key = key_get(afs_file_key(file)); 453c4508464SDavid Howells req->done = afs_file_read_done; 454c4508464SDavid Howells req->cleanup = afs_file_read_cleanup; 45591b467e0SDavid Howells req->pos = first->index; 45691b467e0SDavid Howells req->pos <<= PAGE_SHIFT; 45791b467e0SDavid Howells 458c4508464SDavid Howells /* Add pages to the LRU until it fails. We keep the pages ref'd and 459c4508464SDavid Howells * locked until the read is complete. 46091b467e0SDavid Howells * 46191b467e0SDavid Howells * Note that it's possible for the file size to change whilst we're 46291b467e0SDavid Howells * doing this, but we rely on the server returning less than we asked 46391b467e0SDavid Howells * for if the file shrank. We also rely on this to deal with a partial 46491b467e0SDavid Howells * page at the end of the file. 46591b467e0SDavid Howells */ 46691b467e0SDavid Howells do { 467f86196eaSNikolay Borisov page = lru_to_page(pages); 46891b467e0SDavid Howells list_del(&page->lru); 46991b467e0SDavid Howells index = page->index; 47091b467e0SDavid Howells if (add_to_page_cache_lru(page, mapping, index, 47191b467e0SDavid Howells readahead_gfp_mask(mapping))) { 47291b467e0SDavid Howells put_page(page); 47391b467e0SDavid Howells break; 47491b467e0SDavid Howells } 47591b467e0SDavid Howells 476c4508464SDavid Howells req->nr_pages++; 47791b467e0SDavid Howells } while (req->nr_pages < n); 47891b467e0SDavid Howells 47991b467e0SDavid Howells if (req->nr_pages == 0) { 480c69bf479SDavid Howells afs_put_read(req); 48191b467e0SDavid Howells return 0; 48291b467e0SDavid Howells } 48391b467e0SDavid Howells 484c4508464SDavid Howells req->len = req->nr_pages * PAGE_SIZE; 485c4508464SDavid Howells iov_iter_xarray(&req->def_iter, READ, &file->f_mapping->i_pages, 486c4508464SDavid Howells req->pos, req->len); 487c4508464SDavid Howells req->iter = &req->def_iter; 488c4508464SDavid Howells 489c69bf479SDavid Howells ret = afs_fetch_data(vnode, req); 49091b467e0SDavid Howells if (ret < 0) 49191b467e0SDavid Howells goto error; 49291b467e0SDavid Howells 49391b467e0SDavid Howells afs_put_read(req); 49491b467e0SDavid Howells return 0; 49591b467e0SDavid Howells 49691b467e0SDavid Howells error: 49791b467e0SDavid Howells if (ret == -ENOENT) { 498c4508464SDavid Howells _debug("got NOENT from server - marking file deleted and stale"); 49991b467e0SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 50091b467e0SDavid Howells ret = -ESTALE; 50191b467e0SDavid Howells } 50291b467e0SDavid Howells 50391b467e0SDavid Howells afs_put_read(req); 50491b467e0SDavid Howells return ret; 50591b467e0SDavid Howells } 50691b467e0SDavid Howells 50791b467e0SDavid Howells /* 5089b3f26c9SDavid Howells * read a set of pages 5091da177e4SLinus Torvalds */ 5109b3f26c9SDavid Howells static int afs_readpages(struct file *file, struct address_space *mapping, 5119b3f26c9SDavid Howells struct list_head *pages, unsigned nr_pages) 5121da177e4SLinus Torvalds { 513215804a9SDavid Howells struct key *key = afs_file_key(file); 5149b3f26c9SDavid Howells struct afs_vnode *vnode; 5159b3f26c9SDavid Howells int ret = 0; 5161da177e4SLinus Torvalds 517f6d335c0SAl Viro _enter("{%d},{%lu},,%d", 518f6d335c0SAl Viro key_serial(key), mapping->host->i_ino, nr_pages); 519f6d335c0SAl Viro 520f6d335c0SAl Viro ASSERT(key != NULL); 5211da177e4SLinus Torvalds 5229b3f26c9SDavid Howells vnode = AFS_FS_I(mapping->host); 523ad2a8e60SDan Carpenter if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { 5249b3f26c9SDavid Howells _leave(" = -ESTALE"); 5259b3f26c9SDavid Howells return -ESTALE; 5261da177e4SLinus Torvalds } 5271da177e4SLinus Torvalds 5289b3f26c9SDavid Howells /* attempt to read as many of the pages as possible */ 52991b467e0SDavid Howells while (!list_empty(pages)) { 53091b467e0SDavid Howells ret = afs_readpages_one(file, mapping, pages); 53191b467e0SDavid Howells if (ret < 0) 53291b467e0SDavid Howells break; 53391b467e0SDavid Howells } 5349b3f26c9SDavid Howells 5359b3f26c9SDavid Howells _leave(" = %d [netting]", ret); 5369b3f26c9SDavid Howells return ret; 537ec26815aSDavid Howells } 5381da177e4SLinus Torvalds 5391da177e4SLinus Torvalds /* 540f86726a6SDavid Howells * Adjust the dirty region of the page on truncation or full invalidation, 541f86726a6SDavid Howells * getting rid of the markers altogether if the region is entirely invalidated. 542f86726a6SDavid Howells */ 543f86726a6SDavid Howells static void afs_invalidate_dirty(struct page *page, unsigned int offset, 544f86726a6SDavid Howells unsigned int length) 545f86726a6SDavid Howells { 546f86726a6SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 547f86726a6SDavid Howells unsigned long priv; 548f86726a6SDavid Howells unsigned int f, t, end = offset + length; 549f86726a6SDavid Howells 550f86726a6SDavid Howells priv = page_private(page); 551f86726a6SDavid Howells 552f86726a6SDavid Howells /* we clean up only if the entire page is being invalidated */ 553f86726a6SDavid Howells if (offset == 0 && length == thp_size(page)) 554f86726a6SDavid Howells goto full_invalidate; 555f86726a6SDavid Howells 556f86726a6SDavid Howells /* If the page was dirtied by page_mkwrite(), the PTE stays writable 557f86726a6SDavid Howells * and we don't get another notification to tell us to expand it 558f86726a6SDavid Howells * again. 559f86726a6SDavid Howells */ 560f86726a6SDavid Howells if (afs_is_page_dirty_mmapped(priv)) 561f86726a6SDavid Howells return; 562f86726a6SDavid Howells 563f86726a6SDavid Howells /* We may need to shorten the dirty region */ 56467d78a6fSDavid Howells f = afs_page_dirty_from(page, priv); 56567d78a6fSDavid Howells t = afs_page_dirty_to(page, priv); 566f86726a6SDavid Howells 567f86726a6SDavid Howells if (t <= offset || f >= end) 568f86726a6SDavid Howells return; /* Doesn't overlap */ 569f86726a6SDavid Howells 570f86726a6SDavid Howells if (f < offset && t > end) 571f86726a6SDavid Howells return; /* Splits the dirty region - just absorb it */ 572f86726a6SDavid Howells 573f86726a6SDavid Howells if (f >= offset && t <= end) 574f86726a6SDavid Howells goto undirty; 575f86726a6SDavid Howells 576f86726a6SDavid Howells if (f < offset) 577f86726a6SDavid Howells t = offset; 578f86726a6SDavid Howells else 579f86726a6SDavid Howells f = end; 580f86726a6SDavid Howells if (f == t) 581f86726a6SDavid Howells goto undirty; 582f86726a6SDavid Howells 58367d78a6fSDavid Howells priv = afs_page_dirty(page, f, t); 584f86726a6SDavid Howells set_page_private(page, priv); 58567d78a6fSDavid Howells trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page); 586f86726a6SDavid Howells return; 587f86726a6SDavid Howells 588f86726a6SDavid Howells undirty: 58967d78a6fSDavid Howells trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page); 590f86726a6SDavid Howells clear_page_dirty_for_io(page); 591f86726a6SDavid Howells full_invalidate: 59267d78a6fSDavid Howells trace_afs_page_dirty(vnode, tracepoint_string("inval"), page); 593e87b03f5SDavid Howells detach_page_private(page); 594f86726a6SDavid Howells } 595f86726a6SDavid Howells 596f86726a6SDavid Howells /* 5979b3f26c9SDavid Howells * invalidate part or all of a page 5989b3f26c9SDavid Howells * - release a page and clean up its private data if offset is 0 (indicating 5999b3f26c9SDavid Howells * the entire page) 6009b3f26c9SDavid Howells */ 601d47992f8SLukas Czerner static void afs_invalidatepage(struct page *page, unsigned int offset, 602d47992f8SLukas Czerner unsigned int length) 6039b3f26c9SDavid Howells { 604d47992f8SLukas Czerner _enter("{%lu},%u,%u", page->index, offset, length); 6059b3f26c9SDavid Howells 6069b3f26c9SDavid Howells BUG_ON(!PageLocked(page)); 6079b3f26c9SDavid Howells 608f86726a6SDavid Howells if (PagePrivate(page)) 609f86726a6SDavid Howells afs_invalidate_dirty(page, offset, length); 6109b3f26c9SDavid Howells 611630f5ddaSDavid Howells wait_on_page_fscache(page); 6129b3f26c9SDavid Howells _leave(""); 6139b3f26c9SDavid Howells } 6149b3f26c9SDavid Howells 6159b3f26c9SDavid Howells /* 6169b3f26c9SDavid Howells * release a page and clean up its private state if it's not busy 6179b3f26c9SDavid Howells * - return true if the page can now be released, false if not 6181da177e4SLinus Torvalds */ 619416351f2SDavid Howells static int afs_releasepage(struct page *page, gfp_t gfp_flags) 6201da177e4SLinus Torvalds { 621416351f2SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 6221da177e4SLinus Torvalds 6233b6492dfSDavid Howells _enter("{{%llx:%llu}[%lu],%lx},%x", 624416351f2SDavid Howells vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, 625416351f2SDavid Howells gfp_flags); 6261da177e4SLinus Torvalds 6279b3f26c9SDavid Howells /* deny if page is being written to the cache and the caller hasn't 6289b3f26c9SDavid Howells * elected to wait */ 629630f5ddaSDavid Howells #ifdef CONFIG_AFS_FSCACHE 630630f5ddaSDavid Howells if (PageFsCache(page)) { 631630f5ddaSDavid Howells if (!(gfp_flags & __GFP_DIRECT_RECLAIM) || !(gfp_flags & __GFP_FS)) 632630f5ddaSDavid Howells return false; 633630f5ddaSDavid Howells wait_on_page_fscache(page); 634630f5ddaSDavid Howells } 635630f5ddaSDavid Howells #endif 636630f5ddaSDavid Howells 6379b3f26c9SDavid Howells if (PagePrivate(page)) { 63867d78a6fSDavid Howells trace_afs_page_dirty(vnode, tracepoint_string("rel"), page); 639e87b03f5SDavid Howells detach_page_private(page); 6409b3f26c9SDavid Howells } 6419b3f26c9SDavid Howells 6429b3f26c9SDavid Howells /* indicate that the page can be released */ 6439b3f26c9SDavid Howells _leave(" = T"); 6449b3f26c9SDavid Howells return 1; 645ec26815aSDavid Howells } 6461cf7a151SDavid Howells 6471cf7a151SDavid Howells /* 6481cf7a151SDavid Howells * Handle setting up a memory mapping on an AFS file. 6491cf7a151SDavid Howells */ 6501cf7a151SDavid Howells static int afs_file_mmap(struct file *file, struct vm_area_struct *vma) 6511cf7a151SDavid Howells { 6521cf7a151SDavid Howells int ret; 6531cf7a151SDavid Howells 6541cf7a151SDavid Howells ret = generic_file_mmap(file, vma); 6551cf7a151SDavid Howells if (ret == 0) 6561cf7a151SDavid Howells vma->vm_ops = &afs_vm_ops; 6571cf7a151SDavid Howells return ret; 6581cf7a151SDavid Howells } 659