diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile index cb7a6bcf51eb..16d811f1a2fa 100644 --- a/fs/cachefiles/Makefile +++ b/fs/cachefiles/Makefile @@ -7,6 +7,7 @@ cachefiles-y := \ cache.o \ daemon.o \ interface.o \ + io.o \ key.o \ main.o \ namei.o \ diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index e47c52c34071..ad9d311413ff 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -362,5 +362,6 @@ const struct fscache_cache_ops cachefiles_cache_ops = { .lookup_cookie = cachefiles_lookup_cookie, .withdraw_cookie = cachefiles_withdraw_cookie, .invalidate_cookie = cachefiles_invalidate_cookie, + .begin_operation = cachefiles_begin_operation, .prepare_to_write = cachefiles_prepare_to_write, }; diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index d7aae04edc61..d5868f5514d3 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -105,6 +105,18 @@ struct cachefiles_cache { #include +static inline +struct file *cachefiles_cres_file(struct netfs_cache_resources *cres) +{ + return cres->cache_priv2; +} + +static inline +struct cachefiles_object *cachefiles_cres_object(struct netfs_cache_resources *cres) +{ + return fscache_cres_cookie(cres)->cache_priv; +} + /* * note change of state for daemon */ @@ -177,6 +189,12 @@ extern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object extern void cachefiles_put_object(struct cachefiles_object *object, enum cachefiles_obj_ref_trace why); +/* + * io.c + */ +extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres, + enum fscache_want_state want_state); + /* * key.c */ diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c new file mode 100644 index 000000000000..adeb9a42fd7b --- /dev/null +++ b/fs/cachefiles/io.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* kiocb-using read/write + * + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +/* + * Clean up an operation. + */ +static void cachefiles_end_operation(struct netfs_cache_resources *cres) +{ + struct file *file = cachefiles_cres_file(cres); + + if (file) + fput(file); + fscache_end_cookie_access(fscache_cres_cookie(cres), fscache_access_io_end); +} + +static const struct netfs_cache_ops cachefiles_netfs_cache_ops = { + .end_operation = cachefiles_end_operation, +}; + +/* + * Open the cache file when beginning a cache operation. + */ +bool cachefiles_begin_operation(struct netfs_cache_resources *cres, + enum fscache_want_state want_state) +{ + struct cachefiles_object *object = cachefiles_cres_object(cres); + + if (!cachefiles_cres_file(cres)) { + cres->ops = &cachefiles_netfs_cache_ops; + if (object->file) { + spin_lock(&object->lock); + if (!cres->cache_priv2 && object->file) + cres->cache_priv2 = get_file(object->file); + spin_unlock(&object->lock); + } + } + + if (!cachefiles_cres_file(cres) && want_state != FSCACHE_WANT_PARAMS) { + pr_err("failed to get cres->file\n"); + return false; + } + + return true; +} diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h index d9d830296ec3..1594aefadeac 100644 --- a/include/trace/events/fscache.h +++ b/include/trace/events/fscache.h @@ -78,6 +78,7 @@ enum fscache_access_trace { fscache_access_cache_unpin, fscache_access_invalidate_cookie, fscache_access_invalidate_cookie_end, + fscache_access_io_end, fscache_access_io_not_live, fscache_access_io_read, fscache_access_io_resize, @@ -152,6 +153,7 @@ enum fscache_access_trace { EM(fscache_access_cache_unpin, "UNPIN cache ") \ EM(fscache_access_invalidate_cookie, "BEGIN inval ") \ EM(fscache_access_invalidate_cookie_end,"END inval ") \ + EM(fscache_access_io_end, "END io ") \ EM(fscache_access_io_not_live, "END io_notl") \ EM(fscache_access_io_read, "BEGIN io_read") \ EM(fscache_access_io_resize, "BEGIN io_resz") \