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, int 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 if (!PageLocked(page)) 135 PAGE_BUG(page); 136 137 ret = -ESTALE; 138 if (vnode->flags & AFS_VNODE_DELETED) 139 goto error; 140 141 #ifdef AFS_CACHING_SUPPORT 142 ret = cachefs_page_get_private(page, &pageio, GFP_NOIO); 143 if (ret < 0) 144 goto error; 145 146 /* is it cached? */ 147 ret = cachefs_read_or_alloc_page(vnode->cache, 148 page, 149 afs_file_readpage_read_complete, 150 NULL, 151 GFP_KERNEL); 152 #else 153 ret = -ENOBUFS; 154 #endif 155 156 switch (ret) { 157 /* read BIO submitted and wb-journal entry found */ 158 case 1: 159 BUG(); // TODO - handle wb-journal match 160 161 /* read BIO submitted (page in cache) */ 162 case 0: 163 break; 164 165 /* no page available in cache */ 166 case -ENOBUFS: 167 case -ENODATA: 168 default: 169 desc.fid = vnode->fid; 170 desc.offset = page->index << PAGE_CACHE_SHIFT; 171 desc.size = min((size_t) (inode->i_size - desc.offset), 172 (size_t) PAGE_SIZE); 173 desc.buffer = kmap(page); 174 175 clear_page(desc.buffer); 176 177 /* read the contents of the file from the server into the 178 * page */ 179 ret = afs_vnode_fetch_data(vnode, &desc); 180 kunmap(page); 181 if (ret < 0) { 182 if (ret==-ENOENT) { 183 _debug("got NOENT from server" 184 " - marking file deleted and stale"); 185 vnode->flags |= AFS_VNODE_DELETED; 186 ret = -ESTALE; 187 } 188 189 #ifdef AFS_CACHING_SUPPORT 190 cachefs_uncache_page(vnode->cache, page); 191 #endif 192 goto error; 193 } 194 195 SetPageUptodate(page); 196 197 #ifdef AFS_CACHING_SUPPORT 198 if (cachefs_write_page(vnode->cache, 199 page, 200 afs_file_readpage_write_complete, 201 NULL, 202 GFP_KERNEL) != 0 203 ) { 204 cachefs_uncache_page(vnode->cache, page); 205 unlock_page(page); 206 } 207 #else 208 unlock_page(page); 209 #endif 210 } 211 212 _leave(" = 0"); 213 return 0; 214 215 error: 216 SetPageError(page); 217 unlock_page(page); 218 219 _leave(" = %d", ret); 220 return ret; 221 222 } /* end afs_file_readpage() */ 223 224 /*****************************************************************************/ 225 /* 226 * get a page cookie for the specified page 227 */ 228 #ifdef AFS_CACHING_SUPPORT 229 int afs_cache_get_page_cookie(struct page *page, 230 struct cachefs_page **_page_cookie) 231 { 232 int ret; 233 234 _enter(""); 235 ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO); 236 237 _leave(" = %d", ret); 238 return ret; 239 } /* end afs_cache_get_page_cookie() */ 240 #endif 241 242 /*****************************************************************************/ 243 /* 244 * invalidate part or all of a page 245 */ 246 static int afs_file_invalidatepage(struct page *page, unsigned long offset) 247 { 248 int ret = 1; 249 250 _enter("{%lu},%lu", page->index, offset); 251 252 BUG_ON(!PageLocked(page)); 253 254 if (PagePrivate(page)) { 255 #ifdef AFS_CACHING_SUPPORT 256 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 257 cachefs_uncache_page(vnode->cache,page); 258 #endif 259 260 /* We release buffers only if the entire page is being 261 * invalidated. 262 * The get_block cached value has been unconditionally 263 * invalidated, so real IO is not possible anymore. 264 */ 265 if (offset == 0) { 266 BUG_ON(!PageLocked(page)); 267 268 ret = 0; 269 if (!PageWriteback(page)) 270 ret = page->mapping->a_ops->releasepage(page, 271 0); 272 } 273 } 274 275 _leave(" = %d", ret); 276 return ret; 277 } /* end afs_file_invalidatepage() */ 278 279 /*****************************************************************************/ 280 /* 281 * release a page and cleanup its private data 282 */ 283 static int afs_file_releasepage(struct page *page, int gfp_flags) 284 { 285 struct cachefs_page *pageio; 286 287 _enter("{%lu},%x", page->index, gfp_flags); 288 289 if (PagePrivate(page)) { 290 #ifdef AFS_CACHING_SUPPORT 291 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); 292 cachefs_uncache_page(vnode->cache, page); 293 #endif 294 295 pageio = (struct cachefs_page *) page->private; 296 page->private = 0; 297 ClearPagePrivate(page); 298 299 if (pageio) 300 kfree(pageio); 301 } 302 303 _leave(" = 0"); 304 return 0; 305 } /* end afs_file_releasepage() */ 306