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 .splice_read = generic_file_splice_read, 36 .fsync = afs_fsync, 37 .lock = afs_lock, 38 .flock = afs_flock, 39 }; 40 41 const struct inode_operations afs_file_inode_operations = { 42 .getattr = afs_getattr, 43 .setattr = afs_setattr, 44 .permission = afs_permission, 45 }; 46 47 const struct address_space_operations afs_fs_aops = { 48 .readpage = afs_readpage, 49 .set_page_dirty = afs_set_page_dirty, 50 .launder_page = afs_launder_page, 51 .releasepage = afs_releasepage, 52 .invalidatepage = afs_invalidatepage, 53 .write_begin = afs_write_begin, 54 .write_end = afs_write_end, 55 .writepage = afs_writepage, 56 .writepages = afs_writepages, 57 }; 58 59 /* 60 * open an AFS file or directory and attach a key to it 61 */ 62 int afs_open(struct inode *inode, struct file *file) 63 { 64 struct afs_vnode *vnode = AFS_FS_I(inode); 65 struct key *key; 66 int ret; 67 68 _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 69 70 key = afs_request_key(vnode->volume->cell); 71 if (IS_ERR(key)) { 72 _leave(" = %ld [key]", PTR_ERR(key)); 73 return PTR_ERR(key); 74 } 75 76 ret = afs_validate(vnode, key); 77 if (ret < 0) { 78 _leave(" = %d [val]", ret); 79 return ret; 80 } 81 82 file->private_data = key; 83 _leave(" = 0"); 84 return 0; 85 } 86 87 /* 88 * release an AFS file or directory and discard its key 89 */ 90 int afs_release(struct inode *inode, struct file *file) 91 { 92 struct afs_vnode *vnode = AFS_FS_I(inode); 93 94 _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); 95 96 key_put(file->private_data); 97 _leave(" = 0"); 98 return 0; 99 } 100 101 /* 102 * deal with notification that a page was read from the cache 103 */ 104 #ifdef AFS_CACHING_SUPPORT 105 static void afs_readpage_read_complete(void *cookie_data, 106 struct page *page, 107 void *data, 108 int error) 109 { 110 _enter("%p,%p,%p,%d", cookie_data, page, data, error); 111 112 if (error) 113 SetPageError(page); 114 else 115 SetPageUptodate(page); 116 unlock_page(page); 117 118 } 119 #endif 120 121 /* 122 * deal with notification that a page was written to the cache 123 */ 124 #ifdef AFS_CACHING_SUPPORT 125 static void afs_readpage_write_complete(void *cookie_data, 126 struct page *page, 127 void *data, 128 int error) 129 { 130 _enter("%p,%p,%p,%d", cookie_data, page, data, error); 131 132 unlock_page(page); 133 } 134 #endif 135 136 /* 137 * AFS read page from file, directory or symlink 138 */ 139 static int afs_readpage(struct file *file, struct page *page) 140 { 141 struct afs_vnode *vnode; 142 struct inode *inode; 143 struct key *key; 144 size_t len; 145 off_t offset; 146 int ret; 147 148 inode = page->mapping->host; 149 150 ASSERT(file != NULL); 151 key = file->private_data; 152 ASSERT(key != NULL); 153 154 _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); 155 156 vnode = AFS_FS_I(inode); 157 158 BUG_ON(!PageLocked(page)); 159 160 ret = -ESTALE; 161 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) 162 goto error; 163 164 #ifdef AFS_CACHING_SUPPORT 165 /* is it cached? */ 166 ret = cachefs_read_or_alloc_page(vnode->cache, 167 page, 168 afs_file_readpage_read_complete, 169 NULL, 170 GFP_KERNEL); 171 #else 172 ret = -ENOBUFS; 173 #endif 174 175 switch (ret) { 176 /* read BIO submitted and wb-journal entry found */ 177 case 1: 178 BUG(); // TODO - handle wb-journal match 179 180 /* read BIO submitted (page in cache) */ 181 case 0: 182 break; 183 184 /* no page available in cache */ 185 case -ENOBUFS: 186 case -ENODATA: 187 default: 188 offset = page->index << PAGE_CACHE_SHIFT; 189 len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE); 190 191 /* read the contents of the file from the server into the 192 * page */ 193 ret = afs_vnode_fetch_data(vnode, key, offset, len, page); 194 if (ret < 0) { 195 if (ret == -ENOENT) { 196 _debug("got NOENT from server" 197 " - marking file deleted and stale"); 198 set_bit(AFS_VNODE_DELETED, &vnode->flags); 199 ret = -ESTALE; 200 } 201 #ifdef AFS_CACHING_SUPPORT 202 cachefs_uncache_page(vnode->cache, page); 203 #endif 204 goto error; 205 } 206 207 SetPageUptodate(page); 208 209 #ifdef AFS_CACHING_SUPPORT 210 if (cachefs_write_page(vnode->cache, 211 page, 212 afs_file_readpage_write_complete, 213 NULL, 214 GFP_KERNEL) != 0 215 ) { 216 cachefs_uncache_page(vnode->cache, page); 217 unlock_page(page); 218 } 219 #else 220 unlock_page(page); 221 #endif 222 } 223 224 _leave(" = 0"); 225 return 0; 226 227 error: 228 SetPageError(page); 229 unlock_page(page); 230 _leave(" = %d", ret); 231 return ret; 232 } 233 234 /* 235 * invalidate part or all of a page 236 */ 237 static void afs_invalidatepage(struct page *page, unsigned long offset) 238 { 239 int ret = 1; 240 241 _enter("{%lu},%lu", page->index, offset); 242 243 BUG_ON(!PageLocked(page)); 244 245 if (PagePrivate(page)) { 246 /* We release buffers only if the entire page is being 247 * invalidated. 248 * The get_block cached value has been unconditionally 249 * invalidated, so real IO is not possible anymore. 250 */ 251 if (offset == 0) { 252 BUG_ON(!PageLocked(page)); 253 254 ret = 0; 255 if (!PageWriteback(page)) 256 ret = page->mapping->a_ops->releasepage(page, 257 0); 258 /* possibly should BUG_ON(!ret); - neilb */ 259 } 260 } 261 262 _leave(" = %d", ret); 263 } 264 265 /* 266 * write back a dirty page 267 */ 268 static int afs_launder_page(struct page *page) 269 { 270 _enter("{%lu}", page->index); 271 272 return 0; 273 } 274 275 /* 276 * release a page and cleanup its private data 277 */ 278 static int afs_releasepage(struct page *page, gfp_t gfp_flags) 279 { 280 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 281 struct afs_writeback *wb; 282 283 _enter("{{%x:%u}[%lu],%lx},%x", 284 vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, 285 gfp_flags); 286 287 if (PagePrivate(page)) { 288 wb = (struct afs_writeback *) page_private(page); 289 ASSERT(wb != NULL); 290 set_page_private(page, 0); 291 ClearPagePrivate(page); 292 afs_put_writeback(wb); 293 } 294 295 _leave(" = 0"); 296 return 0; 297 } 298