1 /* 2 * Ceph cache definitions. 3 * 4 * Copyright (C) 2013 by Adfin Solutions, Inc. All Rights Reserved. 5 * Written by Milosz Tanski (milosz@adfin.com) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 9 * as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to: 18 * Free Software Foundation 19 * 51 Franklin Street, Fifth Floor 20 * Boston, MA 02111-1301 USA 21 * 22 */ 23 24 #include "super.h" 25 #include "cache.h" 26 27 struct ceph_aux_inode { 28 u64 version; 29 struct timespec mtime; 30 loff_t size; 31 }; 32 33 struct fscache_netfs ceph_cache_netfs = { 34 .name = "ceph", 35 .version = 0, 36 }; 37 38 static uint16_t ceph_fscache_session_get_key(const void *cookie_netfs_data, 39 void *buffer, uint16_t maxbuf) 40 { 41 const struct ceph_fs_client* fsc = cookie_netfs_data; 42 uint16_t klen; 43 44 klen = sizeof(fsc->client->fsid); 45 if (klen > maxbuf) 46 return 0; 47 48 memcpy(buffer, &fsc->client->fsid, klen); 49 return klen; 50 } 51 52 static const struct fscache_cookie_def ceph_fscache_fsid_object_def = { 53 .name = "CEPH.fsid", 54 .type = FSCACHE_COOKIE_TYPE_INDEX, 55 .get_key = ceph_fscache_session_get_key, 56 }; 57 58 int ceph_fscache_register(void) 59 { 60 return fscache_register_netfs(&ceph_cache_netfs); 61 } 62 63 void ceph_fscache_unregister(void) 64 { 65 fscache_unregister_netfs(&ceph_cache_netfs); 66 } 67 68 int ceph_fscache_register_fs(struct ceph_fs_client* fsc) 69 { 70 fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index, 71 &ceph_fscache_fsid_object_def, 72 fsc, true); 73 if (!fsc->fscache) 74 pr_err("Unable to register fsid: %p fscache cookie\n", fsc); 75 76 return 0; 77 } 78 79 static uint16_t ceph_fscache_inode_get_key(const void *cookie_netfs_data, 80 void *buffer, uint16_t maxbuf) 81 { 82 const struct ceph_inode_info* ci = cookie_netfs_data; 83 uint16_t klen; 84 85 /* use ceph virtual inode (id + snapshot) */ 86 klen = sizeof(ci->i_vino); 87 if (klen > maxbuf) 88 return 0; 89 90 memcpy(buffer, &ci->i_vino, klen); 91 return klen; 92 } 93 94 static uint16_t ceph_fscache_inode_get_aux(const void *cookie_netfs_data, 95 void *buffer, uint16_t bufmax) 96 { 97 struct ceph_aux_inode aux; 98 const struct ceph_inode_info* ci = cookie_netfs_data; 99 const struct inode* inode = &ci->vfs_inode; 100 101 memset(&aux, 0, sizeof(aux)); 102 aux.version = ci->i_version; 103 aux.mtime = inode->i_mtime; 104 aux.size = i_size_read(inode); 105 106 memcpy(buffer, &aux, sizeof(aux)); 107 108 return sizeof(aux); 109 } 110 111 static void ceph_fscache_inode_get_attr(const void *cookie_netfs_data, 112 uint64_t *size) 113 { 114 const struct ceph_inode_info* ci = cookie_netfs_data; 115 *size = i_size_read(&ci->vfs_inode); 116 } 117 118 static enum fscache_checkaux ceph_fscache_inode_check_aux( 119 void *cookie_netfs_data, const void *data, uint16_t dlen) 120 { 121 struct ceph_aux_inode aux; 122 struct ceph_inode_info* ci = cookie_netfs_data; 123 struct inode* inode = &ci->vfs_inode; 124 125 if (dlen != sizeof(aux)) 126 return FSCACHE_CHECKAUX_OBSOLETE; 127 128 memset(&aux, 0, sizeof(aux)); 129 aux.version = ci->i_version; 130 aux.mtime = inode->i_mtime; 131 aux.size = i_size_read(inode); 132 133 if (memcmp(data, &aux, sizeof(aux)) != 0) 134 return FSCACHE_CHECKAUX_OBSOLETE; 135 136 dout("ceph inode 0x%p cached okay", ci); 137 return FSCACHE_CHECKAUX_OKAY; 138 } 139 140 static void ceph_fscache_inode_now_uncached(void* cookie_netfs_data) 141 { 142 struct ceph_inode_info* ci = cookie_netfs_data; 143 struct pagevec pvec; 144 pgoff_t first; 145 int loop, nr_pages; 146 147 pagevec_init(&pvec, 0); 148 first = 0; 149 150 dout("ceph inode 0x%p now uncached", ci); 151 152 while (1) { 153 nr_pages = pagevec_lookup(&pvec, ci->vfs_inode.i_mapping, first, 154 PAGEVEC_SIZE - pagevec_count(&pvec)); 155 156 if (!nr_pages) 157 break; 158 159 for (loop = 0; loop < nr_pages; loop++) 160 ClearPageFsCache(pvec.pages[loop]); 161 162 first = pvec.pages[nr_pages - 1]->index + 1; 163 164 pvec.nr = nr_pages; 165 pagevec_release(&pvec); 166 cond_resched(); 167 } 168 } 169 170 static const struct fscache_cookie_def ceph_fscache_inode_object_def = { 171 .name = "CEPH.inode", 172 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 173 .get_key = ceph_fscache_inode_get_key, 174 .get_attr = ceph_fscache_inode_get_attr, 175 .get_aux = ceph_fscache_inode_get_aux, 176 .check_aux = ceph_fscache_inode_check_aux, 177 .now_uncached = ceph_fscache_inode_now_uncached, 178 }; 179 180 void ceph_fscache_register_inode_cookie(struct inode *inode) 181 { 182 struct ceph_inode_info *ci = ceph_inode(inode); 183 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 184 185 /* No caching for filesystem */ 186 if (fsc->fscache == NULL) 187 return; 188 189 /* Only cache for regular files that are read only */ 190 if (!S_ISREG(inode->i_mode)) 191 return; 192 193 inode_lock_nested(inode, I_MUTEX_CHILD); 194 if (!ci->fscache) { 195 ci->fscache = fscache_acquire_cookie(fsc->fscache, 196 &ceph_fscache_inode_object_def, 197 ci, false); 198 } 199 inode_unlock(inode); 200 } 201 202 void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci) 203 { 204 struct fscache_cookie* cookie; 205 206 if ((cookie = ci->fscache) == NULL) 207 return; 208 209 ci->fscache = NULL; 210 211 fscache_uncache_all_inode_pages(cookie, &ci->vfs_inode); 212 fscache_relinquish_cookie(cookie, 0); 213 } 214 215 static bool ceph_fscache_can_enable(void *data) 216 { 217 struct inode *inode = data; 218 return !inode_is_open_for_write(inode); 219 } 220 221 void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp) 222 { 223 struct ceph_inode_info *ci = ceph_inode(inode); 224 225 if (!fscache_cookie_valid(ci->fscache)) 226 return; 227 228 if (inode_is_open_for_write(inode)) { 229 dout("fscache_file_set_cookie %p %p disabling cache\n", 230 inode, filp); 231 fscache_disable_cookie(ci->fscache, false); 232 fscache_uncache_all_inode_pages(ci->fscache, inode); 233 } else { 234 fscache_enable_cookie(ci->fscache, ceph_fscache_can_enable, 235 inode); 236 if (fscache_cookie_enabled(ci->fscache)) { 237 dout("fscache_file_set_cookie %p %p enabling cache\n", 238 inode, filp); 239 } 240 } 241 } 242 243 static void ceph_vfs_readpage_complete(struct page *page, void *data, int error) 244 { 245 if (!error) 246 SetPageUptodate(page); 247 } 248 249 static void ceph_vfs_readpage_complete_unlock(struct page *page, void *data, int error) 250 { 251 if (!error) 252 SetPageUptodate(page); 253 254 unlock_page(page); 255 } 256 257 static inline bool cache_valid(struct ceph_inode_info *ci) 258 { 259 return ci->i_fscache_gen == ci->i_rdcache_gen; 260 } 261 262 263 /* Atempt to read from the fscache, 264 * 265 * This function is called from the readpage_nounlock context. DO NOT attempt to 266 * unlock the page here (or in the callback). 267 */ 268 int ceph_readpage_from_fscache(struct inode *inode, struct page *page) 269 { 270 struct ceph_inode_info *ci = ceph_inode(inode); 271 int ret; 272 273 if (!cache_valid(ci)) 274 return -ENOBUFS; 275 276 ret = fscache_read_or_alloc_page(ci->fscache, page, 277 ceph_vfs_readpage_complete, NULL, 278 GFP_KERNEL); 279 280 switch (ret) { 281 case 0: /* Page found */ 282 dout("page read submitted\n"); 283 return 0; 284 case -ENOBUFS: /* Pages were not found, and can't be */ 285 case -ENODATA: /* Pages were not found */ 286 dout("page/inode not in cache\n"); 287 return ret; 288 default: 289 dout("%s: unknown error ret = %i\n", __func__, ret); 290 return ret; 291 } 292 } 293 294 int ceph_readpages_from_fscache(struct inode *inode, 295 struct address_space *mapping, 296 struct list_head *pages, 297 unsigned *nr_pages) 298 { 299 struct ceph_inode_info *ci = ceph_inode(inode); 300 int ret; 301 302 if (!cache_valid(ci)) 303 return -ENOBUFS; 304 305 ret = fscache_read_or_alloc_pages(ci->fscache, mapping, pages, nr_pages, 306 ceph_vfs_readpage_complete_unlock, 307 NULL, mapping_gfp_mask(mapping)); 308 309 switch (ret) { 310 case 0: /* All pages found */ 311 dout("all-page read submitted\n"); 312 return 0; 313 case -ENOBUFS: /* Some pages were not found, and can't be */ 314 case -ENODATA: /* some pages were not found */ 315 dout("page/inode not in cache\n"); 316 return ret; 317 default: 318 dout("%s: unknown error ret = %i\n", __func__, ret); 319 return ret; 320 } 321 } 322 323 void ceph_readpage_to_fscache(struct inode *inode, struct page *page) 324 { 325 struct ceph_inode_info *ci = ceph_inode(inode); 326 int ret; 327 328 if (!PageFsCache(page)) 329 return; 330 331 if (!cache_valid(ci)) 332 return; 333 334 ret = fscache_write_page(ci->fscache, page, GFP_KERNEL); 335 if (ret) 336 fscache_uncache_page(ci->fscache, page); 337 } 338 339 void ceph_invalidate_fscache_page(struct inode* inode, struct page *page) 340 { 341 struct ceph_inode_info *ci = ceph_inode(inode); 342 343 if (!PageFsCache(page)) 344 return; 345 346 fscache_wait_on_page_write(ci->fscache, page); 347 fscache_uncache_page(ci->fscache, page); 348 } 349 350 void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc) 351 { 352 fscache_relinquish_cookie(fsc->fscache, 0); 353 fsc->fscache = NULL; 354 } 355 356 /* 357 * caller should hold CEPH_CAP_FILE_{RD,CACHE} 358 */ 359 void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci) 360 { 361 if (cache_valid(ci)) 362 return; 363 364 /* resue i_truncate_mutex. There should be no pending 365 * truncate while the caller holds CEPH_CAP_FILE_RD */ 366 mutex_lock(&ci->i_truncate_mutex); 367 if (!cache_valid(ci)) { 368 if (fscache_check_consistency(ci->fscache)) 369 fscache_invalidate(ci->fscache); 370 spin_lock(&ci->i_ceph_lock); 371 ci->i_fscache_gen = ci->i_rdcache_gen; 372 spin_unlock(&ci->i_ceph_lock); 373 } 374 mutex_unlock(&ci->i_truncate_mutex); 375 } 376