1 /* file.c: AFS filesystem file handling 2 * 3 * Copyright (C) 2002 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/sched.h> 16 #include <linux/slab.h> 17 #include <linux/fs.h> 18 #include <linux/pagemap.h> 19 #include <linux/buffer_head.h> 20 #include "volume.h" 21 #include "vnode.h" 22 #include <rxrpc/call.h> 23 #include "internal.h" 24 25 #if 0 26 static int afs_file_open(struct inode *inode, struct file *file); 27 static int afs_file_release(struct inode *inode, struct file *file); 28 #endif 29 30 static int afs_file_readpage(struct file *file, struct page *page); 31 static int afs_file_invalidatepage(struct page *page, unsigned long offset); 32 static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); 33 34 static ssize_t afs_file_write(struct file *file, const char __user *buf, 35 size_t size, loff_t *off); 36 37 struct inode_operations afs_file_inode_operations = { 38 .getattr = afs_inode_getattr, 39 }; 40 41 struct file_operations afs_file_file_operations = { 42 .read = generic_file_read, 43 .write = afs_file_write, 44 .mmap = generic_file_mmap, 45 #if 0 46 .open = afs_file_open, 47 .release = afs_file_release, 48 .fsync = afs_file_fsync, 49 #endif 50 }; 51 52 struct address_space_operations afs_fs_aops = { 53 .readpage = afs_file_readpage, 54 .sync_page = block_sync_page, 55 .set_page_dirty = __set_page_dirty_nobuffers, 56 .releasepage = afs_file_releasepage, 57 .invalidatepage = afs_file_invalidatepage, 58 }; 59 60 /*****************************************************************************/ 61 /* 62 * AFS file write 63 */ 64 static ssize_t afs_file_write(struct file *file, const char __user *buf, 65 size_t size, loff_t *off) 66 { 67 struct afs_vnode *vnode; 68 69 vnode = AFS_FS_I(file->f_dentry->d_inode); 70 if (vnode->flags & AFS_VNODE_DELETED) 71 return -ESTALE; 72 73 return -EIO; 74 } /* end afs_file_write() */ 75 76 /*****************************************************************************/ 77 /* 78 * deal with notification that a page was read from the cache 79 */ 80 #ifdef AFS_CACHING_SUPPORT 81 static void afs_file_readpage_read_complete(void *cookie_data, 82 struct page *page, 83 void *data, 84 int error) 85 { 86 _enter("%p,%p,%p,%d", cookie_data, page, data, error); 87 88 if (error) 89 SetPageError(page); 90 else 91 SetPageUptodate(page); 92 unlock_page(page); 93 94 } /* end afs_file_readpage_read_complete() */ 95 #endif 96 97 /*****************************************************************************/ 98 /* 99 * deal with notification that a page was written to the cache 100 */ 101 #ifdef AFS_CACHING_SUPPORT 102 static void afs_file_readpage_write_complete(void *cookie_data, 103 struct page *page, 104 void *data, 105 int error) 106 { 107 _enter("%p,%p,%p,%d", cookie_data, page, data, error); 108 109 unlock_page(page); 110 111 } /* end afs_file_readpage_write_complete() */ 112 #endif 113 114 /*****************************************************************************/ 115 /* 116 * AFS read page from file (or symlink) 117 */ 118 static int afs_file_readpage(struct file *file, struct page *page) 119 { 120 struct afs_rxfs_fetch_descriptor desc; 121 #ifdef AFS_CACHING_SUPPORT 122 struct cachefs_page *pageio; 123 #endif 124 struct afs_vnode *vnode; 125 struct inode *inode; 126 int ret; 127 128 inode = page->mapping->host; 129 130 _enter("{%lu},{%lu}", inode->i_ino, page->index); 131 132 vnode = AFS_FS_I(inode); 133 134 BUG_ON(!PageLocked(page)); 135 136 ret = -ESTALE; 137 if (vnode->flags & AFS_VNODE_DELETED) 138 goto error; 139 140 #ifdef AFS_CACHING_SUPPORT 141 ret = cachefs_page_get_private(page, &pageio, GFP_NOIO); 142 if (ret < 0) 143 goto error; 144 145 /* is it cached? */ 146 ret = cachefs_read_or_alloc_page(vnode->cache, 147 page, 148 afs_file_readpage_read_complete, 149 NULL, 150 GFP_KERNEL); 151 #else 152 ret = -ENOBUFS; 153 #endif 154 155 switch (ret) { 156 /* read BIO submitted and wb-journal entry found */ 157 case 1: 158 BUG(); // TODO - handle wb-journal match 159 160 /* read BIO submitted (page in cache) */ 161 case 0: 162 break; 163 164 /* no page available in cache */ 165 case -ENOBUFS: 166 case -ENODATA: 167 default: 168 desc.fid = vnode->fid; 169 desc.offset = page->index << PAGE_CACHE_SHIFT; 170 desc.size = min((size_t) (inode->i_size - desc.offset), 171 (size_t) PAGE_SIZE); 172 desc.buffer = kmap(page); 173 174 clear_page(desc.buffer); 175 176 /* read the contents of the file from the server into the 177 * page */ 178 ret = afs_vnode_fetch_data(vnode, &desc); 179 kunmap(page); 180 if (ret < 0) { 181 if (ret==-ENOENT) { 182 _debug("got NOENT from server" 183 " - marking file deleted and stale"); 184 vnode->flags |= AFS_VNODE_DELETED; 185 ret = -ESTALE; 186 } 187 188 #ifdef AFS_CACHING_SUPPORT 189 cachefs_uncache_page(vnode->cache, page); 190 #endif 191 goto error; 192 } 193 194 SetPageUptodate(page); 195 196 #ifdef AFS_CACHING_SUPPORT 197 if (cachefs_write_page(vnode->cache, 198 page, 199 afs_file_readpage_write_complete, 200 NULL, 201 GFP_KERNEL) != 0 202 ) { 203 cachefs_uncache_page(vnode->cache, page); 204 unlock_page(page); 205 } 206 #else 207 unlock_page(page); 208 #endif 209 } 210 211 _leave(" = 0"); 212 return 0; 213 214 error: 215 SetPageError(page); 216 unlock_page(page); 217 218 _leave(" = %d", ret); 219 return ret; 220 221 } /* end afs_file_readpage() */ 222 223 /*****************************************************************************/ 224 /* 225 * get a page cookie for the specified page 226 */ 227 #ifdef AFS_CACHING_SUPPORT 228 int afs_cache_get_page_cookie(struct page *page, 229 struct cachefs_page **_page_cookie) 230 { 231 int ret; 232 233 _enter(""); 234 ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO); 235 236 _leave(" = %d", ret); 237 return ret; 238 } /* end afs_cache_get_page_cookie() */ 239 #endif 240 241 /*****************************************************************************/ 242 /* 243 * invalidate part or all of a page 244 */ 245 static int afs_file_invalidatepage(struct page *page, unsigned long offset) 246 { 247 int ret = 1; 248 249 _enter("{%lu},%lu", page->index, offset); 250 251 BUG_ON(!PageLocked(page)); 252 253 if (PagePrivate(page)) { 254 #ifdef AFS_CACHING_SUPPORT 255 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 256 cachefs_uncache_page(vnode->cache,page); 257 #endif 258 259 /* We release buffers only if the entire page is being 260 * invalidated. 261 * The get_block cached value has been unconditionally 262 * invalidated, so real IO is not possible anymore. 263 */ 264 if (offset == 0) { 265 BUG_ON(!PageLocked(page)); 266 267 ret = 0; 268 if (!PageWriteback(page)) 269 ret = page->mapping->a_ops->releasepage(page, 270 0); 271 } 272 } 273 274 _leave(" = %d", ret); 275 return ret; 276 } /* end afs_file_invalidatepage() */ 277 278 /*****************************************************************************/ 279 /* 280 * release a page and cleanup its private data 281 */ 282 static int afs_file_releasepage(struct page *page, gfp_t gfp_flags) 283 { 284 struct cachefs_page *pageio; 285 286 _enter("{%lu},%x", page->index, gfp_flags); 287 288 if (PagePrivate(page)) { 289 #ifdef AFS_CACHING_SUPPORT 290 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 291 cachefs_uncache_page(vnode->cache, page); 292 #endif 293 294 pageio = (struct cachefs_page *) page_private(page); 295 set_page_private(page, 0); 296 ClearPagePrivate(page); 297 298 if (pageio) 299 kfree(pageio); 300 } 301 302 _leave(" = 0"); 303 return 0; 304 } /* end afs_file_releasepage() */ 305