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