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, 491da177e4SLinus Torvalds }; 501da177e4SLinus Torvalds 51f5e54d6eSChristoph Hellwig const struct address_space_operations afs_fs_aops = { 52416351f2SDavid Howells .readpage = afs_readpage, 539b3f26c9SDavid Howells .readpages = afs_readpages, 5431143d5dSDavid Howells .set_page_dirty = afs_set_page_dirty, 5531143d5dSDavid Howells .launder_page = afs_launder_page, 56416351f2SDavid Howells .releasepage = afs_releasepage, 57416351f2SDavid Howells .invalidatepage = afs_invalidatepage, 5815b4650eSNick Piggin .write_begin = afs_write_begin, 5915b4650eSNick Piggin .write_end = afs_write_end, 6031143d5dSDavid Howells .writepage = afs_writepage, 6131143d5dSDavid Howells .writepages = afs_writepages, 621da177e4SLinus Torvalds }; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds /* 6500d3b7a4SDavid Howells * open an AFS file or directory and attach a key to it 6600d3b7a4SDavid Howells */ 6700d3b7a4SDavid Howells int afs_open(struct inode *inode, struct file *file) 6800d3b7a4SDavid Howells { 6900d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 7000d3b7a4SDavid Howells struct key *key; 71260a9803SDavid Howells int ret; 7200d3b7a4SDavid Howells 73416351f2SDavid Howells _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 7400d3b7a4SDavid Howells 7500d3b7a4SDavid Howells key = afs_request_key(vnode->volume->cell); 7600d3b7a4SDavid Howells if (IS_ERR(key)) { 7700d3b7a4SDavid Howells _leave(" = %ld [key]", PTR_ERR(key)); 7800d3b7a4SDavid Howells return PTR_ERR(key); 7900d3b7a4SDavid Howells } 8000d3b7a4SDavid Howells 81260a9803SDavid Howells ret = afs_validate(vnode, key); 82260a9803SDavid Howells if (ret < 0) { 83260a9803SDavid Howells _leave(" = %d [val]", ret); 84260a9803SDavid Howells return ret; 85260a9803SDavid Howells } 86260a9803SDavid Howells 8700d3b7a4SDavid Howells file->private_data = key; 8800d3b7a4SDavid Howells _leave(" = 0"); 8900d3b7a4SDavid Howells return 0; 9000d3b7a4SDavid Howells } 9100d3b7a4SDavid Howells 9200d3b7a4SDavid Howells /* 9300d3b7a4SDavid Howells * release an AFS file or directory and discard its key 9400d3b7a4SDavid Howells */ 9500d3b7a4SDavid Howells int afs_release(struct inode *inode, struct file *file) 9600d3b7a4SDavid Howells { 9700d3b7a4SDavid Howells struct afs_vnode *vnode = AFS_FS_I(inode); 9800d3b7a4SDavid Howells 99416351f2SDavid Howells _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 10000d3b7a4SDavid Howells 10100d3b7a4SDavid Howells key_put(file->private_data); 10200d3b7a4SDavid Howells _leave(" = 0"); 10300d3b7a4SDavid Howells return 0; 10400d3b7a4SDavid Howells } 10500d3b7a4SDavid Howells 106196ee9cdSDavid Howells /* 107196ee9cdSDavid Howells * Dispose of a ref to a read record. 108196ee9cdSDavid Howells */ 109196ee9cdSDavid Howells void afs_put_read(struct afs_read *req) 110196ee9cdSDavid Howells { 111196ee9cdSDavid Howells int i; 112196ee9cdSDavid Howells 113196ee9cdSDavid Howells if (atomic_dec_and_test(&req->usage)) { 114196ee9cdSDavid Howells for (i = 0; i < req->nr_pages; i++) 115196ee9cdSDavid Howells if (req->pages[i]) 116196ee9cdSDavid Howells put_page(req->pages[i]); 117196ee9cdSDavid Howells kfree(req); 118196ee9cdSDavid Howells } 119196ee9cdSDavid Howells } 120196ee9cdSDavid Howells 1216566abdbSMatt Kraai #ifdef CONFIG_AFS_FSCACHE 12200d3b7a4SDavid Howells /* 1231da177e4SLinus Torvalds * deal with notification that a page was read from the cache 1241da177e4SLinus Torvalds */ 1259b3f26c9SDavid Howells static void afs_file_readpage_read_complete(struct page *page, 1261da177e4SLinus Torvalds void *data, 1271da177e4SLinus Torvalds int error) 1281da177e4SLinus Torvalds { 1299b3f26c9SDavid Howells _enter("%p,%p,%d", page, data, error); 1301da177e4SLinus Torvalds 1319b3f26c9SDavid Howells /* if the read completes with an error, we just unlock the page and let 1329b3f26c9SDavid Howells * the VM reissue the readpage */ 1339b3f26c9SDavid Howells if (!error) 1341da177e4SLinus Torvalds SetPageUptodate(page); 1351da177e4SLinus Torvalds unlock_page(page); 136ec26815aSDavid Howells } 1376566abdbSMatt Kraai #endif 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds /* 140f6d335c0SAl Viro * read page from file, directory or symlink, given a key to use 1411da177e4SLinus Torvalds */ 142f6d335c0SAl Viro int afs_page_filler(void *data, struct page *page) 1431da177e4SLinus Torvalds { 144f6d335c0SAl Viro struct inode *inode = page->mapping->host; 145f6d335c0SAl Viro struct afs_vnode *vnode = AFS_FS_I(inode); 146196ee9cdSDavid Howells struct afs_read *req; 147f6d335c0SAl Viro struct key *key = data; 1481da177e4SLinus Torvalds int ret; 1491da177e4SLinus Torvalds 15000d3b7a4SDavid Howells _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); 1511da177e4SLinus Torvalds 152cd7619d6SMatt Mackall BUG_ON(!PageLocked(page)); 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds ret = -ESTALE; 15508e0e7c8SDavid Howells if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 1561da177e4SLinus Torvalds goto error; 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds /* is it cached? */ 1599b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 1609b3f26c9SDavid Howells ret = fscache_read_or_alloc_page(vnode->cache, 1611da177e4SLinus Torvalds page, 1621da177e4SLinus Torvalds afs_file_readpage_read_complete, 1631da177e4SLinus Torvalds NULL, 1641da177e4SLinus Torvalds GFP_KERNEL); 1651da177e4SLinus Torvalds #else 1661da177e4SLinus Torvalds ret = -ENOBUFS; 1671da177e4SLinus Torvalds #endif 1681da177e4SLinus Torvalds switch (ret) { 1691da177e4SLinus Torvalds /* read BIO submitted (page in cache) */ 1701da177e4SLinus Torvalds case 0: 1711da177e4SLinus Torvalds break; 1721da177e4SLinus Torvalds 1739b3f26c9SDavid Howells /* page not yet cached */ 1741da177e4SLinus Torvalds case -ENODATA: 1759b3f26c9SDavid Howells _debug("cache said ENODATA"); 1769b3f26c9SDavid Howells goto go_on; 1779b3f26c9SDavid Howells 1789b3f26c9SDavid Howells /* page will not be cached */ 1799b3f26c9SDavid Howells case -ENOBUFS: 1809b3f26c9SDavid Howells _debug("cache said ENOBUFS"); 1811da177e4SLinus Torvalds default: 1829b3f26c9SDavid Howells go_on: 183196ee9cdSDavid Howells req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), 184196ee9cdSDavid Howells GFP_KERNEL); 185196ee9cdSDavid Howells if (!req) 186196ee9cdSDavid Howells goto enomem; 187196ee9cdSDavid Howells 1886db3ac3cSDavid Howells /* We request a full page. If the page is a partial one at the 1896db3ac3cSDavid Howells * end of the file, the server will return a short read and the 1906db3ac3cSDavid Howells * unmarshalling code will clear the unfilled space. 1916db3ac3cSDavid Howells */ 192196ee9cdSDavid Howells atomic_set(&req->usage, 1); 193196ee9cdSDavid Howells req->pos = (loff_t)page->index << PAGE_SHIFT; 1946db3ac3cSDavid Howells req->len = PAGE_SIZE; 195196ee9cdSDavid Howells req->nr_pages = 1; 196196ee9cdSDavid Howells req->pages[0] = page; 197196ee9cdSDavid Howells get_page(page); 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /* read the contents of the file from the server into the 2001da177e4SLinus Torvalds * page */ 201196ee9cdSDavid Howells ret = afs_vnode_fetch_data(vnode, key, req); 202196ee9cdSDavid Howells afs_put_read(req); 2031da177e4SLinus Torvalds if (ret < 0) { 2041da177e4SLinus Torvalds if (ret == -ENOENT) { 2051da177e4SLinus Torvalds _debug("got NOENT from server" 2061da177e4SLinus Torvalds " - marking file deleted and stale"); 20708e0e7c8SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 2081da177e4SLinus Torvalds ret = -ESTALE; 2091da177e4SLinus Torvalds } 2109b3f26c9SDavid Howells 2119b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2129b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 2131da177e4SLinus Torvalds #endif 2149b3f26c9SDavid Howells BUG_ON(PageFsCache(page)); 215*68ae849dSDavid Howells 216*68ae849dSDavid Howells if (ret == -EINTR || 217*68ae849dSDavid Howells ret == -ENOMEM || 218*68ae849dSDavid Howells ret == -ERESTARTSYS || 219*68ae849dSDavid Howells ret == -EAGAIN) 2201da177e4SLinus Torvalds goto error; 221*68ae849dSDavid Howells goto io_error; 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds SetPageUptodate(page); 2251da177e4SLinus Torvalds 2269b3f26c9SDavid Howells /* send the page to the cache */ 2279b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 2289b3f26c9SDavid Howells if (PageFsCache(page) && 2299b3f26c9SDavid Howells fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) { 2309b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 2319b3f26c9SDavid Howells BUG_ON(PageFsCache(page)); 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds #endif 2349b3f26c9SDavid Howells unlock_page(page); 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds _leave(" = 0"); 2381da177e4SLinus Torvalds return 0; 2391da177e4SLinus Torvalds 240*68ae849dSDavid Howells io_error: 241*68ae849dSDavid Howells SetPageError(page); 242*68ae849dSDavid Howells goto error; 243196ee9cdSDavid Howells enomem: 244196ee9cdSDavid Howells ret = -ENOMEM; 2451da177e4SLinus Torvalds error: 2461da177e4SLinus Torvalds unlock_page(page); 2471da177e4SLinus Torvalds _leave(" = %d", ret); 2481da177e4SLinus Torvalds return ret; 249ec26815aSDavid Howells } 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds /* 252f6d335c0SAl Viro * read page from file, directory or symlink, given a file to nominate the key 253f6d335c0SAl Viro * to be used 254f6d335c0SAl Viro */ 255f6d335c0SAl Viro static int afs_readpage(struct file *file, struct page *page) 256f6d335c0SAl Viro { 257f6d335c0SAl Viro struct key *key; 258f6d335c0SAl Viro int ret; 259f6d335c0SAl Viro 260f6d335c0SAl Viro if (file) { 261f6d335c0SAl Viro key = file->private_data; 262f6d335c0SAl Viro ASSERT(key != NULL); 263f6d335c0SAl Viro ret = afs_page_filler(key, page); 264f6d335c0SAl Viro } else { 265f6d335c0SAl Viro struct inode *inode = page->mapping->host; 266f6d335c0SAl Viro key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell); 267f6d335c0SAl Viro if (IS_ERR(key)) { 268f6d335c0SAl Viro ret = PTR_ERR(key); 269f6d335c0SAl Viro } else { 270f6d335c0SAl Viro ret = afs_page_filler(key, page); 271f6d335c0SAl Viro key_put(key); 272f6d335c0SAl Viro } 273f6d335c0SAl Viro } 274f6d335c0SAl Viro return ret; 275f6d335c0SAl Viro } 276f6d335c0SAl Viro 277f6d335c0SAl Viro /* 27891b467e0SDavid Howells * Make pages available as they're filled. 27991b467e0SDavid Howells */ 28091b467e0SDavid Howells static void afs_readpages_page_done(struct afs_call *call, struct afs_read *req) 28191b467e0SDavid Howells { 28251c89e6aSArnd Bergmann #ifdef CONFIG_AFS_FSCACHE 28391b467e0SDavid Howells struct afs_vnode *vnode = call->reply; 28451c89e6aSArnd Bergmann #endif 28591b467e0SDavid Howells struct page *page = req->pages[req->index]; 28691b467e0SDavid Howells 28791b467e0SDavid Howells req->pages[req->index] = NULL; 28891b467e0SDavid Howells SetPageUptodate(page); 28991b467e0SDavid Howells 29091b467e0SDavid Howells /* send the page to the cache */ 29191b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 29291b467e0SDavid Howells if (PageFsCache(page) && 29391b467e0SDavid Howells fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) { 29491b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 29591b467e0SDavid Howells BUG_ON(PageFsCache(page)); 29691b467e0SDavid Howells } 29791b467e0SDavid Howells #endif 29891b467e0SDavid Howells unlock_page(page); 29991b467e0SDavid Howells put_page(page); 30091b467e0SDavid Howells } 30191b467e0SDavid Howells 30291b467e0SDavid Howells /* 30391b467e0SDavid Howells * Read a contiguous set of pages. 30491b467e0SDavid Howells */ 30591b467e0SDavid Howells static int afs_readpages_one(struct file *file, struct address_space *mapping, 30691b467e0SDavid Howells struct list_head *pages) 30791b467e0SDavid Howells { 30891b467e0SDavid Howells struct afs_vnode *vnode = AFS_FS_I(mapping->host); 30991b467e0SDavid Howells struct afs_read *req; 31091b467e0SDavid Howells struct list_head *p; 31191b467e0SDavid Howells struct page *first, *page; 31291b467e0SDavid Howells struct key *key = file->private_data; 31391b467e0SDavid Howells pgoff_t index; 31491b467e0SDavid Howells int ret, n, i; 31591b467e0SDavid Howells 31691b467e0SDavid Howells /* Count the number of contiguous pages at the front of the list. Note 31791b467e0SDavid Howells * that the list goes prev-wards rather than next-wards. 31891b467e0SDavid Howells */ 31991b467e0SDavid Howells first = list_entry(pages->prev, struct page, lru); 32091b467e0SDavid Howells index = first->index + 1; 32191b467e0SDavid Howells n = 1; 32291b467e0SDavid Howells for (p = first->lru.prev; p != pages; p = p->prev) { 32391b467e0SDavid Howells page = list_entry(p, struct page, lru); 32491b467e0SDavid Howells if (page->index != index) 32591b467e0SDavid Howells break; 32691b467e0SDavid Howells index++; 32791b467e0SDavid Howells n++; 32891b467e0SDavid Howells } 32991b467e0SDavid Howells 33091b467e0SDavid Howells req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *) * n, 33191b467e0SDavid Howells GFP_NOFS); 33291b467e0SDavid Howells if (!req) 33391b467e0SDavid Howells return -ENOMEM; 33491b467e0SDavid Howells 33591b467e0SDavid Howells atomic_set(&req->usage, 1); 33691b467e0SDavid Howells req->page_done = afs_readpages_page_done; 33791b467e0SDavid Howells req->pos = first->index; 33891b467e0SDavid Howells req->pos <<= PAGE_SHIFT; 33991b467e0SDavid Howells 34091b467e0SDavid Howells /* Transfer the pages to the request. We add them in until one fails 34191b467e0SDavid Howells * to add to the LRU and then we stop (as that'll make a hole in the 34291b467e0SDavid Howells * contiguous run. 34391b467e0SDavid Howells * 34491b467e0SDavid Howells * Note that it's possible for the file size to change whilst we're 34591b467e0SDavid Howells * doing this, but we rely on the server returning less than we asked 34691b467e0SDavid Howells * for if the file shrank. We also rely on this to deal with a partial 34791b467e0SDavid Howells * page at the end of the file. 34891b467e0SDavid Howells */ 34991b467e0SDavid Howells do { 35091b467e0SDavid Howells page = list_entry(pages->prev, struct page, lru); 35191b467e0SDavid Howells list_del(&page->lru); 35291b467e0SDavid Howells index = page->index; 35391b467e0SDavid Howells if (add_to_page_cache_lru(page, mapping, index, 35491b467e0SDavid Howells readahead_gfp_mask(mapping))) { 35591b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 35691b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 35791b467e0SDavid Howells #endif 35891b467e0SDavid Howells put_page(page); 35991b467e0SDavid Howells break; 36091b467e0SDavid Howells } 36191b467e0SDavid Howells 36291b467e0SDavid Howells req->pages[req->nr_pages++] = page; 36391b467e0SDavid Howells req->len += PAGE_SIZE; 36491b467e0SDavid Howells } while (req->nr_pages < n); 36591b467e0SDavid Howells 36691b467e0SDavid Howells if (req->nr_pages == 0) { 36791b467e0SDavid Howells kfree(req); 36891b467e0SDavid Howells return 0; 36991b467e0SDavid Howells } 37091b467e0SDavid Howells 37191b467e0SDavid Howells ret = afs_vnode_fetch_data(vnode, key, req); 37291b467e0SDavid Howells if (ret < 0) 37391b467e0SDavid Howells goto error; 37491b467e0SDavid Howells 37591b467e0SDavid Howells task_io_account_read(PAGE_SIZE * req->nr_pages); 37691b467e0SDavid Howells afs_put_read(req); 37791b467e0SDavid Howells return 0; 37891b467e0SDavid Howells 37991b467e0SDavid Howells error: 38091b467e0SDavid Howells if (ret == -ENOENT) { 38191b467e0SDavid Howells _debug("got NOENT from server" 38291b467e0SDavid Howells " - marking file deleted and stale"); 38391b467e0SDavid Howells set_bit(AFS_VNODE_DELETED, &vnode->flags); 38491b467e0SDavid Howells ret = -ESTALE; 38591b467e0SDavid Howells } 38691b467e0SDavid Howells 38791b467e0SDavid Howells for (i = 0; i < req->nr_pages; i++) { 38891b467e0SDavid Howells page = req->pages[i]; 38991b467e0SDavid Howells if (page) { 39091b467e0SDavid Howells #ifdef CONFIG_AFS_FSCACHE 39191b467e0SDavid Howells fscache_uncache_page(vnode->cache, page); 39291b467e0SDavid Howells #endif 39391b467e0SDavid Howells SetPageError(page); 39491b467e0SDavid Howells unlock_page(page); 39591b467e0SDavid Howells } 39691b467e0SDavid Howells } 39791b467e0SDavid Howells 39891b467e0SDavid Howells afs_put_read(req); 39991b467e0SDavid Howells return ret; 40091b467e0SDavid Howells } 40191b467e0SDavid Howells 40291b467e0SDavid Howells /* 4039b3f26c9SDavid Howells * read a set of pages 4041da177e4SLinus Torvalds */ 4059b3f26c9SDavid Howells static int afs_readpages(struct file *file, struct address_space *mapping, 4069b3f26c9SDavid Howells struct list_head *pages, unsigned nr_pages) 4071da177e4SLinus Torvalds { 408f6d335c0SAl Viro struct key *key = file->private_data; 4099b3f26c9SDavid Howells struct afs_vnode *vnode; 4109b3f26c9SDavid Howells int ret = 0; 4111da177e4SLinus Torvalds 412f6d335c0SAl Viro _enter("{%d},{%lu},,%d", 413f6d335c0SAl Viro key_serial(key), mapping->host->i_ino, nr_pages); 414f6d335c0SAl Viro 415f6d335c0SAl Viro ASSERT(key != NULL); 4161da177e4SLinus Torvalds 4179b3f26c9SDavid Howells vnode = AFS_FS_I(mapping->host); 418ad2a8e60SDan Carpenter if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { 4199b3f26c9SDavid Howells _leave(" = -ESTALE"); 4209b3f26c9SDavid Howells return -ESTALE; 4211da177e4SLinus Torvalds } 4221da177e4SLinus Torvalds 4239b3f26c9SDavid Howells /* attempt to read as many of the pages as possible */ 4249b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 4259b3f26c9SDavid Howells ret = fscache_read_or_alloc_pages(vnode->cache, 4269b3f26c9SDavid Howells mapping, 4279b3f26c9SDavid Howells pages, 4289b3f26c9SDavid Howells &nr_pages, 4299b3f26c9SDavid Howells afs_file_readpage_read_complete, 4309b3f26c9SDavid Howells NULL, 4319b3f26c9SDavid Howells mapping_gfp_mask(mapping)); 4329b3f26c9SDavid Howells #else 4339b3f26c9SDavid Howells ret = -ENOBUFS; 4349b3f26c9SDavid Howells #endif 4359b3f26c9SDavid Howells 4369b3f26c9SDavid Howells switch (ret) { 4379b3f26c9SDavid Howells /* all pages are being read from the cache */ 4389b3f26c9SDavid Howells case 0: 4399b3f26c9SDavid Howells BUG_ON(!list_empty(pages)); 4409b3f26c9SDavid Howells BUG_ON(nr_pages != 0); 4419b3f26c9SDavid Howells _leave(" = 0 [reading all]"); 4429b3f26c9SDavid Howells return 0; 4439b3f26c9SDavid Howells 4449b3f26c9SDavid Howells /* there were pages that couldn't be read from the cache */ 4459b3f26c9SDavid Howells case -ENODATA: 4469b3f26c9SDavid Howells case -ENOBUFS: 4479b3f26c9SDavid Howells break; 4489b3f26c9SDavid Howells 4499b3f26c9SDavid Howells /* other error */ 4509b3f26c9SDavid Howells default: 4511da177e4SLinus Torvalds _leave(" = %d", ret); 4529b3f26c9SDavid Howells return ret; 4539b3f26c9SDavid Howells } 4549b3f26c9SDavid Howells 45591b467e0SDavid Howells while (!list_empty(pages)) { 45691b467e0SDavid Howells ret = afs_readpages_one(file, mapping, pages); 45791b467e0SDavid Howells if (ret < 0) 45891b467e0SDavid Howells break; 45991b467e0SDavid Howells } 4609b3f26c9SDavid Howells 4619b3f26c9SDavid Howells _leave(" = %d [netting]", ret); 4629b3f26c9SDavid Howells return ret; 463ec26815aSDavid Howells } 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds /* 46631143d5dSDavid Howells * write back a dirty page 46731143d5dSDavid Howells */ 46831143d5dSDavid Howells static int afs_launder_page(struct page *page) 46931143d5dSDavid Howells { 47031143d5dSDavid Howells _enter("{%lu}", page->index); 47131143d5dSDavid Howells 47231143d5dSDavid Howells return 0; 47331143d5dSDavid Howells } 47431143d5dSDavid Howells 47531143d5dSDavid Howells /* 4769b3f26c9SDavid Howells * invalidate part or all of a page 4779b3f26c9SDavid Howells * - release a page and clean up its private data if offset is 0 (indicating 4789b3f26c9SDavid Howells * the entire page) 4799b3f26c9SDavid Howells */ 480d47992f8SLukas Czerner static void afs_invalidatepage(struct page *page, unsigned int offset, 481d47992f8SLukas Czerner unsigned int length) 4829b3f26c9SDavid Howells { 4839b3f26c9SDavid Howells struct afs_writeback *wb = (struct afs_writeback *) page_private(page); 4849b3f26c9SDavid Howells 485d47992f8SLukas Czerner _enter("{%lu},%u,%u", page->index, offset, length); 4869b3f26c9SDavid Howells 4879b3f26c9SDavid Howells BUG_ON(!PageLocked(page)); 4889b3f26c9SDavid Howells 4899b3f26c9SDavid Howells /* we clean up only if the entire page is being invalidated */ 49009cbfeafSKirill A. Shutemov if (offset == 0 && length == PAGE_SIZE) { 4919b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 4929b3f26c9SDavid Howells if (PageFsCache(page)) { 4939b3f26c9SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 4949b3f26c9SDavid Howells fscache_wait_on_page_write(vnode->cache, page); 4959b3f26c9SDavid Howells fscache_uncache_page(vnode->cache, page); 4969b3f26c9SDavid Howells } 4979b3f26c9SDavid Howells #endif 4989b3f26c9SDavid Howells 4999b3f26c9SDavid Howells if (PagePrivate(page)) { 5009b3f26c9SDavid Howells if (wb && !PageWriteback(page)) { 5019b3f26c9SDavid Howells set_page_private(page, 0); 5029b3f26c9SDavid Howells afs_put_writeback(wb); 5039b3f26c9SDavid Howells } 5049b3f26c9SDavid Howells 5059b3f26c9SDavid Howells if (!page_private(page)) 5069b3f26c9SDavid Howells ClearPagePrivate(page); 5079b3f26c9SDavid Howells } 5089b3f26c9SDavid Howells } 5099b3f26c9SDavid Howells 5109b3f26c9SDavid Howells _leave(""); 5119b3f26c9SDavid Howells } 5129b3f26c9SDavid Howells 5139b3f26c9SDavid Howells /* 5149b3f26c9SDavid Howells * release a page and clean up its private state if it's not busy 5159b3f26c9SDavid Howells * - return true if the page can now be released, false if not 5161da177e4SLinus Torvalds */ 517416351f2SDavid Howells static int afs_releasepage(struct page *page, gfp_t gfp_flags) 5181da177e4SLinus Torvalds { 5199b3f26c9SDavid Howells struct afs_writeback *wb = (struct afs_writeback *) page_private(page); 520416351f2SDavid Howells struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 5211da177e4SLinus Torvalds 522416351f2SDavid Howells _enter("{{%x:%u}[%lu],%lx},%x", 523416351f2SDavid Howells vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, 524416351f2SDavid Howells gfp_flags); 5251da177e4SLinus Torvalds 5269b3f26c9SDavid Howells /* deny if page is being written to the cache and the caller hasn't 5279b3f26c9SDavid Howells * elected to wait */ 5289b3f26c9SDavid Howells #ifdef CONFIG_AFS_FSCACHE 529201a1542SDavid Howells if (!fscache_maybe_release_page(vnode->cache, page, gfp_flags)) { 5309b3f26c9SDavid Howells _leave(" = F [cache busy]"); 5319b3f26c9SDavid Howells return 0; 5329b3f26c9SDavid Howells } 5339b3f26c9SDavid Howells #endif 5349b3f26c9SDavid Howells 5359b3f26c9SDavid Howells if (PagePrivate(page)) { 5369b3f26c9SDavid Howells if (wb) { 5379b3f26c9SDavid Howells set_page_private(page, 0); 5389b3f26c9SDavid Howells afs_put_writeback(wb); 5399b3f26c9SDavid Howells } 5409b3f26c9SDavid Howells ClearPagePrivate(page); 5419b3f26c9SDavid Howells } 5429b3f26c9SDavid Howells 5439b3f26c9SDavid Howells /* indicate that the page can be released */ 5449b3f26c9SDavid Howells _leave(" = T"); 5459b3f26c9SDavid Howells return 1; 546ec26815aSDavid Howells } 547