1 /* 2 * V9FS cache definitions. 3 * 4 * Copyright (C) 2009 by Abhishek Kulkarni <adkulkar@umail.iu.edu> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 8 * as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to: 17 * Free Software Foundation 18 * 51 Franklin Street, Fifth Floor 19 * Boston, MA 02111-1301 USA 20 * 21 */ 22 23 #include <linux/jiffies.h> 24 #include <linux/file.h> 25 #include <linux/slab.h> 26 #include <linux/stat.h> 27 #include <linux/sched.h> 28 #include <linux/fs.h> 29 #include <net/9p/9p.h> 30 31 #include "v9fs.h" 32 #include "cache.h" 33 34 #define CACHETAG_LEN 11 35 36 struct fscache_netfs v9fs_cache_netfs = { 37 .name = "9p", 38 .version = 0, 39 }; 40 41 /** 42 * v9fs_random_cachetag - Generate a random tag to be associated 43 * with a new cache session. 44 * 45 * The value of jiffies is used for a fairly randomly cache tag. 46 */ 47 48 static 49 int v9fs_random_cachetag(struct v9fs_session_info *v9ses) 50 { 51 v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL); 52 if (!v9ses->cachetag) 53 return -ENOMEM; 54 55 return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies); 56 } 57 58 const struct fscache_cookie_def v9fs_cache_session_index_def = { 59 .name = "9P.session", 60 .type = FSCACHE_COOKIE_TYPE_INDEX, 61 }; 62 63 void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) 64 { 65 /* If no cache session tag was specified, we generate a random one. */ 66 if (!v9ses->cachetag) { 67 if (v9fs_random_cachetag(v9ses) < 0) { 68 v9ses->fscache = NULL; 69 return; 70 } 71 } 72 73 v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, 74 &v9fs_cache_session_index_def, 75 v9ses->cachetag, 76 strlen(v9ses->cachetag), 77 NULL, 0, 78 v9ses, 0, true); 79 p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n", 80 v9ses, v9ses->fscache); 81 } 82 83 void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses) 84 { 85 p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n", 86 v9ses, v9ses->fscache); 87 fscache_relinquish_cookie(v9ses->fscache, NULL, false); 88 v9ses->fscache = NULL; 89 } 90 91 static enum 92 fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, 93 const void *buffer, 94 uint16_t buflen, 95 loff_t object_size) 96 { 97 const struct v9fs_inode *v9inode = cookie_netfs_data; 98 99 if (buflen != sizeof(v9inode->qid.version)) 100 return FSCACHE_CHECKAUX_OBSOLETE; 101 102 if (memcmp(buffer, &v9inode->qid.version, 103 sizeof(v9inode->qid.version))) 104 return FSCACHE_CHECKAUX_OBSOLETE; 105 106 return FSCACHE_CHECKAUX_OKAY; 107 } 108 109 const struct fscache_cookie_def v9fs_cache_inode_index_def = { 110 .name = "9p.inode", 111 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 112 .check_aux = v9fs_cache_inode_check_aux, 113 }; 114 115 void v9fs_cache_inode_get_cookie(struct inode *inode) 116 { 117 struct v9fs_inode *v9inode; 118 struct v9fs_session_info *v9ses; 119 120 if (!S_ISREG(inode->i_mode)) 121 return; 122 123 v9inode = V9FS_I(inode); 124 if (v9inode->fscache) 125 return; 126 127 v9ses = v9fs_inode2v9ses(inode); 128 v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, 129 &v9fs_cache_inode_index_def, 130 &v9inode->qid.path, 131 sizeof(v9inode->qid.path), 132 &v9inode->qid.version, 133 sizeof(v9inode->qid.version), 134 v9inode, 135 i_size_read(&v9inode->vfs_inode), 136 true); 137 138 p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", 139 inode, v9inode->fscache); 140 } 141 142 void v9fs_cache_inode_put_cookie(struct inode *inode) 143 { 144 struct v9fs_inode *v9inode = V9FS_I(inode); 145 146 if (!v9inode->fscache) 147 return; 148 p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n", 149 inode, v9inode->fscache); 150 151 fscache_relinquish_cookie(v9inode->fscache, &v9inode->qid.version, 152 false); 153 v9inode->fscache = NULL; 154 } 155 156 void v9fs_cache_inode_flush_cookie(struct inode *inode) 157 { 158 struct v9fs_inode *v9inode = V9FS_I(inode); 159 160 if (!v9inode->fscache) 161 return; 162 p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n", 163 inode, v9inode->fscache); 164 165 fscache_relinquish_cookie(v9inode->fscache, NULL, true); 166 v9inode->fscache = NULL; 167 } 168 169 void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) 170 { 171 struct v9fs_inode *v9inode = V9FS_I(inode); 172 173 if (!v9inode->fscache) 174 return; 175 176 mutex_lock(&v9inode->fscache_lock); 177 178 if ((filp->f_flags & O_ACCMODE) != O_RDONLY) 179 v9fs_cache_inode_flush_cookie(inode); 180 else 181 v9fs_cache_inode_get_cookie(inode); 182 183 mutex_unlock(&v9inode->fscache_lock); 184 } 185 186 void v9fs_cache_inode_reset_cookie(struct inode *inode) 187 { 188 struct v9fs_inode *v9inode = V9FS_I(inode); 189 struct v9fs_session_info *v9ses; 190 struct fscache_cookie *old; 191 192 if (!v9inode->fscache) 193 return; 194 195 old = v9inode->fscache; 196 197 mutex_lock(&v9inode->fscache_lock); 198 fscache_relinquish_cookie(v9inode->fscache, NULL, true); 199 200 v9ses = v9fs_inode2v9ses(inode); 201 v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, 202 &v9fs_cache_inode_index_def, 203 &v9inode->qid.path, 204 sizeof(v9inode->qid.path), 205 &v9inode->qid.version, 206 sizeof(v9inode->qid.version), 207 v9inode, 208 i_size_read(&v9inode->vfs_inode), 209 true); 210 p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n", 211 inode, old, v9inode->fscache); 212 213 mutex_unlock(&v9inode->fscache_lock); 214 } 215 216 int __v9fs_fscache_release_page(struct page *page, gfp_t gfp) 217 { 218 struct inode *inode = page->mapping->host; 219 struct v9fs_inode *v9inode = V9FS_I(inode); 220 221 BUG_ON(!v9inode->fscache); 222 223 return fscache_maybe_release_page(v9inode->fscache, page, gfp); 224 } 225 226 void __v9fs_fscache_invalidate_page(struct page *page) 227 { 228 struct inode *inode = page->mapping->host; 229 struct v9fs_inode *v9inode = V9FS_I(inode); 230 231 BUG_ON(!v9inode->fscache); 232 233 if (PageFsCache(page)) { 234 fscache_wait_on_page_write(v9inode->fscache, page); 235 BUG_ON(!PageLocked(page)); 236 fscache_uncache_page(v9inode->fscache, page); 237 } 238 } 239 240 static void v9fs_vfs_readpage_complete(struct page *page, void *data, 241 int error) 242 { 243 if (!error) 244 SetPageUptodate(page); 245 246 unlock_page(page); 247 } 248 249 /** 250 * __v9fs_readpage_from_fscache - read a page from cache 251 * 252 * Returns 0 if the pages are in cache and a BIO is submitted, 253 * 1 if the pages are not in cache and -error otherwise. 254 */ 255 256 int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page) 257 { 258 int ret; 259 const struct v9fs_inode *v9inode = V9FS_I(inode); 260 261 p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); 262 if (!v9inode->fscache) 263 return -ENOBUFS; 264 265 ret = fscache_read_or_alloc_page(v9inode->fscache, 266 page, 267 v9fs_vfs_readpage_complete, 268 NULL, 269 GFP_KERNEL); 270 switch (ret) { 271 case -ENOBUFS: 272 case -ENODATA: 273 p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret); 274 return 1; 275 case 0: 276 p9_debug(P9_DEBUG_FSC, "BIO submitted\n"); 277 return ret; 278 default: 279 p9_debug(P9_DEBUG_FSC, "ret %d\n", ret); 280 return ret; 281 } 282 } 283 284 /** 285 * __v9fs_readpages_from_fscache - read multiple pages from cache 286 * 287 * Returns 0 if the pages are in cache and a BIO is submitted, 288 * 1 if the pages are not in cache and -error otherwise. 289 */ 290 291 int __v9fs_readpages_from_fscache(struct inode *inode, 292 struct address_space *mapping, 293 struct list_head *pages, 294 unsigned *nr_pages) 295 { 296 int ret; 297 const struct v9fs_inode *v9inode = V9FS_I(inode); 298 299 p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages); 300 if (!v9inode->fscache) 301 return -ENOBUFS; 302 303 ret = fscache_read_or_alloc_pages(v9inode->fscache, 304 mapping, pages, nr_pages, 305 v9fs_vfs_readpage_complete, 306 NULL, 307 mapping_gfp_mask(mapping)); 308 switch (ret) { 309 case -ENOBUFS: 310 case -ENODATA: 311 p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret); 312 return 1; 313 case 0: 314 BUG_ON(!list_empty(pages)); 315 BUG_ON(*nr_pages != 0); 316 p9_debug(P9_DEBUG_FSC, "BIO submitted\n"); 317 return ret; 318 default: 319 p9_debug(P9_DEBUG_FSC, "ret %d\n", ret); 320 return ret; 321 } 322 } 323 324 /** 325 * __v9fs_readpage_to_fscache - write a page to the cache 326 * 327 */ 328 329 void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page) 330 { 331 int ret; 332 const struct v9fs_inode *v9inode = V9FS_I(inode); 333 334 p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); 335 ret = fscache_write_page(v9inode->fscache, page, 336 i_size_read(&v9inode->vfs_inode), GFP_KERNEL); 337 p9_debug(P9_DEBUG_FSC, "ret = %d\n", ret); 338 if (ret != 0) 339 v9fs_uncache_page(inode, page); 340 } 341 342 /* 343 * wait for a page to complete writing to the cache 344 */ 345 void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page) 346 { 347 const struct v9fs_inode *v9inode = V9FS_I(inode); 348 p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); 349 if (PageFsCache(page)) 350 fscache_wait_on_page_write(v9inode->fscache, page); 351 } 352