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, 3300d3b7a4SDavid Howells .release = afs_release, 3400d3b7a4SDavid Howells .llseek = generic_file_llseek, 35aad4f8bbSAl Viro .read_iter = generic_file_read_iter, 3650b5551dSAl Viro .write_iter = afs_file_write, 3700d3b7a4SDavid Howells .mmap = generic_file_readonly_mmap, 385ffc4ef4SJens Axboe .splice_read = generic_file_splice_read, 3931143d5dSDavid Howells .fsync = afs_fsync, 40e8d6c554SDavid Howells .lock = afs_lock, 41e8d6c554SDavid Howells .flock = afs_flock, 4200d3b7a4SDavid Howells }; 4300d3b7a4SDavid Howells 44754661f1SArjan van de Ven const struct inode_operations afs_file_inode_operations = { 45416351f2SDavid Howells .getattr = afs_getattr, 4631143d5dSDavid Howells .setattr = afs_setattr, 4700d3b7a4SDavid Howells .permission = afs_permission, 481da177e4SLinus Torvalds }; 491da177e4SLinus Torvalds 50f5e54d6eSChristoph Hellwig const struct address_space_operations afs_fs_aops = { 51416351f2SDavid Howells .readpage = afs_readpage, 529b3f26c9SDavid Howells .readpages = afs_readpages, 5331143d5dSDavid Howells .set_page_dirty = afs_set_page_dirty, 5431143d5dSDavid Howells .launder_page = afs_launder_page, 55416351f2SDavid Howells .releasepage = afs_releasepage, 56416351f2SDavid Howells .invalidatepage = afs_invalidatepage, 5715b4650eSNick Piggin .write_begin = afs_write_begin, 5815b4650eSNick Piggin .write_end = afs_write_end, 5931143d5dSDavid Howells .writepage = afs_writepage, 6031143d5dSDavid Howells .writepages = afs_writepages, 611da177e4SLinus Torvalds }; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds /* 6400d3b7a4SDavid Howells * open an AFS file or directory and attach a key to it 6500d3b7a4SDavid Howells */ 6600d3b7a4SDavid Howells int afs_open(struct inode *inode, struct file *file) 6700d3b7a4SDavid Howells { 6800d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 6900d3b7a4SDavid Howells struct key *key; 70260a9803SDavid Howells int ret; 7100d3b7a4SDavid Howells 72416351f2SDavid Howells _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 7300d3b7a4SDavid Howells 7400d3b7a4SDavid Howells key = afs_request_key(vnode->volume->cell); 7500d3b7a4SDavid Howells if (IS_ERR(key)) { 7600d3b7a4SDavid Howells _leave(" = %ld [key]", PTR_ERR(key)); 7700d3b7a4SDavid Howells return PTR_ERR(key); 7800d3b7a4SDavid Howells } 7900d3b7a4SDavid Howells 80260a9803SDavid Howells ret = afs_validate(vnode, key); 81260a9803SDavid Howells if (ret < 0) { 82260a9803SDavid Howells _leave(" = %d [val]", ret); 83260a9803SDavid Howells return ret; 84260a9803SDavid Howells } 85260a9803SDavid Howells 8600d3b7a4SDavid Howells file->private_data = key; 8700d3b7a4SDavid Howells _leave(" = 0"); 8800d3b7a4SDavid Howells return 0; 8900d3b7a4SDavid Howells } 9000d3b7a4SDavid Howells 9100d3b7a4SDavid Howells /* 9200d3b7a4SDavid Howells * release an AFS file or directory and discard its key 9300d3b7a4SDavid Howells */ 9400d3b7a4SDavid Howells int afs_release(struct inode *inode, struct file *file) 9500d3b7a4SDavid Howells { 9600d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 9700d3b7a4SDavid Howells 98416351f2SDavid Howells _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 9900d3b7a4SDavid Howells 10000d3b7a4SDavid Howells key_put(file->private_data); 10100d3b7a4SDavid Howells _leave(" = 0"); 10200d3b7a4SDavid Howells return 0; 10300d3b7a4SDavid Howells } 10400d3b7a4SDavid Howells 105196ee9cdSDavid Howells /* 106196ee9cdSDavid Howells * Dispose of a ref to a read record. 107196ee9cdSDavid Howells */ 108196ee9cdSDavid Howells void afs_put_read(struct afs_read *req) 109196ee9cdSDavid Howells { 110196ee9cdSDavid Howells int i; 111196ee9cdSDavid Howells 112196ee9cdSDavid Howells if (atomic_dec_and_test(&req->usage)) { 113196ee9cdSDavid Howells for (i = 0; i < req->nr_pages; i++) 114196ee9cdSDavid Howells if (req->pages[i]) 115196ee9cdSDavid Howells put_page(req->pages[i]); 116196ee9cdSDavid Howells kfree(req); 117196ee9cdSDavid Howells } 118196ee9cdSDavid Howells } 119196ee9cdSDavid Howells 1206566abdbSMatt Kraai #ifdef CONFIG_AFS_FSCACHE 12100d3b7a4SDavid Howells /* 1221da177e4SLinus Torvalds * deal with notification that a page was read from the cache 1231da177e4SLinus Torvalds */ 1249b3f26c9SDavid Howells static void afs_file_readpage_read_complete(struct page *page, 1251da177e4SLinus Torvalds void *data, 1261da177e4SLinus Torvalds int error) 1271da177e4SLinus Torvalds { 1289b3f26c9SDavid Howells _enter("%p,%p,%d", page, data, error); 1291da177e4SLinus Torvalds 1309b3f26c9SDavid Howells /* if the read completes with an error, we just unlock the page and let 1319b3f26c9SDavid Howells * the VM reissue the readpage */ 1329b3f26c9SDavid Howells if (!error) 1331da177e4SLinus Torvalds SetPageUptodate(page); 1341da177e4SLinus Torvalds unlock_page(page); 135ec26815aSDavid Howells } 1366566abdbSMatt Kraai #endif 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds /* 139f6d335c0SAl Viro * read page from file, directory or symlink, given a key to use 1401da177e4SLinus Torvalds */ 141f6d335c0SAl Viro int afs_page_filler(void *data, struct page *page) 1421da177e4SLinus Torvalds { 143f6d335c0SAl Viro struct inode *inode = page->mapping->host; 144f6d335c0SAl Viro struct afs_vnode *vnode = AFS_FS_I(inode); 145196ee9cdSDavid Howells struct afs_read *req; 146f6d335c0SAl Viro struct key *key = data; 1471da177e4SLinus Torvalds int ret; 1481da177e4SLinus Torvalds 14900d3b7a4SDavid Howells _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); 1501da177e4SLinus Torvalds 151cd7619d6SMatt Mackall BUG_ON(!PageLocked(page)); 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds ret = -ESTALE; 15408e0e7c8SDavid Howells if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 1551da177e4SLinus Torvalds goto error; 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* is it cached? */ 1589b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1599b3f26c9SDavid Howells ret = fscache_read_or_alloc_page(vnode->cache, 1601da177e4SLinus Torvalds page, 1611da177e4SLinus Torvalds afs_file_readpage_read_complete, 1621da177e4SLinus Torvalds NULL, 1631da177e4SLinus Torvalds GFP_KERNEL); 1641da177e4SLinus Torvalds #else 1651da177e4SLinus Torvalds ret = -ENOBUFS; 1661da177e4SLinus Torvalds #endif 1671da177e4SLinus Torvalds switch (ret) { 1681da177e4SLinus Torvalds /* read BIO submitted (page in cache) */ 1691da177e4SLinus Torvalds case 0: 1701da177e4SLinus Torvalds break; 1711da177e4SLinus Torvalds 1729b3f26c9SDavid Howells /* page not yet cached */ 1731da177e4SLinus Torvalds case -ENODATA: 1749b3f26c9SDavid Howells _debug("cache said ENODATA"); 1759b3f26c9SDavid Howells goto go_on; 1769b3f26c9SDavid Howells 1779b3f26c9SDavid Howells /* page will not be cached */ 1789b3f26c9SDavid Howells case -ENOBUFS: 1799b3f26c9SDavid Howells _debug("cache said ENOBUFS"); 1801da177e4SLinus Torvalds default: 1819b3f26c9SDavid Howells go_on: 182196ee9cdSDavid Howells req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), 183196ee9cdSDavid Howells GFP_KERNEL); 184196ee9cdSDavid Howells if (!req) 185196ee9cdSDavid Howells goto enomem; 186196ee9cdSDavid Howells 187*6db3ac3cSDavid Howells /* We request a full page. If the page is a partial one at the 188*6db3ac3cSDavid Howells * end of the file, the server will return a short read and the 189*6db3ac3cSDavid Howells * unmarshalling code will clear the unfilled space. 190*6db3ac3cSDavid Howells */ 191196ee9cdSDavid Howells atomic_set(&req->usage, 1); 192196ee9cdSDavid Howells req->pos = (loff_t)page->index << PAGE_SHIFT; 193*6db3ac3cSDavid Howells req->len = PAGE_SIZE; 194196ee9cdSDavid Howells req->nr_pages = 1; 195196ee9cdSDavid Howells req->pages[0] = page; 196196ee9cdSDavid Howells get_page(page); 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds /* read the contents of the file from the server into the 1991da177e4SLinus Torvalds * page */ 200196ee9cdSDavid Howells ret = afs_vnode_fetch_data(vnode, key, req); 201196ee9cdSDavid Howells afs_put_read(req); 2021da177e4SLinus Torvalds if (ret < 0) { 2031da177e4SLinus Torvalds if (ret == -ENOENT) { 2041da177e4SLinus Torvalds _debug("got NOENT from server" 2051da177e4SLinus Torvalds " - marking file deleted and stale"); 20608e0e7c8SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 2071da177e4SLinus Torvalds ret = -ESTALE; 2081da177e4SLinus Torvalds } 2099b3f26c9SDavid Howells 2109b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2119b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 2121da177e4SLinus Torvalds #endif 2139b3f26c9SDavid Howells BUG_ON(PageFsCache(page)); 2141da177e4SLinus Torvalds goto error; 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds SetPageUptodate(page); 2181da177e4SLinus Torvalds 2199b3f26c9SDavid Howells /* send the page to the cache */ 2209b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2219b3f26c9SDavid Howells if (PageFsCache(page) && 2229b3f26c9SDavid Howells fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) { 2239b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 2249b3f26c9SDavid Howells BUG_ON(PageFsCache(page)); 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds #endif 2279b3f26c9SDavid Howells unlock_page(page); 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds _leave(" = 0"); 2311da177e4SLinus Torvalds return 0; 2321da177e4SLinus Torvalds 233196ee9cdSDavid Howells enomem: 234196ee9cdSDavid Howells ret = -ENOMEM; 2351da177e4SLinus Torvalds error: 2361da177e4SLinus Torvalds SetPageError(page); 2371da177e4SLinus Torvalds unlock_page(page); 2381da177e4SLinus Torvalds _leave(" = %d", ret); 2391da177e4SLinus Torvalds return ret; 240ec26815aSDavid Howells } 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds /* 243f6d335c0SAl Viro * read page from file, directory or symlink, given a file to nominate the key 244f6d335c0SAl Viro * to be used 245f6d335c0SAl Viro */ 246f6d335c0SAl Viro static int afs_readpage(struct file *file, struct page *page) 247f6d335c0SAl Viro { 248f6d335c0SAl Viro struct key *key; 249f6d335c0SAl Viro int ret; 250f6d335c0SAl Viro 251f6d335c0SAl Viro if (file) { 252f6d335c0SAl Viro key = file->private_data; 253f6d335c0SAl Viro ASSERT(key != NULL); 254f6d335c0SAl Viro ret = afs_page_filler(key, page); 255f6d335c0SAl Viro } else { 256f6d335c0SAl Viro struct inode *inode = page->mapping->host; 257f6d335c0SAl Viro key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell); 258f6d335c0SAl Viro if (IS_ERR(key)) { 259f6d335c0SAl Viro ret = PTR_ERR(key); 260f6d335c0SAl Viro } else { 261f6d335c0SAl Viro ret = afs_page_filler(key, page); 262f6d335c0SAl Viro key_put(key); 263f6d335c0SAl Viro } 264f6d335c0SAl Viro } 265f6d335c0SAl Viro return ret; 266f6d335c0SAl Viro } 267f6d335c0SAl Viro 268f6d335c0SAl Viro /* 26991b467e0SDavid Howells * Make pages available as they're filled. 27091b467e0SDavid Howells */ 27191b467e0SDavid Howells static void afs_readpages_page_done(struct afs_call *call, struct afs_read *req) 27291b467e0SDavid Howells { 27351c89e6aSArnd Bergmann #ifdef CONFIG_AFS_FSCACHE 27491b467e0SDavid Howells struct afs_vnode *vnode = call->reply; 27551c89e6aSArnd Bergmann #endif 27691b467e0SDavid Howells struct page *page = req->pages[req->index]; 27791b467e0SDavid Howells 27891b467e0SDavid Howells req->pages[req->index] = NULL; 27991b467e0SDavid Howells SetPageUptodate(page); 28091b467e0SDavid Howells 28191b467e0SDavid Howells /* send the page to the cache */ 28291b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 28391b467e0SDavid Howells if (PageFsCache(page) && 28491b467e0SDavid Howells fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) { 28591b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 28691b467e0SDavid Howells BUG_ON(PageFsCache(page)); 28791b467e0SDavid Howells } 28891b467e0SDavid Howells #endif 28991b467e0SDavid Howells unlock_page(page); 29091b467e0SDavid Howells put_page(page); 29191b467e0SDavid Howells } 29291b467e0SDavid Howells 29391b467e0SDavid Howells /* 29491b467e0SDavid Howells * Read a contiguous set of pages. 29591b467e0SDavid Howells */ 29691b467e0SDavid Howells static int afs_readpages_one(struct file *file, struct address_space *mapping, 29791b467e0SDavid Howells struct list_head *pages) 29891b467e0SDavid Howells { 29991b467e0SDavid Howells struct afs_vnode *vnode = AFS_FS_I(mapping->host); 30091b467e0SDavid Howells struct afs_read *req; 30191b467e0SDavid Howells struct list_head *p; 30291b467e0SDavid Howells struct page *first, *page; 30391b467e0SDavid Howells struct key *key = file->private_data; 30491b467e0SDavid Howells pgoff_t index; 30591b467e0SDavid Howells int ret, n, i; 30691b467e0SDavid Howells 30791b467e0SDavid Howells /* Count the number of contiguous pages at the front of the list. Note 30891b467e0SDavid Howells * that the list goes prev-wards rather than next-wards. 30991b467e0SDavid Howells */ 31091b467e0SDavid Howells first = list_entry(pages->prev, struct page, lru); 31191b467e0SDavid Howells index = first->index + 1; 31291b467e0SDavid Howells n = 1; 31391b467e0SDavid Howells for (p = first->lru.prev; p != pages; p = p->prev) { 31491b467e0SDavid Howells page = list_entry(p, struct page, lru); 31591b467e0SDavid Howells if (page->index != index) 31691b467e0SDavid Howells break; 31791b467e0SDavid Howells index++; 31891b467e0SDavid Howells n++; 31991b467e0SDavid Howells } 32091b467e0SDavid Howells 32191b467e0SDavid Howells req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *) * n, 32291b467e0SDavid Howells GFP_NOFS); 32391b467e0SDavid Howells if (!req) 32491b467e0SDavid Howells return -ENOMEM; 32591b467e0SDavid Howells 32691b467e0SDavid Howells atomic_set(&req->usage, 1); 32791b467e0SDavid Howells req->page_done = afs_readpages_page_done; 32891b467e0SDavid Howells req->pos = first->index; 32991b467e0SDavid Howells req->pos <<= PAGE_SHIFT; 33091b467e0SDavid Howells 33191b467e0SDavid Howells /* Transfer the pages to the request. We add them in until one fails 33291b467e0SDavid Howells * to add to the LRU and then we stop (as that'll make a hole in the 33391b467e0SDavid Howells * contiguous run. 33491b467e0SDavid Howells * 33591b467e0SDavid Howells * Note that it's possible for the file size to change whilst we're 33691b467e0SDavid Howells * doing this, but we rely on the server returning less than we asked 33791b467e0SDavid Howells * for if the file shrank. We also rely on this to deal with a partial 33891b467e0SDavid Howells * page at the end of the file. 33991b467e0SDavid Howells */ 34091b467e0SDavid Howells do { 34191b467e0SDavid Howells page = list_entry(pages->prev, struct page, lru); 34291b467e0SDavid Howells list_del(&page->lru); 34391b467e0SDavid Howells index = page->index; 34491b467e0SDavid Howells if (add_to_page_cache_lru(page, mapping, index, 34591b467e0SDavid Howells readahead_gfp_mask(mapping))) { 34691b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 34791b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 34891b467e0SDavid Howells #endif 34991b467e0SDavid Howells put_page(page); 35091b467e0SDavid Howells break; 35191b467e0SDavid Howells } 35291b467e0SDavid Howells 35391b467e0SDavid Howells req->pages[req->nr_pages++] = page; 35491b467e0SDavid Howells req->len += PAGE_SIZE; 35591b467e0SDavid Howells } while (req->nr_pages < n); 35691b467e0SDavid Howells 35791b467e0SDavid Howells if (req->nr_pages == 0) { 35891b467e0SDavid Howells kfree(req); 35991b467e0SDavid Howells return 0; 36091b467e0SDavid Howells } 36191b467e0SDavid Howells 36291b467e0SDavid Howells ret = afs_vnode_fetch_data(vnode, key, req); 36391b467e0SDavid Howells if (ret < 0) 36491b467e0SDavid Howells goto error; 36591b467e0SDavid Howells 36691b467e0SDavid Howells task_io_account_read(PAGE_SIZE * req->nr_pages); 36791b467e0SDavid Howells afs_put_read(req); 36891b467e0SDavid Howells return 0; 36991b467e0SDavid Howells 37091b467e0SDavid Howells error: 37191b467e0SDavid Howells if (ret == -ENOENT) { 37291b467e0SDavid Howells _debug("got NOENT from server" 37391b467e0SDavid Howells " - marking file deleted and stale"); 37491b467e0SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 37591b467e0SDavid Howells ret = -ESTALE; 37691b467e0SDavid Howells } 37791b467e0SDavid Howells 37891b467e0SDavid Howells for (i = 0; i < req->nr_pages; i++) { 37991b467e0SDavid Howells page = req->pages[i]; 38091b467e0SDavid Howells if (page) { 38191b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 38291b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 38391b467e0SDavid Howells #endif 38491b467e0SDavid Howells SetPageError(page); 38591b467e0SDavid Howells unlock_page(page); 38691b467e0SDavid Howells } 38791b467e0SDavid Howells } 38891b467e0SDavid Howells 38991b467e0SDavid Howells afs_put_read(req); 39091b467e0SDavid Howells return ret; 39191b467e0SDavid Howells } 39291b467e0SDavid Howells 39391b467e0SDavid Howells /* 3949b3f26c9SDavid Howells * read a set of pages 3951da177e4SLinus Torvalds */ 3969b3f26c9SDavid Howells static int afs_readpages(struct file *file, struct address_space *mapping, 3979b3f26c9SDavid Howells struct list_head *pages, unsigned nr_pages) 3981da177e4SLinus Torvalds { 399f6d335c0SAl Viro struct key *key = file->private_data; 4009b3f26c9SDavid Howells struct afs_vnode *vnode; 4019b3f26c9SDavid Howells int ret = 0; 4021da177e4SLinus Torvalds 403f6d335c0SAl Viro _enter("{%d},{%lu},,%d", 404f6d335c0SAl Viro key_serial(key), mapping->host->i_ino, nr_pages); 405f6d335c0SAl Viro 406f6d335c0SAl Viro ASSERT(key != NULL); 4071da177e4SLinus Torvalds 4089b3f26c9SDavid Howells vnode = AFS_FS_I(mapping->host); 409ad2a8e60SDan Carpenter if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { 4109b3f26c9SDavid Howells _leave(" = -ESTALE"); 4119b3f26c9SDavid Howells return -ESTALE; 4121da177e4SLinus Torvalds } 4131da177e4SLinus Torvalds 4149b3f26c9SDavid Howells /* attempt to read as many of the pages as possible */ 4159b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 4169b3f26c9SDavid Howells ret = fscache_read_or_alloc_pages(vnode->cache, 4179b3f26c9SDavid Howells mapping, 4189b3f26c9SDavid Howells pages, 4199b3f26c9SDavid Howells &nr_pages, 4209b3f26c9SDavid Howells afs_file_readpage_read_complete, 4219b3f26c9SDavid Howells NULL, 4229b3f26c9SDavid Howells mapping_gfp_mask(mapping)); 4239b3f26c9SDavid Howells #else 4249b3f26c9SDavid Howells ret = -ENOBUFS; 4259b3f26c9SDavid Howells #endif 4269b3f26c9SDavid Howells 4279b3f26c9SDavid Howells switch (ret) { 4289b3f26c9SDavid Howells /* all pages are being read from the cache */ 4299b3f26c9SDavid Howells case 0: 4309b3f26c9SDavid Howells BUG_ON(!list_empty(pages)); 4319b3f26c9SDavid Howells BUG_ON(nr_pages != 0); 4329b3f26c9SDavid Howells _leave(" = 0 [reading all]"); 4339b3f26c9SDavid Howells return 0; 4349b3f26c9SDavid Howells 4359b3f26c9SDavid Howells /* there were pages that couldn't be read from the cache */ 4369b3f26c9SDavid Howells case -ENODATA: 4379b3f26c9SDavid Howells case -ENOBUFS: 4389b3f26c9SDavid Howells break; 4399b3f26c9SDavid Howells 4409b3f26c9SDavid Howells /* other error */ 4419b3f26c9SDavid Howells default: 4421da177e4SLinus Torvalds _leave(" = %d", ret); 4439b3f26c9SDavid Howells return ret; 4449b3f26c9SDavid Howells } 4459b3f26c9SDavid Howells 44691b467e0SDavid Howells while (!list_empty(pages)) { 44791b467e0SDavid Howells ret = afs_readpages_one(file, mapping, pages); 44891b467e0SDavid Howells if (ret < 0) 44991b467e0SDavid Howells break; 45091b467e0SDavid Howells } 4519b3f26c9SDavid Howells 4529b3f26c9SDavid Howells _leave(" = %d [netting]", ret); 4539b3f26c9SDavid Howells return ret; 454ec26815aSDavid Howells } 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds /* 45731143d5dSDavid Howells * write back a dirty page 45831143d5dSDavid Howells */ 45931143d5dSDavid Howells static int afs_launder_page(struct page *page) 46031143d5dSDavid Howells { 46131143d5dSDavid Howells _enter("{%lu}", page->index); 46231143d5dSDavid Howells 46331143d5dSDavid Howells return 0; 46431143d5dSDavid Howells } 46531143d5dSDavid Howells 46631143d5dSDavid Howells /* 4679b3f26c9SDavid Howells * invalidate part or all of a page 4689b3f26c9SDavid Howells * - release a page and clean up its private data if offset is 0 (indicating 4699b3f26c9SDavid Howells * the entire page) 4709b3f26c9SDavid Howells */ 471d47992f8SLukas Czerner static void afs_invalidatepage(struct page *page, unsigned int offset, 472d47992f8SLukas Czerner unsigned int length) 4739b3f26c9SDavid Howells { 4749b3f26c9SDavid Howells struct afs_writeback *wb = (struct afs_writeback *) page_private(page); 4759b3f26c9SDavid Howells 476d47992f8SLukas Czerner _enter("{%lu},%u,%u", page->index, offset, length); 4779b3f26c9SDavid Howells 4789b3f26c9SDavid Howells BUG_ON(!PageLocked(page)); 4799b3f26c9SDavid Howells 4809b3f26c9SDavid Howells /* we clean up only if the entire page is being invalidated */ 48109cbfeafSKirill A. Shutemov if (offset == 0 && length == PAGE_SIZE) { 4829b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 4839b3f26c9SDavid Howells if (PageFsCache(page)) { 4849b3f26c9SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 4859b3f26c9SDavid Howells fscache_wait_on_page_write(vnode->cache, page); 4869b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 4879b3f26c9SDavid Howells } 4889b3f26c9SDavid Howells #endif 4899b3f26c9SDavid Howells 4909b3f26c9SDavid Howells if (PagePrivate(page)) { 4919b3f26c9SDavid Howells if (wb && !PageWriteback(page)) { 4929b3f26c9SDavid Howells set_page_private(page, 0); 4939b3f26c9SDavid Howells afs_put_writeback(wb); 4949b3f26c9SDavid Howells } 4959b3f26c9SDavid Howells 4969b3f26c9SDavid Howells if (!page_private(page)) 4979b3f26c9SDavid Howells ClearPagePrivate(page); 4989b3f26c9SDavid Howells } 4999b3f26c9SDavid Howells } 5009b3f26c9SDavid Howells 5019b3f26c9SDavid Howells _leave(""); 5029b3f26c9SDavid Howells } 5039b3f26c9SDavid Howells 5049b3f26c9SDavid Howells /* 5059b3f26c9SDavid Howells * release a page and clean up its private state if it's not busy 5069b3f26c9SDavid Howells * - return true if the page can now be released, false if not 5071da177e4SLinus Torvalds */ 508416351f2SDavid Howells static int afs_releasepage(struct page *page, gfp_t gfp_flags) 5091da177e4SLinus Torvalds { 5109b3f26c9SDavid Howells struct afs_writeback *wb = (struct afs_writeback *) page_private(page); 511416351f2SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 5121da177e4SLinus Torvalds 513416351f2SDavid Howells _enter("{{%x:%u}[%lu],%lx},%x", 514416351f2SDavid Howells vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, 515416351f2SDavid Howells gfp_flags); 5161da177e4SLinus Torvalds 5179b3f26c9SDavid Howells /* deny if page is being written to the cache and the caller hasn't 5189b3f26c9SDavid Howells * elected to wait */ 5199b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 520201a1542SDavid Howells if (!fscache_maybe_release_page(vnode->cache, page, gfp_flags)) { 5219b3f26c9SDavid Howells _leave(" = F [cache busy]"); 5229b3f26c9SDavid Howells return 0; 5239b3f26c9SDavid Howells } 5249b3f26c9SDavid Howells #endif 5259b3f26c9SDavid Howells 5269b3f26c9SDavid Howells if (PagePrivate(page)) { 5279b3f26c9SDavid Howells if (wb) { 5289b3f26c9SDavid Howells set_page_private(page, 0); 5299b3f26c9SDavid Howells afs_put_writeback(wb); 5309b3f26c9SDavid Howells } 5319b3f26c9SDavid Howells ClearPagePrivate(page); 5329b3f26c9SDavid Howells } 5339b3f26c9SDavid Howells 5349b3f26c9SDavid Howells /* indicate that the page can be released */ 5359b3f26c9SDavid Howells _leave(" = T"); 5369b3f26c9SDavid Howells return 1; 537ec26815aSDavid Howells } 538