diff options
Diffstat (limited to 'fs/cachefiles/internal.h')
| -rw-r--r-- | fs/cachefiles/internal.h | 270 | 
1 files changed, 159 insertions, 111 deletions
| diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index 0a511c36dab8..8dd54d9375b6 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -1,7 +1,7 @@  /* SPDX-License-Identifier: GPL-2.0-or-later */  /* General netfs cache on cache files internal defs   * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.   * Written by David Howells ([email protected])   */ @@ -13,58 +13,72 @@  #include <linux/fscache-cache.h> -#include <linux/timer.h> -#include <linux/wait_bit.h>  #include <linux/cred.h> -#include <linux/workqueue.h>  #include <linux/security.h> +#define CACHEFILES_DIO_BLOCK_SIZE 4096 +  struct cachefiles_cache;  struct cachefiles_object; -extern unsigned cachefiles_debug; -#define CACHEFILES_DEBUG_KENTER	1 -#define CACHEFILES_DEBUG_KLEAVE	2 -#define CACHEFILES_DEBUG_KDEBUG	4 +enum cachefiles_content { +	/* These values are saved on disk */ +	CACHEFILES_CONTENT_NO_DATA	= 0, /* No content stored */ +	CACHEFILES_CONTENT_SINGLE	= 1, /* Content is monolithic, all is present */ +	CACHEFILES_CONTENT_ALL		= 2, /* Content is all present, no map */ +	CACHEFILES_CONTENT_BACKFS_MAP	= 3, /* Content is piecemeal, mapped through backing fs */ +	CACHEFILES_CONTENT_DIRTY	= 4, /* Content is dirty (only seen on disk) */ +	nr__cachefiles_content +}; -#define cachefiles_gfp (__GFP_RECLAIM | __GFP_NORETRY | __GFP_NOMEMALLOC) +/* + * Cached volume representation. + */ +struct cachefiles_volume { +	struct cachefiles_cache		*cache; +	struct list_head		cache_link;	/* Link in cache->volumes */ +	struct fscache_volume		*vcookie;	/* The netfs's representation */ +	struct dentry			*dentry;	/* The volume dentry */ +	struct dentry			*fanout[256];	/* Fanout subdirs */ +};  /* - * node records + * Backing file state.   */  struct cachefiles_object { -	struct fscache_object		fscache;	/* fscache handle */ -	struct cachefiles_lookup_data	*lookup_data;	/* cached lookup data */ -	struct dentry			*dentry;	/* the file/dir representing this object */ -	struct dentry			*backer;	/* backing file */ -	loff_t				i_size;		/* object size */ +	struct fscache_cookie		*cookie;	/* Netfs data storage object cookie */ +	struct cachefiles_volume	*volume;	/* Cache volume that holds this object */ +	struct list_head		cache_link;	/* Link in cache->*_list */ +	struct file			*file;		/* The file representing this object */ +	char				*d_name;	/* Backing file name */ +	int				debug_id; +	spinlock_t			lock; +	refcount_t			ref; +	u8				d_name_len;	/* Length of filename */ +	enum cachefiles_content		content_info:8;	/* Info about content presence */  	unsigned long			flags; -#define CACHEFILES_OBJECT_ACTIVE	0		/* T if marked active */ -	atomic_t			usage;		/* object usage count */ -	uint8_t				type;		/* object type */ -	uint8_t				new;		/* T if object new */ -	spinlock_t			work_lock; -	struct rb_node			active_node;	/* link in active tree (dentry is key) */ +#define CACHEFILES_OBJECT_USING_TMPFILE	0		/* Have an unlinked tmpfile */  }; -extern struct kmem_cache *cachefiles_object_jar; -  /*   * Cache files cache definition   */  struct cachefiles_cache { -	struct fscache_cache		cache;		/* FS-Cache record */ +	struct fscache_cache		*cache;		/* Cache cookie */  	struct vfsmount			*mnt;		/* mountpoint holding the cache */ +	struct dentry			*store;		/* Directory into which live objects go */  	struct dentry			*graveyard;	/* directory into which dead objects go */  	struct file			*cachefilesd;	/* manager daemon handle */ +	struct list_head		volumes;	/* List of volume objects */ +	struct list_head		object_list;	/* List of active objects */ +	spinlock_t			object_list_lock; /* Lock for volumes and object_list */  	const struct cred		*cache_cred;	/* security override for accessing cache */  	struct mutex			daemon_mutex;	/* command serialisation mutex */  	wait_queue_head_t		daemon_pollwq;	/* poll waitqueue for daemon */ -	struct rb_root			active_nodes;	/* active nodes (can't be culled) */ -	rwlock_t			active_lock;	/* lock for active_nodes */  	atomic_t			gravecounter;	/* graveyard uniquifier */  	atomic_t			f_released;	/* number of objects released lately */  	atomic_long_t			b_released;	/* number of blocks released lately */ +	atomic_long_t			b_writing;	/* Number of blocks being written */  	unsigned			frun_percent;	/* when to stop culling (% files) */  	unsigned			fcull_percent;	/* when to start culling (% files) */  	unsigned			fstop_percent;	/* when to stop allocating (% files) */ @@ -89,38 +103,19 @@ struct cachefiles_cache {  	char				*tag;		/* cache binding tag */  }; -/* - * backing file read tracking - */ -struct cachefiles_one_read { -	wait_queue_entry_t			monitor;	/* link into monitored waitqueue */ -	struct page			*back_page;	/* backing file page we're waiting for */ -	struct page			*netfs_page;	/* netfs page we're going to fill */ -	struct fscache_retrieval	*op;		/* retrieval op covering this */ -	struct list_head		op_link;	/* link in op's todo list */ -}; - -/* - * backing file write tracking - */ -struct cachefiles_one_write { -	struct page			*netfs_page;	/* netfs page to copy */ -	struct cachefiles_object	*object; -	struct list_head		obj_link;	/* link in object's lists */ -	fscache_rw_complete_t		end_io_func; -	void				*context; -}; +#include <trace/events/cachefiles.h> -/* - * auxiliary data xattr buffer - */ -struct cachefiles_xattr { -	uint16_t			len; -	uint8_t				type; -	uint8_t				data[]; -}; +static inline +struct file *cachefiles_cres_file(struct netfs_cache_resources *cres) +{ +	return cres->cache_priv2; +} -#include <trace/events/cachefiles.h> +static inline +struct cachefiles_object *cachefiles_cres_object(struct netfs_cache_resources *cres) +{ +	return fscache_cres_cookie(cres)->cache_priv; +}  /*   * note change of state for daemon @@ -132,74 +127,118 @@ static inline void cachefiles_state_changed(struct cachefiles_cache *cache)  }  /* - * bind.c + * cache.c   */ -extern int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args); -extern void cachefiles_daemon_unbind(struct cachefiles_cache *cache); +extern int cachefiles_add_cache(struct cachefiles_cache *cache); +extern void cachefiles_withdraw_cache(struct cachefiles_cache *cache); + +enum cachefiles_has_space_for { +	cachefiles_has_space_check, +	cachefiles_has_space_for_write, +	cachefiles_has_space_for_create, +}; +extern int cachefiles_has_space(struct cachefiles_cache *cache, +				unsigned fnr, unsigned bnr, +				enum cachefiles_has_space_for reason);  /*   * daemon.c   */  extern const struct file_operations cachefiles_daemon_fops; -extern int cachefiles_has_space(struct cachefiles_cache *cache, -				unsigned fnr, unsigned bnr); +/* + * error_inject.c + */ +#ifdef CONFIG_CACHEFILES_ERROR_INJECTION +extern unsigned int cachefiles_error_injection_state; +extern int cachefiles_register_error_injection(void); +extern void cachefiles_unregister_error_injection(void); + +#else +#define cachefiles_error_injection_state 0 + +static inline int cachefiles_register_error_injection(void) +{ +	return 0; +} + +static inline void cachefiles_unregister_error_injection(void) +{ +} +#endif + + +static inline int cachefiles_inject_read_error(void) +{ +	return cachefiles_error_injection_state & 2 ? -EIO : 0; +} + +static inline int cachefiles_inject_write_error(void) +{ +	return cachefiles_error_injection_state & 2 ? -EIO : +		cachefiles_error_injection_state & 1 ? -ENOSPC : +		0; +} + +static inline int cachefiles_inject_remove_error(void) +{ +	return cachefiles_error_injection_state & 2 ? -EIO : 0; +}  /*   * interface.c   */  extern const struct fscache_cache_ops cachefiles_cache_ops; +extern void cachefiles_see_object(struct cachefiles_object *object, +				  enum cachefiles_obj_ref_trace why); +extern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object, +							enum cachefiles_obj_ref_trace why); +extern void cachefiles_put_object(struct cachefiles_object *object, +				  enum cachefiles_obj_ref_trace why); -void cachefiles_put_object(struct fscache_object *_object, -			   enum fscache_obj_ref_trace why); +/* + * io.c + */ +extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres, +				       enum fscache_want_state want_state);  /*   * key.c   */ -extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type); +extern bool cachefiles_cook_key(struct cachefiles_object *object); + +/* + * main.c + */ +extern struct kmem_cache *cachefiles_object_jar;  /*   * namei.c   */ -extern void cachefiles_mark_object_inactive(struct cachefiles_cache *cache, -					    struct cachefiles_object *object, -					    blkcnt_t i_blocks); -extern int cachefiles_delete_object(struct cachefiles_cache *cache, -				    struct cachefiles_object *object); -extern int cachefiles_walk_to_object(struct cachefiles_object *parent, -				     struct cachefiles_object *object, -				     const char *key, -				     struct cachefiles_xattr *auxdata); +extern void cachefiles_unmark_inode_in_use(struct cachefiles_object *object, +					   struct file *file); +extern int cachefiles_bury_object(struct cachefiles_cache *cache, +				  struct cachefiles_object *object, +				  struct dentry *dir, +				  struct dentry *rep, +				  enum fscache_why_object_killed why); +extern int cachefiles_delete_object(struct cachefiles_object *object, +				    enum fscache_why_object_killed why); +extern bool cachefiles_look_up_object(struct cachefiles_object *object);  extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,  					       struct dentry *dir, -					       const char *name); +					       const char *name, +					       bool *_is_new); +extern void cachefiles_put_directory(struct dentry *dir);  extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,  			   char *filename);  extern int cachefiles_check_in_use(struct cachefiles_cache *cache,  				   struct dentry *dir, char *filename); - -/* - * rdwr.c - */ -extern int cachefiles_read_or_alloc_page(struct fscache_retrieval *, -					 struct page *, gfp_t); -extern int cachefiles_read_or_alloc_pages(struct fscache_retrieval *, -					  struct list_head *, unsigned *, -					  gfp_t); -extern int cachefiles_allocate_page(struct fscache_retrieval *, struct page *, -				    gfp_t); -extern int cachefiles_allocate_pages(struct fscache_retrieval *, -				     struct list_head *, unsigned *, gfp_t); -extern int cachefiles_write_page(struct fscache_storage *, struct page *); -extern void cachefiles_uncache_page(struct fscache_object *, struct page *); - -/* - * rdwr2.c - */ -extern int cachefiles_begin_read_operation(struct netfs_read_request *, -					   struct fscache_retrieval *); +extern struct file *cachefiles_create_tmpfile(struct cachefiles_object *object); +extern bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache, +				      struct cachefiles_object *object);  /*   * security.c @@ -222,28 +261,32 @@ static inline void cachefiles_end_secure(struct cachefiles_cache *cache,  }  /* + * volume.c + */ +void cachefiles_acquire_volume(struct fscache_volume *volume); +void cachefiles_free_volume(struct fscache_volume *volume); +void cachefiles_withdraw_volume(struct cachefiles_volume *volume); + +/*   * xattr.c   */ -extern int cachefiles_check_object_type(struct cachefiles_object *object); -extern int cachefiles_set_object_xattr(struct cachefiles_object *object, -				       struct cachefiles_xattr *auxdata); -extern int cachefiles_update_object_xattr(struct cachefiles_object *object, -					  struct cachefiles_xattr *auxdata); -extern int cachefiles_check_auxdata(struct cachefiles_object *object); -extern int cachefiles_check_object_xattr(struct cachefiles_object *object, -					 struct cachefiles_xattr *auxdata); +extern int cachefiles_set_object_xattr(struct cachefiles_object *object); +extern int cachefiles_check_auxdata(struct cachefiles_object *object, +				    struct file *file);  extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, +					  struct cachefiles_object *object,  					  struct dentry *dentry); - +extern void cachefiles_prepare_to_write(struct fscache_cookie *cookie); +extern bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume); +extern int cachefiles_check_volume_xattr(struct cachefiles_volume *volume);  /* - * error handling + * Error handling   */ -  #define cachefiles_io_error(___cache, FMT, ...)		\  do {							\  	pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__);	\ -	fscache_io_error(&(___cache)->cache);		\ +	fscache_io_error((___cache)->cache);		\  	set_bit(CACHEFILES_DEAD, &(___cache)->flags);	\  } while (0) @@ -251,15 +294,20 @@ do {							\  do {									\  	struct cachefiles_cache *___cache;				\  									\ -	___cache = container_of((object)->fscache.cache,		\ -				struct cachefiles_cache, cache);	\ -	cachefiles_io_error(___cache, FMT, ##__VA_ARGS__);		\ +	___cache = (object)->volume->cache;				\ +	cachefiles_io_error(___cache, FMT " [o=%08x]", ##__VA_ARGS__,	\ +			    (object)->debug_id);			\  } while (0)  /* - * debug tracing + * Debug tracing   */ +extern unsigned cachefiles_debug; +#define CACHEFILES_DEBUG_KENTER	1 +#define CACHEFILES_DEBUG_KLEAVE	2 +#define CACHEFILES_DEBUG_KDEBUG	4 +  #define dbgprintk(FMT, ...) \  	printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) |