1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* FS-Cache interface to CacheFiles 3 * 4 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/slab.h> 9 #include <linux/mount.h> 10 #include <linux/xattr.h> 11 #include <linux/file.h> 12 #include <linux/falloc.h> 13 #include <trace/events/fscache.h> 14 #include "internal.h" 15 16 static atomic_t cachefiles_object_debug_id; 17 18 /* 19 * Allocate a cache object record. 20 */ 21 static 22 struct cachefiles_object *cachefiles_alloc_object(struct fscache_cookie *cookie) 23 { 24 struct fscache_volume *vcookie = cookie->volume; 25 struct cachefiles_volume *volume = vcookie->cache_priv; 26 struct cachefiles_object *object; 27 28 _enter("{%s},%x,", vcookie->key, cookie->debug_id); 29 30 object = kmem_cache_zalloc(cachefiles_object_jar, GFP_KERNEL); 31 if (!object) 32 return NULL; 33 34 if (cachefiles_ondemand_init_obj_info(object, volume)) { 35 kmem_cache_free(cachefiles_object_jar, object); 36 return NULL; 37 } 38 39 refcount_set(&object->ref, 1); 40 41 spin_lock_init(&object->lock); 42 INIT_LIST_HEAD(&object->cache_link); 43 object->volume = volume; 44 object->debug_id = atomic_inc_return(&cachefiles_object_debug_id); 45 object->cookie = fscache_get_cookie(cookie, fscache_cookie_get_attach_object); 46 47 fscache_count_object(vcookie->cache); 48 trace_cachefiles_ref(object->debug_id, cookie->debug_id, 1, 49 cachefiles_obj_new); 50 return object; 51 } 52 53 /* 54 * Note that an object has been seen. 55 */ 56 void cachefiles_see_object(struct cachefiles_object *object, 57 enum cachefiles_obj_ref_trace why) 58 { 59 trace_cachefiles_ref(object->debug_id, object->cookie->debug_id, 60 refcount_read(&object->ref), why); 61 } 62 63 /* 64 * Increment the usage count on an object; 65 */ 66 struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object, 67 enum cachefiles_obj_ref_trace why) 68 { 69 int r; 70 71 __refcount_inc(&object->ref, &r); 72 trace_cachefiles_ref(object->debug_id, object->cookie->debug_id, r, why); 73 return object; 74 } 75 76 /* 77 * dispose of a reference to an object 78 */ 79 void cachefiles_put_object(struct cachefiles_object *object, 80 enum cachefiles_obj_ref_trace why) 81 { 82 unsigned int object_debug_id = object->debug_id; 83 unsigned int cookie_debug_id = object->cookie->debug_id; 84 struct fscache_cache *cache; 85 bool done; 86 int r; 87 88 done = __refcount_dec_and_test(&object->ref, &r); 89 trace_cachefiles_ref(object_debug_id, cookie_debug_id, r, why); 90 if (done) { 91 _debug("- kill object OBJ%x", object_debug_id); 92 93 ASSERTCMP(object->file, ==, NULL); 94 95 kfree(object->d_name); 96 cachefiles_ondemand_deinit_obj_info(object); 97 cache = object->volume->cache->cache; 98 fscache_put_cookie(object->cookie, fscache_cookie_put_object); 99 object->cookie = NULL; 100 kmem_cache_free(cachefiles_object_jar, object); 101 fscache_uncount_object(cache); 102 } 103 104 _leave(""); 105 } 106 107 /* 108 * Adjust the size of a cache file if necessary to match the DIO size. We keep 109 * the EOF marker a multiple of DIO blocks so that we don't fall back to doing 110 * non-DIO for a partial block straddling the EOF, but we also have to be 111 * careful of someone expanding the file and accidentally accreting the 112 * padding. 113 */ 114 static int cachefiles_adjust_size(struct cachefiles_object *object) 115 { 116 struct iattr newattrs; 117 struct file *file = object->file; 118 uint64_t ni_size; 119 loff_t oi_size; 120 int ret; 121 122 ni_size = object->cookie->object_size; 123 ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); 124 125 _enter("{OBJ%x},[%llu]", 126 object->debug_id, (unsigned long long) ni_size); 127 128 if (!file) 129 return -ENOBUFS; 130 131 oi_size = i_size_read(file_inode(file)); 132 if (oi_size == ni_size) 133 return 0; 134 135 inode_lock(file_inode(file)); 136 137 /* if there's an extension to a partial page at the end of the backing 138 * file, we need to discard the partial page so that we pick up new 139 * data after it */ 140 if (oi_size & ~PAGE_MASK && ni_size > oi_size) { 141 _debug("discard tail %llx", oi_size); 142 newattrs.ia_valid = ATTR_SIZE; 143 newattrs.ia_size = oi_size & PAGE_MASK; 144 ret = cachefiles_inject_remove_error(); 145 if (ret == 0) 146 ret = notify_change(&nop_mnt_idmap, file->f_path.dentry, 147 &newattrs, NULL); 148 if (ret < 0) 149 goto truncate_failed; 150 } 151 152 newattrs.ia_valid = ATTR_SIZE; 153 newattrs.ia_size = ni_size; 154 ret = cachefiles_inject_write_error(); 155 if (ret == 0) 156 ret = notify_change(&nop_mnt_idmap, file->f_path.dentry, 157 &newattrs, NULL); 158 159 truncate_failed: 160 inode_unlock(file_inode(file)); 161 162 if (ret < 0) 163 trace_cachefiles_io_error(NULL, file_inode(file), ret, 164 cachefiles_trace_notify_change_error); 165 if (ret == -EIO) { 166 cachefiles_io_error_obj(object, "Size set failed"); 167 ret = -ENOBUFS; 168 } 169 170 _leave(" = %d", ret); 171 return ret; 172 } 173 174 /* 175 * Attempt to look up the nominated node in this cache 176 */ 177 static bool cachefiles_lookup_cookie(struct fscache_cookie *cookie) 178 { 179 struct cachefiles_object *object; 180 struct cachefiles_cache *cache = cookie->volume->cache->cache_priv; 181 const struct cred *saved_cred; 182 bool success; 183 184 object = cachefiles_alloc_object(cookie); 185 if (!object) 186 goto fail; 187 188 _enter("{OBJ%x}", object->debug_id); 189 190 if (!cachefiles_cook_key(object)) 191 goto fail_put; 192 193 cookie->cache_priv = object; 194 195 cachefiles_begin_secure(cache, &saved_cred); 196 197 success = cachefiles_look_up_object(object); 198 if (!success) 199 goto fail_withdraw; 200 201 cachefiles_see_object(object, cachefiles_obj_see_lookup_cookie); 202 203 spin_lock(&cache->object_list_lock); 204 list_add(&object->cache_link, &cache->object_list); 205 spin_unlock(&cache->object_list_lock); 206 cachefiles_adjust_size(object); 207 208 cachefiles_end_secure(cache, saved_cred); 209 _leave(" = t"); 210 return true; 211 212 fail_withdraw: 213 cachefiles_end_secure(cache, saved_cred); 214 cachefiles_see_object(object, cachefiles_obj_see_lookup_failed); 215 fscache_caching_failed(cookie); 216 _debug("failed c=%08x o=%08x", cookie->debug_id, object->debug_id); 217 /* The caller holds an access count on the cookie, so we need them to 218 * drop it before we can withdraw the object. 219 */ 220 return false; 221 222 fail_put: 223 cachefiles_put_object(object, cachefiles_obj_put_alloc_fail); 224 fail: 225 return false; 226 } 227 228 /* 229 * Shorten the backing object to discard any dirty data and free up 230 * any unused granules. 231 */ 232 static bool cachefiles_shorten_object(struct cachefiles_object *object, 233 struct file *file, loff_t new_size) 234 { 235 struct cachefiles_cache *cache = object->volume->cache; 236 struct inode *inode = file_inode(file); 237 loff_t i_size, dio_size; 238 int ret; 239 240 dio_size = round_up(new_size, CACHEFILES_DIO_BLOCK_SIZE); 241 i_size = i_size_read(inode); 242 243 trace_cachefiles_trunc(object, inode, i_size, dio_size, 244 cachefiles_trunc_shrink); 245 ret = cachefiles_inject_remove_error(); 246 if (ret == 0) 247 ret = vfs_truncate(&file->f_path, dio_size); 248 if (ret < 0) { 249 trace_cachefiles_io_error(object, file_inode(file), ret, 250 cachefiles_trace_trunc_error); 251 cachefiles_io_error_obj(object, "Trunc-to-size failed %d", ret); 252 cachefiles_remove_object_xattr(cache, object, file->f_path.dentry); 253 return false; 254 } 255 256 if (new_size < dio_size) { 257 trace_cachefiles_trunc(object, inode, dio_size, new_size, 258 cachefiles_trunc_dio_adjust); 259 ret = cachefiles_inject_write_error(); 260 if (ret == 0) 261 ret = vfs_fallocate(file, FALLOC_FL_ZERO_RANGE, 262 new_size, dio_size - new_size); 263 if (ret < 0) { 264 trace_cachefiles_io_error(object, file_inode(file), ret, 265 cachefiles_trace_fallocate_error); 266 cachefiles_io_error_obj(object, "Trunc-to-dio-size failed %d", ret); 267 cachefiles_remove_object_xattr(cache, object, file->f_path.dentry); 268 return false; 269 } 270 } 271 272 return true; 273 } 274 275 /* 276 * Resize the backing object. 277 */ 278 static void cachefiles_resize_cookie(struct netfs_cache_resources *cres, 279 loff_t new_size) 280 { 281 struct cachefiles_object *object = cachefiles_cres_object(cres); 282 struct cachefiles_cache *cache = object->volume->cache; 283 struct fscache_cookie *cookie = object->cookie; 284 const struct cred *saved_cred; 285 struct file *file = cachefiles_cres_file(cres); 286 loff_t old_size = cookie->object_size; 287 288 _enter("%llu->%llu", old_size, new_size); 289 290 if (new_size < old_size) { 291 cachefiles_begin_secure(cache, &saved_cred); 292 cachefiles_shorten_object(object, file, new_size); 293 cachefiles_end_secure(cache, saved_cred); 294 object->cookie->object_size = new_size; 295 return; 296 } 297 298 /* The file is being expanded. We don't need to do anything 299 * particularly. cookie->initial_size doesn't change and so the point 300 * at which we have to download before doesn't change. 301 */ 302 cookie->object_size = new_size; 303 } 304 305 /* 306 * Commit changes to the object as we drop it. 307 */ 308 static void cachefiles_commit_object(struct cachefiles_object *object, 309 struct cachefiles_cache *cache) 310 { 311 bool update = false; 312 313 if (test_and_clear_bit(FSCACHE_COOKIE_LOCAL_WRITE, &object->cookie->flags)) 314 update = true; 315 if (test_and_clear_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &object->cookie->flags)) 316 update = true; 317 if (update) 318 cachefiles_set_object_xattr(object); 319 320 if (test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) 321 cachefiles_commit_tmpfile(cache, object); 322 } 323 324 /* 325 * Finalise and object and close the VFS structs that we have. 326 */ 327 static void cachefiles_clean_up_object(struct cachefiles_object *object, 328 struct cachefiles_cache *cache) 329 { 330 if (test_bit(FSCACHE_COOKIE_RETIRED, &object->cookie->flags)) { 331 if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) { 332 cachefiles_see_object(object, cachefiles_obj_see_clean_delete); 333 _debug("- inval object OBJ%x", object->debug_id); 334 cachefiles_delete_object(object, FSCACHE_OBJECT_WAS_RETIRED); 335 } else { 336 cachefiles_see_object(object, cachefiles_obj_see_clean_drop_tmp); 337 _debug("- inval object OBJ%x tmpfile", object->debug_id); 338 } 339 } else { 340 cachefiles_see_object(object, cachefiles_obj_see_clean_commit); 341 cachefiles_commit_object(object, cache); 342 } 343 344 cachefiles_unmark_inode_in_use(object, object->file); 345 if (object->file) { 346 fput(object->file); 347 object->file = NULL; 348 } 349 } 350 351 /* 352 * Withdraw caching for a cookie. 353 */ 354 static void cachefiles_withdraw_cookie(struct fscache_cookie *cookie) 355 { 356 struct cachefiles_object *object = cookie->cache_priv; 357 struct cachefiles_cache *cache = object->volume->cache; 358 const struct cred *saved_cred; 359 360 _enter("o=%x", object->debug_id); 361 cachefiles_see_object(object, cachefiles_obj_see_withdraw_cookie); 362 363 if (!list_empty(&object->cache_link)) { 364 spin_lock(&cache->object_list_lock); 365 cachefiles_see_object(object, cachefiles_obj_see_withdrawal); 366 list_del_init(&object->cache_link); 367 spin_unlock(&cache->object_list_lock); 368 } 369 370 cachefiles_ondemand_clean_object(object); 371 372 if (object->file) { 373 cachefiles_begin_secure(cache, &saved_cred); 374 cachefiles_clean_up_object(object, cache); 375 cachefiles_end_secure(cache, saved_cred); 376 } 377 378 cookie->cache_priv = NULL; 379 cachefiles_put_object(object, cachefiles_obj_put_detach); 380 } 381 382 /* 383 * Invalidate the storage associated with a cookie. 384 */ 385 static bool cachefiles_invalidate_cookie(struct fscache_cookie *cookie) 386 { 387 struct cachefiles_object *object = cookie->cache_priv; 388 struct file *new_file, *old_file; 389 bool old_tmpfile; 390 391 _enter("o=%x,[%llu]", object->debug_id, object->cookie->object_size); 392 393 old_tmpfile = test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags); 394 395 if (!object->file) { 396 fscache_resume_after_invalidation(cookie); 397 _leave(" = t [light]"); 398 return true; 399 } 400 401 new_file = cachefiles_create_tmpfile(object); 402 if (IS_ERR(new_file)) 403 goto failed; 404 405 /* Substitute the VFS target */ 406 _debug("sub"); 407 spin_lock(&object->lock); 408 409 old_file = object->file; 410 object->file = new_file; 411 object->content_info = CACHEFILES_CONTENT_NO_DATA; 412 set_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags); 413 set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &object->cookie->flags); 414 415 spin_unlock(&object->lock); 416 _debug("subbed"); 417 418 /* Allow I/O to take place again */ 419 fscache_resume_after_invalidation(cookie); 420 421 if (old_file) { 422 if (!old_tmpfile) { 423 struct cachefiles_volume *volume = object->volume; 424 struct dentry *fan = volume->fanout[(u8)cookie->key_hash]; 425 426 inode_lock_nested(d_inode(fan), I_MUTEX_PARENT); 427 cachefiles_bury_object(volume->cache, object, fan, 428 old_file->f_path.dentry, 429 FSCACHE_OBJECT_INVALIDATED); 430 } 431 fput(old_file); 432 } 433 434 _leave(" = t"); 435 return true; 436 437 failed: 438 _leave(" = f"); 439 return false; 440 } 441 442 const struct fscache_cache_ops cachefiles_cache_ops = { 443 .name = "cachefiles", 444 .acquire_volume = cachefiles_acquire_volume, 445 .free_volume = cachefiles_free_volume, 446 .lookup_cookie = cachefiles_lookup_cookie, 447 .withdraw_cookie = cachefiles_withdraw_cookie, 448 .invalidate_cookie = cachefiles_invalidate_cookie, 449 .begin_operation = cachefiles_begin_operation, 450 .resize_cookie = cachefiles_resize_cookie, 451 .prepare_to_write = cachefiles_prepare_to_write, 452 }; 453