108e0e7c8SDavid Howells /* AFS filesystem file handling 21da177e4SLinus Torvalds * 308e0e7c8SDavid Howells * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved. 41da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com) 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include <linux/kernel.h> 131da177e4SLinus Torvalds #include <linux/module.h> 141da177e4SLinus Torvalds #include <linux/init.h> 151da177e4SLinus Torvalds #include <linux/fs.h> 161da177e4SLinus Torvalds #include <linux/pagemap.h> 1731143d5dSDavid Howells #include <linux/writeback.h> 185a0e3ad6STejun Heo #include <linux/gfp.h> 1991b467e0SDavid Howells #include <linux/task_io_accounting_ops.h> 201da177e4SLinus Torvalds #include "internal.h" 211da177e4SLinus Torvalds 22416351f2SDavid Howells static int afs_readpage(struct file *file, struct page *page); 23d47992f8SLukas Czerner static void afs_invalidatepage(struct page *page, unsigned int offset, 24d47992f8SLukas Czerner unsigned int length); 25416351f2SDavid Howells static int afs_releasepage(struct page *page, gfp_t gfp_flags); 2631143d5dSDavid Howells static int afs_launder_page(struct page *page); 271da177e4SLinus Torvalds 289b3f26c9SDavid Howells static int afs_readpages(struct file *filp, struct address_space *mapping, 299b3f26c9SDavid Howells struct list_head *pages, unsigned nr_pages); 309b3f26c9SDavid Howells 3100d3b7a4SDavid Howells const struct file_operations afs_file_operations = { 3200d3b7a4SDavid Howells .open = afs_open, 3358fed94dSDavid Howells .flush = afs_flush, 3400d3b7a4SDavid Howells .release = afs_release, 3500d3b7a4SDavid Howells .llseek = generic_file_llseek, 36aad4f8bbSAl Viro .read_iter = generic_file_read_iter, 3750b5551dSAl Viro .write_iter = afs_file_write, 3800d3b7a4SDavid Howells .mmap = generic_file_readonly_mmap, 395ffc4ef4SJens Axboe .splice_read = generic_file_splice_read, 4031143d5dSDavid Howells .fsync = afs_fsync, 41e8d6c554SDavid Howells .lock = afs_lock, 42e8d6c554SDavid Howells .flock = afs_flock, 4300d3b7a4SDavid Howells }; 4400d3b7a4SDavid Howells 45754661f1SArjan van de Ven const struct inode_operations afs_file_inode_operations = { 46416351f2SDavid Howells .getattr = afs_getattr, 4731143d5dSDavid Howells .setattr = afs_setattr, 4800d3b7a4SDavid Howells .permission = afs_permission, 49d3e3b7eaSDavid Howells .listxattr = afs_listxattr, 501da177e4SLinus Torvalds }; 511da177e4SLinus Torvalds 52f5e54d6eSChristoph Hellwig const struct address_space_operations afs_fs_aops = { 53416351f2SDavid Howells .readpage = afs_readpage, 549b3f26c9SDavid Howells .readpages = afs_readpages, 5531143d5dSDavid Howells .set_page_dirty = afs_set_page_dirty, 5631143d5dSDavid Howells .launder_page = afs_launder_page, 57416351f2SDavid Howells .releasepage = afs_releasepage, 58416351f2SDavid Howells .invalidatepage = afs_invalidatepage, 5915b4650eSNick Piggin .write_begin = afs_write_begin, 6015b4650eSNick Piggin .write_end = afs_write_end, 6131143d5dSDavid Howells .writepage = afs_writepage, 6231143d5dSDavid Howells .writepages = afs_writepages, 631da177e4SLinus Torvalds }; 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds /* 6600d3b7a4SDavid Howells * open an AFS file or directory and attach a key to it 6700d3b7a4SDavid Howells */ 6800d3b7a4SDavid Howells int afs_open(struct inode *inode, struct file *file) 6900d3b7a4SDavid Howells { 7000d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 71*215804a9SDavid Howells struct afs_file *af; 7200d3b7a4SDavid Howells struct key *key; 73260a9803SDavid Howells int ret; 7400d3b7a4SDavid Howells 75416351f2SDavid Howells _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 7600d3b7a4SDavid Howells 7700d3b7a4SDavid Howells key = afs_request_key(vnode->volume->cell); 7800d3b7a4SDavid Howells if (IS_ERR(key)) { 79*215804a9SDavid Howells ret = PTR_ERR(key); 80*215804a9SDavid Howells goto error; 81*215804a9SDavid Howells } 82*215804a9SDavid Howells 83*215804a9SDavid Howells af = kzalloc(sizeof(*af), GFP_KERNEL); 84*215804a9SDavid Howells if (!af) { 85*215804a9SDavid Howells ret = -ENOMEM; 86*215804a9SDavid Howells goto error_key; 8700d3b7a4SDavid Howells } 8800d3b7a4SDavid Howells 89260a9803SDavid Howells ret = afs_validate(vnode, key); 90*215804a9SDavid Howells if (ret < 0) 91*215804a9SDavid Howells goto error_af; 92260a9803SDavid Howells 93*215804a9SDavid Howells af->key = key; 94*215804a9SDavid Howells file->private_data = af; 9500d3b7a4SDavid Howells _leave(" = 0"); 9600d3b7a4SDavid Howells return 0; 97*215804a9SDavid Howells 98*215804a9SDavid Howells error_af: 99*215804a9SDavid Howells kfree(af); 100*215804a9SDavid Howells error_key: 101*215804a9SDavid Howells key_put(key); 102*215804a9SDavid Howells error: 103*215804a9SDavid Howells _leave(" = %d", ret); 104*215804a9SDavid Howells return ret; 10500d3b7a4SDavid Howells } 10600d3b7a4SDavid Howells 10700d3b7a4SDavid Howells /* 10800d3b7a4SDavid Howells * release an AFS file or directory and discard its key 10900d3b7a4SDavid Howells */ 11000d3b7a4SDavid Howells int afs_release(struct inode *inode, struct file *file) 11100d3b7a4SDavid Howells { 11200d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 113*215804a9SDavid Howells struct afs_file *af = file->private_data; 11400d3b7a4SDavid Howells 115416351f2SDavid Howells _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 11600d3b7a4SDavid Howells 117*215804a9SDavid Howells file->private_data = NULL; 118*215804a9SDavid Howells key_put(af->key); 119*215804a9SDavid Howells kfree(af); 12000d3b7a4SDavid Howells _leave(" = 0"); 12100d3b7a4SDavid Howells return 0; 12200d3b7a4SDavid Howells } 12300d3b7a4SDavid Howells 124196ee9cdSDavid Howells /* 125196ee9cdSDavid Howells * Dispose of a ref to a read record. 126196ee9cdSDavid Howells */ 127196ee9cdSDavid Howells void afs_put_read(struct afs_read *req) 128196ee9cdSDavid Howells { 129196ee9cdSDavid Howells int i; 130196ee9cdSDavid Howells 131196ee9cdSDavid Howells if (atomic_dec_and_test(&req->usage)) { 132196ee9cdSDavid Howells for (i = 0; i < req->nr_pages; i++) 133196ee9cdSDavid Howells if (req->pages[i]) 134196ee9cdSDavid Howells put_page(req->pages[i]); 135196ee9cdSDavid Howells kfree(req); 136196ee9cdSDavid Howells } 137196ee9cdSDavid Howells } 138196ee9cdSDavid Howells 1396566abdbSMatt Kraai #ifdef CONFIG_AFS_FSCACHE 14000d3b7a4SDavid Howells /* 1411da177e4SLinus Torvalds * deal with notification that a page was read from the cache 1421da177e4SLinus Torvalds */ 1439b3f26c9SDavid Howells static void afs_file_readpage_read_complete(struct page *page, 1441da177e4SLinus Torvalds void *data, 1451da177e4SLinus Torvalds int error) 1461da177e4SLinus Torvalds { 1479b3f26c9SDavid Howells _enter("%p,%p,%d", page, data, error); 1481da177e4SLinus Torvalds 1499b3f26c9SDavid Howells /* if the read completes with an error, we just unlock the page and let 1509b3f26c9SDavid Howells * the VM reissue the readpage */ 1519b3f26c9SDavid Howells if (!error) 1521da177e4SLinus Torvalds SetPageUptodate(page); 1531da177e4SLinus Torvalds unlock_page(page); 154ec26815aSDavid Howells } 1556566abdbSMatt Kraai #endif 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* 158d2ddc776SDavid Howells * Fetch file data from the volume. 159d2ddc776SDavid Howells */ 160d2ddc776SDavid Howells int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *desc) 161d2ddc776SDavid Howells { 162d2ddc776SDavid Howells struct afs_fs_cursor fc; 163d2ddc776SDavid Howells int ret; 164d2ddc776SDavid Howells 165d2ddc776SDavid Howells _enter("%s{%x:%u.%u},%x,,,", 166d2ddc776SDavid Howells vnode->volume->name, 167d2ddc776SDavid Howells vnode->fid.vid, 168d2ddc776SDavid Howells vnode->fid.vnode, 169d2ddc776SDavid Howells vnode->fid.unique, 170d2ddc776SDavid Howells key_serial(key)); 171d2ddc776SDavid Howells 172d2ddc776SDavid Howells ret = -ERESTARTSYS; 173d2ddc776SDavid Howells if (afs_begin_vnode_operation(&fc, vnode, key)) { 174d2ddc776SDavid Howells while (afs_select_fileserver(&fc)) { 175d2ddc776SDavid Howells fc.cb_break = vnode->cb_break + vnode->cb_s_break; 176d2ddc776SDavid Howells afs_fs_fetch_data(&fc, desc); 177d2ddc776SDavid Howells } 178d2ddc776SDavid Howells 179d2ddc776SDavid Howells afs_check_for_remote_deletion(&fc, fc.vnode); 180d2ddc776SDavid Howells afs_vnode_commit_status(&fc, vnode, fc.cb_break); 181d2ddc776SDavid Howells ret = afs_end_vnode_operation(&fc); 182d2ddc776SDavid Howells } 183d2ddc776SDavid Howells 184d2ddc776SDavid Howells _leave(" = %d", ret); 185d2ddc776SDavid Howells return ret; 186d2ddc776SDavid Howells } 187d2ddc776SDavid Howells 188d2ddc776SDavid Howells /* 189f6d335c0SAl Viro * read page from file, directory or symlink, given a key to use 1901da177e4SLinus Torvalds */ 191f6d335c0SAl Viro int afs_page_filler(void *data, struct page *page) 1921da177e4SLinus Torvalds { 193f6d335c0SAl Viro struct inode *inode = page->mapping->host; 194f6d335c0SAl Viro struct afs_vnode *vnode = AFS_FS_I(inode); 195196ee9cdSDavid Howells struct afs_read *req; 196f6d335c0SAl Viro struct key *key = data; 1971da177e4SLinus Torvalds int ret; 1981da177e4SLinus Torvalds 19900d3b7a4SDavid Howells _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); 2001da177e4SLinus Torvalds 201cd7619d6SMatt Mackall BUG_ON(!PageLocked(page)); 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds ret = -ESTALE; 20408e0e7c8SDavid Howells if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 2051da177e4SLinus Torvalds goto error; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds /* is it cached? */ 2089b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2099b3f26c9SDavid Howells ret = fscache_read_or_alloc_page(vnode->cache, 2101da177e4SLinus Torvalds page, 2111da177e4SLinus Torvalds afs_file_readpage_read_complete, 2121da177e4SLinus Torvalds NULL, 2131da177e4SLinus Torvalds GFP_KERNEL); 2141da177e4SLinus Torvalds #else 2151da177e4SLinus Torvalds ret = -ENOBUFS; 2161da177e4SLinus Torvalds #endif 2171da177e4SLinus Torvalds switch (ret) { 2181da177e4SLinus Torvalds /* read BIO submitted (page in cache) */ 2191da177e4SLinus Torvalds case 0: 2201da177e4SLinus Torvalds break; 2211da177e4SLinus Torvalds 2229b3f26c9SDavid Howells /* page not yet cached */ 2231da177e4SLinus Torvalds case -ENODATA: 2249b3f26c9SDavid Howells _debug("cache said ENODATA"); 2259b3f26c9SDavid Howells goto go_on; 2269b3f26c9SDavid Howells 2279b3f26c9SDavid Howells /* page will not be cached */ 2289b3f26c9SDavid Howells case -ENOBUFS: 2299b3f26c9SDavid Howells _debug("cache said ENOBUFS"); 2301da177e4SLinus Torvalds default: 2319b3f26c9SDavid Howells go_on: 232196ee9cdSDavid Howells req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), 233196ee9cdSDavid Howells GFP_KERNEL); 234196ee9cdSDavid Howells if (!req) 235196ee9cdSDavid Howells goto enomem; 236196ee9cdSDavid Howells 2376db3ac3cSDavid Howells /* We request a full page. If the page is a partial one at the 2386db3ac3cSDavid Howells * end of the file, the server will return a short read and the 2396db3ac3cSDavid Howells * unmarshalling code will clear the unfilled space. 2406db3ac3cSDavid Howells */ 241196ee9cdSDavid Howells atomic_set(&req->usage, 1); 242196ee9cdSDavid Howells req->pos = (loff_t)page->index << PAGE_SHIFT; 2436db3ac3cSDavid Howells req->len = PAGE_SIZE; 244196ee9cdSDavid Howells req->nr_pages = 1; 245196ee9cdSDavid Howells req->pages[0] = page; 246196ee9cdSDavid Howells get_page(page); 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds /* read the contents of the file from the server into the 2491da177e4SLinus Torvalds * page */ 250d2ddc776SDavid Howells ret = afs_fetch_data(vnode, key, req); 251196ee9cdSDavid Howells afs_put_read(req); 252dab17c1aSDavid Howells 253dab17c1aSDavid Howells if (ret >= 0 && S_ISDIR(inode->i_mode) && 254dab17c1aSDavid Howells !afs_dir_check_page(inode, page)) 255dab17c1aSDavid Howells ret = -EIO; 256dab17c1aSDavid Howells 2571da177e4SLinus Torvalds if (ret < 0) { 2581da177e4SLinus Torvalds if (ret == -ENOENT) { 2591da177e4SLinus Torvalds _debug("got NOENT from server" 2601da177e4SLinus Torvalds " - marking file deleted and stale"); 26108e0e7c8SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 2621da177e4SLinus Torvalds ret = -ESTALE; 2631da177e4SLinus Torvalds } 2649b3f26c9SDavid Howells 2659b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2669b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 2671da177e4SLinus Torvalds #endif 2689b3f26c9SDavid Howells BUG_ON(PageFsCache(page)); 26968ae849dSDavid Howells 27068ae849dSDavid Howells if (ret == -EINTR || 27168ae849dSDavid Howells ret == -ENOMEM || 27268ae849dSDavid Howells ret == -ERESTARTSYS || 27368ae849dSDavid Howells ret == -EAGAIN) 2741da177e4SLinus Torvalds goto error; 27568ae849dSDavid Howells goto io_error; 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds SetPageUptodate(page); 2791da177e4SLinus Torvalds 2809b3f26c9SDavid Howells /* send the page to the cache */ 2819b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2829b3f26c9SDavid Howells if (PageFsCache(page) && 2839b3f26c9SDavid Howells fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) { 2849b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 2859b3f26c9SDavid Howells BUG_ON(PageFsCache(page)); 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds #endif 2889b3f26c9SDavid Howells unlock_page(page); 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds _leave(" = 0"); 2921da177e4SLinus Torvalds return 0; 2931da177e4SLinus Torvalds 29468ae849dSDavid Howells io_error: 29568ae849dSDavid Howells SetPageError(page); 29668ae849dSDavid Howells goto error; 297196ee9cdSDavid Howells enomem: 298196ee9cdSDavid Howells ret = -ENOMEM; 2991da177e4SLinus Torvalds error: 3001da177e4SLinus Torvalds unlock_page(page); 3011da177e4SLinus Torvalds _leave(" = %d", ret); 3021da177e4SLinus Torvalds return ret; 303ec26815aSDavid Howells } 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds /* 306f6d335c0SAl Viro * read page from file, directory or symlink, given a file to nominate the key 307f6d335c0SAl Viro * to be used 308f6d335c0SAl Viro */ 309f6d335c0SAl Viro static int afs_readpage(struct file *file, struct page *page) 310f6d335c0SAl Viro { 311f6d335c0SAl Viro struct key *key; 312f6d335c0SAl Viro int ret; 313f6d335c0SAl Viro 314f6d335c0SAl Viro if (file) { 315*215804a9SDavid Howells key = afs_file_key(file); 316f6d335c0SAl Viro ASSERT(key != NULL); 317f6d335c0SAl Viro ret = afs_page_filler(key, page); 318f6d335c0SAl Viro } else { 319f6d335c0SAl Viro struct inode *inode = page->mapping->host; 320d2ddc776SDavid Howells key = afs_request_key(AFS_FS_S(inode->i_sb)->cell); 321f6d335c0SAl Viro if (IS_ERR(key)) { 322f6d335c0SAl Viro ret = PTR_ERR(key); 323f6d335c0SAl Viro } else { 324f6d335c0SAl Viro ret = afs_page_filler(key, page); 325f6d335c0SAl Viro key_put(key); 326f6d335c0SAl Viro } 327f6d335c0SAl Viro } 328f6d335c0SAl Viro return ret; 329f6d335c0SAl Viro } 330f6d335c0SAl Viro 331f6d335c0SAl Viro /* 33291b467e0SDavid Howells * Make pages available as they're filled. 33391b467e0SDavid Howells */ 33491b467e0SDavid Howells static void afs_readpages_page_done(struct afs_call *call, struct afs_read *req) 33591b467e0SDavid Howells { 33651c89e6aSArnd Bergmann #ifdef CONFIG_AFS_FSCACHE 33797e3043aSDavid Howells struct afs_vnode *vnode = call->reply[0]; 33851c89e6aSArnd Bergmann #endif 33991b467e0SDavid Howells struct page *page = req->pages[req->index]; 34091b467e0SDavid Howells 34191b467e0SDavid Howells req->pages[req->index] = NULL; 34291b467e0SDavid Howells SetPageUptodate(page); 34391b467e0SDavid Howells 34491b467e0SDavid Howells /* send the page to the cache */ 34591b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 34691b467e0SDavid Howells if (PageFsCache(page) && 34791b467e0SDavid Howells fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) { 34891b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 34991b467e0SDavid Howells BUG_ON(PageFsCache(page)); 35091b467e0SDavid Howells } 35191b467e0SDavid Howells #endif 35291b467e0SDavid Howells unlock_page(page); 35391b467e0SDavid Howells put_page(page); 35491b467e0SDavid Howells } 35591b467e0SDavid Howells 35691b467e0SDavid Howells /* 35791b467e0SDavid Howells * Read a contiguous set of pages. 35891b467e0SDavid Howells */ 35991b467e0SDavid Howells static int afs_readpages_one(struct file *file, struct address_space *mapping, 36091b467e0SDavid Howells struct list_head *pages) 36191b467e0SDavid Howells { 36291b467e0SDavid Howells struct afs_vnode *vnode = AFS_FS_I(mapping->host); 36391b467e0SDavid Howells struct afs_read *req; 36491b467e0SDavid Howells struct list_head *p; 36591b467e0SDavid Howells struct page *first, *page; 366*215804a9SDavid Howells struct key *key = afs_file_key(file); 36791b467e0SDavid Howells pgoff_t index; 36891b467e0SDavid Howells int ret, n, i; 36991b467e0SDavid Howells 37091b467e0SDavid Howells /* Count the number of contiguous pages at the front of the list. Note 37191b467e0SDavid Howells * that the list goes prev-wards rather than next-wards. 37291b467e0SDavid Howells */ 37391b467e0SDavid Howells first = list_entry(pages->prev, struct page, lru); 37491b467e0SDavid Howells index = first->index + 1; 37591b467e0SDavid Howells n = 1; 37691b467e0SDavid Howells for (p = first->lru.prev; p != pages; p = p->prev) { 37791b467e0SDavid Howells page = list_entry(p, struct page, lru); 37891b467e0SDavid Howells if (page->index != index) 37991b467e0SDavid Howells break; 38091b467e0SDavid Howells index++; 38191b467e0SDavid Howells n++; 38291b467e0SDavid Howells } 38391b467e0SDavid Howells 38491b467e0SDavid Howells req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *) * n, 38591b467e0SDavid Howells GFP_NOFS); 38691b467e0SDavid Howells if (!req) 38791b467e0SDavid Howells return -ENOMEM; 38891b467e0SDavid Howells 38991b467e0SDavid Howells atomic_set(&req->usage, 1); 39091b467e0SDavid Howells req->page_done = afs_readpages_page_done; 39191b467e0SDavid Howells req->pos = first->index; 39291b467e0SDavid Howells req->pos <<= PAGE_SHIFT; 39391b467e0SDavid Howells 39491b467e0SDavid Howells /* Transfer the pages to the request. We add them in until one fails 39591b467e0SDavid Howells * to add to the LRU and then we stop (as that'll make a hole in the 39691b467e0SDavid Howells * contiguous run. 39791b467e0SDavid Howells * 39891b467e0SDavid Howells * Note that it's possible for the file size to change whilst we're 39991b467e0SDavid Howells * doing this, but we rely on the server returning less than we asked 40091b467e0SDavid Howells * for if the file shrank. We also rely on this to deal with a partial 40191b467e0SDavid Howells * page at the end of the file. 40291b467e0SDavid Howells */ 40391b467e0SDavid Howells do { 40491b467e0SDavid Howells page = list_entry(pages->prev, struct page, lru); 40591b467e0SDavid Howells list_del(&page->lru); 40691b467e0SDavid Howells index = page->index; 40791b467e0SDavid Howells if (add_to_page_cache_lru(page, mapping, index, 40891b467e0SDavid Howells readahead_gfp_mask(mapping))) { 40991b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 41091b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 41191b467e0SDavid Howells #endif 41291b467e0SDavid Howells put_page(page); 41391b467e0SDavid Howells break; 41491b467e0SDavid Howells } 41591b467e0SDavid Howells 41691b467e0SDavid Howells req->pages[req->nr_pages++] = page; 41791b467e0SDavid Howells req->len += PAGE_SIZE; 41891b467e0SDavid Howells } while (req->nr_pages < n); 41991b467e0SDavid Howells 42091b467e0SDavid Howells if (req->nr_pages == 0) { 42191b467e0SDavid Howells kfree(req); 42291b467e0SDavid Howells return 0; 42391b467e0SDavid Howells } 42491b467e0SDavid Howells 425d2ddc776SDavid Howells ret = afs_fetch_data(vnode, key, req); 42691b467e0SDavid Howells if (ret < 0) 42791b467e0SDavid Howells goto error; 42891b467e0SDavid Howells 42991b467e0SDavid Howells task_io_account_read(PAGE_SIZE * req->nr_pages); 43091b467e0SDavid Howells afs_put_read(req); 43191b467e0SDavid Howells return 0; 43291b467e0SDavid Howells 43391b467e0SDavid Howells error: 43491b467e0SDavid Howells if (ret == -ENOENT) { 43591b467e0SDavid Howells _debug("got NOENT from server" 43691b467e0SDavid Howells " - marking file deleted and stale"); 43791b467e0SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 43891b467e0SDavid Howells ret = -ESTALE; 43991b467e0SDavid Howells } 44091b467e0SDavid Howells 44191b467e0SDavid Howells for (i = 0; i < req->nr_pages; i++) { 44291b467e0SDavid Howells page = req->pages[i]; 44391b467e0SDavid Howells if (page) { 44491b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 44591b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 44691b467e0SDavid Howells #endif 44791b467e0SDavid Howells SetPageError(page); 44891b467e0SDavid Howells unlock_page(page); 44991b467e0SDavid Howells } 45091b467e0SDavid Howells } 45191b467e0SDavid Howells 45291b467e0SDavid Howells afs_put_read(req); 45391b467e0SDavid Howells return ret; 45491b467e0SDavid Howells } 45591b467e0SDavid Howells 45691b467e0SDavid Howells /* 4579b3f26c9SDavid Howells * read a set of pages 4581da177e4SLinus Torvalds */ 4599b3f26c9SDavid Howells static int afs_readpages(struct file *file, struct address_space *mapping, 4609b3f26c9SDavid Howells struct list_head *pages, unsigned nr_pages) 4611da177e4SLinus Torvalds { 462*215804a9SDavid Howells struct key *key = afs_file_key(file); 4639b3f26c9SDavid Howells struct afs_vnode *vnode; 4649b3f26c9SDavid Howells int ret = 0; 4651da177e4SLinus Torvalds 466f6d335c0SAl Viro _enter("{%d},{%lu},,%d", 467f6d335c0SAl Viro key_serial(key), mapping->host->i_ino, nr_pages); 468f6d335c0SAl Viro 469f6d335c0SAl Viro ASSERT(key != NULL); 4701da177e4SLinus Torvalds 4719b3f26c9SDavid Howells vnode = AFS_FS_I(mapping->host); 472ad2a8e60SDan Carpenter if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { 4739b3f26c9SDavid Howells _leave(" = -ESTALE"); 4749b3f26c9SDavid Howells return -ESTALE; 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 4779b3f26c9SDavid Howells /* attempt to read as many of the pages as possible */ 4789b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 4799b3f26c9SDavid Howells ret = fscache_read_or_alloc_pages(vnode->cache, 4809b3f26c9SDavid Howells mapping, 4819b3f26c9SDavid Howells pages, 4829b3f26c9SDavid Howells &nr_pages, 4839b3f26c9SDavid Howells afs_file_readpage_read_complete, 4849b3f26c9SDavid Howells NULL, 4859b3f26c9SDavid Howells mapping_gfp_mask(mapping)); 4869b3f26c9SDavid Howells #else 4879b3f26c9SDavid Howells ret = -ENOBUFS; 4889b3f26c9SDavid Howells #endif 4899b3f26c9SDavid Howells 4909b3f26c9SDavid Howells switch (ret) { 4919b3f26c9SDavid Howells /* all pages are being read from the cache */ 4929b3f26c9SDavid Howells case 0: 4939b3f26c9SDavid Howells BUG_ON(!list_empty(pages)); 4949b3f26c9SDavid Howells BUG_ON(nr_pages != 0); 4959b3f26c9SDavid Howells _leave(" = 0 [reading all]"); 4969b3f26c9SDavid Howells return 0; 4979b3f26c9SDavid Howells 4989b3f26c9SDavid Howells /* there were pages that couldn't be read from the cache */ 4999b3f26c9SDavid Howells case -ENODATA: 5009b3f26c9SDavid Howells case -ENOBUFS: 5019b3f26c9SDavid Howells break; 5029b3f26c9SDavid Howells 5039b3f26c9SDavid Howells /* other error */ 5049b3f26c9SDavid Howells default: 5051da177e4SLinus Torvalds _leave(" = %d", ret); 5069b3f26c9SDavid Howells return ret; 5079b3f26c9SDavid Howells } 5089b3f26c9SDavid Howells 50991b467e0SDavid Howells while (!list_empty(pages)) { 51091b467e0SDavid Howells ret = afs_readpages_one(file, mapping, pages); 51191b467e0SDavid Howells if (ret < 0) 51291b467e0SDavid Howells break; 51391b467e0SDavid Howells } 5149b3f26c9SDavid Howells 5159b3f26c9SDavid Howells _leave(" = %d [netting]", ret); 5169b3f26c9SDavid Howells return ret; 517ec26815aSDavid Howells } 5181da177e4SLinus Torvalds 5191da177e4SLinus Torvalds /* 52031143d5dSDavid Howells * write back a dirty page 52131143d5dSDavid Howells */ 52231143d5dSDavid Howells static int afs_launder_page(struct page *page) 52331143d5dSDavid Howells { 52431143d5dSDavid Howells _enter("{%lu}", page->index); 52531143d5dSDavid Howells 52631143d5dSDavid Howells return 0; 52731143d5dSDavid Howells } 52831143d5dSDavid Howells 52931143d5dSDavid Howells /* 5309b3f26c9SDavid Howells * invalidate part or all of a page 5319b3f26c9SDavid Howells * - release a page and clean up its private data if offset is 0 (indicating 5329b3f26c9SDavid Howells * the entire page) 5339b3f26c9SDavid Howells */ 534d47992f8SLukas Czerner static void afs_invalidatepage(struct page *page, unsigned int offset, 535d47992f8SLukas Czerner unsigned int length) 5369b3f26c9SDavid Howells { 5379b3f26c9SDavid Howells struct afs_writeback *wb = (struct afs_writeback *) page_private(page); 5389b3f26c9SDavid Howells 539d47992f8SLukas Czerner _enter("{%lu},%u,%u", page->index, offset, length); 5409b3f26c9SDavid Howells 5419b3f26c9SDavid Howells BUG_ON(!PageLocked(page)); 5429b3f26c9SDavid Howells 5439b3f26c9SDavid Howells /* we clean up only if the entire page is being invalidated */ 54409cbfeafSKirill A. Shutemov if (offset == 0 && length == PAGE_SIZE) { 5459b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 5469b3f26c9SDavid Howells if (PageFsCache(page)) { 5479b3f26c9SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 5489b3f26c9SDavid Howells fscache_wait_on_page_write(vnode->cache, page); 5499b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 5509b3f26c9SDavid Howells } 5519b3f26c9SDavid Howells #endif 5529b3f26c9SDavid Howells 5539b3f26c9SDavid Howells if (PagePrivate(page)) { 5549b3f26c9SDavid Howells if (wb && !PageWriteback(page)) { 5559b3f26c9SDavid Howells set_page_private(page, 0); 5569b3f26c9SDavid Howells afs_put_writeback(wb); 5579b3f26c9SDavid Howells } 5589b3f26c9SDavid Howells 5599b3f26c9SDavid Howells if (!page_private(page)) 5609b3f26c9SDavid Howells ClearPagePrivate(page); 5619b3f26c9SDavid Howells } 5629b3f26c9SDavid Howells } 5639b3f26c9SDavid Howells 5649b3f26c9SDavid Howells _leave(""); 5659b3f26c9SDavid Howells } 5669b3f26c9SDavid Howells 5679b3f26c9SDavid Howells /* 5689b3f26c9SDavid Howells * release a page and clean up its private state if it's not busy 5699b3f26c9SDavid Howells * - return true if the page can now be released, false if not 5701da177e4SLinus Torvalds */ 571416351f2SDavid Howells static int afs_releasepage(struct page *page, gfp_t gfp_flags) 5721da177e4SLinus Torvalds { 5739b3f26c9SDavid Howells struct afs_writeback *wb = (struct afs_writeback *) page_private(page); 574416351f2SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 5751da177e4SLinus Torvalds 576416351f2SDavid Howells _enter("{{%x:%u}[%lu],%lx},%x", 577416351f2SDavid Howells vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, 578416351f2SDavid Howells gfp_flags); 5791da177e4SLinus Torvalds 5809b3f26c9SDavid Howells /* deny if page is being written to the cache and the caller hasn't 5819b3f26c9SDavid Howells * elected to wait */ 5829b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 583201a1542SDavid Howells if (!fscache_maybe_release_page(vnode->cache, page, gfp_flags)) { 5849b3f26c9SDavid Howells _leave(" = F [cache busy]"); 5859b3f26c9SDavid Howells return 0; 5869b3f26c9SDavid Howells } 5879b3f26c9SDavid Howells #endif 5889b3f26c9SDavid Howells 5899b3f26c9SDavid Howells if (PagePrivate(page)) { 5909b3f26c9SDavid Howells if (wb) { 5919b3f26c9SDavid Howells set_page_private(page, 0); 5929b3f26c9SDavid Howells afs_put_writeback(wb); 5939b3f26c9SDavid Howells } 5949b3f26c9SDavid Howells ClearPagePrivate(page); 5959b3f26c9SDavid Howells } 5969b3f26c9SDavid Howells 5979b3f26c9SDavid Howells /* indicate that the page can be released */ 5989b3f26c9SDavid Howells _leave(" = T"); 5999b3f26c9SDavid Howells return 1; 600ec26815aSDavid Howells } 601