1 /* AFS filesystem file handling 2 * 3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/init.h> 15 #include <linux/slab.h> 16 #include <linux/fs.h> 17 #include <linux/pagemap.h> 18 #include <linux/writeback.h> 19 #include "internal.h" 20 21 static int afs_readpage(struct file *file, struct page *page); 22 static void afs_invalidatepage(struct page *page, unsigned long offset); 23 static int afs_releasepage(struct page *page, gfp_t gfp_flags); 24 static int afs_launder_page(struct page *page); 25 26 const struct file_operations afs_file_operations = { 27 .open = afs_open, 28 .release = afs_release, 29 .llseek = generic_file_llseek, 30 .read = do_sync_read, 31 .write = do_sync_write, 32 .aio_read = generic_file_aio_read, 33 .aio_write = afs_file_write, 34 .mmap = generic_file_readonly_mmap, 35 .sendfile = generic_file_sendfile, 36 .fsync = afs_fsync, 37 }; 38 39 const struct inode_operations afs_file_inode_operations = { 40 .getattr = afs_getattr, 41 .setattr = afs_setattr, 42 .permission = afs_permission, 43 }; 44 45 const struct address_space_operations afs_fs_aops = { 46 .readpage = afs_readpage, 47 .set_page_dirty = afs_set_page_dirty, 48 .launder_page = afs_launder_page, 49 .releasepage = afs_releasepage, 50 .invalidatepage = afs_invalidatepage, 51 .prepare_write = afs_prepare_write, 52 .commit_write = afs_commit_write, 53 .writepage = afs_writepage, 54 .writepages = afs_writepages, 55 }; 56 57 /* 58 * open an AFS file or directory and attach a key to it 59 */ 60 int afs_open(struct inode *inode, struct file *file) 61 { 62 struct afs_vnode *vnode = AFS_FS_I(inode); 63 struct key *key; 64 int ret; 65 66 _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 67 68 key = afs_request_key(vnode->volume->cell); 69 if (IS_ERR(key)) { 70 _leave(" = %ld [key]", PTR_ERR(key)); 71 return PTR_ERR(key); 72 } 73 74 ret = afs_validate(vnode, key); 75 if (ret < 0) { 76 _leave(" = %d [val]", ret); 77 return ret; 78 } 79 80 file->private_data = key; 81 _leave(" = 0"); 82 return 0; 83 } 84 85 /* 86 * release an AFS file or directory and discard its key 87 */ 88 int afs_release(struct inode *inode, struct file *file) 89 { 90 struct afs_vnode *vnode = AFS_FS_I(inode); 91 92 _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 93 94 key_put(file->private_data); 95 _leave(" = 0"); 96 return 0; 97 } 98 99 /* 100 * deal with notification that a page was read from the cache 101 */ 102 #ifdef AFS_CACHING_SUPPORT 103 static void afs_readpage_read_complete(void *cookie_data, 104 struct page *page, 105 void *data, 106 int error) 107 { 108 _enter("%p,%p,%p,%d", cookie_data, page, data, error); 109 110 if (error) 111 SetPageError(page); 112 else 113 SetPageUptodate(page); 114 unlock_page(page); 115 116 } 117 #endif 118 119 /* 120 * deal with notification that a page was written to the cache 121 */ 122 #ifdef AFS_CACHING_SUPPORT 123 static void afs_readpage_write_complete(void *cookie_data, 124 struct page *page, 125 void *data, 126 int error) 127 { 128 _enter("%p,%p,%p,%d", cookie_data, page, data, error); 129 130 unlock_page(page); 131 } 132 #endif 133 134 /* 135 * AFS read page from file, directory or symlink 136 */ 137 static int afs_readpage(struct file *file, struct page *page) 138 { 139 struct afs_vnode *vnode; 140 struct inode *inode; 141 struct key *key; 142 size_t len; 143 off_t offset; 144 int ret; 145 146 inode = page->mapping->host; 147 148 ASSERT(file != NULL); 149 key = file->private_data; 150 ASSERT(key != NULL); 151 152 _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); 153 154 vnode = AFS_FS_I(inode); 155 156 BUG_ON(!PageLocked(page)); 157 158 ret = -ESTALE; 159 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 160 goto error; 161 162 #ifdef AFS_CACHING_SUPPORT 163 /* is it cached? */ 164 ret = cachefs_read_or_alloc_page(vnode->cache, 165 page, 166 afs_file_readpage_read_complete, 167 NULL, 168 GFP_KERNEL); 169 #else 170 ret = -ENOBUFS; 171 #endif 172 173 switch (ret) { 174 /* read BIO submitted and wb-journal entry found */ 175 case 1: 176 BUG(); // TODO - handle wb-journal match 177 178 /* read BIO submitted (page in cache) */ 179 case 0: 180 break; 181 182 /* no page available in cache */ 183 case -ENOBUFS: 184 case -ENODATA: 185 default: 186 offset = page->index << PAGE_CACHE_SHIFT; 187 len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE); 188 189 /* read the contents of the file from the server into the 190 * page */ 191 ret = afs_vnode_fetch_data(vnode, key, offset, len, page); 192 if (ret < 0) { 193 if (ret == -ENOENT) { 194 _debug("got NOENT from server" 195 " - marking file deleted and stale"); 196 set_bit(AFS_VNODE_DELETED, &vnode->flags); 197 ret = -ESTALE; 198 } 199 #ifdef AFS_CACHING_SUPPORT 200 cachefs_uncache_page(vnode->cache, page); 201 #endif 202 goto error; 203 } 204 205 SetPageUptodate(page); 206 207 #ifdef AFS_CACHING_SUPPORT 208 if (cachefs_write_page(vnode->cache, 209 page, 210 afs_file_readpage_write_complete, 211 NULL, 212 GFP_KERNEL) != 0 213 ) { 214 cachefs_uncache_page(vnode->cache, page); 215 unlock_page(page); 216 } 217 #else 218 unlock_page(page); 219 #endif 220 } 221 222 _leave(" = 0"); 223 return 0; 224 225 error: 226 SetPageError(page); 227 unlock_page(page); 228 _leave(" = %d", ret); 229 return ret; 230 } 231 232 /* 233 * invalidate part or all of a page 234 */ 235 static void afs_invalidatepage(struct page *page, unsigned long offset) 236 { 237 int ret = 1; 238 239 _enter("{%lu},%lu", page->index, offset); 240 241 BUG_ON(!PageLocked(page)); 242 243 if (PagePrivate(page)) { 244 /* We release buffers only if the entire page is being 245 * invalidated. 246 * The get_block cached value has been unconditionally 247 * invalidated, so real IO is not possible anymore. 248 */ 249 if (offset == 0) { 250 BUG_ON(!PageLocked(page)); 251 252 ret = 0; 253 if (!PageWriteback(page)) 254 ret = page->mapping->a_ops->releasepage(page, 255 0); 256 /* possibly should BUG_ON(!ret); - neilb */ 257 } 258 } 259 260 _leave(" = %d", ret); 261 } 262 263 /* 264 * write back a dirty page 265 */ 266 static int afs_launder_page(struct page *page) 267 { 268 _enter("{%lu}", page->index); 269 270 return 0; 271 } 272 273 /* 274 * release a page and cleanup its private data 275 */ 276 static int afs_releasepage(struct page *page, gfp_t gfp_flags) 277 { 278 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 279 struct afs_writeback *wb; 280 281 _enter("{{%x:%u}[%lu],%lx},%x", 282 vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, 283 gfp_flags); 284 285 if (PagePrivate(page)) { 286 wb = (struct afs_writeback *) page_private(page); 287 ASSERT(wb != NULL); 288 set_page_private(page, 0); 289 ClearPagePrivate(page); 290 afs_put_writeback(wb); 291 } 292 293 _leave(" = 0"); 294 return 0; 295 } 296