diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/fs.h | 4 | ||||
-rw-r--r-- | include/linux/fscache-cache.h | 614 | ||||
-rw-r--r-- | include/linux/fscache.h | 1021 | ||||
-rw-r--r-- | include/linux/netfs.h | 15 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 9 | ||||
-rw-r--r-- | include/linux/writeback.h | 1 | ||||
-rw-r--r-- | include/trace/events/cachefiles.h | 527 | ||||
-rw-r--r-- | include/trace/events/fscache.h | 642 | ||||
-rw-r--r-- | include/trace/events/netfs.h | 5 |
10 files changed, 1290 insertions, 1549 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index 58e911cb3885..f5d3bf5b69a6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2173,6 +2173,7 @@ struct super_operations { #define S_ENCRYPTED (1 << 14) /* Encrypted file (using fs/crypto/) */ #define S_CASEFOLD (1 << 15) /* Casefolded file */ #define S_VERITY (1 << 16) /* Verity file (using fs/verity/) */ +#define S_KERNEL_FILE (1 << 17) /* File is in use by the kernel (eg. fs/cachefiles) */ /* * Note that nosuid etc flags are inode-specific: setting some file-system @@ -2342,6 +2343,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, * Used to detect that mark_inode_dirty() should not move * inode between dirty lists. * + * I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback. + * * Q: What is the difference between I_WILL_FREE and I_FREEING? */ #define I_DIRTY_SYNC (1 << 0) @@ -2364,6 +2367,7 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, #define I_CREATING (1 << 15) #define I_DONTCACHE (1 << 16) #define I_SYNC_QUEUED (1 << 17) +#define I_PINNING_FSCACHE_WB (1 << 18) #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 8d39491c5f9f..a174cedf4d90 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* General filesystem caching backing cache interface * - * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * NOTE!!! See: @@ -15,207 +15,34 @@ #define _LINUX_FSCACHE_CACHE_H #include <linux/fscache.h> -#include <linux/sched.h> -#include <linux/workqueue.h> -#define NR_MAXCACHES BITS_PER_LONG - -struct fscache_cache; -struct fscache_cache_ops; -struct fscache_object; -struct fscache_operation; - -enum fscache_obj_ref_trace { - fscache_obj_get_add_to_deps, - fscache_obj_get_queue, - fscache_obj_put_alloc_fail, - fscache_obj_put_attach_fail, - fscache_obj_put_drop_obj, - fscache_obj_put_enq_dep, - fscache_obj_put_queue, - fscache_obj_put_work, - fscache_obj_ref__nr_traces +enum fscache_cache_trace; +enum fscache_cookie_trace; +enum fscache_access_trace; + +enum fscache_cache_state { + FSCACHE_CACHE_IS_NOT_PRESENT, /* No cache is present for this name */ + FSCACHE_CACHE_IS_PREPARING, /* A cache is preparing to come live */ + FSCACHE_CACHE_IS_ACTIVE, /* Attached cache is active and can be used */ + FSCACHE_CACHE_GOT_IOERROR, /* Attached cache stopped on I/O error */ + FSCACHE_CACHE_IS_WITHDRAWN, /* Attached cache is being withdrawn */ +#define NR__FSCACHE_CACHE_STATE (FSCACHE_CACHE_IS_WITHDRAWN + 1) }; /* - * cache tag definition - */ -struct fscache_cache_tag { - struct list_head link; - struct fscache_cache *cache; /* cache referred to by this tag */ - unsigned long flags; -#define FSCACHE_TAG_RESERVED 0 /* T if tag is reserved for a cache */ - atomic_t usage; - char name[]; /* tag name */ -}; - -/* - * cache definition + * Cache cookie. */ struct fscache_cache { const struct fscache_cache_ops *ops; - struct fscache_cache_tag *tag; /* tag representing this cache */ - struct kobject *kobj; /* system representation of this cache */ - struct list_head link; /* link in list of caches */ - size_t max_index_size; /* maximum size of index data */ - char identifier[36]; /* cache label */ - - /* node management */ - struct work_struct op_gc; /* operation garbage collector */ - struct list_head object_list; /* list of data/index objects */ - struct list_head op_gc_list; /* list of ops to be deleted */ - spinlock_t object_list_lock; - spinlock_t op_gc_list_lock; + struct list_head cache_link; /* Link in cache list */ + void *cache_priv; /* Private cache data (or NULL) */ + refcount_t ref; + atomic_t n_volumes; /* Number of active volumes; */ + atomic_t n_accesses; /* Number of in-progress accesses on the cache */ atomic_t object_count; /* no. of live objects in this cache */ - struct fscache_object *fsdef; /* object for the fsdef index */ - unsigned long flags; -#define FSCACHE_IOERROR 0 /* cache stopped on I/O error */ -#define FSCACHE_CACHE_WITHDRAWN 1 /* cache has been withdrawn */ -}; - -extern wait_queue_head_t fscache_cache_cleared_wq; - -/* - * operation to be applied to a cache object - * - retrieval initiation operations are done in the context of the process - * that issued them, and not in an async thread pool - */ -typedef void (*fscache_operation_release_t)(struct fscache_operation *op); -typedef void (*fscache_operation_processor_t)(struct fscache_operation *op); -typedef void (*fscache_operation_cancel_t)(struct fscache_operation *op); - -enum fscache_operation_state { - FSCACHE_OP_ST_BLANK, /* Op is not yet submitted */ - FSCACHE_OP_ST_INITIALISED, /* Op is initialised */ - FSCACHE_OP_ST_PENDING, /* Op is blocked from running */ - FSCACHE_OP_ST_IN_PROGRESS, /* Op is in progress */ - FSCACHE_OP_ST_COMPLETE, /* Op is complete */ - FSCACHE_OP_ST_CANCELLED, /* Op has been cancelled */ - FSCACHE_OP_ST_DEAD /* Op is now dead */ -}; - -struct fscache_operation { - struct work_struct work; /* record for async ops */ - struct list_head pend_link; /* link in object->pending_ops */ - struct fscache_object *object; /* object to be operated upon */ - - unsigned long flags; -#define FSCACHE_OP_TYPE 0x000f /* operation type */ -#define FSCACHE_OP_ASYNC 0x0001 /* - async op, processor may sleep for disk */ -#define FSCACHE_OP_MYTHREAD 0x0002 /* - processing is done be issuing thread, not pool */ -#define FSCACHE_OP_WAITING 4 /* cleared when op is woken */ -#define FSCACHE_OP_EXCLUSIVE 5 /* exclusive op, other ops must wait */ -#define FSCACHE_OP_DEC_READ_CNT 6 /* decrement object->n_reads on destruction */ -#define FSCACHE_OP_UNUSE_COOKIE 7 /* call fscache_unuse_cookie() on completion */ -#define FSCACHE_OP_KEEP_FLAGS 0x00f0 /* flags to keep when repurposing an op */ - - enum fscache_operation_state state; - atomic_t usage; - unsigned debug_id; /* debugging ID */ - - /* operation processor callback - * - can be NULL if FSCACHE_OP_WAITING is going to be used to perform - * the op in a non-pool thread */ - fscache_operation_processor_t processor; - - /* Operation cancellation cleanup (optional) */ - fscache_operation_cancel_t cancel; - - /* operation releaser */ - fscache_operation_release_t release; -}; - -extern atomic_t fscache_op_debug_id; -extern void fscache_op_work_func(struct work_struct *work); - -extern void fscache_enqueue_operation(struct fscache_operation *); -extern void fscache_op_complete(struct fscache_operation *, bool); -extern void fscache_put_operation(struct fscache_operation *); -extern void fscache_operation_init(struct fscache_cookie *, - struct fscache_operation *, - fscache_operation_processor_t, - fscache_operation_cancel_t, - fscache_operation_release_t); - -/* - * data read operation - */ -struct fscache_retrieval { - struct fscache_operation op; - struct fscache_cookie *cookie; /* The netfs cookie */ - struct address_space *mapping; /* netfs pages */ - fscache_rw_complete_t end_io_func; /* function to call on I/O completion */ - void *context; /* netfs read context (pinned) */ - struct list_head to_do; /* list of things to be done by the backend */ - atomic_t n_pages; /* number of pages to be retrieved */ -}; - -typedef int (*fscache_page_retrieval_func_t)(struct fscache_retrieval *op, - struct page *page, - gfp_t gfp); - -typedef int (*fscache_pages_retrieval_func_t)(struct fscache_retrieval *op, - struct list_head *pages, - unsigned *nr_pages, - gfp_t gfp); - -/** - * fscache_get_retrieval - Get an extra reference on a retrieval operation - * @op: The retrieval operation to get a reference on - * - * Get an extra reference on a retrieval operation. - */ -static inline -struct fscache_retrieval *fscache_get_retrieval(struct fscache_retrieval *op) -{ - atomic_inc(&op->op.usage); - return op; -} - -/** - * fscache_enqueue_retrieval - Enqueue a retrieval operation for processing - * @op: The retrieval operation affected - * - * Enqueue a retrieval operation for processing by the FS-Cache thread pool. - */ -static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op) -{ - fscache_enqueue_operation(&op->op); -} - -/** - * fscache_retrieval_complete - Record (partial) completion of a retrieval - * @op: The retrieval operation affected - * @n_pages: The number of pages to account for - */ -static inline void fscache_retrieval_complete(struct fscache_retrieval *op, - int n_pages) -{ - if (atomic_sub_return_relaxed(n_pages, &op->n_pages) <= 0) - fscache_op_complete(&op->op, false); -} - -/** - * fscache_put_retrieval - Drop a reference to a retrieval operation - * @op: The retrieval operation affected - * - * Drop a reference to a retrieval operation. - */ -static inline void fscache_put_retrieval(struct fscache_retrieval *op) -{ - fscache_put_operation(&op->op); -} - -/* - * cached page storage work item - * - used to do three things: - * - batch writes to the cache - * - do cache writes asynchronously - * - defer writes until cache object lookup completion - */ -struct fscache_storage { - struct fscache_operation op; - pgoff_t store_limit; /* don't write more than this */ + unsigned int debug_id; + enum fscache_cache_state state; + char *name; }; /* @@ -225,341 +52,154 @@ struct fscache_cache_ops { /* name of cache provider */ const char *name; - /* allocate an object record for a cookie */ - struct fscache_object *(*alloc_object)(struct fscache_cache *cache, - struct fscache_cookie *cookie); - - /* look up the object for a cookie - * - return -ETIMEDOUT to be requeued - */ - int (*lookup_object)(struct fscache_object *object); - - /* finished looking up */ - void (*lookup_complete)(struct fscache_object *object); - - /* increment the usage count on this object (may fail if unmounting) */ - struct fscache_object *(*grab_object)(struct fscache_object *object, - enum fscache_obj_ref_trace why); + /* Acquire a volume */ + void (*acquire_volume)(struct fscache_volume *volume); - /* pin an object in the cache */ - int (*pin_object)(struct fscache_object *object); + /* Free the cache's data attached to a volume */ + void (*free_volume)(struct fscache_volume *volume); - /* unpin an object in the cache */ - void (*unpin_object)(struct fscache_object *object); + /* Look up a cookie in the cache */ + bool (*lookup_cookie)(struct fscache_cookie *cookie); - /* check the consistency between the backing cache and the FS-Cache - * cookie */ - int (*check_consistency)(struct fscache_operation *op); + /* Withdraw an object without any cookie access counts held */ + void (*withdraw_cookie)(struct fscache_cookie *cookie); - /* store the updated auxiliary data on an object */ - void (*update_object)(struct fscache_object *object); + /* Change the size of a data object */ + void (*resize_cookie)(struct netfs_cache_resources *cres, + loff_t new_size); /* Invalidate an object */ - void (*invalidate_object)(struct fscache_operation *op); - - /* discard the resources pinned by an object and effect retirement if - * necessary */ - void (*drop_object)(struct fscache_object *object); - - /* dispose of a reference to an object */ - void (*put_object)(struct fscache_object *object, - enum fscache_obj_ref_trace why); - - /* sync a cache */ - void (*sync_cache)(struct fscache_cache *cache); - - /* notification that the attributes of a non-index object (such as - * i_size) have changed */ - int (*attr_changed)(struct fscache_object *object); - - /* reserve space for an object's data and associated metadata */ - int (*reserve_space)(struct fscache_object *object, loff_t i_size); - - /* request a backing block for a page be read or allocated in the - * cache */ - fscache_page_retrieval_func_t read_or_alloc_page; - - /* request backing blocks for a list of pages be read or allocated in - * the cache */ - fscache_pages_retrieval_func_t read_or_alloc_pages; - - /* request a backing block for a page be allocated in the cache so that - * it can be written directly */ - fscache_page_retrieval_func_t allocate_page; - - /* request backing blocks for pages be allocated in the cache so that - * they can be written directly */ - fscache_pages_retrieval_func_t allocate_pages; - - /* write a page to its backing block in the cache */ - int (*write_page)(struct fscache_storage *op, struct page *page); - - /* detach backing block from a page (optional) - * - must release the cookie lock before returning - * - may sleep - */ - void (*uncache_page)(struct fscache_object *object, - struct page *page); - - /* dissociate a cache from all the pages it was backing */ - void (*dissociate_pages)(struct fscache_cache *cache); + bool (*invalidate_cookie)(struct fscache_cookie *cookie); - /* Begin a read operation for the netfs lib */ - int (*begin_read_operation)(struct netfs_read_request *rreq, - struct fscache_retrieval *op); -}; - -extern struct fscache_cookie fscache_fsdef_index; + /* Begin an operation for the netfs lib */ + bool (*begin_operation)(struct netfs_cache_resources *cres, + enum fscache_want_state want_state); -/* - * Event list for fscache_object::{event_mask,events} - */ -enum { - FSCACHE_OBJECT_EV_NEW_CHILD, /* T if object has a new child */ - FSCACHE_OBJECT_EV_PARENT_READY, /* T if object's parent is ready */ - FSCACHE_OBJECT_EV_UPDATE, /* T if object should be updated */ - FSCACHE_OBJECT_EV_INVALIDATE, /* T if cache requested object invalidation */ - FSCACHE_OBJECT_EV_CLEARED, /* T if accessors all gone */ - FSCACHE_OBJECT_EV_ERROR, /* T if fatal error occurred during processing */ - FSCACHE_OBJECT_EV_KILL, /* T if netfs relinquished or cache withdrew object */ - NR_FSCACHE_OBJECT_EVENTS -}; - -#define FSCACHE_OBJECT_EVENTS_MASK ((1UL << NR_FSCACHE_OBJECT_EVENTS) - 1) - -/* - * States for object state machine. - */ -struct fscache_transition { - unsigned long events; - const struct fscache_state *transit_to; + /* Prepare to write to a live cache object */ + void (*prepare_to_write)(struct fscache_cookie *cookie); }; -struct fscache_state { - char name[24]; - char short_name[8]; - const struct fscache_state *(*work)(struct fscache_object *object, - int event); - const struct fscache_transition transitions[]; -}; +extern struct workqueue_struct *fscache_wq; +extern wait_queue_head_t fscache_clearance_waiters; /* - * on-disk cache file or index handle + * out-of-line cache backend functions */ -struct fscache_object { - const struct fscache_state *state; /* Object state machine state */ - const struct fscache_transition *oob_table; /* OOB state transition table */ - int debug_id; /* debugging ID */ - int n_children; /* number of child objects */ - int n_ops; /* number of extant ops on object */ - int n_obj_ops; /* number of object ops outstanding on object */ - int n_in_progress; /* number of ops in progress */ - int n_exclusive; /* number of exclusive ops queued or in progress */ - atomic_t n_reads; /* number of read ops in progress */ - spinlock_t lock; /* state and operations lock */ - - unsigned long lookup_jif; /* time at which lookup started */ - unsigned long oob_event_mask; /* OOB events this object is interested in */ - unsigned long event_mask; /* events this object is interested in */ - unsigned long events; /* events to be processed by this object - * (order is important - using fls) */ - - unsigned long flags; -#define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */ -#define FSCACHE_OBJECT_PENDING_WRITE 1 /* T if object has pending write */ -#define FSCACHE_OBJECT_WAITING 2 /* T if object is waiting on its parent */ -#define FSCACHE_OBJECT_IS_LIVE 3 /* T if object is not withdrawn or relinquished */ -#define FSCACHE_OBJECT_IS_LOOKED_UP 4 /* T if object has been looked up */ -#define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */ -#define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */ -#define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */ -#define FSCACHE_OBJECT_RUN_AFTER_DEAD 8 /* T if object has been dispatched after death */ - - struct list_head cache_link; /* link in cache->object_list */ - struct hlist_node cookie_link; /* link in cookie->backing_objects */ - struct fscache_cache *cache; /* cache that supplied this object */ - struct fscache_cookie *cookie; /* netfs's file/index object */ - struct fscache_object *parent; /* parent object */ - struct work_struct work; /* attention scheduling record */ - struct list_head dependents; /* FIFO of dependent objects */ - struct list_head dep_link; /* link in parent's dependents list */ - struct list_head pending_ops; /* unstarted operations on this object */ - pgoff_t store_limit; /* current storage limit */ - loff_t store_limit_l; /* current storage limit */ -}; - -extern void fscache_object_init(struct fscache_object *, struct fscache_cookie *, - struct fscache_cache *); -extern void fscache_object_destroy(struct fscache_object *); - -extern void fscache_object_lookup_negative(struct fscache_object *object); -extern void fscache_obtained_object(struct fscache_object *object); - -static inline bool fscache_object_is_live(struct fscache_object *object) -{ - return test_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags); -} - -static inline bool fscache_object_is_dying(struct fscache_object *object) -{ - return !fscache_object_is_live(object); -} - -static inline bool fscache_object_is_available(struct fscache_object *object) -{ - return test_bit(FSCACHE_OBJECT_IS_AVAILABLE, &object->flags); -} +extern struct rw_semaphore fscache_addremove_sem; +extern struct fscache_cache *fscache_acquire_cache(const char *name); +extern void fscache_relinquish_cache(struct fscache_cache *cache); +extern int fscache_add_cache(struct fscache_cache *cache, + const struct fscache_cache_ops *ops, + void *cache_priv); +extern void fscache_withdraw_cache(struct fscache_cache *cache); +extern void fscache_withdraw_volume(struct fscache_volume *volume); +extern void fscache_withdraw_cookie(struct fscache_cookie *cookie); -static inline bool fscache_cache_is_broken(struct fscache_object *object) -{ - return test_bit(FSCACHE_IOERROR, &object->cache->flags); -} +extern void fscache_io_error(struct fscache_cache *cache); -static inline bool fscache_object_is_active(struct fscache_object *object) -{ - return fscache_object_is_available(object) && - fscache_object_is_live(object) && - !fscache_cache_is_broken(object); -} +extern void fscache_end_volume_access(struct fscache_volume *volume, + struct fscache_cookie *cookie, + enum fscache_access_trace why); + +extern struct fscache_cookie *fscache_get_cookie(struct fscache_cookie *cookie, + enum fscache_cookie_trace where); +extern void fscache_put_cookie(struct fscache_cookie *cookie, + enum fscache_cookie_trace where); +extern void fscache_end_cookie_access(struct fscache_cookie *cookie, + enum fscache_access_trace why); +extern void fscache_cookie_lookup_negative(struct fscache_cookie *cookie); +extern void fscache_resume_after_invalidation(struct fscache_cookie *cookie); +extern void fscache_caching_failed(struct fscache_cookie *cookie); +extern bool fscache_wait_for_operation(struct netfs_cache_resources *cred, + enum fscache_want_state state); /** - * fscache_object_destroyed - Note destruction of an object in a cache - * @cache: The cache from which the object came + * fscache_cookie_state - Read the state of a cookie + * @cookie: The cookie to query * - * Note the destruction and deallocation of an object record in a cache. + * Get the state of a cookie, imposing an ordering between the cookie contents + * and the state value. Paired with fscache_set_cookie_state(). */ -static inline void fscache_object_destroyed(struct fscache_cache *cache) +static inline +enum fscache_cookie_state fscache_cookie_state(struct fscache_cookie *cookie) { - if (atomic_dec_and_test(&cache->object_count)) - wake_up_all(&fscache_cache_cleared_wq); + return smp_load_acquire(&cookie->state); } /** - * fscache_object_lookup_error - Note an object encountered an error - * @object: The object on which the error was encountered + * fscache_get_key - Get a pointer to the cookie key + * @cookie: The cookie to query * - * Note that an object encountered a fatal error (usually an I/O error) and - * that it should be withdrawn as soon as possible. + * Return a pointer to the where a cookie's key is stored. */ -static inline void fscache_object_lookup_error(struct fscache_object *object) +static inline void *fscache_get_key(struct fscache_cookie *cookie) { - set_bit(FSCACHE_OBJECT_EV_ERROR, &object->events); + if (cookie->key_len <= sizeof(cookie->inline_key)) + return cookie->inline_key; + else + return cookie->key; } -/** - * fscache_set_store_limit - Set the maximum size to be stored in an object - * @object: The object to set the maximum on - * @i_size: The limit to set in bytes - * - * Set the maximum size an object is permitted to reach, implying the highest - * byte that may be written. Intended to be called by the attr_changed() op. - * - * See Documentation/filesystems/caching/backend-api.rst for a complete - * description. - */ -static inline -void fscache_set_store_limit(struct fscache_object *object, loff_t i_size) +static inline struct fscache_cookie *fscache_cres_cookie(struct netfs_cache_resources *cres) { - object->store_limit_l = i_size; - object->store_limit = i_size >> PAGE_SHIFT; - if (i_size & ~PAGE_MASK) - object->store_limit++; + return cres->cache_priv; } /** - * fscache_end_io - End a retrieval operation on a page - * @op: The FS-Cache operation covering the retrieval - * @page: The page that was to be fetched - * @error: The error code (0 if successful) + * fscache_count_object - Tell fscache that an object has been added + * @cache: The cache to account to * - * Note the end of an operation to retrieve a page, as covered by a particular - * operation record. + * Tell fscache that an object has been added to the cache. This prevents the + * cache from tearing down the cache structure until the object is uncounted. */ -static inline void fscache_end_io(struct fscache_retrieval *op, - struct page *page, int error) +static inline void fscache_count_object(struct fscache_cache *cache) { - op->end_io_func(page, op->context, error); -} - -static inline void __fscache_use_cookie(struct fscache_cookie *cookie) -{ - atomic_inc(&cookie->n_active); + atomic_inc(&cache->object_count); } /** - * fscache_use_cookie - Request usage of cookie attached to an object - * @object: Object description - * - * Request usage of the cookie attached to an object. NULL is returned if the - * relinquishment had reduced the cookie usage count to 0. + * fscache_uncount_object - Tell fscache that an object has been removed + * @cache: The cache to account to + * + * Tell fscache that an object has been removed from the cache and will no + * longer be accessed. After this point, the cache cookie may be destroyed. */ -static inline bool fscache_use_cookie(struct fscache_object *object) -{ - struct fscache_cookie *cookie = object->cookie; - return atomic_inc_not_zero(&cookie->n_active) != 0; -} - -static inline bool __fscache_unuse_cookie(struct fscache_cookie *cookie) -{ - return atomic_dec_and_test(&cookie->n_active); -} - -static inline void __fscache_wake_unused_cookie(struct fscache_cookie *cookie) +static inline void fscache_uncount_object(struct fscache_cache *cache) { - wake_up_var(&cookie->n_active); + if (atomic_dec_and_test(&cache->object_count)) + wake_up_all(&fscache_clearance_waiters); } /** - * fscache_unuse_cookie - Cease usage of cookie attached to an object - * @object: Object description - * - * Cease usage of the cookie attached to an object. When the users count - * reaches zero then the cookie relinquishment will be permitted to proceed. - */ -static inline void fscache_unuse_cookie(struct fscache_object *object) -{ - struct fscache_cookie *cookie = object->cookie; - if (__fscache_unuse_cookie(cookie)) - __fscache_wake_unused_cookie(cookie); -} - -/* - * out-of-line cache backend functions - */ -extern __printf(3, 4) -void fscache_init_cache(struct fscache_cache *cache, - const struct fscache_cache_ops *ops, - const char *idfmt, ...); - -extern int fscache_add_cache(struct fscache_cache *cache, - struct fscache_object *fsdef, - const char *tagname); -extern void fscache_withdraw_cache(struct fscache_cache *cache); - -extern void fscache_io_error(struct fscache_cache *cache); - -extern void fscache_mark_page_cached(struct fscache_retrieval *op, - struct page *page); - -extern void fscache_mark_pages_cached(struct fscache_retrieval *op, - struct pagevec *pagevec); - -extern bool fscache_object_sleep_till_congested(signed long *timeoutp); - -extern enum fscache_checkaux fscache_check_aux(struct fscache_object *object, - const void *data, - uint16_t datalen, - loff_t object_size); - -extern void fscache_object_retrying_stale(struct fscache_object *object); - -enum fscache_why_object_killed { - FSCACHE_OBJECT_IS_STALE, - FSCACHE_OBJECT_NO_SPACE, - FSCACHE_OBJECT_WAS_RETIRED, - FSCACHE_OBJECT_WAS_CULLED, -}; -extern void fscache_object_mark_killed(struct fscache_object *object, - enum fscache_why_object_killed why); + * fscache_wait_for_objects - Wait for all objects to be withdrawn + * @cache: The cache to query + * + * Wait for all extant objects in a cache to finish being withdrawn + * and go away. + */ +static inline void fscache_wait_for_objects(struct fscache_cache *cache) +{ + wait_event(fscache_clearance_waiters, + atomic_read(&cache->object_count) == 0); +} + +#ifdef CONFIG_FSCACHE_STATS +extern atomic_t fscache_n_read; +extern atomic_t fscache_n_write; +extern atomic_t fscache_n_no_write_space; +extern atomic_t fscache_n_no_create_space; +extern atomic_t fscache_n_culled; +#define fscache_count_read() atomic_inc(&fscache_n_read) +#define fscache_count_write() atomic_inc(&fscache_n_write) +#define fscache_count_no_write_space() atomic_inc(&fscache_n_no_write_space) +#define fscache_count_no_create_space() atomic_inc(&fscache_n_no_create_space) +#define fscache_count_culled() atomic_inc(&fscache_n_culled) +#else +#define fscache_count_read() do {} while(0) +#define fscache_count_write() do {} while(0) +#define fscache_count_no_write_space() do {} while(0) +#define fscache_count_no_create_space() do {} while(0) +#define fscache_count_culled() do {} while(0) +#endif #endif /* _LINUX_FSCACHE_CACHE_H */ diff --git a/include/linux/fscache.h b/include/linux/fscache.h index 3b2282c157f7..ede50406bcb0 100644 --- a/include/linux/fscache.h +++ b/include/linux/fscache.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* General filesystem caching interface * - * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * NOTE!!! See: @@ -15,146 +15,126 @@ #define _LINUX_FSCACHE_H #include <linux/fs.h> -#include <linux/list.h> -#include <linux/pagemap.h> -#include <linux/pagevec.h> -#include <linux/list_bl.h> #include <linux/netfs.h> +#include <linux/writeback.h> #if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +#define __fscache_available (1) #define fscache_available() (1) +#define fscache_volume_valid(volume) (volume) #define fscache_cookie_valid(cookie) (cookie) +#define fscache_resources_valid(cres) ((cres)->cache_priv) +#define fscache_cookie_enabled(cookie) (cookie && !test_bit(FSCACHE_COOKIE_DISABLED, &cookie->flags)) #else +#define __fscache_available (0) #define fscache_available() (0) +#define fscache_volume_valid(volume) (0) #define fscache_cookie_valid(cookie) (0) +#define fscache_resources_valid(cres) (false) +#define fscache_cookie_enabled(cookie) (0) #endif +struct fscache_cookie; -/* pattern used to fill dead space in an index entry */ -#define FSCACHE_INDEX_DEADFILL_PATTERN 0x79 +#define FSCACHE_ADV_SINGLE_CHUNK 0x01 /* The object is a single chunk of data */ +#define FSCACHE_ADV_WRITE_CACHE 0x00 /* Do cache if written to locally */ +#define FSCACHE_ADV_WRITE_NOCACHE 0x02 /* Don't cache if written to locally */ -struct pagevec; -struct fscache_cache_tag; -struct fscache_cookie; -struct fscache_netfs; -struct netfs_read_request; - -typedef void (*fscache_rw_complete_t)(struct page *page, - void *context, - int error); - -/* result of index entry consultation */ -enum fscache_checkaux { - FSCACHE_CHECKAUX_OKAY, /* entry okay as is */ - FSCACHE_CHECKAUX_NEEDS_UPDATE, /* entry requires update */ - FSCACHE_CHECKAUX_OBSOLETE, /* entry requires deletion */ +#define FSCACHE_INVAL_DIO_WRITE 0x01 /* Invalidate due to DIO write */ + +enum fscache_want_state { + FSCACHE_WANT_PARAMS, + FSCACHE_WANT_WRITE, + FSCACHE_WANT_READ, }; /* - * fscache cookie definition - */ -struct fscache_cookie_def { - /* name of cookie type */ - char name[16]; - - /* cookie type */ - uint8_t type; -#define FSCACHE_COOKIE_TYPE_INDEX 0 -#define FSCACHE_COOKIE_TYPE_DATAFILE 1 - - /* select the cache into which to insert an entry in this index - * - optional - * - should return a cache identifier or NULL to cause the cache to be - * inherited from the parent if possible or the first cache picked - * for a non-index file if not - */ - struct fscache_cache_tag *(*select_cache)( - const void *parent_netfs_data, - const void *cookie_netfs_data); - - /* consult the netfs about the state of an object - * - this function can be absent if the index carries no state data - * - the netfs data from the cookie being used as the target is - * presented, as is the auxiliary data and the object size - */ - enum fscache_checkaux (*check_aux)(void *cookie_netfs_data, - const void *data, - uint16_t datalen, - loff_t object_size); - - /* get an extra reference on a read context - * - this function can be absent if the completion function doesn't - * require a context - */ - void (*get_context)(void *cookie_netfs_data, void *context); - - /* release an extra reference on a read context - * - this function can be absent if the completion function doesn't - * require a context - */ - void (*put_context)(void *cookie_netfs_data, void *context); - - /* indicate page that now have cache metadata retained - * - this function should mark the specified page as now being cached - * - the page will have been marked with PG_fscache before this is - * called, so this is optional - */ - void (*mark_page_cached)(void *cookie_netfs_data, - struct address_space *mapping, - struct page *page); -}; + * Data object state. + */ +enum fscache_cookie_state { + FSCACHE_COOKIE_STATE_QUIESCENT, /* The cookie is uncached */ + FSCACHE_COOKIE_STATE_LOOKING_UP, /* The cache object is being looked up */ + FSCACHE_COOKIE_STATE_CREATING, /* The cache object is being created */ + FSCACHE_COOKIE_STATE_ACTIVE, /* The cache is active, readable and writable */ + FSCACHE_COOKIE_STATE_INVALIDATING, /* The cache is being invalidated */ + FSCACHE_COOKIE_STATE_FAILED, /* The cache failed, withdraw to clear */ + FSCACHE_COOKIE_STATE_LRU_DISCARDING, /* The cookie is being discarded by the LRU */ + FSCACHE_COOKIE_STATE_WITHDRAWING, /* The cookie is being withdrawn */ + FSCACHE_COOKIE_STATE_RELINQUISHING, /* The cookie is being relinquished */ + FSCACHE_COOKIE_STATE_DROPPED, /* The cookie has been dropped */ +#define FSCACHE_COOKIE_STATE__NR (FSCACHE_COOKIE_STATE_DROPPED + 1) +} __attribute__((mode(byte))); /* - * fscache cached network filesystem type - * - name, version and ops must be filled in before registration - * - all other fields will be set during registration + * Volume representation cookie. */ -struct fscache_netfs { - uint32_t version; /* indexing version */ - const char *name; /* filesystem name */ - struct fscache_cookie *primary_index; +struct fscache_volume { + refcount_t ref; + atomic_t n_cookies; /* Number of data cookies in volume */ + atomic_t n_accesses; /* Number of cache accesses in progress */ + unsigned int debug_id; + unsigned int key_hash; /* Hash of key string */ + char *key; /* Volume ID, eg. "afs@example.com@1234" */ + struct list_head proc_link; /* Link in /proc/fs/fscache/volumes */ + struct hlist_bl_node hash_link; /* Link in hash table */ + struct work_struct work; + struct fscache_cache *cache; /* The cache in which this resides */ + void *cache_priv; /* Cache private data */ + spinlock_t lock; + unsigned long flags; +#define FSCACHE_VOLUME_RELINQUISHED 0 /* Volume is being cleaned up */ +#define FSCACHE_VOLUME_INVALIDATE 1 /* Volume was invalidated */ +#define FSCACHE_VOLUME_COLLIDED_WITH 2 /* Volume was collided with */ +#define FSCACHE_VOLUME_ACQUIRE_PENDING 3 /* Volume is waiting to complete acquisition */ +#define FSCACHE_VOLUME_CREATING 4 /* Volume is being created on disk */ + u8 coherency_len; /* Length of the coherency data */ + u8 coherency[]; /* Coherency data */ }; /* - * data file or index object cookie + * Data file representation cookie. * - a file will only appear in one cache * - a request to cache a file may or may not be honoured, subject to * constraints such as disk space * - indices are created on disk just-in-time */ struct fscache_cookie { - refcount_t ref; /* number of users of this cookie */ - atomic_t n_children; /* number of children of this cookie */ - atomic_t n_active; /* number of active users of netfs ptrs */ + refcount_t ref; + atomic_t n_active; /* number of active users of cookie */ + atomic_t n_accesses; /* Number of cache accesses in progress */ unsigned int debug_id; + unsigned int inval_counter; /* Number of invalidations made */ spinlock_t lock; - spinlock_t stores_lock; /* lock on page store tree */ - struct hlist_head backing_objects; /* object(s) backing this file/index */ - const struct fscache_cookie_def *def; /* definition */ - struct fscache_cookie *parent; /* parent of this entry */ + struct fscache_volume *volume; /* Parent volume of this file. */ + void *cache_priv; /* Cache-side representation */ struct hlist_bl_node hash_link; /* Link in hash table */ struct list_head proc_link; /* Link in proc list */ - void *netfs_data; /* back pointer to netfs */ - struct radix_tree_root stores; /* pages to be stored on this cookie */ -#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */ -#define FSCACHE_COOKIE_STORING_TAG 1 /* pages tag: writing to cache */ - + struct list_head commit_link; /* Link in commit queue */ + struct work_struct work; /* Commit/relinq/withdraw work */ + loff_t object_size; /* Size of the netfs object */ + unsigned long unused_at; /* Time at which unused (jiffies) */ unsigned long flags; -#define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */ -#define FSCACHE_COOKIE_NO_DATA_YET 1 /* T if new object with no cached data yet */ -#define FSCACHE_COOKIE_UNAVAILABLE 2 /* T if cookie is unavailable (error, etc) */ -#define FSCACHE_COOKIE_INVALIDATING 3 /* T if cookie is being invalidated */ -#define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */ -#define FSCACHE_COOKIE_ENABLED 5 /* T if cookie is enabled */ -#define FSCACHE_COOKIE_ENABLEMENT_LOCK 6 /* T if cookie is being en/disabled */ -#define FSCACHE_COOKIE_AUX_UPDATED 8 /* T if the auxiliary data was updated */ -#define FSCACHE_COOKIE_ACQUIRED 9 /* T if cookie is in use */ -#define FSCACHE_COOKIE_RELINQUISHING 10 /* T if cookie is being relinquished */ - - u8 type; /* Type of object */ +#define FSCACHE_COOKIE_RELINQUISHED 0 /* T if cookie has been relinquished */ +#define FSCACHE_COOKIE_RETIRED 1 /* T if this cookie has retired on relinq */ +#define FSCACHE_COOKIE_IS_CACHING 2 /* T if this cookie is cached */ +#define FSCACHE_COOKIE_NO_DATA_TO_READ 3 /* T if this cookie has nothing to read */ +#define FSCACHE_COOKIE_NEEDS_UPDATE 4 /* T if attrs have been updated */ +#define FSCACHE_COOKIE_HAS_BEEN_CACHED 5 /* T if cookie needs withdraw-on-relinq */ +#define FSCACHE_COOKIE_DISABLED 6 /* T if cookie has been disabled */ +#define FSCACHE_COOKIE_LOCAL_WRITE 7 /* T if cookie has been modified locally */ +#define FSCACHE_COOKIE_NO_ACCESS_WAKE 8 /* T if no wake when n_accesses goes 0 */ +#define FSCACHE_COOKIE_DO_RELINQUISH 9 /* T if this cookie needs relinquishment */ +#define FSCACHE_COOKIE_DO_WITHDRAW 10 /* T if this cookie needs withdrawing */ +#define FSCACHE_COOKIE_DO_LRU_DISCARD 11 /* T if this cookie needs LRU discard */ +#define FSCACHE_COOKIE_DO_PREP_TO_WRITE 12 /* T if cookie needs write preparation */ +#define FSCACHE_COOKIE_HAVE_DATA 13 /* T if this cookie has data stored */ +#define FSCACHE_COOKIE_IS_HASHED 14 /* T if this cookie is hashed */ + + enum fscache_cookie_state state; + u8 advice; /* FSCACHE_ADV_* */ u8 key_len; /* Length of index key */ u8 aux_len; /* Length of auxiliary data */ - u32 key_hash; /* Hash of parent, type, key, len */ + u32 key_hash; /* Hash of volume, key, len */ union { void *key; /* Index key */ u8 inline_key[16]; /* - If the key is short enough */ @@ -165,11 +145,6 @@ struct fscache_cookie { }; }; -static inline bool fscache_cookie_enabled(struct fscache_cookie *cookie) -{ - return fscache_cookie_valid(cookie) && test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); -} - /* * slow-path functions for when there is actually caching available, and the * netfs does actually have a valid token @@ -177,699 +152,523 @@ static inline bool fscache_cookie_enabled(struct fscache_cookie *cookie) * - these are undefined symbols when FS-Cache is not configured and the * optimiser takes care of not using them */ -extern int __fscache_register_netfs(struct fscache_netfs *); -extern void __fscache_unregister_netfs(struct fscache_netfs *); -extern struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *); -extern void __fscache_release_cache_tag(struct fscache_cache_tag *); +extern struct fscache_volume *__fscache_acquire_volume(const char *, const char *, + const void *, size_t); +extern void __fscache_relinquish_volume(struct fscache_volume *, const void *, bool); extern struct fscache_cookie *__fscache_acquire_cookie( - struct fscache_cookie *, - const struct fscache_cookie_def *, + struct fscache_volume *, + u8, const void *, size_t, const void *, size_t, - void *, loff_t, bool); -extern void __fscache_relinquish_cookie(struct fscache_cookie *, const void *, bool); -extern int __fscache_check_consistency(struct fscache_cookie *, const void *); -extern void __fscache_update_cookie(struct fscache_cookie *, const void *); -extern int __fscache_attr_changed(struct fscache_cookie *); -extern void __fscache_invalidate(struct fscache_cookie *); -extern void __fscache_wait_on_invalidate(struct fscache_cookie *); - -#ifdef FSCACHE_USE_NEW_IO_API -extern int __fscache_begin_read_operation(struct netfs_read_request *, struct fscache_cookie *); -#else -extern int __fscache_read_or_alloc_page(struct fscache_cookie *, - struct page *, - fscache_rw_complete_t, - void *, - gfp_t); -extern int __fscache_read_or_alloc_pages(struct fscache_cookie *, - struct address_space *, - struct list_head *, - unsigned *, - fscache_rw_complete_t, - void *, - gfp_t); -extern int __fscache_alloc_page(struct fscache_cookie *, struct page *, gfp_t); -extern int __fscache_write_page(struct fscache_cookie *, struct page *, loff_t, gfp_t); -extern void __fscache_uncache_page(struct fscache_cookie *, struct page *); -extern bool __fscache_check_page_write(struct fscache_cookie *, struct page *); -extern void __fscache_wait_on_page_write(struct fscache_cookie *, struct page *); -extern bool __fscache_maybe_release_page(struct fscache_cookie *, struct page *, - gfp_t); -extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *, - struct inode *); -extern void __fscache_readpages_cancel(struct fscache_cookie *cookie, - struct list_head *pages); -#endif /* FSCACHE_USE_NEW_IO_API */ - -extern void __fscache_disable_cookie(struct fscache_cookie *, const void *, bool); -extern void __fscache_enable_cookie(struct fscache_cookie *, const void *, loff_t, - bool (*)(void *), void *); + loff_t); +extern void __fscache_use_cookie(struct fscache_cookie *, bool); +extern void __fscache_unuse_cookie(struct fscache_cookie *, const void *, const loff_t *); +extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool); +extern void __fscache_resize_cookie(struct fscache_cookie *, loff_t); +extern void __fscache_invalidate(struct fscache_cookie *, const void *, loff_t, unsigned int); +extern int __fscache_begin_read_operation(struct netfs_cache_resources *, struct fscache_cookie *); +extern int __fscache_begin_write_operation(struct netfs_cache_resources *, struct fscache_cookie *); + +extern void __fscache_write_to_cache(struct fscache_cookie *, struct address_space *, + loff_t, size_t, loff_t, netfs_io_terminated_t, void *, + bool); +extern void __fscache_clear_page_bits(struct address_space *, loff_t, size_t); /** - * fscache_register_netfs - Register a filesystem as desiring caching services - * @netfs: The description of the filesystem + * fscache_acquire_volume - Register a volume as desiring caching services + * @volume_key: An identification string for the volume + * @cache_name: The name of the cache to use (or NULL for the default) + * @coherency_data: Piece of arbitrary coherency data to check (or NULL) + * @coherency_len: The size of the coherency data * - * Register a filesystem as desiring caching services if they're available. + * Register a volume as desiring caching services if they're available. The + * caller must provide an identifier for the volume and may also indicate which + * cache it should be in. If a preexisting volume entry is found in the cache, + * the coherency data must match otherwise the entry will be invalidated. * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. + * Returns a cookie pointer on success, -ENOMEM if out of memory or -EBUSY if a + * cache volume of that name is already acquired. Note that "NULL" is a valid + * cookie pointer and can be returned if caching is refused. */ static inline -int fscache_register_netfs(struct fscache_netfs *netfs) +struct fscache_volume *fscache_acquire_volume(const char *volume_key, + const char *cache_name, + const void *coherency_data, + size_t coherency_len) { - if (fscache_available()) - return __fscache_register_netfs(netfs); - else - return 0; + if (!fscache_available()) + return NULL; + return __fscache_acquire_volume(volume_key, cache_name, + coherency_data, coherency_len); } /** - * fscache_unregister_netfs - Indicate that a filesystem no longer desires - * caching services - * @netfs: The description of the filesystem + * fscache_relinquish_volume - Cease caching a volume + * @volume: The volume cookie + * @coherency_data: Piece of arbitrary coherency data to set (or NULL) + * @invalidate: True if the volume should be invalidated * - * Indicate that a filesystem no longer desires caching services for the - * moment. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. + * Indicate that a filesystem no longer desires caching services for a volume. + * The caller must have relinquished all file cookies prior to calling this. + * The stored coherency data is updated. */ static inline -void fscache_unregister_netfs(struct fscache_netfs *netfs) +void fscache_relinquish_volume(struct fscache_volume *volume, + const void *coherency_data, + bool invalidate) { - if (fscache_available()) - __fscache_unregister_netfs(netfs); + if (fscache_volume_valid(volume)) + __fscache_relinquish_volume(volume, coherency_data, invalidate); } /** - * fscache_lookup_cache_tag - Look up a cache tag - * @name: The name of the tag to search for + * fscache_acquire_cookie - Acquire a cookie to represent a cache object + * @volume: The volume in which to locate/create this cookie + * @advice: Advice flags (FSCACHE_COOKIE_ADV_*) + * @index_key: The index key for this cookie + * @index_key_len: Size of the index key + * @aux_data: The auxiliary data for the cookie (may be NULL) + * @aux_data_len: Size of the auxiliary data buffer + * @object_size: The initial size of object * - * Acquire a specific cache referral tag that can be used to select a specific - * cache in which to cache an index. + * Acquire a cookie to represent a data file within the given cache volume. * * See Documentation/filesystems/caching/netfs-api.rst for a complete * description. */ static inline -struct fscache_cache_tag *fscache_lookup_cache_tag(const char *name) +struct fscache_cookie *fscache_acquire_cookie(struct fscache_volume *volume, + u8 advice, + const void *index_key, + size_t index_key_len, + const void *aux_data, + size_t aux_data_len, + loff_t object_size) { - if (fscache_available()) - return __fscache_lookup_cache_tag(name); - else + if (!fscache_volume_valid(volume)) return NULL; + return __fscache_acquire_cookie(volume, advice, + index_key, index_key_len, + aux_data, aux_data_len, + object_size); } /** - * fscache_release_cache_tag - Release a cache tag - * @tag: The tag to release - * - * Release a reference to a cache referral tag previously looked up. + * fscache_use_cookie - Request usage of cookie attached to an object + * @object: Object description + * @will_modify: If cache is expected to be modified locally * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. + * Request usage of the cookie attached to an object. The caller should tell + * the cache if the object's contents are about to be modified locally and then + * the cache can apply the policy that has been set to handle this case. */ -static inline -void fscache_release_cache_tag(struct fscache_cache_tag *tag) +static inline void fscache_use_cookie(struct fscache_cookie *cookie, + bool will_modify) { - if (fscache_available()) - __fscache_release_cache_tag(tag); + if (fscache_cookie_valid(cookie)) + __fscache_use_cookie(cookie, will_modify); } /** - * fscache_acquire_cookie - Acquire a cookie to represent a cache object - * @parent: The cookie that's to be the parent of this one - * @def: A description of the cache object, including callback operations - * @index_key: The index key for this cookie - * @index_key_len: Size of the index key - * @aux_data: The auxiliary data for the cookie (may be NULL) - * @aux_data_len: Size of the auxiliary data buffer - * @netfs_data: An arbitrary piece of data to be kept in the cookie to - * represent the cache object to the netfs - * @object_size: The initial size of object - * @enable: Whether or not to enable a data cookie immediately + * fscache_unuse_cookie - Cease usage of cookie attached to an object + * @object: Object description + * @aux_data: Updated auxiliary data (or NULL) + * @object_size: Revised size of the object (or NULL) * - * This function is used to inform FS-Cache about part of an index hierarchy - * that can be used to locate files. This is done by requesting a cookie for - * each index in the path to the file. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. + * Cease usage of the cookie attached to an object. When the users count + * reaches zero then the cookie relinquishment will be permitted to proceed. */ -static inline -struct fscache_cookie *fscache_acquire_cookie( - struct fscache_cookie *parent, - const struct fscache_cookie_def *def, - const void *index_key, - size_t index_key_len, - const void *aux_data, - size_t aux_data_len, - void *netfs_data, - loff_t object_size, - bool enable) +static inline void fscache_unuse_cookie(struct fscache_cookie *cookie, + const void *aux_data, + const loff_t *object_size) { - if (fscache_cookie_valid(parent) && fscache_cookie_enabled(parent)) - return __fscache_acquire_cookie(parent, def, - index_key, index_key_len, - aux_data, aux_data_len, - netfs_data, object_size, enable); - else - return NULL; + if (fscache_cookie_valid(cookie)) + __fscache_unuse_cookie(cookie, aux_data, object_size); } /** * fscache_relinquish_cookie - Return the cookie to the cache, maybe discarding * it * @cookie: The cookie being returned - * @aux_data: The updated auxiliary data for the cookie (may be NULL) * @retire: True if the cache object the cookie represents is to be discarded * * This function returns a cookie to the cache, forcibly discarding the - * associated cache object if retire is set to true. The opportunity is - * provided to update the auxiliary data in the cache before the object is - * disconnected. + * associated cache object if retire is set to true. * * See Documentation/filesystems/caching/netfs-api.rst for a complete * description. */ static inline -void fscache_relinquish_cookie(struct fscache_cookie *cookie, - const void *aux_data, - bool retire) +void fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire) { if (fscache_cookie_valid(cookie)) - __fscache_relinquish_cookie(cookie, aux_data, retire); + __fscache_relinquish_cookie(cookie, retire); } -/** - * fscache_check_consistency - Request validation of a cache's auxiliary data - * @cookie: The cookie representing the cache object - * @aux_data: The updated auxiliary data for the cookie (may be NULL) - * - * Request an consistency check from fscache, which passes the request to the - * backing cache. The auxiliary data on the cookie will be updated first if - * @aux_data is set. - * - * Returns 0 if consistent and -ESTALE if inconsistent. May also - * return -ENOMEM and -ERESTARTSYS. +/* + * Find the auxiliary data on a cookie. */ -static inline -int fscache_check_consistency(struct fscache_cookie *cookie, - const void *aux_data) +static inline void *fscache_get_aux(struct fscache_cookie *cookie) { - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_check_consistency(cookie, aux_data); + if (cookie->aux_len <= sizeof(cookie->inline_aux)) + return cookie->inline_aux; else - return 0; + return cookie->aux; } -/** - * fscache_update_cookie - Request that a cache object be updated - * @cookie: The cookie representing the cache object - * @aux_data: The updated auxiliary data for the cookie (may be NULL) - * - * Request an update of the index data for the cache object associated with the - * cookie. The auxiliary data on the cookie will be updated first if @aux_data - * is set. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. +/* + * Update the auxiliary data on a cookie. */ static inline -void fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data) +void fscache_update_aux(struct fscache_cookie *cookie, + const void *aux_data, const loff_t *object_size) { - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - __fscache_update_cookie(cookie, aux_data); + void *p = fscache_get_aux(cookie); + + if (aux_data && p) + memcpy(p, aux_data, cookie->aux_len); + if (object_size) + cookie->object_size = *object_size; } -/** - * fscache_pin_cookie - Pin a data-storage cache object in its cache - * @cookie: The cookie representing the cache object - * - * Permit data-storage cache objects to be pinned in the cache. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ +#ifdef CONFIG_FSCACHE_STATS +extern atomic_t fscache_n_updates; +#endif + static inline -int fscache_pin_cookie(struct fscache_cookie *cookie) +void __fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data, + const loff_t *object_size) { - return -ENOBUFS; +#ifdef CONFIG_FSCACHE_STATS + atomic_inc(&fscache_n_updates); +#endif + fscache_update_aux(cookie, aux_data, object_size); + smp_wmb(); + set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &cookie->flags); } /** - * fscache_pin_cookie - Unpin a data-storage cache object in its cache + * fscache_update_cookie - Request that a cache object be updated * @cookie: The cookie representing the cache object + * @aux_data: The updated auxiliary data for the cookie (may be NULL) + * @object_size: The current size of the object (may be NULL) * - * Permit data-storage cache objects to be unpinned from the cache. + * Request an update of the index data for the cache object associated with the + * cookie. The auxiliary data on the cookie will be updated first if @aux_data + * is set and the object size will be updated and the object possibly trimmed + * if @object_size is set. * * See Documentation/filesystems/caching/netfs-api.rst for a complete * description. */ static inline -void fscache_unpin_cookie(struct fscache_cookie *cookie) +void fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data, + const loff_t *object_size) { + if (fscache_cookie_enabled(cookie)) + __fscache_update_cookie(cookie, aux_data, object_size); } /** - * fscache_attr_changed - Notify cache that an object's attributes changed + * fscache_resize_cookie - Request that a cache object be resized * @cookie: The cookie representing the cache object + * @new_size: The new size of the object (may be NULL) * - * Send a notification to the cache indicating that an object's attributes have - * changed. This includes the data size. These attributes will be obtained - * through the get_attr() cookie definition op. + * Request that the size of an object be changed. * - * See Documentation/filesystems/caching/netfs-api.rst for a complete + * See Documentation/filesystems/caching/netfs-api.txt for a complete * description. */ static inline -int fscache_attr_changed(struct fscache_cookie *cookie) +void fscache_resize_cookie(struct fscache_cookie *cookie, loff_t new_size) { - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_attr_changed(cookie); - else - return -ENOBUFS; + if (fscache_cookie_enabled(cookie)) + __fscache_resize_cookie(cookie, new_size); } /** * fscache_invalidate - Notify cache that an object needs invalidation * @cookie: The cookie representing the cache object + * @aux_data: The updated auxiliary data for the cookie (may be NULL) + * @size: The revised size of the object. + * @flags: Invalidation flags (FSCACHE_INVAL_*) * * Notify the cache that an object is needs to be invalidated and that it - * should abort any retrievals or stores it is doing on the cache. The object - * is then marked non-caching until such time as the invalidation is complete. - * - * This can be called with spinlocks held. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ -static inline -void fscache_invalidate(struct fscache_cookie *cookie) -{ - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - __fscache_invalidate(cookie); -} - -/** - * fscache_wait_on_invalidate - Wait for invalidation to complete - * @cookie: The cookie representing the cache object + * should abort any retrievals or stores it is doing on the cache. This + * increments inval_counter on the cookie which can be used by the caller to + * reconsider I/O requests as they complete. * - * Wait for the invalidation of an object to complete. + * If @flags has FSCACHE_INVAL_DIO_WRITE set, this indicates that this is due + * to a direct I/O write and will cause caching to be disabled on this cookie + * until it is completely unused. * * See Documentation/filesystems/caching/netfs-api.rst for a complete * description. */ static inline -void fscache_wait_on_invalidate(struct fscache_cookie *cookie) +void fscache_invalidate(struct fscache_cookie *cookie, + const void *aux_data, loff_t size, unsigned int flags) { - if (fscache_cookie_valid(cookie)) - __fscache_wait_on_invalidate(cookie); + if (fscache_cookie_enabled(cookie)) + __fscache_invalidate(cookie, aux_data, size, flags); } /** - * fscache_reserve_space - Reserve data space for a cached object - * @cookie: The cookie representing the cache object - * @i_size: The amount of space to be reserved - * - * Reserve an amount of space in the cache for the cache object attached to a - * cookie so that a write to that object within the space can always be - * honoured. + * fscache_operation_valid - Return true if operations resources are usable + * @cres: The resources to check. * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. + * Returns a pointer to the operations table if usable or NULL if not. */ static inline -int fscache_reserve_space(struct fscache_cookie *cookie, loff_t size) +const struct netfs_cache_ops *fscache_operation_valid(const struct netfs_cache_resources *cres) { - return -ENOBUFS; + return fscache_resources_valid(cres) ? cres->ops : NULL; } -#ifdef FSCACHE_USE_NEW_IO_API - /** * fscache_begin_read_operation - Begin a read operation for the netfs lib - * @rreq: The read request being undertaken + * @cres: The cache resources for the read being performed * @cookie: The cookie representing the cache object * - * Begin a read operation on behalf of the netfs helper library. @rreq - * indicates the read request to which the operation state should be attached; - * @cookie indicates the cache object that will be accessed. + * Begin a read operation on behalf of the netfs helper library. @cres + * indicates the cache resources to which the operation state should be + * attached; @cookie indicates the cache object that will be accessed. * * This is intended to be called from the ->begin_cache_operation() netfs lib * operation as implemented by the network filesystem. * + * @cres->inval_counter is set from @cookie->inval_counter for comparison at + * the end of the operation. This allows invalidation during the operation to + * be detected by the caller. + * * Returns: * * 0 - Success * * -ENOBUFS - No caching available * * Other error code from the cache, such as -ENOMEM. */ static inline -int fscache_begin_read_operation(struct netfs_read_request *rreq, +int fscache_begin_read_operation(struct netfs_cache_resources *cres, struct fscache_cookie *cookie) { - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_begin_read_operation(rreq, cookie); + if (fscache_cookie_enabled(cookie)) + return __fscache_begin_read_operation(cres, cookie); return -ENOBUFS; } -#else /* FSCACHE_USE_NEW_IO_API */ - -/** - * fscache_read_or_alloc_page - Read a page from the cache or allocate a block - * in which to store it - * @cookie: The cookie representing the cache object - * @page: The netfs page to fill if possible - * @end_io_func: The callback to invoke when and if the page is filled - * @context: An arbitrary piece of data to pass on to end_io_func() - * @gfp: The conditions under which memory allocation should be made - * - * Read a page from the cache, or if that's not possible make a potential - * one-block reservation in the cache into which the page may be stored once - * fetched from the server. - * - * If the page is not backed by the cache object, or if it there's some reason - * it can't be, -ENOBUFS will be returned and nothing more will be done for - * that page. - * - * Else, if that page is backed by the cache, a read will be initiated directly - * to the netfs's page and 0 will be returned by this function. The - * end_io_func() callback will be invoked when the operation terminates on a - * completion or failure. Note that the callback may be invoked before the - * return. - * - * Else, if the page is unbacked, -ENODATA is returned and a block may have - * been allocated in the cache. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ -static inline -int fscache_read_or_alloc_page(struct fscache_cookie *cookie, - struct page *page, - fscache_rw_complete_t end_io_func, - void *context, - gfp_t gfp) -{ - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_read_or_alloc_page(cookie, page, end_io_func, - context, gfp); - else - return -ENOBUFS; -} - /** - * fscache_read_or_alloc_pages - Read pages from the cache and/or allocate - * blocks in which to store them - * @cookie: The cookie representing the cache object - * @mapping: The netfs inode mapping to which the pages will be attached - * @pages: A list of potential netfs pages to be filled - * @nr_pages: Number of pages to be read and/or allocated - * @end_io_func: The callback to invoke when and if each page is filled - * @context: An arbitrary piece of data to pass on to end_io_func() - * @gfp: The conditions under which memory allocation should be made - * - * Read a set of pages from the cache, or if that's not possible, attempt to - * make a potential one-block reservation for each page in the cache into which - * that page may be stored once fetched from the server. - * - * If some pages are not backed by the cache object, or if it there's some - * reason they can't be, -ENOBUFS will be returned and nothing more will be - * done for that pages. - * - * Else, if some of the pages are backed by the cache, a read will be initiated - * directly to the netfs's page and 0 will be returned by this function. The - * end_io_func() callback will be invoked when the operation terminates on a - * completion or failure. Note that the callback may be invoked before the - * return. - * - * Else, if a page is unbacked, -ENODATA is returned and a block may have - * been allocated in the cache. - * - * Because the function may want to return all of -ENOBUFS, -ENODATA and 0 in - * regard to different pages, the return values are prioritised in that order. - * Any pages submitted for reading are removed from the pages list. + * fscache_read - Start a read from the cache. + * @cres: The cache resources to use + * @start_pos: The beginning file offset in the cache file + * @iter: The buffer to fill - and also the length + * @read_hole: How to handle a hole in the data. + * @term_func: The function to call upon completion + * @term_func_priv: The private data for @term_func * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ -static inline -int fscache_read_or_alloc_pages(struct fscache_cookie *cookie, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages, - fscache_rw_complete_t end_io_func, - void *context, - gfp_t gfp) -{ - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_read_or_alloc_pages(cookie, mapping, pages, - nr_pages, end_io_func, - context, gfp); - else - return -ENOBUFS; -} - -/** - * fscache_alloc_page - Allocate a block in which to store a page - * @cookie: The cookie representing the cache object - * @page: The netfs page to allocate a page for - * @gfp: The conditions under which memory allocation should be made + * Start a read from the cache. @cres indicates the cache object to read from + * and must be obtained by a call to fscache_begin_operation() beforehand. * - * Request Allocation a block in the cache in which to store a netfs page - * without retrieving any contents from the cache. + * The data is read into the iterator, @iter, and that also indicates the size + * of the operation. @start_pos is the start position in the file, though if + * @seek_data is set appropriately, the cache can use SEEK_DATA to find the + * next piece of data, writing zeros for the hole into the iterator. * - * If the page is not backed by a file then -ENOBUFS will be returned and - * nothing more will be done, and no reservation will be made. + * Upon termination of the operation, @term_func will be called and supplied + * with @term_func_priv plus the amount of data written, if successful, or the + * error code otherwise. * - * Else, a block will be allocated if one wasn't already, and 0 will be - * returned + * @read_hole indicates how a partially populated region in the cache should be + * handled. It can be one of a number of settings: * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ -static inline -int fscache_alloc_page(struct fscache_cookie *cookie, - struct page *page, - gfp_t gfp) -{ - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_alloc_page(cookie, page, gfp); - else - return -ENOBUFS; -} - -/** - * fscache_readpages_cancel - Cancel read/alloc on pages - * @cookie: The cookie representing the inode's cache object. - * @pages: The netfs pages that we canceled write on in readpages() + * NETFS_READ_HOLE_IGNORE - Just try to read (may return a short read). * - * Uncache/unreserve the pages reserved earlier in readpages() via - * fscache_readpages_or_alloc() and similar. In most successful caches in - * readpages() this doesn't do anything. In cases when the underlying netfs's - * readahead failed we need to clean up the pagelist (unmark and uncache). + * NETFS_READ_HOLE_CLEAR - Seek for data, clearing the part of the buffer + * skipped over, then do as for IGNORE. * - * This function may sleep as it may have to clean up disk state. + * NETFS_READ_HOLE_FAIL - Give ENODATA if we encounter a hole. */ static inline -void fscache_readpages_cancel(struct fscache_cookie *cookie, - struct list_head *pages) +int fscache_read(struct netfs_cache_resources *cres, + loff_t start_pos, + struct iov_iter *iter, + enum netfs_read_from_hole read_hole, + netfs_io_terminated_t term_func, + void *term_func_priv) { - if (fscache_cookie_valid(cookie)) - __fscache_readpages_cancel(cookie, pages); + const struct netfs_cache_ops *ops = fscache_operation_valid(cres); + return ops->read(cres, start_pos, iter, read_hole, + term_func, term_func_priv); } /** - * fscache_write_page - Request storage of a page in the cache + * fscache_begin_write_operation - Begin a write operation for the netfs lib + * @cres: The cache resources for the write being performed * @cookie: The cookie representing the cache object - * @page: The netfs page to store - * @object_size: Updated size of object - * @gfp: The conditions under which memory allocation should be made * - * Request the contents of the netfs page be written into the cache. This - * request may be ignored if no cache block is currently allocated, in which - * case it will return -ENOBUFS. + * Begin a write operation on behalf of the netfs helper library. @cres + * indicates the cache resources to which the operation state should be + * attached; @cookie indicates the cache object that will be accessed. * - * If a cache block was already allocated, a write will be initiated and 0 will - * be returned. The PG_fscache_write page bit is set immediately and will then - * be cleared at the completion of the write to indicate the success or failure - * of the operation. Note that the completion may happen before the return. + * @cres->inval_counter is set from @cookie->inval_counter for comparison at + * the end of the operation. This allows invalidation during the operation to + * be detected by the caller. * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. + * Returns: + * * 0 - Success + * * -ENOBUFS - No caching available + * * Other error code from the cache, such as -ENOMEM. */ static inline -int fscache_write_page(struct fscache_cookie *cookie, - struct page *page, - loff_t object_size, - gfp_t gfp) +int fscache_begin_write_operation(struct netfs_cache_resources *cres, + struct fscache_cookie *cookie) { - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - return __fscache_write_page(cookie, page, object_size, gfp); - else - return -ENOBUFS; + if (fscache_cookie_enabled(cookie)) + return __fscache_begin_write_operation(cres, cookie); + return -ENOBUFS; } /** - * fscache_uncache_page - Indicate that caching is no longer required on a page - * @cookie: The cookie representing the cache object - * @page: The netfs page that was being cached. + * fscache_write - Start a write to the cache. + * @cres: The cache resources to use + * @start_pos: The beginning file offset in the cache file + * @iter: The data to write - and also the length + * @term_func: The function to call upon completion + * @term_func_priv: The private data for @term_func * - * Tell the cache that we no longer want a page to be cached and that it should - * remove any knowledge of the netfs page it may have. + * Start a write to the cache. @cres indicates the cache object to write to and + * must be obtained by a call to fscache_begin_operation() beforehand. * - * Note that this cannot cancel any outstanding I/O operations between this - * page and the cache. + * The data to be written is obtained from the iterator, @iter, and that also + * indicates the size of the operation. @start_pos is the start position in + * the file. * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. + * Upon termination of the operation, @term_func will be called and supplied + * with @term_func_priv plus the amount of data written, if successful, or the + * error code otherwise. */ static inline -void fscache_uncache_page(struct fscache_cookie *cookie, - struct page *page) +int fscache_write(struct netfs_cache_resources *cres, + loff_t start_pos, + struct iov_iter *iter, + netfs_io_terminated_t term_func, + void *term_func_priv) { - if (fscache_cookie_valid(cookie)) - __fscache_uncache_page(cookie, page); + const struct netfs_cache_ops *ops = fscache_operation_valid(cres); + return ops->write(cres, start_pos, iter, term_func, term_func_priv); } /** - * fscache_check_page_write - Ask if a page is being writing to the cache + * fscache_clear_page_bits - Clear the PG_fscache bits from a set of pages * @cookie: The cookie representing the cache object - * @page: The netfs page that is being cached. - * - * Ask the cache if a page is being written to the cache. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ -static inline -bool fscache_check_page_write(struct fscache_cookie *cookie, - struct page *page) + * @mapping: The netfs inode to use as the source + * @start: The start position in @mapping + * @len: The amount of data to unlock + * @caching: If PG_fscache has been set + * + * Clear the PG_fscache flag from a sequence of pages and wake up anyone who's + * waiting. + */ +static inline void fscache_clear_page_bits(struct fscache_cookie *cookie, + struct address_space *mapping, + loff_t start, size_t len, + bool caching) { - if (fscache_cookie_valid(cookie)) - return __fscache_check_page_write(cookie, page); - return false; + if (caching) + __fscache_clear_page_bits(mapping, start, len); } /** - * fscache_wait_on_page_write - Wait for a page to complete writing to the cache + * fscache_write_to_cache - Save a write to the cache and clear PG_fscache * @cookie: The cookie representing the cache object - * @page: The netfs page that is being cached. - * - * Ask the cache to wake us up when a page is no longer being written to the - * cache. - * - * See Documentation/filesystems/caching/netfs-api.rst for a complete - * description. - */ -static inline -void fscache_wait_on_page_write(struct fscache_cookie *cookie, - struct page *page) + * @mapping: The netfs inode to use as the source + * @start: The start position in @mapping + * @len: The amount of data to write back + * @i_size: The new size of the inode + * @term_func: The function to call upon completion + * @term_func_priv: The private data for @term_func + * @caching: If PG_fscache has been set + * + * Helper function for a netfs to write dirty data from an inode into the cache + * object that's backing it. + * + * @start and @len describe the range of the data. This does not need to be + * page-aligned, but to satisfy DIO requirements, the cache may expand it up to + * the page boundaries on either end. All the pages covering the range must be + * marked with PG_fscache. + * + * If given, @term_func will be called upon completion and supplied with + * @term_func_priv. Note that the PG_fscache flags will have been cleared by + * this point, so the netfs must retain its own pin on the mapping. + */ +static inline void fscache_write_to_cache(struct fscache_cookie *cookie, + struct address_space *mapping, + loff_t start, size_t len, loff_t i_size, + netfs_io_terminated_t term_func, + void *term_func_priv, + bool caching) { - if (fscache_cookie_valid(cookie)) - __fscache_wait_on_page_write(cookie, page); -} + if (caching) + __fscache_write_to_cache(cookie, mapping, start, len, i_size, + term_func, term_func_priv, caching); + else if (term_func) + term_func(term_func_priv, -ENOBUFS, false); -/** - * fscache_maybe_release_page - Consider releasing a page, cancelling a store - * @cookie: The cookie representing the cache object - * @page: The netfs page that is being cached. - * @gfp: The gfp flags passed to releasepage() - * - * Consider releasing a page for the vmscan algorithm, on behalf of the netfs's - * releasepage() call. A storage request on the page may cancelled if it is - * not currently being processed. - * - * The function returns true if the page no longer has a storage request on it, - * and false if a storage request is left in place. If true is returned, the - * page will have been passed to fscache_uncache_page(). If false is returned - * the page cannot be freed yet. - */ -static inline -bool fscache_maybe_release_page(struct fscache_cookie *cookie, - struct page *page, - gfp_t gfp) -{ - if (fscache_cookie_valid(cookie) && PageFsCache(page)) - return __fscache_maybe_release_page(cookie, page, gfp); - return true; } +#if __fscache_available +extern int fscache_set_page_dirty(struct page *page, struct fscache_cookie *cookie); +#else +#define fscache_set_page_dirty(PAGE, COOKIE) (__set_page_dirty_nobuffers((PAGE))) +#endif + /** - * fscache_uncache_all_inode_pages - Uncache all an inode's pages - * @cookie: The cookie representing the inode's cache object. - * @inode: The inode to uncache pages from. - * - * Uncache all the pages in an inode that are marked PG_fscache, assuming them - * to be associated with the given cookie. + * fscache_unpin_writeback - Unpin writeback resources + * @wbc: The writeback control + * @cookie: The cookie referring to the cache object * - * This function may sleep. It will wait for pages that are being written out - * and will wait whilst the PG_fscache mark is removed by the cache. + * Unpin the writeback resources pinned by fscache_set_page_dirty(). This is + * intended to be called by the netfs's ->write_inode() method. */ -static inline -void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie, - struct inode *inode) +static inline void fscache_unpin_writeback(struct writeback_control *wbc, + struct fscache_cookie *cookie) { - if (fscache_cookie_valid(cookie)) - __fscache_uncache_all_inode_pages(cookie, inode); + if (wbc->unpinned_fscache_wb) + fscache_unuse_cookie(cookie, NULL, NULL); } -#endif /* FSCACHE_USE_NEW_IO_API */ - /** - * fscache_disable_cookie - Disable a cookie - * @cookie: The cookie representing the cache object - * @aux_data: The updated auxiliary data for the cookie (may be NULL) - * @invalidate: Invalidate the backing object - * - * Disable a cookie from accepting further alloc, read, write, invalidate, - * update or acquire operations. Outstanding operations can still be waited - * upon and pages can still be uncached and the cookie relinquished. - * - * This will not return until all outstanding operations have completed. + * fscache_clear_inode_writeback - Clear writeback resources pinned by an inode + * @cookie: The cookie referring to the cache object + * @inode: The inode to clean up + * @aux: Auxiliary data to apply to the inode * - * If @invalidate is set, then the backing object will be invalidated and - * detached, otherwise it will just be detached. - * - * If @aux_data is set, then auxiliary data will be updated from that. + * Clear any writeback resources held by an inode when the inode is evicted. + * This must be called before clear_inode() is called. */ -static inline -void fscache_disable_cookie(struct fscache_cookie *cookie, - const void *aux_data, - bool invalidate) +static inline void fscache_clear_inode_writeback(struct fscache_cookie *cookie, + struct inode *inode, + const void *aux) { - if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) - __fscache_disable_cookie(cookie, aux_data, invalidate); + if (inode->i_state & I_PINNING_FSCACHE_WB) { + loff_t i_size = i_size_read(inode); + fscache_unuse_cookie(cookie, aux, &i_size); + } } /** - * fscache_enable_cookie - Reenable a cookie - * @cookie: The cookie representing the cache object - * @aux_data: The updated auxiliary data for the cookie (may be NULL) - * @object_size: Current size of object - * @can_enable: A function to permit enablement once lock is held - * @data: Data for can_enable() - * - * Reenable a previously disabled cookie, allowing it to accept further alloc, - * read, write, invalidate, update or acquire operations. An attempt will be - * made to immediately reattach the cookie to a backing object. If @aux_data - * is set, the auxiliary data attached to the cookie will be updated. + * fscache_note_page_release - Note that a netfs page got released + * @cookie: The cookie corresponding to the file * - * The can_enable() function is called (if not NULL) once the enablement lock - * is held to rule on whether enablement is still permitted to go ahead. + * Note that a page that has been copied to the cache has been released. This + * means that future reads will need to look in the cache to see if it's there. */ static inline -void fscache_enable_cookie(struct fscache_cookie *cookie, - const void *aux_data, - loff_t object_size, - bool (*can_enable)(void *data), - void *data) +void fscache_note_page_release(struct fscache_cookie *cookie) { - if (fscache_cookie_valid(cookie) && !fscache_cookie_enabled(cookie)) - __fscache_enable_cookie(cookie, aux_data, object_size, - can_enable, data); + if (cookie && + test_bit(FSCACHE_COOKIE_HAVE_DATA, &cookie->flags) && + test_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags)) + clear_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags); } #endif /* _LINUX_FSCACHE_H */ diff --git a/include/linux/netfs.h b/include/linux/netfs.h index ca0683b9e3d1..b46c39d98bbd 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -124,6 +124,7 @@ struct netfs_cache_resources { void *cache_priv; void *cache_priv2; unsigned int debug_id; /* Cookie debug ID */ + unsigned int inval_counter; /* object->inval_counter at begin_op */ }; /* @@ -196,6 +197,15 @@ struct netfs_read_request_ops { }; /* + * How to handle reading from a hole. + */ +enum netfs_read_from_hole { + NETFS_READ_HOLE_IGNORE, + NETFS_READ_HOLE_CLEAR, + NETFS_READ_HOLE_FAIL, +}; + +/* * Table of operations for access to a cache. This is obtained by * rreq->ops->begin_cache_operation(). */ @@ -207,7 +217,7 @@ struct netfs_cache_ops { int (*read)(struct netfs_cache_resources *cres, loff_t start_pos, struct iov_iter *iter, - bool seek_data, + enum netfs_read_from_hole read_hole, netfs_io_terminated_t term_func, void *term_func_priv); @@ -232,7 +242,8 @@ struct netfs_cache_ops { * actually do. */ int (*prepare_write)(struct netfs_cache_resources *cres, - loff_t *_start, size_t *_len, loff_t i_size); + loff_t *_start, size_t *_len, loff_t i_size, + bool no_space_allocated_yet); }; struct readahead_control; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 05f249f20f55..00835bacd236 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -275,7 +275,6 @@ struct nfs4_copy_state { #define NFS_INO_ACL_LRU_SET (2) /* Inode is on the LRU list */ #define NFS_INO_INVALIDATING (3) /* inode is being invalidated */ #define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */ -#define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */ #define NFS_INO_FORCE_READDIR (7) /* force readdirplus */ #define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */ #define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */ diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 2a9acbfe00f0..77b2dba27bbb 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -120,11 +120,6 @@ struct nfs_client { * This is used to generate the mv0 callback address. */ char cl_ipaddr[48]; - -#ifdef CONFIG_NFS_FSCACHE - struct fscache_cookie *fscache; /* client index cache cookie */ -#endif - struct net *cl_net; struct list_head pending_cb_stateids; }; @@ -194,8 +189,8 @@ struct nfs_server { struct nfs_auth_info auth_info; /* parsed auth flavors */ #ifdef CONFIG_NFS_FSCACHE - struct nfs_fscache_key *fscache_key; /* unique key for superblock */ - struct fscache_cookie *fscache; /* superblock cookie */ + struct fscache_volume *fscache; /* superblock cookie */ + char *fscache_uniq; /* Uniquifier (or NULL) */ #endif u32 pnfs_blksize; /* layout_blksize attr */ diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 3bfd487d1dd2..fec248ab1fec 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -68,6 +68,7 @@ struct writeback_control { unsigned for_reclaim:1; /* Invoked from the page allocator */ unsigned range_cyclic:1; /* range_start is cyclic */ unsigned for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ + unsigned unpinned_fscache_wb:1; /* Cleared I_PINNING_FSCACHE_WB */ /* * When writeback IOs are bounced through async layers, only the diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h index 920b6a303d60..1172529b5b49 100644 --- a/include/trace/events/cachefiles.h +++ b/include/trace/events/cachefiles.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* CacheFiles tracepoints * - * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) */ #undef TRACE_SYSTEM @@ -19,9 +19,83 @@ #define __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY enum cachefiles_obj_ref_trace { - cachefiles_obj_put_wait_retry = fscache_obj_ref__nr_traces, - cachefiles_obj_put_wait_timeo, - cachefiles_obj_ref__nr_traces + cachefiles_obj_get_ioreq, + cachefiles_obj_new, + cachefiles_obj_put_alloc_fail, + cachefiles_obj_put_detach, + cachefiles_obj_put_ioreq, + cachefiles_obj_see_clean_commit, + cachefiles_obj_see_clean_delete, + cachefiles_obj_see_clean_drop_tmp, + cachefiles_obj_see_lookup_cookie, + cachefiles_obj_see_lookup_failed, + cachefiles_obj_see_withdraw_cookie, + cachefiles_obj_see_withdrawal, +}; + +enum fscache_why_object_killed { + FSCACHE_OBJECT_IS_STALE, + FSCACHE_OBJECT_IS_WEIRD, + FSCACHE_OBJECT_INVALIDATED, + FSCACHE_OBJECT_NO_SPACE, + FSCACHE_OBJECT_WAS_RETIRED, + FSCACHE_OBJECT_WAS_CULLED, + FSCACHE_VOLUME_IS_WEIRD, +}; + +enum cachefiles_coherency_trace { + cachefiles_coherency_check_aux, + cachefiles_coherency_check_content, + cachefiles_coherency_check_dirty, + cachefiles_coherency_check_len, + cachefiles_coherency_check_objsize, + cachefiles_coherency_check_ok, + cachefiles_coherency_check_type, + cachefiles_coherency_check_xattr, + cachefiles_coherency_set_fail, + cachefiles_coherency_set_ok, + cachefiles_coherency_vol_check_cmp, + cachefiles_coherency_vol_check_ok, + cachefiles_coherency_vol_check_xattr, + cachefiles_coherency_vol_set_fail, + cachefiles_coherency_vol_set_ok, +}; + +enum cachefiles_trunc_trace { + cachefiles_trunc_dio_adjust, + cachefiles_trunc_expand_tmpfile, + cachefiles_trunc_shrink, +}; + +enum cachefiles_prepare_read_trace { + cachefiles_trace_read_after_eof, + cachefiles_trace_read_found_hole, + cachefiles_trace_read_found_part, + cachefiles_trace_read_have_data, + cachefiles_trace_read_no_data, + cachefiles_trace_read_no_file, + cachefiles_trace_read_seek_error, + cachefiles_trace_read_seek_nxio, +}; + +enum cachefiles_error_trace { + cachefiles_trace_fallocate_error, + cachefiles_trace_getxattr_error, + cachefiles_trace_link_error, + cachefiles_trace_lookup_error, + cachefiles_trace_mkdir_error, + cachefiles_trace_notify_change_error, + cachefiles_trace_open_error, + cachefiles_trace_read_error, + cachefiles_trace_remxattr_error, + cachefiles_trace_rename_error, + cachefiles_trace_seek_error, + cachefiles_trace_setxattr_error, + cachefiles_trace_statfs_error, + cachefiles_trace_tmpfile_error, + cachefiles_trace_trunc_error, + cachefiles_trace_unlink_error, + cachefiles_trace_write_error, }; #endif @@ -31,21 +105,78 @@ enum cachefiles_obj_ref_trace { */ #define cachefiles_obj_kill_traces \ EM(FSCACHE_OBJECT_IS_STALE, "stale") \ + EM(FSCACHE_OBJECT_IS_WEIRD, "weird") \ + EM(FSCACHE_OBJECT_INVALIDATED, "inval") \ EM(FSCACHE_OBJECT_NO_SPACE, "no_space") \ EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \ - E_(FSCACHE_OBJECT_WAS_CULLED, "was_culled") + EM(FSCACHE_OBJECT_WAS_CULLED, "was_culled") \ + E_(FSCACHE_VOLUME_IS_WEIRD, "volume_weird") #define cachefiles_obj_ref_traces \ - EM(fscache_obj_get_add_to_deps, "GET add_to_deps") \ - EM(fscache_obj_get_queue, "GET queue") \ - EM(fscache_obj_put_alloc_fail, "PUT alloc_fail") \ - EM(fscache_obj_put_attach_fail, "PUT attach_fail") \ - EM(fscache_obj_put_drop_obj, "PUT drop_obj") \ - EM(fscache_obj_put_enq_dep, "PUT enq_dep") \ - EM(fscache_obj_put_queue, "PUT queue") \ - EM(fscache_obj_put_work, "PUT work") \ - EM(cachefiles_obj_put_wait_retry, "PUT wait_retry") \ - E_(cachefiles_obj_put_wait_timeo, "PUT wait_timeo") + EM(cachefiles_obj_get_ioreq, "GET ioreq") \ + EM(cachefiles_obj_new, "NEW obj") \ + EM(cachefiles_obj_put_alloc_fail, "PUT alloc_fail") \ + EM(cachefiles_obj_put_detach, "PUT detach") \ + EM(cachefiles_obj_put_ioreq, "PUT ioreq") \ + EM(cachefiles_obj_see_clean_commit, "SEE clean_commit") \ + EM(cachefiles_obj_see_clean_delete, "SEE clean_delete") \ + EM(cachefiles_obj_see_clean_drop_tmp, "SEE clean_drop_tmp") \ + EM(cachefiles_obj_see_lookup_cookie, "SEE lookup_cookie") \ + EM(cachefiles_obj_see_lookup_failed, "SEE lookup_failed") \ + EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \ + E_(cachefiles_obj_see_withdrawal, "SEE withdrawal") + +#define cachefiles_coherency_traces \ + EM(cachefiles_coherency_check_aux, "BAD aux ") \ + EM(cachefiles_coherency_check_content, "BAD cont") \ + EM(cachefiles_coherency_check_dirty, "BAD dirt") \ + EM(cachefiles_coherency_check_len, "BAD len ") \ + EM(cachefiles_coherency_check_objsize, "BAD osiz") \ + EM(cachefiles_coherency_check_ok, "OK ") \ + EM(cachefiles_coherency_check_type, "BAD type") \ + EM(cachefiles_coherency_check_xattr, "BAD xatt") \ + EM(cachefiles_coherency_set_fail, "SET fail") \ + EM(cachefiles_coherency_set_ok, "SET ok ") \ + EM(cachefiles_coherency_vol_check_cmp, "VOL BAD cmp ") \ + EM(cachefiles_coherency_vol_check_ok, "VOL OK ") \ + EM(cachefiles_coherency_vol_check_xattr,"VOL BAD xatt") \ + EM(cachefiles_coherency_vol_set_fail, "VOL SET fail") \ + E_(cachefiles_coherency_vol_set_ok, "VOL SET ok ") + +#define cachefiles_trunc_traces \ + EM(cachefiles_trunc_dio_adjust, "DIOADJ") \ + EM(cachefiles_trunc_expand_tmpfile, "EXPTMP") \ + E_(cachefiles_trunc_shrink, "SHRINK") + +#define cachefiles_prepare_read_traces \ + EM(cachefiles_trace_read_after_eof, "after-eof ") \ + EM(cachefiles_trace_read_found_hole, "found-hole") \ + EM(cachefiles_trace_read_found_part, "found-part") \ + EM(cachefiles_trace_read_have_data, "have-data ") \ + EM(cachefiles_trace_read_no_data, "no-data ") \ + EM(cachefiles_trace_read_no_file, "no-file ") \ + EM(cachefiles_trace_read_seek_error, "seek-error") \ + E_(cachefiles_trace_read_seek_nxio, "seek-enxio") + +#define cachefiles_error_traces \ + EM(cachefiles_trace_fallocate_error, "fallocate") \ + EM(cachefiles_trace_getxattr_error, "getxattr") \ + EM(cachefiles_trace_link_error, "link") \ + EM(cachefiles_trace_lookup_error, "lookup") \ + EM(cachefiles_trace_mkdir_error, "mkdir") \ + EM(cachefiles_trace_notify_change_error, "notify_change") \ + EM(cachefiles_trace_open_error, "open") \ + EM(cachefiles_trace_read_error, "read") \ + EM(cachefiles_trace_remxattr_error, "remxattr") \ + EM(cachefiles_trace_rename_error, "rename") \ + EM(cachefiles_trace_seek_error, "seek") \ + EM(cachefiles_trace_setxattr_error, "setxattr") \ + EM(cachefiles_trace_statfs_error, "statfs") \ + EM(cachefiles_trace_tmpfile_error, "tmpfile") \ + EM(cachefiles_trace_trunc_error, "trunc") \ + EM(cachefiles_trace_unlink_error, "unlink") \ + E_(cachefiles_trace_write_error, "write") + /* * Export enum symbols via userspace. @@ -57,6 +188,10 @@ enum cachefiles_obj_ref_trace { cachefiles_obj_kill_traces; cachefiles_obj_ref_traces; +cachefiles_coherency_traces; +cachefiles_trunc_traces; +cachefiles_prepare_read_traces; +cachefiles_error_traces; /* * Now redefine the EM() and E_() macros to map the enums to the strings that @@ -69,12 +204,12 @@ cachefiles_obj_ref_traces; TRACE_EVENT(cachefiles_ref, - TP_PROTO(struct cachefiles_object *obj, - struct fscache_cookie *cookie, - enum cachefiles_obj_ref_trace why, - int usage), + TP_PROTO(unsigned int object_debug_id, + unsigned int cookie_debug_id, + int usage, + enum cachefiles_obj_ref_trace why), - TP_ARGS(obj, cookie, why, usage), + TP_ARGS(object_debug_id, cookie_debug_id, usage, why), /* Note that obj may be NULL */ TP_STRUCT__entry( @@ -85,8 +220,8 @@ TRACE_EVENT(cachefiles_ref, ), TP_fast_assign( - __entry->obj = obj->fscache.debug_id; - __entry->cookie = cookie->debug_id; + __entry->obj = object_debug_id; + __entry->cookie = cookie_debug_id; __entry->usage = usage; __entry->why = why; ), @@ -98,69 +233,65 @@ TRACE_EVENT(cachefiles_ref, TRACE_EVENT(cachefiles_lookup, TP_PROTO(struct cachefiles_object *obj, - struct dentry *de, - struct inode *inode), + struct dentry *de), - TP_ARGS(obj, de, inode), + TP_ARGS(obj, de), TP_STRUCT__entry( __field(unsigned int, obj ) - __field(struct dentry *, de ) - __field(struct inode *, inode ) + __field(short, error ) + __field(unsigned long, ino ) ), TP_fast_assign( - __entry->obj = obj->fscache.debug_id; - __entry->de = de; - __entry->inode = inode; + __entry->obj = obj->debug_id; + __entry->ino = (!IS_ERR(de) && d_backing_inode(de) ? + d_backing_inode(de)->i_ino : 0); + __entry->error = IS_ERR(de) ? PTR_ERR(de) : 0; ), - TP_printk("o=%08x d=%p i=%p", - __entry->obj, __entry->de, __entry->inode) + TP_printk("o=%08x i=%lx e=%d", + __entry->obj, __entry->ino, __entry->error) ); -TRACE_EVENT(cachefiles_mkdir, - TP_PROTO(struct cachefiles_object *obj, - struct dentry *de, int ret), +TRACE_EVENT(cachefiles_tmpfile, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer), - TP_ARGS(obj, de, ret), + TP_ARGS(obj, backer), TP_STRUCT__entry( - __field(unsigned int, obj ) - __field(struct dentry *, de ) - __field(int, ret ) + __field(unsigned int, obj ) + __field(unsigned int, backer ) ), TP_fast_assign( - __entry->obj = obj->fscache.debug_id; - __entry->de = de; - __entry->ret = ret; + __entry->obj = obj->debug_id; + __entry->backer = backer->i_ino; ), - TP_printk("o=%08x d=%p r=%u", - __entry->obj, __entry->de, __entry->ret) + TP_printk("o=%08x b=%08x", + __entry->obj, + __entry->backer) ); -TRACE_EVENT(cachefiles_create, - TP_PROTO(struct cachefiles_object *obj, - struct dentry *de, int ret), +TRACE_EVENT(cachefiles_link, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer), - TP_ARGS(obj, de, ret), + TP_ARGS(obj, backer), TP_STRUCT__entry( - __field(unsigned int, obj ) - __field(struct dentry *, de ) - __field(int, ret ) + __field(unsigned int, obj ) + __field(unsigned int, backer ) ), TP_fast_assign( - __entry->obj = obj->fscache.debug_id; - __entry->de = de; - __entry->ret = ret; + __entry->obj = obj->debug_id; + __entry->backer = backer->i_ino; ), - TP_printk("o=%08x d=%p r=%u", - __entry->obj, __entry->de, __entry->ret) + TP_printk("o=%08x b=%08x", + __entry->obj, + __entry->backer) ); TRACE_EVENT(cachefiles_unlink, @@ -178,7 +309,7 @@ TRACE_EVENT(cachefiles_unlink, ), TP_fast_assign( - __entry->obj = obj ? obj->fscache.debug_id : UINT_MAX; + __entry->obj = obj ? obj->debug_id : UINT_MAX; __entry->de = de; __entry->why = why; ), @@ -205,7 +336,7 @@ TRACE_EVENT(cachefiles_rename, ), TP_fast_assign( - __entry->obj = obj ? obj->fscache.debug_id : UINT_MAX; + __entry->obj = obj ? obj->debug_id : UINT_MAX; __entry->de = de; __entry->to = to; __entry->why = why; @@ -216,103 +347,285 @@ TRACE_EVENT(cachefiles_rename, __print_symbolic(__entry->why, cachefiles_obj_kill_traces)) ); -TRACE_EVENT(cachefiles_mark_active, +TRACE_EVENT(cachefiles_coherency, TP_PROTO(struct cachefiles_object *obj, - struct dentry *de), + ino_t ino, + enum cachefiles_content content, + enum cachefiles_coherency_trace why), - TP_ARGS(obj, de), + TP_ARGS(obj, ino, content, why), /* Note that obj may be NULL */ TP_STRUCT__entry( - __field(unsigned int, obj ) - __field(struct dentry *, de ) + __field(unsigned int, obj ) + __field(enum cachefiles_coherency_trace, why ) + __field(enum cachefiles_content, content ) + __field(u64, ino ) ), TP_fast_assign( - __entry->obj = obj->fscache.debug_id; - __entry->de = de; + __entry->obj = obj->debug_id; + __entry->why = why; + __entry->content = content; + __entry->ino = ino; ), - TP_printk("o=%08x d=%p", - __entry->obj, __entry->de) + TP_printk("o=%08x %s i=%llx c=%u", + __entry->obj, + __print_symbolic(__entry->why, cachefiles_coherency_traces), + __entry->ino, + __entry->content) ); -TRACE_EVENT(cachefiles_wait_active, - TP_PROTO(struct cachefiles_object *obj, - struct dentry *de, - struct cachefiles_object *xobj), +TRACE_EVENT(cachefiles_vol_coherency, + TP_PROTO(struct cachefiles_volume *volume, + ino_t ino, + enum cachefiles_coherency_trace why), - TP_ARGS(obj, de, xobj), + TP_ARGS(volume, ino, why), /* Note that obj may be NULL */ TP_STRUCT__entry( - __field(unsigned int, obj ) - __field(unsigned int, xobj ) - __field(struct dentry *, de ) - __field(u16, flags ) - __field(u16, fsc_flags ) + __field(unsigned int, vol ) + __field(enum cachefiles_coherency_trace, why ) + __field(u64, ino ) ), TP_fast_assign( - __entry->obj = obj->fscache.debug_id; - __entry->de = de; - __entry->xobj = xobj->fscache.debug_id; - __entry->flags = xobj->flags; - __entry->fsc_flags = xobj->fscache.flags; + __entry->vol = volume->vcookie->debug_id; + __entry->why = why; + __entry->ino = ino; ), - TP_printk("o=%08x d=%p wo=%08x wf=%x wff=%x", - __entry->obj, __entry->de, __entry->xobj, - __entry->flags, __entry->fsc_flags) + TP_printk("V=%08x %s i=%llx", + __entry->vol, + __print_symbolic(__entry->why, cachefiles_coherency_traces), + __entry->ino) ); -TRACE_EVENT(cachefiles_mark_inactive, +TRACE_EVENT(cachefiles_prep_read, + TP_PROTO(struct netfs_read_subrequest *sreq, + enum netfs_read_source source, + enum cachefiles_prepare_read_trace why, + ino_t cache_inode), + + TP_ARGS(sreq, source, why, cache_inode), + + TP_STRUCT__entry( + __field(unsigned int, rreq ) + __field(unsigned short, index ) + __field(unsigned short, flags ) + __field(enum netfs_read_source, source ) + __field(enum cachefiles_prepare_read_trace, why ) + __field(size_t, len ) + __field(loff_t, start ) + __field(unsigned int, netfs_inode ) + __field(unsigned int, cache_inode ) + ), + + TP_fast_assign( + __entry->rreq = sreq->rreq->debug_id; + __entry->index = sreq->debug_index; + __entry->flags = sreq->flags; + __entry->source = source; + __entry->why = why; + __entry->len = sreq->len; + __entry->start = sreq->start; + __entry->netfs_inode = sreq->rreq->inode->i_ino; + __entry->cache_inode = cache_inode; + ), + + TP_printk("R=%08x[%u] %s %s f=%02x s=%llx %zx ni=%x b=%x", + __entry->rreq, __entry->index, + __print_symbolic(__entry->source, netfs_sreq_sources), + __print_symbolic(__entry->why, cachefiles_prepare_read_traces), + __entry->flags, + __entry->start, __entry->len, + __entry->netfs_inode, __entry->cache_inode) + ); + +TRACE_EVENT(cachefiles_read, + TP_PROTO(struct cachefiles_object *obj, + struct inode *backer, + loff_t start, + size_t len), + + TP_ARGS(obj, backer, start, len), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(size_t, len ) + __field(loff_t, start ) + ), + + TP_fast_assign( + __entry->obj = obj->debug_id; + __entry->backer = backer->i_ino; + __entry->start = start; + __entry->len = len; + ), + + TP_printk("o=%08x b=%08x s=%llx l=%zx", + __entry->obj, + __entry->backer, + __entry->start, + __entry->len) + ); + +TRACE_EVENT(cachefiles_write, + TP_PROTO(struct cachefiles_object *obj, + struct inode *backer, + loff_t start, + size_t len), + + TP_ARGS(obj, backer, start, len), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(size_t, len ) + __field(loff_t, start ) + ), + + TP_fast_assign( + __entry->obj = obj->debug_id; + __entry->backer = backer->i_ino; + __entry->start = start; + __entry->len = len; + ), + + TP_printk("o=%08x b=%08x s=%llx l=%zx", + __entry->obj, + __entry->backer, + __entry->start, + __entry->len) + ); + +TRACE_EVENT(cachefiles_trunc, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer, + loff_t from, loff_t to, enum cachefiles_trunc_trace why), + + TP_ARGS(obj, backer, from, to, why), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(enum cachefiles_trunc_trace, why ) + __field(loff_t, from ) + __field(loff_t, to ) + ), + + TP_fast_assign( + __entry->obj = obj->debug_id; + __entry->backer = backer->i_ino; + __entry->from = from; + __entry->to = to; + __entry->why = why; + ), + + TP_printk("o=%08x b=%08x %s l=%llx->%llx", + __entry->obj, + __entry->backer, + __print_symbolic(__entry->why, cachefiles_trunc_traces), + __entry->from, + __entry->to) + ); + +TRACE_EVENT(cachefiles_mark_active, TP_PROTO(struct cachefiles_object *obj, - struct dentry *de, struct inode *inode), - TP_ARGS(obj, de, inode), + TP_ARGS(obj, inode), /* Note that obj may be NULL */ TP_STRUCT__entry( __field(unsigned int, obj ) - __field(struct dentry *, de ) - __field(struct inode *, inode ) + __field(ino_t, inode ) ), TP_fast_assign( - __entry->obj = obj->fscache.debug_id; - __entry->de = de; - __entry->inode = inode; + __entry->obj = obj ? obj->debug_id : 0; + __entry->inode = inode->i_ino; ), - TP_printk("o=%08x d=%p i=%p", - __entry->obj, __entry->de, __entry->inode) + TP_printk("o=%08x i=%lx", + __entry->obj, __entry->inode) ); -TRACE_EVENT(cachefiles_mark_buried, +TRACE_EVENT(cachefiles_mark_inactive, TP_PROTO(struct cachefiles_object *obj, - struct dentry *de, - enum fscache_why_object_killed why), + struct inode *inode), - TP_ARGS(obj, de, why), + TP_ARGS(obj, inode), /* Note that obj may be NULL */ TP_STRUCT__entry( __field(unsigned int, obj ) - __field(struct dentry *, de ) - __field(enum fscache_why_object_killed, why ) + __field(ino_t, inode ) ), TP_fast_assign( - __entry->obj = obj ? obj->fscache.debug_id : UINT_MAX; - __entry->de = de; - __entry->why = why; + __entry->obj = obj ? obj->debug_id : 0; + __entry->inode = inode->i_ino; ), - TP_printk("o=%08x d=%p w=%s", - __entry->obj, __entry->de, - __print_symbolic(__entry->why, cachefiles_obj_kill_traces)) + TP_printk("o=%08x i=%lx", + __entry->obj, __entry->inode) + ); + +TRACE_EVENT(cachefiles_vfs_error, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer, + int error, enum cachefiles_error_trace where), + + TP_ARGS(obj, backer, error, where), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(enum cachefiles_error_trace, where ) + __field(short, error ) + ), + + TP_fast_assign( + __entry->obj = obj ? obj->debug_id : 0; + __entry->backer = backer->i_ino; + __entry->error = error; + __entry->where = where; + ), + + TP_printk("o=%08x b=%08x %s e=%d", + __entry->obj, + __entry->backer, + __print_symbolic(__entry->where, cachefiles_error_traces), + __entry->error) + ); + +TRACE_EVENT(cachefiles_io_error, + TP_PROTO(struct cachefiles_object *obj, struct inode *backer, + int error, enum cachefiles_error_trace where), + + TP_ARGS(obj, backer, error, where), + + TP_STRUCT__entry( + __field(unsigned int, obj ) + __field(unsigned int, backer ) + __field(enum cachefiles_error_trace, where ) + __field(short, error ) + ), + + TP_fast_assign( + __entry->obj = obj ? obj->debug_id : 0; + __entry->backer = backer->i_ino; + __entry->error = error; + __entry->where = where; + ), + + TP_printk("o=%08x b=%08x %s e=%d", + __entry->obj, + __entry->backer, + __print_symbolic(__entry->where, cachefiles_error_traces), + __entry->error) ); #endif /* _TRACE_CACHEFILES_H */ diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h index 446392f5ba83..cb3fb337e880 100644 --- a/include/trace/events/fscache.h +++ b/include/trace/events/fscache.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* FS-Cache tracepoints * - * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) */ #undef TRACE_SYSTEM @@ -19,65 +19,83 @@ #ifndef __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY #define __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY +enum fscache_cache_trace { + fscache_cache_collision, + fscache_cache_get_acquire, + fscache_cache_new_acquire, + fscache_cache_put_alloc_volume, + fscache_cache_put_cache, + fscache_cache_put_prep_failed, + fscache_cache_put_relinquish, + fscache_cache_put_volume, +}; + +enum fscache_volume_trace { + fscache_volume_collision, + fscache_volume_get_cookie, + fscache_volume_get_create_work, + fscache_volume_get_hash_collision, + fscache_volume_free, + fscache_volume_new_acquire, + fscache_volume_put_cookie, + fscache_volume_put_create_work, + fscache_volume_put_hash_collision, + fscache_volume_put_relinquish, + fscache_volume_see_create_work, + fscache_volume_see_hash_wake, + fscache_volume_wait_create_work, +}; + enum fscache_cookie_trace { fscache_cookie_collision, fscache_cookie_discard, - fscache_cookie_get_acquire_parent, fscache_cookie_get_attach_object, - fscache_cookie_get_reacquire, - fscache_cookie_get_register_netfs, - fscache_cookie_put_acquire_nobufs, - fscache_cookie_put_dup_netfs, - fscache_cookie_put_relinquish, + fscache_cookie_get_end_access, + fscache_cookie_get_hash_collision, + fscache_cookie_get_inval_work, + fscache_cookie_get_lru, + fscache_cookie_get_use_work, + fscache_cookie_new_acquire, + fscache_cookie_put_hash_collision, + fscache_cookie_put_lru, fscache_cookie_put_object, - fscache_cookie_put_parent, -}; - -enum fscache_page_trace { - fscache_page_cached, - fscache_page_inval, - fscache_page_maybe_release, - fscache_page_radix_clear_store, - fscache_page_radix_delete, - fscache_page_radix_insert, - fscache_page_radix_pend2store, - fscache_page_radix_set_pend, - fscache_page_uncache, - fscache_page_write, - fscache_page_write_end, - fscache_page_write_end_pend, - fscache_page_write_end_noc, - fscache_page_write_wait, - fscache_page_trace__nr + fscache_cookie_put_over_queued, + fscache_cookie_put_relinquish, + fscache_cookie_put_withdrawn, + fscache_cookie_put_work, + fscache_cookie_see_active, + fscache_cookie_see_lru_discard, + fscache_cookie_see_lru_do_one, + fscache_cookie_see_relinquish, + fscache_cookie_see_withdraw, + fscache_cookie_see_work, }; -enum fscache_op_trace { - fscache_op_cancel, - fscache_op_cancel_all, - fscache_op_cancelled, - fscache_op_completed, - fscache_op_enqueue_async, - fscache_op_enqueue_mythread, - fscache_op_gc, - fscache_op_init, - fscache_op_put, - fscache_op_run, - fscache_op_signal, - fscache_op_submit, - fscache_op_submit_ex, - fscache_op_work, - fscache_op_trace__nr +enum fscache_active_trace { + fscache_active_use, + fscache_active_use_modify, + fscache_active_unuse, }; -enum fscache_page_op_trace { - fscache_page_op_alloc_one, - fscache_page_op_attr_changed, - fscache_page_op_check_consistency, - fscache_page_op_invalidate, - fscache_page_op_retr_multi, - fscache_page_op_retr_one, - fscache_page_op_write_one, - fscache_page_op_trace__nr +enum fscache_access_trace { + fscache_access_acquire_volume, + fscache_access_acquire_volume_end, + fscache_access_cache_pin, + 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, + fscache_access_io_wait, + fscache_access_io_write, + fscache_access_lookup_cookie, + fscache_access_lookup_cookie_end, + fscache_access_lookup_cookie_end_failed, + fscache_access_relinquish_volume, + fscache_access_relinquish_volume_end, + fscache_access_unlive, }; #endif @@ -85,59 +103,79 @@ enum fscache_page_op_trace { /* * Declare tracing information enums and their string mappings for display. */ +#define fscache_cache_traces \ + EM(fscache_cache_collision, "*COLLIDE*") \ + EM(fscache_cache_get_acquire, "GET acq ") \ + EM(fscache_cache_new_acquire, "NEW acq ") \ + EM(fscache_cache_put_alloc_volume, "PUT alvol") \ + EM(fscache_cache_put_cache, "PUT cache") \ + EM(fscache_cache_put_prep_failed, "PUT pfail") \ + EM(fscache_cache_put_relinquish, "PUT relnq") \ + E_(fscache_cache_put_volume, "PUT vol ") + +#define fscache_volume_traces \ + EM(fscache_volume_collision, "*COLLIDE*") \ + EM(fscache_volume_get_cookie, "GET cook ") \ + EM(fscache_volume_get_create_work, "GET creat") \ + EM(fscache_volume_get_hash_collision, "GET hcoll") \ + EM(fscache_volume_free, "FREE ") \ + EM(fscache_volume_new_acquire, "NEW acq ") \ + EM(fscache_volume_put_cookie, "PUT cook ") \ + EM(fscache_volume_put_create_work, "PUT creat") \ + EM(fscache_volume_put_hash_collision, "PUT hcoll") \ + EM(fscache_volume_put_relinquish, "PUT relnq") \ + EM(fscache_volume_see_create_work, "SEE creat") \ + EM(fscache_volume_see_hash_wake, "SEE hwake") \ + E_(fscache_volume_wait_create_work, "WAIT crea") + #define fscache_cookie_traces \ - EM(fscache_cookie_collision, "*COLLISION*") \ - EM(fscache_cookie_discard, "DISCARD") \ - EM(fscache_cookie_get_acquire_parent, "GET prn") \ - EM(fscache_cookie_get_attach_object, "GET obj") \ - EM(fscache_cookie_get_reacquire, "GET raq") \ - EM(fscache_cookie_get_register_netfs, "GET net") \ - EM(fscache_cookie_put_acquire_nobufs, "PUT nbf") \ - EM(fscache_cookie_put_dup_netfs, "PUT dnt") \ - EM(fscache_cookie_put_relinquish, "PUT rlq") \ - EM(fscache_cookie_put_object, "PUT obj") \ - E_(fscache_cookie_put_parent, "PUT prn") - -#define fscache_page_traces \ - EM(fscache_page_cached, "Cached ") \ - EM(fscache_page_inval, "InvalPg") \ - EM(fscache_page_maybe_release, "MayRels") \ - EM(fscache_page_uncache, "Uncache") \ - EM(fscache_page_radix_clear_store, "RxCStr ") \ - EM(fscache_page_radix_delete, "RxDel ") \ - EM(fscache_page_radix_insert, "RxIns ") \ - EM(fscache_page_radix_pend2store, "RxP2S ") \ - EM(fscache_page_radix_set_pend, "RxSPend ") \ - EM(fscache_page_write, "WritePg") \ - EM(fscache_page_write_end, "EndPgWr") \ - EM(fscache_page_write_end_pend, "EndPgWP") \ - EM(fscache_page_write_end_noc, "EndPgNC") \ - E_(fscache_page_write_wait, "WtOnWrt") - -#define fscache_op_traces \ - EM(fscache_op_cancel, "Cancel1") \ - EM(fscache_op_cancel_all, "CancelA") \ - EM(fscache_op_cancelled, "Canclld") \ - EM(fscache_op_completed, "Complet") \ - EM(fscache_op_enqueue_async, "EnqAsyn") \ - EM(fscache_op_enqueue_mythread, "EnqMyTh") \ - EM(fscache_op_gc, "GC ") \ - EM(fscache_op_init, "Init ") \ - EM(fscache_op_put, "Put ") \ - EM(fscache_op_run, "Run ") \ - EM(fscache_op_signal, "Signal ") \ - EM(fscache_op_submit, "Submit ") \ - EM(fscache_op_submit_ex, "SubmitX") \ - E_(fscache_op_work, "Work ") - -#define fscache_page_op_traces \ - EM(fscache_page_op_alloc_one, "Alloc1 ") \ - EM(fscache_page_op_attr_changed, "AttrChg") \ - EM(fscache_page_op_check_consistency, "CheckCn") \ - EM(fscache_page_op_invalidate, "Inval ") \ - EM(fscache_page_op_retr_multi, "RetrMul") \ - EM(fscache_page_op_retr_one, "Retr1 ") \ - E_(fscache_page_op_write_one, "Write1 ") + EM(fscache_cookie_collision, "*COLLIDE*") \ + EM(fscache_cookie_discard, "DISCARD ") \ + EM(fscache_cookie_get_attach_object, "GET attch") \ + EM(fscache_cookie_get_hash_collision, "GET hcoll") \ + EM(fscache_cookie_get_end_access, "GQ endac") \ + EM(fscache_cookie_get_inval_work, "GQ inval") \ + EM(fscache_cookie_get_lru, "GET lru ") \ + EM(fscache_cookie_get_use_work, "GQ use ") \ + EM(fscache_cookie_new_acquire, "NEW acq ") \ + EM(fscache_cookie_put_hash_collision, "PUT hcoll") \ + EM(fscache_cookie_put_lru, "PUT lru ") \ + EM(fscache_cookie_put_object, "PUT obj ") \ + EM(fscache_cookie_put_over_queued, "PQ overq") \ + EM(fscache_cookie_put_relinquish, "PUT relnq") \ + EM(fscache_cookie_put_withdrawn, "PUT wthdn") \ + EM(fscache_cookie_put_work, "PQ work ") \ + EM(fscache_cookie_see_active, "- activ") \ + EM(fscache_cookie_see_lru_discard, "- x-lru") \ + EM(fscache_cookie_see_lru_do_one, "- lrudo") \ + EM(fscache_cookie_see_relinquish, "- x-rlq") \ + EM(fscache_cookie_see_withdraw, "- x-wth") \ + E_(fscache_cookie_see_work, "- work ") + +#define fscache_active_traces \ + EM(fscache_active_use, "USE ") \ + EM(fscache_active_use_modify, "USE-m ") \ + E_(fscache_active_unuse, "UNUSE ") + +#define fscache_access_traces \ + EM(fscache_access_acquire_volume, "BEGIN acq_vol") \ + EM(fscache_access_acquire_volume_end, "END acq_vol") \ + EM(fscache_access_cache_pin, "PIN cache ") \ + 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") \ + EM(fscache_access_io_wait, "WAIT io ") \ + EM(fscache_access_io_write, "BEGIN io_writ") \ + EM(fscache_access_lookup_cookie, "BEGIN lookup ") \ + EM(fscache_access_lookup_cookie_end, "END lookup ") \ + EM(fscache_access_lookup_cookie_end_failed,"END lookupf") \ + EM(fscache_access_relinquish_volume, "BEGIN rlq_vol") \ + EM(fscache_access_relinquish_volume_end,"END rlq_vol") \ + E_(fscache_access_unlive, "END unlive ") /* * Export enum symbols via userspace. @@ -147,7 +185,10 @@ enum fscache_page_op_trace { #define EM(a, b) TRACE_DEFINE_ENUM(a); #define E_(a, b) TRACE_DEFINE_ENUM(a); +fscache_cache_traces; +fscache_volume_traces; fscache_cookie_traces; +fscache_access_traces; /* * Now redefine the EM() and E_() macros to map the enums to the strings that @@ -159,362 +200,297 @@ fscache_cookie_traces; #define E_(a, b) { a, b } -TRACE_EVENT(fscache_cookie, - TP_PROTO(unsigned int cookie_debug_id, - int ref, - enum fscache_cookie_trace where), +TRACE_EVENT(fscache_cache, + TP_PROTO(unsigned int cache_debug_id, + int usage, + enum fscache_cache_trace where), - TP_ARGS(cookie_debug_id, ref, where), + TP_ARGS(cache_debug_id, usage, where), TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(enum fscache_cookie_trace, where ) - __field(int, ref ) + __field(unsigned int, cache ) + __field(int, usage ) + __field(enum fscache_cache_trace, where ) ), TP_fast_assign( - __entry->cookie = cookie_debug_id; + __entry->cache = cache_debug_id; + __entry->usage = usage; __entry->where = where; - __entry->ref = ref; ), - TP_printk("%s c=%08x r=%d", - __print_symbolic(__entry->where, fscache_cookie_traces), - __entry->cookie, __entry->ref) + TP_printk("C=%08x %s r=%d", + __entry->cache, + __print_symbolic(__entry->where, fscache_cache_traces), + __entry->usage) ); -TRACE_EVENT(fscache_netfs, - TP_PROTO(struct fscache_netfs *netfs), +TRACE_EVENT(fscache_volume, + TP_PROTO(unsigned int volume_debug_id, + int usage, + enum fscache_volume_trace where), - TP_ARGS(netfs), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __array(char, name, 8 ) - ), - - TP_fast_assign( - __entry->cookie = netfs->primary_index->debug_id; - strncpy(__entry->name, netfs->name, 8); - __entry->name[7] = 0; - ), - - TP_printk("c=%08x n=%s", - __entry->cookie, __entry->name) - ); - -TRACE_EVENT(fscache_acquire, - TP_PROTO(struct fscache_cookie *cookie), - - TP_ARGS(cookie), + TP_ARGS(volume_debug_id, usage, where), TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(unsigned int, parent ) - __array(char, name, 8 ) - __field(int, p_ref ) - __field(int, p_n_children ) - __field(u8, p_flags ) + __field(unsigned int, volume ) + __field(int, usage ) + __field(enum fscache_volume_trace, where ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->parent = cookie->parent->debug_id; - __entry->p_ref = refcount_read(&cookie->parent->ref); - __entry->p_n_children = atomic_read(&cookie->parent->n_children); - __entry->p_flags = cookie->parent->flags; - memcpy(__entry->name, cookie->def->name, 8); - __entry->name[7] = 0; + __entry->volume = volume_debug_id; + __entry->usage = usage; + __entry->where = where; ), - TP_printk("c=%08x p=%08x pr=%d pc=%d pf=%02x n=%s", - __entry->cookie, __entry->parent, __entry->p_ref, - __entry->p_n_children, __entry->p_flags, __entry->name) + TP_printk("V=%08x %s u=%d", + __entry->volume, + __print_symbolic(__entry->where, fscache_volume_traces), + __entry->usage) ); -TRACE_EVENT(fscache_relinquish, - TP_PROTO(struct fscache_cookie *cookie, bool retire), +TRACE_EVENT(fscache_cookie, + TP_PROTO(unsigned int cookie_debug_id, + int ref, + enum fscache_cookie_trace where), - TP_ARGS(cookie, retire), + TP_ARGS(cookie_debug_id, ref, where), TP_STRUCT__entry( __field(unsigned int, cookie ) - __field(unsigned int, parent ) __field(int, ref ) - __field(int, n_children ) - __field(int, n_active ) - __field(u8, flags ) - __field(bool, retire ) + __field(enum fscache_cookie_trace, where ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->parent = cookie->parent->debug_id; - __entry->ref = refcount_read(&cookie->ref); - __entry->n_children = atomic_read(&cookie->n_children); - __entry->n_active = atomic_read(&cookie->n_active); - __entry->flags = cookie->flags; - __entry->retire = retire; + __entry->cookie = cookie_debug_id; + __entry->ref = ref; + __entry->where = where; ), - TP_printk("c=%08x r=%d p=%08x Nc=%d Na=%d f=%02x r=%u", - __entry->cookie, __entry->ref, - __entry->parent, __entry->n_children, __entry->n_active, - __entry->flags, __entry->retire) + TP_printk("c=%08x %s r=%d", + __entry->cookie, + __print_symbolic(__entry->where, fscache_cookie_traces), + __entry->ref) ); -TRACE_EVENT(fscache_enable, - TP_PROTO(struct fscache_cookie *cookie), +TRACE_EVENT(fscache_active, + TP_PROTO(unsigned int cookie_debug_id, + int ref, + int n_active, + int n_accesses, + enum fscache_active_trace why), - TP_ARGS(cookie), + TP_ARGS(cookie_debug_id, ref, n_active, n_accesses, why), TP_STRUCT__entry( __field(unsigned int, cookie ) __field(int, ref ) - __field(int, n_children ) __field(int, n_active ) - __field(u8, flags ) + __field(int, n_accesses ) + __field(enum fscache_active_trace, why ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->ref = refcount_read(&cookie->ref); - __entry->n_children = atomic_read(&cookie->n_children); - __entry->n_active = atomic_read(&cookie->n_active); - __entry->flags = cookie->flags; + __entry->cookie = cookie_debug_id; + __entry->ref = ref; + __entry->n_active = n_active; + __entry->n_accesses = n_accesses; + __entry->why = why; ), - TP_printk("c=%08x r=%d Nc=%d Na=%d f=%02x", - __entry->cookie, __entry->ref, - __entry->n_children, __entry->n_active, __entry->flags) + TP_printk("c=%08x %s r=%d a=%d c=%d", + __entry->cookie, + __print_symbolic(__entry->why, fscache_active_traces), + __entry->ref, + __entry->n_accesses, + __entry->n_active) ); -TRACE_EVENT(fscache_disable, - TP_PROTO(struct fscache_cookie *cookie), +TRACE_EVENT(fscache_access_cache, + TP_PROTO(unsigned int cache_debug_id, + int ref, + int n_accesses, + enum fscache_access_trace why), - TP_ARGS(cookie), + TP_ARGS(cache_debug_id, ref, n_accesses, why), TP_STRUCT__entry( - __field(unsigned int, cookie ) + __field(unsigned int, cache ) __field(int, ref ) - __field(int, n_children ) - __field(int, n_active ) - __field(u8, flags ) + __field(int, n_accesses ) + __field(enum fscache_access_trace, why ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->ref = refcount_read(&cookie->ref); - __entry->n_children = atomic_read(&cookie->n_children); - __entry->n_active = atomic_read(&cookie->n_active); - __entry->flags = cookie->flags; + __entry->cache = cache_debug_id; + __entry->ref = ref; + __entry->n_accesses = n_accesses; + __entry->why = why; ), - TP_printk("c=%08x r=%d Nc=%d Na=%d f=%02x", - __entry->cookie, __entry->ref, - __entry->n_children, __entry->n_active, __entry->flags) + TP_printk("C=%08x %s r=%d a=%d", + __entry->cache, + __print_symbolic(__entry->why, fscache_access_traces), + __entry->ref, + __entry->n_accesses) ); -TRACE_EVENT(fscache_osm, - TP_PROTO(struct fscache_object *object, - const struct fscache_state *state, - bool wait, bool oob, s8 event_num), +TRACE_EVENT(fscache_access_volume, + TP_PROTO(unsigned int volume_debug_id, + unsigned int cookie_debug_id, + int ref, + int n_accesses, + enum fscache_access_trace why), - TP_ARGS(object, state, wait, oob, event_num), + TP_ARGS(volume_debug_id, cookie_debug_id, ref, n_accesses, why), TP_STRUCT__entry( + __field(unsigned int, volume ) __field(unsigned int, cookie ) - __field(unsigned int, object ) - __array(char, state, 8 ) - __field(bool, wait ) - __field(bool, oob ) - __field(s8, event_num ) + __field(int, ref ) + __field(int, n_accesses ) + __field(enum fscache_access_trace, why ) ), TP_fast_assign( - __entry->cookie = object->cookie->debug_id; - __entry->object = object->debug_id; - __entry->wait = wait; - __entry->oob = oob; - __entry->event_num = event_num; - memcpy(__entry->state, state->short_name, 8); + __entry->volume = volume_debug_id; + __entry->cookie = cookie_debug_id; + __entry->ref = ref; + __entry->n_accesses = n_accesses; + __entry->why = why; ), - TP_printk("c=%08x o=%08d %s %s%sev=%d", + TP_printk("V=%08x c=%08x %s r=%d a=%d", + __entry->volume, __entry->cookie, - __entry->object, - __entry->state, - __print_symbolic(__entry->wait, - { true, "WAIT" }, - { false, "WORK" }), - __print_symbolic(__entry->oob, - { true, " OOB " }, - { false, " " }), - __entry->event_num) + __print_symbolic(__entry->why, fscache_access_traces), + __entry->ref, + __entry->n_accesses) ); -TRACE_EVENT(fscache_page, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - enum fscache_page_trace why), +TRACE_EVENT(fscache_access, + TP_PROTO(unsigned int cookie_debug_id, + int ref, + int n_accesses, + enum fscache_access_trace why), - TP_ARGS(cookie, page, why), + TP_ARGS(cookie_debug_id, ref, n_accesses, why), TP_STRUCT__entry( __field(unsigned int, cookie ) - __field(pgoff_t, page ) - __field(enum fscache_page_trace, why ) + __field(int, ref ) + __field(int, n_accesses ) + __field(enum fscache_access_trace, why ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page->index; - __entry->why = why; + __entry->cookie = cookie_debug_id; + __entry->ref = ref; + __entry->n_accesses = n_accesses; + __entry->why = why; ), - TP_printk("c=%08x %s pg=%lx", + TP_printk("c=%08x %s r=%d a=%d", __entry->cookie, - __print_symbolic(__entry->why, fscache_page_traces), - __entry->page) - ); - -TRACE_EVENT(fscache_check_page, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - void *val, int n), - - TP_ARGS(cookie, page, val, n), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(void *, page ) - __field(void *, val ) - __field(int, n ) - ), - - TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page; - __entry->val = val; - __entry->n = n; - ), - - TP_printk("c=%08x pg=%p val=%p n=%d", - __entry->cookie, __entry->page, __entry->val, __entry->n) + __print_symbolic(__entry->why, fscache_access_traces), + __entry->ref, + __entry->n_accesses) ); -TRACE_EVENT(fscache_wake_cookie, +TRACE_EVENT(fscache_acquire, TP_PROTO(struct fscache_cookie *cookie), TP_ARGS(cookie), TP_STRUCT__entry( __field(unsigned int, cookie ) + __field(unsigned int, volume ) + __field(int, v_ref ) + __field(int, v_n_cookies ) ), TP_fast_assign( __entry->cookie = cookie->debug_id; + __entry->volume = cookie->volume->debug_id; + __entry->v_ref = refcount_read(&cookie->volume->ref); + __entry->v_n_cookies = atomic_read(&cookie->volume->n_cookies); ), - TP_printk("c=%08x", __entry->cookie) - ); - -TRACE_EVENT(fscache_op, - TP_PROTO(struct fscache_cookie *cookie, struct fscache_operation *op, - enum fscache_op_trace why), - - TP_ARGS(cookie, op, why), - - TP_STRUCT__entry( - __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(enum fscache_op_trace, why ) - ), - - TP_fast_assign( - __entry->cookie = cookie ? cookie->debug_id : 0; - __entry->op = op->debug_id; - __entry->why = why; - ), - - TP_printk("c=%08x op=%08x %s", - __entry->cookie, __entry->op, - __print_symbolic(__entry->why, fscache_op_traces)) + TP_printk("c=%08x V=%08x vr=%d vc=%d", + __entry->cookie, + __entry->volume, __entry->v_ref, __entry->v_n_cookies) ); -TRACE_EVENT(fscache_page_op, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - struct fscache_operation *op, enum fscache_page_op_trace what), +TRACE_EVENT(fscache_relinquish, + TP_PROTO(struct fscache_cookie *cookie, bool retire), - TP_ARGS(cookie, page, op, what), + TP_ARGS(cookie, retire), TP_STRUCT__entry( __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(pgoff_t, page ) - __field(enum fscache_page_op_trace, what ) + __field(unsigned int, volume ) + __field(int, ref ) + __field(int, n_active ) + __field(u8, flags ) + __field(bool, retire ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page ? page->index : 0; - __entry->op = op->debug_id; - __entry->what = what; + __entry->cookie = cookie->debug_id; + __entry->volume = cookie->volume->debug_id; + __entry->ref = refcount_read(&cookie->ref); + __entry->n_active = atomic_read(&cookie->n_active); + __entry->flags = cookie->flags; + __entry->retire = retire; ), - TP_printk("c=%08x %s pg=%lx op=%08x", - __entry->cookie, - __print_symbolic(__entry->what, fscache_page_op_traces), - __entry->page, __entry->op) + TP_printk("c=%08x V=%08x r=%d U=%d f=%02x rt=%u", + __entry->cookie, __entry->volume, __entry->ref, + __entry->n_active, __entry->flags, __entry->retire) ); -TRACE_EVENT(fscache_wrote_page, - TP_PROTO(struct fscache_cookie *cookie, struct page *page, - struct fscache_operation *op, int ret), +TRACE_EVENT(fscache_invalidate, + TP_PROTO(struct fscache_cookie *cookie, loff_t new_size), - TP_ARGS(cookie, page, op, ret), + TP_ARGS(cookie, new_size), TP_STRUCT__entry( __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(pgoff_t, page ) - __field(int, ret ) + __field(loff_t, new_size ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->page = page->index; - __entry->op = op->debug_id; - __entry->ret = ret; + __entry->cookie = cookie->debug_id; + __entry->new_size = new_size; ), - TP_printk("c=%08x pg=%lx op=%08x ret=%d", - __entry->cookie, __entry->page, __entry->op, __entry->ret) + TP_printk("c=%08x sz=%llx", + __entry->cookie, __entry->new_size) ); -TRACE_EVENT(fscache_gang_lookup, - TP_PROTO(struct fscache_cookie *cookie, struct fscache_operation *op, - void **results, int n, pgoff_t store_limit), +TRACE_EVENT(fscache_resize, + TP_PROTO(struct fscache_cookie *cookie, loff_t new_size), - TP_ARGS(cookie, op, results, n, store_limit), + TP_ARGS(cookie, new_size), TP_STRUCT__entry( __field(unsigned int, cookie ) - __field(unsigned int, op ) - __field(pgoff_t, results0 ) - __field(int, n ) - __field(pgoff_t, store_limit ) + __field(loff_t, old_size ) + __field(loff_t, new_size ) ), TP_fast_assign( - __entry->cookie = cookie->debug_id; - __entry->op = op->debug_id; - __entry->results0 = results[0] ? ((struct page *)results[0])->index : (pgoff_t)-1; - __entry->n = n; - __entry->store_limit = store_limit; + __entry->cookie = cookie->debug_id; + __entry->old_size = cookie->object_size; + __entry->new_size = new_size; ), - TP_printk("c=%08x op=%08x r0=%lx n=%d sl=%lx", - __entry->cookie, __entry->op, __entry->results0, __entry->n, - __entry->store_limit) + TP_printk("c=%08x os=%08llx sz=%08llx", + __entry->cookie, + __entry->old_size, + __entry->new_size) ); #endif /* _TRACE_FSCACHE_H */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 4d470bffd9f1..e6f4ebbb4c69 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -135,6 +135,7 @@ TRACE_EVENT(netfs_read, __field(loff_t, start ) __field(size_t, len ) __field(enum netfs_read_trace, what ) + __field(unsigned int, netfs_inode ) ), TP_fast_assign( @@ -143,12 +144,14 @@ TRACE_EVENT(netfs_read, __entry->start = start; __entry->len = len; __entry->what = what; + __entry->netfs_inode = rreq->inode->i_ino; ), - TP_printk("R=%08x %s c=%08x s=%llx %zx", + TP_printk("R=%08x %s c=%08x ni=%x s=%llx %zx", __entry->rreq, __print_symbolic(__entry->what, netfs_read_traces), __entry->cookie, + __entry->netfs_inode, __entry->start, __entry->len) ); |