Skip to content

Commit 1f08c92

Browse files
committedJan 7, 2022
cachefiles: Implement backing file wrangling
Implement the wrangling of backing files, including the following pieces: (1) Lookup and creation of a file on disk, using a tmpfile if the file isn't yet present. The file is then opened, sized for DIO and the file handle is attached to the cachefiles_object struct. The inode is marked to indicate that it's in use by a kernel service. (2) Invalidation of an object, creating a tmpfile and switching the file pointer in the cachefiles object. (3) Committing a file to disk, including setting the coherency xattr on it and, if necessary, creating a hard link to it. Note that this would be a good place to use Omar Sandoval's vfs_link() with AT_LINK_REPLACE[1] as I may have to unlink an old file before I can link a tmpfile into place. (4) Withdrawal of open objects when a cache is being withdrawn or a cookie is relinquished. This involves committing or discarding the file. Changes ======= ver #2: - Fix logging of wrong error[1]. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/20211203094950.GA2480@kili/ [1] Link: https://lore.kernel.org/r/163819644097.215744.4505389616742411239.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/163906949512.143852.14222856795032602080.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/163967158526.1823006.17482695321424642675.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/164021557060.640689.16373541458119269871.stgit@warthog.procyon.org.uk/ # v4
1 parent 07a90e9 commit 1f08c92

File tree

5 files changed

+619
-1
lines changed

5 files changed

+619
-1
lines changed
 

‎fs/cachefiles/cache.c

+31-1
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,36 @@ int cachefiles_has_space(struct cachefiles_cache *cache,
262262
return ret;
263263
}
264264

265+
/*
266+
* Mark all the objects as being out of service and queue them all for cleanup.
267+
*/
268+
static void cachefiles_withdraw_objects(struct cachefiles_cache *cache)
269+
{
270+
struct cachefiles_object *object;
271+
unsigned int count = 0;
272+
273+
_enter("");
274+
275+
spin_lock(&cache->object_list_lock);
276+
277+
while (!list_empty(&cache->object_list)) {
278+
object = list_first_entry(&cache->object_list,
279+
struct cachefiles_object, cache_link);
280+
cachefiles_see_object(object, cachefiles_obj_see_withdrawal);
281+
list_del_init(&object->cache_link);
282+
fscache_withdraw_cookie(object->cookie);
283+
count++;
284+
if ((count & 63) == 0) {
285+
spin_unlock(&cache->object_list_lock);
286+
cond_resched();
287+
spin_lock(&cache->object_list_lock);
288+
}
289+
}
290+
291+
spin_unlock(&cache->object_list_lock);
292+
_leave(" [%u objs]", count);
293+
}
294+
265295
/*
266296
* Withdraw volumes.
267297
*/
@@ -326,7 +356,7 @@ void cachefiles_withdraw_cache(struct cachefiles_cache *cache)
326356
/* we now have to destroy all the active objects pertaining to this
327357
* cache - which we do by passing them off to thread pool to be
328358
* disposed of */
329-
// PLACEHOLDER: Withdraw objects
359+
cachefiles_withdraw_objects(cache);
330360
fscache_wait_for_objects(fscache);
331361

332362
cachefiles_withdraw_volumes(cache);

‎fs/cachefiles/daemon.c

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ static int cachefiles_daemon_open(struct inode *inode, struct file *file)
106106
mutex_init(&cache->daemon_mutex);
107107
init_waitqueue_head(&cache->daemon_pollwq);
108108
INIT_LIST_HEAD(&cache->volumes);
109+
INIT_LIST_HEAD(&cache->object_list);
109110
spin_lock_init(&cache->object_list_lock);
110111

111112
/* set default caching limits

‎fs/cachefiles/interface.c

+260
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,268 @@ void cachefiles_put_object(struct cachefiles_object *object,
9999
_leave("");
100100
}
101101

102+
/*
103+
* Adjust the size of a cache file if necessary to match the DIO size. We keep
104+
* the EOF marker a multiple of DIO blocks so that we don't fall back to doing
105+
* non-DIO for a partial block straddling the EOF, but we also have to be
106+
* careful of someone expanding the file and accidentally accreting the
107+
* padding.
108+
*/
109+
static int cachefiles_adjust_size(struct cachefiles_object *object)
110+
{
111+
struct iattr newattrs;
112+
struct file *file = object->file;
113+
uint64_t ni_size;
114+
loff_t oi_size;
115+
int ret;
116+
117+
ni_size = object->cookie->object_size;
118+
ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE);
119+
120+
_enter("{OBJ%x},[%llu]",
121+
object->debug_id, (unsigned long long) ni_size);
122+
123+
if (!file)
124+
return -ENOBUFS;
125+
126+
oi_size = i_size_read(file_inode(file));
127+
if (oi_size == ni_size)
128+
return 0;
129+
130+
inode_lock(file_inode(file));
131+
132+
/* if there's an extension to a partial page at the end of the backing
133+
* file, we need to discard the partial page so that we pick up new
134+
* data after it */
135+
if (oi_size & ~PAGE_MASK && ni_size > oi_size) {
136+
_debug("discard tail %llx", oi_size);
137+
newattrs.ia_valid = ATTR_SIZE;
138+
newattrs.ia_size = oi_size & PAGE_MASK;
139+
ret = cachefiles_inject_remove_error();
140+
if (ret == 0)
141+
ret = notify_change(&init_user_ns, file->f_path.dentry,
142+
&newattrs, NULL);
143+
if (ret < 0)
144+
goto truncate_failed;
145+
}
146+
147+
newattrs.ia_valid = ATTR_SIZE;
148+
newattrs.ia_size = ni_size;
149+
ret = cachefiles_inject_write_error();
150+
if (ret == 0)
151+
ret = notify_change(&init_user_ns, file->f_path.dentry,
152+
&newattrs, NULL);
153+
154+
truncate_failed:
155+
inode_unlock(file_inode(file));
156+
157+
if (ret < 0)
158+
trace_cachefiles_io_error(NULL, file_inode(file), ret,
159+
cachefiles_trace_notify_change_error);
160+
if (ret == -EIO) {
161+
cachefiles_io_error_obj(object, "Size set failed");
162+
ret = -ENOBUFS;
163+
}
164+
165+
_leave(" = %d", ret);
166+
return ret;
167+
}
168+
169+
/*
170+
* Attempt to look up the nominated node in this cache
171+
*/
172+
static bool cachefiles_lookup_cookie(struct fscache_cookie *cookie)
173+
{
174+
struct cachefiles_object *object;
175+
struct cachefiles_cache *cache = cookie->volume->cache->cache_priv;
176+
const struct cred *saved_cred;
177+
bool success;
178+
179+
object = cachefiles_alloc_object(cookie);
180+
if (!object)
181+
goto fail;
182+
183+
_enter("{OBJ%x}", object->debug_id);
184+
185+
if (!cachefiles_cook_key(object))
186+
goto fail_put;
187+
188+
cookie->cache_priv = object;
189+
190+
cachefiles_begin_secure(cache, &saved_cred);
191+
192+
success = cachefiles_look_up_object(object);
193+
if (!success)
194+
goto fail_withdraw;
195+
196+
cachefiles_see_object(object, cachefiles_obj_see_lookup_cookie);
197+
198+
spin_lock(&cache->object_list_lock);
199+
list_add(&object->cache_link, &cache->object_list);
200+
spin_unlock(&cache->object_list_lock);
201+
cachefiles_adjust_size(object);
202+
203+
cachefiles_end_secure(cache, saved_cred);
204+
_leave(" = t");
205+
return true;
206+
207+
fail_withdraw:
208+
cachefiles_end_secure(cache, saved_cred);
209+
cachefiles_see_object(object, cachefiles_obj_see_lookup_failed);
210+
fscache_caching_failed(cookie);
211+
_debug("failed c=%08x o=%08x", cookie->debug_id, object->debug_id);
212+
/* The caller holds an access count on the cookie, so we need them to
213+
* drop it before we can withdraw the object.
214+
*/
215+
return false;
216+
217+
fail_put:
218+
cachefiles_put_object(object, cachefiles_obj_put_alloc_fail);
219+
fail:
220+
return false;
221+
}
222+
223+
/*
224+
* Commit changes to the object as we drop it.
225+
*/
226+
static void cachefiles_commit_object(struct cachefiles_object *object,
227+
struct cachefiles_cache *cache)
228+
{
229+
bool update = false;
230+
231+
if (test_and_clear_bit(FSCACHE_COOKIE_LOCAL_WRITE, &object->cookie->flags))
232+
update = true;
233+
if (test_and_clear_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &object->cookie->flags))
234+
update = true;
235+
if (update)
236+
cachefiles_set_object_xattr(object);
237+
238+
if (test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags))
239+
cachefiles_commit_tmpfile(cache, object);
240+
}
241+
242+
/*
243+
* Finalise and object and close the VFS structs that we have.
244+
*/
245+
static void cachefiles_clean_up_object(struct cachefiles_object *object,
246+
struct cachefiles_cache *cache)
247+
{
248+
if (test_bit(FSCACHE_COOKIE_RETIRED, &object->cookie->flags)) {
249+
if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) {
250+
cachefiles_see_object(object, cachefiles_obj_see_clean_delete);
251+
_debug("- inval object OBJ%x", object->debug_id);
252+
cachefiles_delete_object(object, FSCACHE_OBJECT_WAS_RETIRED);
253+
} else {
254+
cachefiles_see_object(object, cachefiles_obj_see_clean_drop_tmp);
255+
_debug("- inval object OBJ%x tmpfile", object->debug_id);
256+
}
257+
} else {
258+
cachefiles_see_object(object, cachefiles_obj_see_clean_commit);
259+
cachefiles_commit_object(object, cache);
260+
}
261+
262+
cachefiles_unmark_inode_in_use(object, object->file);
263+
if (object->file) {
264+
fput(object->file);
265+
object->file = NULL;
266+
}
267+
}
268+
269+
/*
270+
* Withdraw caching for a cookie.
271+
*/
272+
static void cachefiles_withdraw_cookie(struct fscache_cookie *cookie)
273+
{
274+
struct cachefiles_object *object = cookie->cache_priv;
275+
struct cachefiles_cache *cache = object->volume->cache;
276+
const struct cred *saved_cred;
277+
278+
_enter("o=%x", object->debug_id);
279+
cachefiles_see_object(object, cachefiles_obj_see_withdraw_cookie);
280+
281+
if (!list_empty(&object->cache_link)) {
282+
spin_lock(&cache->object_list_lock);
283+
cachefiles_see_object(object, cachefiles_obj_see_withdrawal);
284+
list_del_init(&object->cache_link);
285+
spin_unlock(&cache->object_list_lock);
286+
}
287+
288+
if (object->file) {
289+
cachefiles_begin_secure(cache, &saved_cred);
290+
cachefiles_clean_up_object(object, cache);
291+
cachefiles_end_secure(cache, saved_cred);
292+
}
293+
294+
cookie->cache_priv = NULL;
295+
cachefiles_put_object(object, cachefiles_obj_put_detach);
296+
}
297+
298+
/*
299+
* Invalidate the storage associated with a cookie.
300+
*/
301+
static bool cachefiles_invalidate_cookie(struct fscache_cookie *cookie)
302+
{
303+
struct cachefiles_object *object = cookie->cache_priv;
304+
struct file *new_file, *old_file;
305+
bool old_tmpfile;
306+
307+
_enter("o=%x,[%llu]", object->debug_id, object->cookie->object_size);
308+
309+
old_tmpfile = test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags);
310+
311+
if (!object->file) {
312+
fscache_resume_after_invalidation(cookie);
313+
_leave(" = t [light]");
314+
return true;
315+
}
316+
317+
new_file = cachefiles_create_tmpfile(object);
318+
if (IS_ERR(new_file))
319+
goto failed;
320+
321+
/* Substitute the VFS target */
322+
_debug("sub");
323+
spin_lock(&object->lock);
324+
325+
old_file = object->file;
326+
object->file = new_file;
327+
object->content_info = CACHEFILES_CONTENT_NO_DATA;
328+
set_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags);
329+
set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &object->cookie->flags);
330+
331+
spin_unlock(&object->lock);
332+
_debug("subbed");
333+
334+
/* Allow I/O to take place again */
335+
fscache_resume_after_invalidation(cookie);
336+
337+
if (old_file) {
338+
if (!old_tmpfile) {
339+
struct cachefiles_volume *volume = object->volume;
340+
struct dentry *fan = volume->fanout[(u8)cookie->key_hash];
341+
342+
inode_lock_nested(d_inode(fan), I_MUTEX_PARENT);
343+
cachefiles_bury_object(volume->cache, object, fan,
344+
old_file->f_path.dentry,
345+
FSCACHE_OBJECT_INVALIDATED);
346+
}
347+
fput(old_file);
348+
}
349+
350+
_leave(" = t");
351+
return true;
352+
353+
failed:
354+
_leave(" = f");
355+
return false;
356+
}
357+
102358
const struct fscache_cache_ops cachefiles_cache_ops = {
103359
.name = "cachefiles",
104360
.acquire_volume = cachefiles_acquire_volume,
105361
.free_volume = cachefiles_free_volume,
362+
.lookup_cookie = cachefiles_lookup_cookie,
363+
.withdraw_cookie = cachefiles_withdraw_cookie,
364+
.invalidate_cookie = cachefiles_invalidate_cookie,
365+
.prepare_to_write = cachefiles_prepare_to_write,
106366
};

‎fs/cachefiles/internal.h

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <linux/cred.h>
1717
#include <linux/security.h>
1818

19+
#define CACHEFILES_DIO_BLOCK_SIZE 4096
20+
1921
struct cachefiles_cache;
2022
struct cachefiles_object;
2123

@@ -68,6 +70,7 @@ struct cachefiles_cache {
6870
struct dentry *graveyard; /* directory into which dead objects go */
6971
struct file *cachefilesd; /* manager daemon handle */
7072
struct list_head volumes; /* List of volume objects */
73+
struct list_head object_list; /* List of active objects */
7174
spinlock_t object_list_lock; /* Lock for volumes and object_list */
7275
const struct cred *cache_cred; /* security override for accessing cache */
7376
struct mutex daemon_mutex; /* command serialisation mutex */
@@ -194,6 +197,9 @@ extern int cachefiles_bury_object(struct cachefiles_cache *cache,
194197
struct dentry *dir,
195198
struct dentry *rep,
196199
enum fscache_why_object_killed why);
200+
extern int cachefiles_delete_object(struct cachefiles_object *object,
201+
enum fscache_why_object_killed why);
202+
extern bool cachefiles_look_up_object(struct cachefiles_object *object);
197203
extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
198204
struct dentry *dir,
199205
const char *name,
@@ -205,6 +211,9 @@ extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
205211

206212
extern int cachefiles_check_in_use(struct cachefiles_cache *cache,
207213
struct dentry *dir, char *filename);
214+
extern struct file *cachefiles_create_tmpfile(struct cachefiles_object *object);
215+
extern bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
216+
struct cachefiles_object *object);
208217

209218
/*
210219
* security.c

‎fs/cachefiles/namei.c

+318
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,324 @@ int cachefiles_bury_object(struct cachefiles_cache *cache,
404404
return 0;
405405
}
406406

407+
/*
408+
* Delete a cache file.
409+
*/
410+
int cachefiles_delete_object(struct cachefiles_object *object,
411+
enum fscache_why_object_killed why)
412+
{
413+
struct cachefiles_volume *volume = object->volume;
414+
struct dentry *dentry = object->file->f_path.dentry;
415+
struct dentry *fan = volume->fanout[(u8)object->cookie->key_hash];
416+
int ret;
417+
418+
_enter(",OBJ%x{%pD}", object->debug_id, object->file);
419+
420+
/* Stop the dentry being negated if it's only pinned by a file struct. */
421+
dget(dentry);
422+
423+
inode_lock_nested(d_backing_inode(fan), I_MUTEX_PARENT);
424+
ret = cachefiles_unlink(volume->cache, object, fan, dentry, why);
425+
inode_unlock(d_backing_inode(fan));
426+
dput(dentry);
427+
return ret;
428+
}
429+
430+
/*
431+
* Create a temporary file and leave it unattached and un-xattr'd until the
432+
* time comes to discard the object from memory.
433+
*/
434+
struct file *cachefiles_create_tmpfile(struct cachefiles_object *object)
435+
{
436+
struct cachefiles_volume *volume = object->volume;
437+
struct cachefiles_cache *cache = volume->cache;
438+
const struct cred *saved_cred;
439+
struct dentry *fan = volume->fanout[(u8)object->cookie->key_hash];
440+
struct file *file;
441+
struct path path;
442+
uint64_t ni_size = object->cookie->object_size;
443+
long ret;
444+
445+
ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE);
446+
447+
cachefiles_begin_secure(cache, &saved_cred);
448+
449+
path.mnt = cache->mnt;
450+
ret = cachefiles_inject_write_error();
451+
if (ret == 0)
452+
path.dentry = vfs_tmpfile(&init_user_ns, fan, S_IFREG, O_RDWR);
453+
else
454+
path.dentry = ERR_PTR(ret);
455+
if (IS_ERR(path.dentry)) {
456+
trace_cachefiles_vfs_error(object, d_inode(fan), PTR_ERR(path.dentry),
457+
cachefiles_trace_tmpfile_error);
458+
if (PTR_ERR(path.dentry) == -EIO)
459+
cachefiles_io_error_obj(object, "Failed to create tmpfile");
460+
file = ERR_CAST(path.dentry);
461+
goto out;
462+
}
463+
464+
trace_cachefiles_tmpfile(object, d_backing_inode(path.dentry));
465+
466+
if (!cachefiles_mark_inode_in_use(object, path.dentry)) {
467+
file = ERR_PTR(-EBUSY);
468+
goto out_dput;
469+
}
470+
471+
if (ni_size > 0) {
472+
trace_cachefiles_trunc(object, d_backing_inode(path.dentry), 0, ni_size,
473+
cachefiles_trunc_expand_tmpfile);
474+
ret = cachefiles_inject_write_error();
475+
if (ret == 0)
476+
ret = vfs_truncate(&path, ni_size);
477+
if (ret < 0) {
478+
trace_cachefiles_vfs_error(
479+
object, d_backing_inode(path.dentry), ret,
480+
cachefiles_trace_trunc_error);
481+
file = ERR_PTR(ret);
482+
goto out_dput;
483+
}
484+
}
485+
486+
file = open_with_fake_path(&path, O_RDWR | O_LARGEFILE | O_DIRECT,
487+
d_backing_inode(path.dentry), cache->cache_cred);
488+
if (IS_ERR(file)) {
489+
trace_cachefiles_vfs_error(object, d_backing_inode(path.dentry),
490+
PTR_ERR(file),
491+
cachefiles_trace_open_error);
492+
goto out_dput;
493+
}
494+
if (unlikely(!file->f_op->read_iter) ||
495+
unlikely(!file->f_op->write_iter)) {
496+
fput(file);
497+
pr_notice("Cache does not support read_iter and write_iter\n");
498+
file = ERR_PTR(-EINVAL);
499+
}
500+
501+
out_dput:
502+
dput(path.dentry);
503+
out:
504+
cachefiles_end_secure(cache, saved_cred);
505+
return file;
506+
}
507+
508+
/*
509+
* Create a new file.
510+
*/
511+
static bool cachefiles_create_file(struct cachefiles_object *object)
512+
{
513+
struct file *file;
514+
int ret;
515+
516+
ret = cachefiles_has_space(object->volume->cache, 1, 0);
517+
if (ret < 0)
518+
return false;
519+
520+
file = cachefiles_create_tmpfile(object);
521+
if (IS_ERR(file))
522+
return false;
523+
524+
set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &object->cookie->flags);
525+
set_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags);
526+
_debug("create -> %pD{ino=%lu}", file, file_inode(file)->i_ino);
527+
object->file = file;
528+
return true;
529+
}
530+
531+
/*
532+
* Open an existing file, checking its attributes and replacing it if it is
533+
* stale.
534+
*/
535+
static bool cachefiles_open_file(struct cachefiles_object *object,
536+
struct dentry *dentry)
537+
{
538+
struct cachefiles_cache *cache = object->volume->cache;
539+
struct file *file;
540+
struct path path;
541+
int ret;
542+
543+
_enter("%pd", dentry);
544+
545+
if (!cachefiles_mark_inode_in_use(object, dentry))
546+
return false;
547+
548+
/* We need to open a file interface onto a data file now as we can't do
549+
* it on demand because writeback called from do_exit() sees
550+
* current->fs == NULL - which breaks d_path() called from ext4 open.
551+
*/
552+
path.mnt = cache->mnt;
553+
path.dentry = dentry;
554+
file = open_with_fake_path(&path, O_RDWR | O_LARGEFILE | O_DIRECT,
555+
d_backing_inode(dentry), cache->cache_cred);
556+
if (IS_ERR(file)) {
557+
trace_cachefiles_vfs_error(object, d_backing_inode(dentry),
558+
PTR_ERR(file),
559+
cachefiles_trace_open_error);
560+
goto error;
561+
}
562+
563+
if (unlikely(!file->f_op->read_iter) ||
564+
unlikely(!file->f_op->write_iter)) {
565+
pr_notice("Cache does not support read_iter and write_iter\n");
566+
goto error_fput;
567+
}
568+
_debug("file -> %pd positive", dentry);
569+
570+
ret = cachefiles_check_auxdata(object, file);
571+
if (ret < 0)
572+
goto check_failed;
573+
574+
object->file = file;
575+
576+
/* Always update the atime on an object we've just looked up (this is
577+
* used to keep track of culling, and atimes are only updated by read,
578+
* write and readdir but not lookup or open).
579+
*/
580+
touch_atime(&file->f_path);
581+
dput(dentry);
582+
return true;
583+
584+
check_failed:
585+
fscache_cookie_lookup_negative(object->cookie);
586+
cachefiles_unmark_inode_in_use(object, file);
587+
if (ret == -ESTALE) {
588+
fput(file);
589+
dput(dentry);
590+
return cachefiles_create_file(object);
591+
}
592+
error_fput:
593+
fput(file);
594+
error:
595+
dput(dentry);
596+
return false;
597+
}
598+
599+
/*
600+
* walk from the parent object to the child object through the backing
601+
* filesystem, creating directories as we go
602+
*/
603+
bool cachefiles_look_up_object(struct cachefiles_object *object)
604+
{
605+
struct cachefiles_volume *volume = object->volume;
606+
struct dentry *dentry, *fan = volume->fanout[(u8)object->cookie->key_hash];
607+
int ret;
608+
609+
_enter("OBJ%x,%s,", object->debug_id, object->d_name);
610+
611+
/* Look up path "cache/vol/fanout/file". */
612+
ret = cachefiles_inject_read_error();
613+
if (ret == 0)
614+
dentry = lookup_positive_unlocked(object->d_name, fan,
615+
object->d_name_len);
616+
else
617+
dentry = ERR_PTR(ret);
618+
trace_cachefiles_lookup(object, dentry);
619+
if (IS_ERR(dentry)) {
620+
if (dentry == ERR_PTR(-ENOENT))
621+
goto new_file;
622+
if (dentry == ERR_PTR(-EIO))
623+
cachefiles_io_error_obj(object, "Lookup failed");
624+
return false;
625+
}
626+
627+
if (!d_is_reg(dentry)) {
628+
pr_err("%pd is not a file\n", dentry);
629+
inode_lock_nested(d_inode(fan), I_MUTEX_PARENT);
630+
ret = cachefiles_bury_object(volume->cache, object, fan, dentry,
631+
FSCACHE_OBJECT_IS_WEIRD);
632+
dput(dentry);
633+
if (ret < 0)
634+
return false;
635+
goto new_file;
636+
}
637+
638+
if (!cachefiles_open_file(object, dentry))
639+
return false;
640+
641+
_leave(" = t [%lu]", file_inode(object->file)->i_ino);
642+
return true;
643+
644+
new_file:
645+
fscache_cookie_lookup_negative(object->cookie);
646+
return cachefiles_create_file(object);
647+
}
648+
649+
/*
650+
* Attempt to link a temporary file into its rightful place in the cache.
651+
*/
652+
bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
653+
struct cachefiles_object *object)
654+
{
655+
struct cachefiles_volume *volume = object->volume;
656+
struct dentry *dentry, *fan = volume->fanout[(u8)object->cookie->key_hash];
657+
bool success = false;
658+
int ret;
659+
660+
_enter(",%pD", object->file);
661+
662+
inode_lock_nested(d_inode(fan), I_MUTEX_PARENT);
663+
ret = cachefiles_inject_read_error();
664+
if (ret == 0)
665+
dentry = lookup_one_len(object->d_name, fan, object->d_name_len);
666+
else
667+
dentry = ERR_PTR(ret);
668+
if (IS_ERR(dentry)) {
669+
trace_cachefiles_vfs_error(object, d_inode(fan), PTR_ERR(dentry),
670+
cachefiles_trace_lookup_error);
671+
_debug("lookup fail %ld", PTR_ERR(dentry));
672+
goto out_unlock;
673+
}
674+
675+
if (!d_is_negative(dentry)) {
676+
if (d_backing_inode(dentry) == file_inode(object->file)) {
677+
success = true;
678+
goto out_dput;
679+
}
680+
681+
ret = cachefiles_unlink(volume->cache, object, fan, dentry,
682+
FSCACHE_OBJECT_IS_STALE);
683+
if (ret < 0)
684+
goto out_dput;
685+
686+
dput(dentry);
687+
ret = cachefiles_inject_read_error();
688+
if (ret == 0)
689+
dentry = lookup_one_len(object->d_name, fan, object->d_name_len);
690+
else
691+
dentry = ERR_PTR(ret);
692+
if (IS_ERR(dentry)) {
693+
trace_cachefiles_vfs_error(object, d_inode(fan), PTR_ERR(dentry),
694+
cachefiles_trace_lookup_error);
695+
_debug("lookup fail %ld", PTR_ERR(dentry));
696+
goto out_unlock;
697+
}
698+
}
699+
700+
ret = cachefiles_inject_read_error();
701+
if (ret == 0)
702+
ret = vfs_link(object->file->f_path.dentry, &init_user_ns,
703+
d_inode(fan), dentry, NULL);
704+
if (ret < 0) {
705+
trace_cachefiles_vfs_error(object, d_inode(fan), ret,
706+
cachefiles_trace_link_error);
707+
_debug("link fail %d", ret);
708+
} else {
709+
trace_cachefiles_link(object, file_inode(object->file));
710+
spin_lock(&object->lock);
711+
/* TODO: Do we want to switch the file pointer to the new dentry? */
712+
clear_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags);
713+
spin_unlock(&object->lock);
714+
success = true;
715+
}
716+
717+
out_dput:
718+
dput(dentry);
719+
out_unlock:
720+
inode_unlock(d_inode(fan));
721+
_leave(" = %u", success);
722+
return success;
723+
}
724+
407725
/*
408726
* Look up an inode to be checked or culled. Return -EBUSY if the inode is
409727
* marked in use.

0 commit comments

Comments
 (0)
Please sign in to comment.