1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* CacheFiles path walking and related routines |
3 | * |
4 | * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. |
5 | * Written by David Howells (dhowells@redhat.com) |
6 | */ |
7 | |
8 | #include <linux/fs.h> |
9 | #include <linux/namei.h> |
10 | #include "internal.h" |
11 | |
12 | /* |
13 | * Mark the backing file as being a cache file if it's not already in use. The |
14 | * mark tells the culling request command that it's not allowed to cull the |
15 | * file or directory. The caller must hold the inode lock. |
16 | */ |
17 | static bool __cachefiles_mark_inode_in_use(struct cachefiles_object *object, |
18 | struct inode *inode) |
19 | { |
20 | bool can_use = false; |
21 | |
22 | if (!(inode->i_flags & S_KERNEL_FILE)) { |
23 | inode->i_flags |= S_KERNEL_FILE; |
24 | trace_cachefiles_mark_active(obj: object, inode); |
25 | can_use = true; |
26 | } else { |
27 | trace_cachefiles_mark_failed(obj: object, inode); |
28 | } |
29 | |
30 | return can_use; |
31 | } |
32 | |
33 | static bool cachefiles_mark_inode_in_use(struct cachefiles_object *object, |
34 | struct inode *inode) |
35 | { |
36 | bool can_use; |
37 | |
38 | inode_lock(inode); |
39 | can_use = __cachefiles_mark_inode_in_use(object, inode); |
40 | inode_unlock(inode); |
41 | return can_use; |
42 | } |
43 | |
44 | /* |
45 | * Unmark a backing inode. The caller must hold the inode lock. |
46 | */ |
47 | static void __cachefiles_unmark_inode_in_use(struct cachefiles_object *object, |
48 | struct inode *inode) |
49 | { |
50 | inode->i_flags &= ~S_KERNEL_FILE; |
51 | trace_cachefiles_mark_inactive(obj: object, inode); |
52 | } |
53 | |
54 | static void cachefiles_do_unmark_inode_in_use(struct cachefiles_object *object, |
55 | struct inode *inode) |
56 | { |
57 | inode_lock(inode); |
58 | __cachefiles_unmark_inode_in_use(object, inode); |
59 | inode_unlock(inode); |
60 | } |
61 | |
62 | /* |
63 | * Unmark a backing inode and tell cachefilesd that there's something that can |
64 | * be culled. |
65 | */ |
66 | void cachefiles_unmark_inode_in_use(struct cachefiles_object *object, |
67 | struct file *file) |
68 | { |
69 | struct cachefiles_cache *cache = object->volume->cache; |
70 | struct inode *inode = file_inode(f: file); |
71 | |
72 | cachefiles_do_unmark_inode_in_use(object, inode); |
73 | |
74 | if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) { |
75 | atomic_long_add(i: inode->i_blocks, v: &cache->b_released); |
76 | if (atomic_inc_return(v: &cache->f_released)) |
77 | cachefiles_state_changed(cache); |
78 | } |
79 | } |
80 | |
81 | /* |
82 | * get a subdirectory |
83 | */ |
84 | struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, |
85 | struct dentry *dir, |
86 | const char *dirname, |
87 | bool *_is_new) |
88 | { |
89 | struct dentry *subdir; |
90 | struct path path; |
91 | int ret; |
92 | |
93 | _enter(",,%s" , dirname); |
94 | |
95 | /* search the current directory for the element name */ |
96 | inode_lock_nested(inode: d_inode(dentry: dir), subclass: I_MUTEX_PARENT); |
97 | |
98 | retry: |
99 | ret = cachefiles_inject_read_error(); |
100 | if (ret == 0) |
101 | subdir = lookup_one_len(dirname, dir, strlen(dirname)); |
102 | else |
103 | subdir = ERR_PTR(error: ret); |
104 | trace_cachefiles_lookup(NULL, dir, de: subdir); |
105 | if (IS_ERR(ptr: subdir)) { |
106 | trace_cachefiles_vfs_error(NULL, backer: d_backing_inode(upper: dir), |
107 | error: PTR_ERR(ptr: subdir), |
108 | where: cachefiles_trace_lookup_error); |
109 | if (PTR_ERR(ptr: subdir) == -ENOMEM) |
110 | goto nomem_d_alloc; |
111 | goto lookup_error; |
112 | } |
113 | |
114 | _debug("subdir -> %pd %s" , |
115 | subdir, d_backing_inode(subdir) ? "positive" : "negative" ); |
116 | |
117 | /* we need to create the subdir if it doesn't exist yet */ |
118 | if (d_is_negative(dentry: subdir)) { |
119 | ret = cachefiles_has_space(cache, fnr: 1, bnr: 0, |
120 | reason: cachefiles_has_space_for_create); |
121 | if (ret < 0) |
122 | goto mkdir_error; |
123 | |
124 | _debug("attempt mkdir" ); |
125 | |
126 | path.mnt = cache->mnt; |
127 | path.dentry = dir; |
128 | ret = security_path_mkdir(dir: &path, dentry: subdir, mode: 0700); |
129 | if (ret < 0) |
130 | goto mkdir_error; |
131 | ret = cachefiles_inject_write_error(); |
132 | if (ret == 0) |
133 | ret = vfs_mkdir(&nop_mnt_idmap, d_inode(dentry: dir), subdir, 0700); |
134 | if (ret < 0) { |
135 | trace_cachefiles_vfs_error(NULL, backer: d_inode(dentry: dir), error: ret, |
136 | where: cachefiles_trace_mkdir_error); |
137 | goto mkdir_error; |
138 | } |
139 | trace_cachefiles_mkdir(dir, subdir); |
140 | |
141 | if (unlikely(d_unhashed(subdir))) { |
142 | cachefiles_put_directory(dir: subdir); |
143 | goto retry; |
144 | } |
145 | ASSERT(d_backing_inode(subdir)); |
146 | |
147 | _debug("mkdir -> %pd{ino=%lu}" , |
148 | subdir, d_backing_inode(subdir)->i_ino); |
149 | if (_is_new) |
150 | *_is_new = true; |
151 | } |
152 | |
153 | /* Tell rmdir() it's not allowed to delete the subdir */ |
154 | inode_lock(inode: d_inode(dentry: subdir)); |
155 | inode_unlock(inode: d_inode(dentry: dir)); |
156 | |
157 | if (!__cachefiles_mark_inode_in_use(NULL, inode: d_inode(dentry: subdir))) { |
158 | pr_notice("cachefiles: Inode already in use: %pd (B=%lx)\n" , |
159 | subdir, d_inode(subdir)->i_ino); |
160 | goto mark_error; |
161 | } |
162 | |
163 | inode_unlock(inode: d_inode(dentry: subdir)); |
164 | |
165 | /* we need to make sure the subdir is a directory */ |
166 | ASSERT(d_backing_inode(subdir)); |
167 | |
168 | if (!d_can_lookup(dentry: subdir)) { |
169 | pr_err("%s is not a directory\n" , dirname); |
170 | ret = -EIO; |
171 | goto check_error; |
172 | } |
173 | |
174 | ret = -EPERM; |
175 | if (!(d_backing_inode(upper: subdir)->i_opflags & IOP_XATTR) || |
176 | !d_backing_inode(upper: subdir)->i_op->lookup || |
177 | !d_backing_inode(upper: subdir)->i_op->mkdir || |
178 | !d_backing_inode(upper: subdir)->i_op->rename || |
179 | !d_backing_inode(upper: subdir)->i_op->rmdir || |
180 | !d_backing_inode(upper: subdir)->i_op->unlink) |
181 | goto check_error; |
182 | |
183 | _leave(" = [%lu]" , d_backing_inode(subdir)->i_ino); |
184 | return subdir; |
185 | |
186 | check_error: |
187 | cachefiles_put_directory(dir: subdir); |
188 | _leave(" = %d [check]" , ret); |
189 | return ERR_PTR(error: ret); |
190 | |
191 | mark_error: |
192 | inode_unlock(inode: d_inode(dentry: subdir)); |
193 | dput(subdir); |
194 | return ERR_PTR(error: -EBUSY); |
195 | |
196 | mkdir_error: |
197 | inode_unlock(inode: d_inode(dentry: dir)); |
198 | dput(subdir); |
199 | pr_err("mkdir %s failed with error %d\n" , dirname, ret); |
200 | return ERR_PTR(error: ret); |
201 | |
202 | lookup_error: |
203 | inode_unlock(inode: d_inode(dentry: dir)); |
204 | ret = PTR_ERR(ptr: subdir); |
205 | pr_err("Lookup %s failed with error %d\n" , dirname, ret); |
206 | return ERR_PTR(error: ret); |
207 | |
208 | nomem_d_alloc: |
209 | inode_unlock(inode: d_inode(dentry: dir)); |
210 | _leave(" = -ENOMEM" ); |
211 | return ERR_PTR(error: -ENOMEM); |
212 | } |
213 | |
214 | /* |
215 | * Put a subdirectory. |
216 | */ |
217 | void cachefiles_put_directory(struct dentry *dir) |
218 | { |
219 | if (dir) { |
220 | cachefiles_do_unmark_inode_in_use(NULL, inode: d_inode(dentry: dir)); |
221 | dput(dir); |
222 | } |
223 | } |
224 | |
225 | /* |
226 | * Remove a regular file from the cache. |
227 | */ |
228 | static int cachefiles_unlink(struct cachefiles_cache *cache, |
229 | struct cachefiles_object *object, |
230 | struct dentry *dir, struct dentry *dentry, |
231 | enum fscache_why_object_killed why) |
232 | { |
233 | struct path path = { |
234 | .mnt = cache->mnt, |
235 | .dentry = dir, |
236 | }; |
237 | int ret; |
238 | |
239 | trace_cachefiles_unlink(obj: object, ino: d_inode(dentry)->i_ino, why); |
240 | ret = security_path_unlink(dir: &path, dentry); |
241 | if (ret < 0) { |
242 | cachefiles_io_error(cache, "Unlink security error" ); |
243 | return ret; |
244 | } |
245 | |
246 | ret = cachefiles_inject_remove_error(); |
247 | if (ret == 0) { |
248 | ret = vfs_unlink(&nop_mnt_idmap, d_backing_inode(upper: dir), dentry, NULL); |
249 | if (ret == -EIO) |
250 | cachefiles_io_error(cache, "Unlink failed" ); |
251 | } |
252 | if (ret != 0) |
253 | trace_cachefiles_vfs_error(obj: object, backer: d_backing_inode(upper: dir), error: ret, |
254 | where: cachefiles_trace_unlink_error); |
255 | return ret; |
256 | } |
257 | |
258 | /* |
259 | * Delete an object representation from the cache |
260 | * - File backed objects are unlinked |
261 | * - Directory backed objects are stuffed into the graveyard for userspace to |
262 | * delete |
263 | */ |
264 | int cachefiles_bury_object(struct cachefiles_cache *cache, |
265 | struct cachefiles_object *object, |
266 | struct dentry *dir, |
267 | struct dentry *rep, |
268 | enum fscache_why_object_killed why) |
269 | { |
270 | struct dentry *grave, *trap; |
271 | struct path path, path_to_graveyard; |
272 | char nbuffer[8 + 8 + 1]; |
273 | int ret; |
274 | |
275 | _enter(",'%pd','%pd'" , dir, rep); |
276 | |
277 | if (rep->d_parent != dir) { |
278 | inode_unlock(inode: d_inode(dentry: dir)); |
279 | _leave(" = -ESTALE" ); |
280 | return -ESTALE; |
281 | } |
282 | |
283 | /* non-directories can just be unlinked */ |
284 | if (!d_is_dir(dentry: rep)) { |
285 | dget(dentry: rep); /* Stop the dentry being negated if it's only pinned |
286 | * by a file struct. |
287 | */ |
288 | ret = cachefiles_unlink(cache, object, dir, dentry: rep, why); |
289 | dput(rep); |
290 | |
291 | inode_unlock(inode: d_inode(dentry: dir)); |
292 | _leave(" = %d" , ret); |
293 | return ret; |
294 | } |
295 | |
296 | /* directories have to be moved to the graveyard */ |
297 | _debug("move stale object to graveyard" ); |
298 | inode_unlock(inode: d_inode(dentry: dir)); |
299 | |
300 | try_again: |
301 | /* first step is to make up a grave dentry in the graveyard */ |
302 | sprintf(buf: nbuffer, fmt: "%08x%08x" , |
303 | (uint32_t) ktime_get_real_seconds(), |
304 | (uint32_t) atomic_inc_return(v: &cache->gravecounter)); |
305 | |
306 | /* do the multiway lock magic */ |
307 | trap = lock_rename(cache->graveyard, dir); |
308 | |
309 | /* do some checks before getting the grave dentry */ |
310 | if (rep->d_parent != dir || IS_DEADDIR(d_inode(rep))) { |
311 | /* the entry was probably culled when we dropped the parent dir |
312 | * lock */ |
313 | unlock_rename(cache->graveyard, dir); |
314 | _leave(" = 0 [culled?]" ); |
315 | return 0; |
316 | } |
317 | |
318 | if (!d_can_lookup(dentry: cache->graveyard)) { |
319 | unlock_rename(cache->graveyard, dir); |
320 | cachefiles_io_error(cache, "Graveyard no longer a directory" ); |
321 | return -EIO; |
322 | } |
323 | |
324 | if (trap == rep) { |
325 | unlock_rename(cache->graveyard, dir); |
326 | cachefiles_io_error(cache, "May not make directory loop" ); |
327 | return -EIO; |
328 | } |
329 | |
330 | if (d_mountpoint(dentry: rep)) { |
331 | unlock_rename(cache->graveyard, dir); |
332 | cachefiles_io_error(cache, "Mountpoint in cache" ); |
333 | return -EIO; |
334 | } |
335 | |
336 | grave = lookup_one_len(nbuffer, cache->graveyard, strlen(nbuffer)); |
337 | if (IS_ERR(ptr: grave)) { |
338 | unlock_rename(cache->graveyard, dir); |
339 | trace_cachefiles_vfs_error(obj: object, backer: d_inode(dentry: cache->graveyard), |
340 | error: PTR_ERR(ptr: grave), |
341 | where: cachefiles_trace_lookup_error); |
342 | |
343 | if (PTR_ERR(ptr: grave) == -ENOMEM) { |
344 | _leave(" = -ENOMEM" ); |
345 | return -ENOMEM; |
346 | } |
347 | |
348 | cachefiles_io_error(cache, "Lookup error %ld" , PTR_ERR(grave)); |
349 | return -EIO; |
350 | } |
351 | |
352 | if (d_is_positive(dentry: grave)) { |
353 | unlock_rename(cache->graveyard, dir); |
354 | dput(grave); |
355 | grave = NULL; |
356 | cond_resched(); |
357 | goto try_again; |
358 | } |
359 | |
360 | if (d_mountpoint(dentry: grave)) { |
361 | unlock_rename(cache->graveyard, dir); |
362 | dput(grave); |
363 | cachefiles_io_error(cache, "Mountpoint in graveyard" ); |
364 | return -EIO; |
365 | } |
366 | |
367 | /* target should not be an ancestor of source */ |
368 | if (trap == grave) { |
369 | unlock_rename(cache->graveyard, dir); |
370 | dput(grave); |
371 | cachefiles_io_error(cache, "May not make directory loop" ); |
372 | return -EIO; |
373 | } |
374 | |
375 | /* attempt the rename */ |
376 | path.mnt = cache->mnt; |
377 | path.dentry = dir; |
378 | path_to_graveyard.mnt = cache->mnt; |
379 | path_to_graveyard.dentry = cache->graveyard; |
380 | ret = security_path_rename(old_dir: &path, old_dentry: rep, new_dir: &path_to_graveyard, new_dentry: grave, flags: 0); |
381 | if (ret < 0) { |
382 | cachefiles_io_error(cache, "Rename security error %d" , ret); |
383 | } else { |
384 | struct renamedata rd = { |
385 | .old_mnt_idmap = &nop_mnt_idmap, |
386 | .old_dir = d_inode(dentry: dir), |
387 | .old_dentry = rep, |
388 | .new_mnt_idmap = &nop_mnt_idmap, |
389 | .new_dir = d_inode(dentry: cache->graveyard), |
390 | .new_dentry = grave, |
391 | }; |
392 | trace_cachefiles_rename(obj: object, ino: d_inode(dentry: rep)->i_ino, why); |
393 | ret = cachefiles_inject_read_error(); |
394 | if (ret == 0) |
395 | ret = vfs_rename(&rd); |
396 | if (ret != 0) |
397 | trace_cachefiles_vfs_error(obj: object, backer: d_inode(dentry: dir), error: ret, |
398 | where: cachefiles_trace_rename_error); |
399 | if (ret != 0 && ret != -ENOMEM) |
400 | cachefiles_io_error(cache, |
401 | "Rename failed with error %d" , ret); |
402 | } |
403 | |
404 | __cachefiles_unmark_inode_in_use(object, inode: d_inode(dentry: rep)); |
405 | unlock_rename(cache->graveyard, dir); |
406 | dput(grave); |
407 | _leave(" = 0" ); |
408 | return 0; |
409 | } |
410 | |
411 | /* |
412 | * Delete a cache file. |
413 | */ |
414 | int cachefiles_delete_object(struct cachefiles_object *object, |
415 | enum fscache_why_object_killed why) |
416 | { |
417 | struct cachefiles_volume *volume = object->volume; |
418 | struct dentry *dentry = object->file->f_path.dentry; |
419 | struct dentry *fan = volume->fanout[(u8)object->cookie->key_hash]; |
420 | int ret; |
421 | |
422 | _enter(",OBJ%x{%pD}" , object->debug_id, object->file); |
423 | |
424 | /* Stop the dentry being negated if it's only pinned by a file struct. */ |
425 | dget(dentry); |
426 | |
427 | inode_lock_nested(inode: d_backing_inode(upper: fan), subclass: I_MUTEX_PARENT); |
428 | ret = cachefiles_unlink(cache: volume->cache, object, dir: fan, dentry, why); |
429 | inode_unlock(inode: d_backing_inode(upper: fan)); |
430 | dput(dentry); |
431 | return ret; |
432 | } |
433 | |
434 | /* |
435 | * Create a temporary file and leave it unattached and un-xattr'd until the |
436 | * time comes to discard the object from memory. |
437 | */ |
438 | struct file *cachefiles_create_tmpfile(struct cachefiles_object *object) |
439 | { |
440 | struct cachefiles_volume *volume = object->volume; |
441 | struct cachefiles_cache *cache = volume->cache; |
442 | const struct cred *saved_cred; |
443 | struct dentry *fan = volume->fanout[(u8)object->cookie->key_hash]; |
444 | struct file *file; |
445 | const struct path parentpath = { .mnt = cache->mnt, .dentry = fan }; |
446 | uint64_t ni_size; |
447 | long ret; |
448 | |
449 | |
450 | cachefiles_begin_secure(cache, saved_cred: &saved_cred); |
451 | |
452 | ret = cachefiles_inject_write_error(); |
453 | if (ret == 0) { |
454 | file = kernel_tmpfile_open(idmap: &nop_mnt_idmap, parentpath: &parentpath, |
455 | S_IFREG | 0600, |
456 | O_RDWR | O_LARGEFILE | O_DIRECT, |
457 | cred: cache->cache_cred); |
458 | ret = PTR_ERR_OR_ZERO(ptr: file); |
459 | } |
460 | if (ret) { |
461 | trace_cachefiles_vfs_error(obj: object, backer: d_inode(dentry: fan), error: ret, |
462 | where: cachefiles_trace_tmpfile_error); |
463 | if (ret == -EIO) |
464 | cachefiles_io_error_obj(object, "Failed to create tmpfile" ); |
465 | goto err; |
466 | } |
467 | |
468 | trace_cachefiles_tmpfile(obj: object, backer: file_inode(f: file)); |
469 | |
470 | /* This is a newly created file with no other possible user */ |
471 | if (!cachefiles_mark_inode_in_use(object, inode: file_inode(f: file))) |
472 | WARN_ON(1); |
473 | |
474 | ret = cachefiles_ondemand_init_object(object); |
475 | if (ret < 0) |
476 | goto err_unuse; |
477 | |
478 | ni_size = object->cookie->object_size; |
479 | ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); |
480 | |
481 | if (ni_size > 0) { |
482 | trace_cachefiles_trunc(obj: object, backer: file_inode(f: file), from: 0, to: ni_size, |
483 | why: cachefiles_trunc_expand_tmpfile); |
484 | ret = cachefiles_inject_write_error(); |
485 | if (ret == 0) |
486 | ret = vfs_truncate(&file->f_path, ni_size); |
487 | if (ret < 0) { |
488 | trace_cachefiles_vfs_error( |
489 | obj: object, backer: file_inode(f: file), error: ret, |
490 | where: cachefiles_trace_trunc_error); |
491 | goto err_unuse; |
492 | } |
493 | } |
494 | |
495 | ret = -EINVAL; |
496 | if (unlikely(!file->f_op->read_iter) || |
497 | unlikely(!file->f_op->write_iter)) { |
498 | fput(file); |
499 | pr_notice("Cache does not support read_iter and write_iter\n" ); |
500 | goto err_unuse; |
501 | } |
502 | out: |
503 | cachefiles_end_secure(cache, saved_cred); |
504 | return file; |
505 | |
506 | err_unuse: |
507 | cachefiles_do_unmark_inode_in_use(object, inode: file_inode(f: file)); |
508 | fput(file); |
509 | err: |
510 | file = ERR_PTR(error: ret); |
511 | goto out; |
512 | } |
513 | |
514 | /* |
515 | * Create a new file. |
516 | */ |
517 | static bool cachefiles_create_file(struct cachefiles_object *object) |
518 | { |
519 | struct file *file; |
520 | int ret; |
521 | |
522 | ret = cachefiles_has_space(cache: object->volume->cache, fnr: 1, bnr: 0, |
523 | reason: cachefiles_has_space_for_create); |
524 | if (ret < 0) |
525 | return false; |
526 | |
527 | file = cachefiles_create_tmpfile(object); |
528 | if (IS_ERR(ptr: file)) |
529 | return false; |
530 | |
531 | set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, addr: &object->cookie->flags); |
532 | set_bit(CACHEFILES_OBJECT_USING_TMPFILE, addr: &object->flags); |
533 | _debug("create -> %pD{ino=%lu}" , file, file_inode(file)->i_ino); |
534 | object->file = file; |
535 | return true; |
536 | } |
537 | |
538 | /* |
539 | * Open an existing file, checking its attributes and replacing it if it is |
540 | * stale. |
541 | */ |
542 | static bool cachefiles_open_file(struct cachefiles_object *object, |
543 | struct dentry *dentry) |
544 | { |
545 | struct cachefiles_cache *cache = object->volume->cache; |
546 | struct file *file; |
547 | struct path path; |
548 | int ret; |
549 | |
550 | _enter("%pd" , dentry); |
551 | |
552 | if (!cachefiles_mark_inode_in_use(object, inode: d_inode(dentry))) { |
553 | pr_notice("cachefiles: Inode already in use: %pd (B=%lx)\n" , |
554 | dentry, d_inode(dentry)->i_ino); |
555 | return false; |
556 | } |
557 | |
558 | /* We need to open a file interface onto a data file now as we can't do |
559 | * it on demand because writeback called from do_exit() sees |
560 | * current->fs == NULL - which breaks d_path() called from ext4 open. |
561 | */ |
562 | path.mnt = cache->mnt; |
563 | path.dentry = dentry; |
564 | file = kernel_file_open(path: &path, O_RDWR | O_LARGEFILE | O_DIRECT, |
565 | inode: d_backing_inode(upper: dentry), cred: cache->cache_cred); |
566 | if (IS_ERR(ptr: file)) { |
567 | trace_cachefiles_vfs_error(obj: object, backer: d_backing_inode(upper: dentry), |
568 | error: PTR_ERR(ptr: file), |
569 | where: cachefiles_trace_open_error); |
570 | goto error; |
571 | } |
572 | |
573 | if (unlikely(!file->f_op->read_iter) || |
574 | unlikely(!file->f_op->write_iter)) { |
575 | pr_notice("Cache does not support read_iter and write_iter\n" ); |
576 | goto error_fput; |
577 | } |
578 | _debug("file -> %pd positive" , dentry); |
579 | |
580 | ret = cachefiles_ondemand_init_object(object); |
581 | if (ret < 0) |
582 | goto error_fput; |
583 | |
584 | ret = cachefiles_check_auxdata(object, file); |
585 | if (ret < 0) |
586 | goto check_failed; |
587 | |
588 | clear_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, addr: &object->cookie->flags); |
589 | |
590 | object->file = file; |
591 | |
592 | /* Always update the atime on an object we've just looked up (this is |
593 | * used to keep track of culling, and atimes are only updated by read, |
594 | * write and readdir but not lookup or open). |
595 | */ |
596 | touch_atime(&file->f_path); |
597 | dput(dentry); |
598 | return true; |
599 | |
600 | check_failed: |
601 | fscache_cookie_lookup_negative(cookie: object->cookie); |
602 | cachefiles_unmark_inode_in_use(object, file); |
603 | fput(file); |
604 | dput(dentry); |
605 | if (ret == -ESTALE) |
606 | return cachefiles_create_file(object); |
607 | return false; |
608 | |
609 | error_fput: |
610 | fput(file); |
611 | error: |
612 | cachefiles_do_unmark_inode_in_use(object, inode: d_inode(dentry)); |
613 | dput(dentry); |
614 | return false; |
615 | } |
616 | |
617 | /* |
618 | * walk from the parent object to the child object through the backing |
619 | * filesystem, creating directories as we go |
620 | */ |
621 | bool cachefiles_look_up_object(struct cachefiles_object *object) |
622 | { |
623 | struct cachefiles_volume *volume = object->volume; |
624 | struct dentry *dentry, *fan = volume->fanout[(u8)object->cookie->key_hash]; |
625 | int ret; |
626 | |
627 | _enter("OBJ%x,%s," , object->debug_id, object->d_name); |
628 | |
629 | /* Look up path "cache/vol/fanout/file". */ |
630 | ret = cachefiles_inject_read_error(); |
631 | if (ret == 0) |
632 | dentry = lookup_positive_unlocked(object->d_name, fan, |
633 | object->d_name_len); |
634 | else |
635 | dentry = ERR_PTR(error: ret); |
636 | trace_cachefiles_lookup(obj: object, dir: fan, de: dentry); |
637 | if (IS_ERR(ptr: dentry)) { |
638 | if (dentry == ERR_PTR(error: -ENOENT)) |
639 | goto new_file; |
640 | if (dentry == ERR_PTR(error: -EIO)) |
641 | cachefiles_io_error_obj(object, "Lookup failed" ); |
642 | return false; |
643 | } |
644 | |
645 | if (!d_is_reg(dentry)) { |
646 | pr_err("%pd is not a file\n" , dentry); |
647 | inode_lock_nested(inode: d_inode(dentry: fan), subclass: I_MUTEX_PARENT); |
648 | ret = cachefiles_bury_object(cache: volume->cache, object, dir: fan, rep: dentry, |
649 | why: FSCACHE_OBJECT_IS_WEIRD); |
650 | dput(dentry); |
651 | if (ret < 0) |
652 | return false; |
653 | goto new_file; |
654 | } |
655 | |
656 | if (!cachefiles_open_file(object, dentry)) |
657 | return false; |
658 | |
659 | _leave(" = t [%lu]" , file_inode(object->file)->i_ino); |
660 | return true; |
661 | |
662 | new_file: |
663 | fscache_cookie_lookup_negative(cookie: object->cookie); |
664 | return cachefiles_create_file(object); |
665 | } |
666 | |
667 | /* |
668 | * Attempt to link a temporary file into its rightful place in the cache. |
669 | */ |
670 | bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache, |
671 | struct cachefiles_object *object) |
672 | { |
673 | struct cachefiles_volume *volume = object->volume; |
674 | struct dentry *dentry, *fan = volume->fanout[(u8)object->cookie->key_hash]; |
675 | bool success = false; |
676 | int ret; |
677 | |
678 | _enter(",%pD" , object->file); |
679 | |
680 | inode_lock_nested(inode: d_inode(dentry: fan), subclass: I_MUTEX_PARENT); |
681 | ret = cachefiles_inject_read_error(); |
682 | if (ret == 0) |
683 | dentry = lookup_one_len(object->d_name, fan, object->d_name_len); |
684 | else |
685 | dentry = ERR_PTR(error: ret); |
686 | if (IS_ERR(ptr: dentry)) { |
687 | trace_cachefiles_vfs_error(obj: object, backer: d_inode(dentry: fan), error: PTR_ERR(ptr: dentry), |
688 | where: cachefiles_trace_lookup_error); |
689 | _debug("lookup fail %ld" , PTR_ERR(dentry)); |
690 | goto out_unlock; |
691 | } |
692 | |
693 | if (!d_is_negative(dentry)) { |
694 | if (d_backing_inode(upper: dentry) == file_inode(f: object->file)) { |
695 | success = true; |
696 | goto out_dput; |
697 | } |
698 | |
699 | ret = cachefiles_unlink(cache: volume->cache, object, dir: fan, dentry, |
700 | why: FSCACHE_OBJECT_IS_STALE); |
701 | if (ret < 0) |
702 | goto out_dput; |
703 | |
704 | dput(dentry); |
705 | ret = cachefiles_inject_read_error(); |
706 | if (ret == 0) |
707 | dentry = lookup_one_len(object->d_name, fan, object->d_name_len); |
708 | else |
709 | dentry = ERR_PTR(error: ret); |
710 | if (IS_ERR(ptr: dentry)) { |
711 | trace_cachefiles_vfs_error(obj: object, backer: d_inode(dentry: fan), error: PTR_ERR(ptr: dentry), |
712 | where: cachefiles_trace_lookup_error); |
713 | _debug("lookup fail %ld" , PTR_ERR(dentry)); |
714 | goto out_unlock; |
715 | } |
716 | } |
717 | |
718 | ret = cachefiles_inject_read_error(); |
719 | if (ret == 0) |
720 | ret = vfs_link(object->file->f_path.dentry, &nop_mnt_idmap, |
721 | d_inode(dentry: fan), dentry, NULL); |
722 | if (ret < 0) { |
723 | trace_cachefiles_vfs_error(obj: object, backer: d_inode(dentry: fan), error: ret, |
724 | where: cachefiles_trace_link_error); |
725 | _debug("link fail %d" , ret); |
726 | } else { |
727 | trace_cachefiles_link(obj: object, backer: file_inode(f: object->file)); |
728 | spin_lock(lock: &object->lock); |
729 | /* TODO: Do we want to switch the file pointer to the new dentry? */ |
730 | clear_bit(CACHEFILES_OBJECT_USING_TMPFILE, addr: &object->flags); |
731 | spin_unlock(lock: &object->lock); |
732 | success = true; |
733 | } |
734 | |
735 | out_dput: |
736 | dput(dentry); |
737 | out_unlock: |
738 | inode_unlock(inode: d_inode(dentry: fan)); |
739 | _leave(" = %u" , success); |
740 | return success; |
741 | } |
742 | |
743 | /* |
744 | * Look up an inode to be checked or culled. Return -EBUSY if the inode is |
745 | * marked in use. |
746 | */ |
747 | static struct dentry *cachefiles_lookup_for_cull(struct cachefiles_cache *cache, |
748 | struct dentry *dir, |
749 | char *filename) |
750 | { |
751 | struct dentry *victim; |
752 | int ret = -ENOENT; |
753 | |
754 | inode_lock_nested(inode: d_inode(dentry: dir), subclass: I_MUTEX_PARENT); |
755 | |
756 | victim = lookup_one_len(filename, dir, strlen(filename)); |
757 | if (IS_ERR(ptr: victim)) |
758 | goto lookup_error; |
759 | if (d_is_negative(dentry: victim)) |
760 | goto lookup_put; |
761 | if (d_inode(dentry: victim)->i_flags & S_KERNEL_FILE) |
762 | goto lookup_busy; |
763 | return victim; |
764 | |
765 | lookup_busy: |
766 | ret = -EBUSY; |
767 | lookup_put: |
768 | inode_unlock(inode: d_inode(dentry: dir)); |
769 | dput(victim); |
770 | return ERR_PTR(error: ret); |
771 | |
772 | lookup_error: |
773 | inode_unlock(inode: d_inode(dentry: dir)); |
774 | ret = PTR_ERR(ptr: victim); |
775 | if (ret == -ENOENT) |
776 | return ERR_PTR(error: -ESTALE); /* Probably got retired by the netfs */ |
777 | |
778 | if (ret == -EIO) { |
779 | cachefiles_io_error(cache, "Lookup failed" ); |
780 | } else if (ret != -ENOMEM) { |
781 | pr_err("Internal error: %d\n" , ret); |
782 | ret = -EIO; |
783 | } |
784 | |
785 | return ERR_PTR(error: ret); |
786 | } |
787 | |
788 | /* |
789 | * Cull an object if it's not in use |
790 | * - called only by cache manager daemon |
791 | */ |
792 | int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, |
793 | char *filename) |
794 | { |
795 | struct dentry *victim; |
796 | struct inode *inode; |
797 | int ret; |
798 | |
799 | _enter(",%pd/,%s" , dir, filename); |
800 | |
801 | victim = cachefiles_lookup_for_cull(cache, dir, filename); |
802 | if (IS_ERR(ptr: victim)) |
803 | return PTR_ERR(ptr: victim); |
804 | |
805 | /* check to see if someone is using this object */ |
806 | inode = d_inode(dentry: victim); |
807 | inode_lock(inode); |
808 | if (inode->i_flags & S_KERNEL_FILE) { |
809 | ret = -EBUSY; |
810 | } else { |
811 | /* Stop the cache from picking it back up */ |
812 | inode->i_flags |= S_KERNEL_FILE; |
813 | ret = 0; |
814 | } |
815 | inode_unlock(inode); |
816 | if (ret < 0) |
817 | goto error_unlock; |
818 | |
819 | ret = cachefiles_bury_object(cache, NULL, dir, rep: victim, |
820 | why: FSCACHE_OBJECT_WAS_CULLED); |
821 | if (ret < 0) |
822 | goto error; |
823 | |
824 | fscache_count_culled(); |
825 | dput(victim); |
826 | _leave(" = 0" ); |
827 | return 0; |
828 | |
829 | error_unlock: |
830 | inode_unlock(inode: d_inode(dentry: dir)); |
831 | error: |
832 | dput(victim); |
833 | if (ret == -ENOENT) |
834 | return -ESTALE; /* Probably got retired by the netfs */ |
835 | |
836 | if (ret != -ENOMEM) { |
837 | pr_err("Internal error: %d\n" , ret); |
838 | ret = -EIO; |
839 | } |
840 | |
841 | _leave(" = %d" , ret); |
842 | return ret; |
843 | } |
844 | |
845 | /* |
846 | * Find out if an object is in use or not |
847 | * - called only by cache manager daemon |
848 | * - returns -EBUSY or 0 to indicate whether an object is in use or not |
849 | */ |
850 | int cachefiles_check_in_use(struct cachefiles_cache *cache, struct dentry *dir, |
851 | char *filename) |
852 | { |
853 | struct dentry *victim; |
854 | int ret = 0; |
855 | |
856 | victim = cachefiles_lookup_for_cull(cache, dir, filename); |
857 | if (IS_ERR(ptr: victim)) |
858 | return PTR_ERR(ptr: victim); |
859 | |
860 | inode_unlock(inode: d_inode(dentry: dir)); |
861 | dput(victim); |
862 | return ret; |
863 | } |
864 | |