162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/* General netfs cache on cache files internal defs
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifdef pr_fmt
962306a36Sopenharmony_ci#undef pr_fmt
1062306a36Sopenharmony_ci#endif
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define pr_fmt(fmt) "CacheFiles: " fmt
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/fscache-cache.h>
1662306a36Sopenharmony_ci#include <linux/cred.h>
1762306a36Sopenharmony_ci#include <linux/security.h>
1862306a36Sopenharmony_ci#include <linux/xarray.h>
1962306a36Sopenharmony_ci#include <linux/cachefiles.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define CACHEFILES_DIO_BLOCK_SIZE 4096
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct cachefiles_cache;
2462306a36Sopenharmony_cistruct cachefiles_object;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cienum cachefiles_content {
2762306a36Sopenharmony_ci	/* These values are saved on disk */
2862306a36Sopenharmony_ci	CACHEFILES_CONTENT_NO_DATA	= 0, /* No content stored */
2962306a36Sopenharmony_ci	CACHEFILES_CONTENT_SINGLE	= 1, /* Content is monolithic, all is present */
3062306a36Sopenharmony_ci	CACHEFILES_CONTENT_ALL		= 2, /* Content is all present, no map */
3162306a36Sopenharmony_ci	CACHEFILES_CONTENT_BACKFS_MAP	= 3, /* Content is piecemeal, mapped through backing fs */
3262306a36Sopenharmony_ci	CACHEFILES_CONTENT_DIRTY	= 4, /* Content is dirty (only seen on disk) */
3362306a36Sopenharmony_ci	nr__cachefiles_content
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/*
3762306a36Sopenharmony_ci * Cached volume representation.
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_cistruct cachefiles_volume {
4062306a36Sopenharmony_ci	struct cachefiles_cache		*cache;
4162306a36Sopenharmony_ci	struct list_head		cache_link;	/* Link in cache->volumes */
4262306a36Sopenharmony_ci	struct fscache_volume		*vcookie;	/* The netfs's representation */
4362306a36Sopenharmony_ci	struct dentry			*dentry;	/* The volume dentry */
4462306a36Sopenharmony_ci	struct dentry			*fanout[256];	/* Fanout subdirs */
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * Backing file state.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_cistruct cachefiles_object {
5162306a36Sopenharmony_ci	struct fscache_cookie		*cookie;	/* Netfs data storage object cookie */
5262306a36Sopenharmony_ci	struct cachefiles_volume	*volume;	/* Cache volume that holds this object */
5362306a36Sopenharmony_ci	struct list_head		cache_link;	/* Link in cache->*_list */
5462306a36Sopenharmony_ci	struct file			*file;		/* The file representing this object */
5562306a36Sopenharmony_ci	char				*d_name;	/* Backing file name */
5662306a36Sopenharmony_ci	int				debug_id;
5762306a36Sopenharmony_ci	spinlock_t			lock;
5862306a36Sopenharmony_ci	refcount_t			ref;
5962306a36Sopenharmony_ci	u8				d_name_len;	/* Length of filename */
6062306a36Sopenharmony_ci	enum cachefiles_content		content_info:8;	/* Info about content presence */
6162306a36Sopenharmony_ci	unsigned long			flags;
6262306a36Sopenharmony_ci#define CACHEFILES_OBJECT_USING_TMPFILE	0		/* Have an unlinked tmpfile */
6362306a36Sopenharmony_ci#ifdef CONFIG_CACHEFILES_ONDEMAND
6462306a36Sopenharmony_ci	int				ondemand_id;
6562306a36Sopenharmony_ci#endif
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#define CACHEFILES_ONDEMAND_ID_CLOSED	-1
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/*
7162306a36Sopenharmony_ci * Cache files cache definition
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistruct cachefiles_cache {
7462306a36Sopenharmony_ci	struct fscache_cache		*cache;		/* Cache cookie */
7562306a36Sopenharmony_ci	struct vfsmount			*mnt;		/* mountpoint holding the cache */
7662306a36Sopenharmony_ci	struct dentry			*store;		/* Directory into which live objects go */
7762306a36Sopenharmony_ci	struct dentry			*graveyard;	/* directory into which dead objects go */
7862306a36Sopenharmony_ci	struct file			*cachefilesd;	/* manager daemon handle */
7962306a36Sopenharmony_ci	struct list_head		volumes;	/* List of volume objects */
8062306a36Sopenharmony_ci	struct list_head		object_list;	/* List of active objects */
8162306a36Sopenharmony_ci	spinlock_t			object_list_lock; /* Lock for volumes and object_list */
8262306a36Sopenharmony_ci	const struct cred		*cache_cred;	/* security override for accessing cache */
8362306a36Sopenharmony_ci	struct mutex			daemon_mutex;	/* command serialisation mutex */
8462306a36Sopenharmony_ci	wait_queue_head_t		daemon_pollwq;	/* poll waitqueue for daemon */
8562306a36Sopenharmony_ci	atomic_t			gravecounter;	/* graveyard uniquifier */
8662306a36Sopenharmony_ci	atomic_t			f_released;	/* number of objects released lately */
8762306a36Sopenharmony_ci	atomic_long_t			b_released;	/* number of blocks released lately */
8862306a36Sopenharmony_ci	atomic_long_t			b_writing;	/* Number of blocks being written */
8962306a36Sopenharmony_ci	unsigned			frun_percent;	/* when to stop culling (% files) */
9062306a36Sopenharmony_ci	unsigned			fcull_percent;	/* when to start culling (% files) */
9162306a36Sopenharmony_ci	unsigned			fstop_percent;	/* when to stop allocating (% files) */
9262306a36Sopenharmony_ci	unsigned			brun_percent;	/* when to stop culling (% blocks) */
9362306a36Sopenharmony_ci	unsigned			bcull_percent;	/* when to start culling (% blocks) */
9462306a36Sopenharmony_ci	unsigned			bstop_percent;	/* when to stop allocating (% blocks) */
9562306a36Sopenharmony_ci	unsigned			bsize;		/* cache's block size */
9662306a36Sopenharmony_ci	unsigned			bshift;		/* ilog2(bsize) */
9762306a36Sopenharmony_ci	uint64_t			frun;		/* when to stop culling */
9862306a36Sopenharmony_ci	uint64_t			fcull;		/* when to start culling */
9962306a36Sopenharmony_ci	uint64_t			fstop;		/* when to stop allocating */
10062306a36Sopenharmony_ci	sector_t			brun;		/* when to stop culling */
10162306a36Sopenharmony_ci	sector_t			bcull;		/* when to start culling */
10262306a36Sopenharmony_ci	sector_t			bstop;		/* when to stop allocating */
10362306a36Sopenharmony_ci	unsigned long			flags;
10462306a36Sopenharmony_ci#define CACHEFILES_READY		0	/* T if cache prepared */
10562306a36Sopenharmony_ci#define CACHEFILES_DEAD			1	/* T if cache dead */
10662306a36Sopenharmony_ci#define CACHEFILES_CULLING		2	/* T if cull engaged */
10762306a36Sopenharmony_ci#define CACHEFILES_STATE_CHANGED	3	/* T if state changed (poll trigger) */
10862306a36Sopenharmony_ci#define CACHEFILES_ONDEMAND_MODE	4	/* T if in on-demand read mode */
10962306a36Sopenharmony_ci	char				*rootdirname;	/* name of cache root directory */
11062306a36Sopenharmony_ci	char				*secctx;	/* LSM security context */
11162306a36Sopenharmony_ci	char				*tag;		/* cache binding tag */
11262306a36Sopenharmony_ci	refcount_t			unbind_pincount;/* refcount to do daemon unbind */
11362306a36Sopenharmony_ci	struct xarray			reqs;		/* xarray of pending on-demand requests */
11462306a36Sopenharmony_ci	unsigned long			req_id_next;
11562306a36Sopenharmony_ci	struct xarray			ondemand_ids;	/* xarray for ondemand_id allocation */
11662306a36Sopenharmony_ci	u32				ondemand_id_next;
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	return IS_ENABLED(CONFIG_CACHEFILES_ONDEMAND) &&
12262306a36Sopenharmony_ci		test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags);
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistruct cachefiles_req {
12662306a36Sopenharmony_ci	struct cachefiles_object *object;
12762306a36Sopenharmony_ci	struct completion done;
12862306a36Sopenharmony_ci	int error;
12962306a36Sopenharmony_ci	struct cachefiles_msg msg;
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci#define CACHEFILES_REQ_NEW	XA_MARK_1
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#include <trace/events/cachefiles.h>
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic inline
13762306a36Sopenharmony_cistruct file *cachefiles_cres_file(struct netfs_cache_resources *cres)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	return cres->cache_priv2;
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic inline
14362306a36Sopenharmony_cistruct cachefiles_object *cachefiles_cres_object(struct netfs_cache_resources *cres)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	return fscache_cres_cookie(cres)->cache_priv;
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/*
14962306a36Sopenharmony_ci * note change of state for daemon
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic inline void cachefiles_state_changed(struct cachefiles_cache *cache)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	set_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
15462306a36Sopenharmony_ci	wake_up_all(&cache->daemon_pollwq);
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/*
15862306a36Sopenharmony_ci * cache.c
15962306a36Sopenharmony_ci */
16062306a36Sopenharmony_ciextern int cachefiles_add_cache(struct cachefiles_cache *cache);
16162306a36Sopenharmony_ciextern void cachefiles_withdraw_cache(struct cachefiles_cache *cache);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cienum cachefiles_has_space_for {
16462306a36Sopenharmony_ci	cachefiles_has_space_check,
16562306a36Sopenharmony_ci	cachefiles_has_space_for_write,
16662306a36Sopenharmony_ci	cachefiles_has_space_for_create,
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ciextern int cachefiles_has_space(struct cachefiles_cache *cache,
16962306a36Sopenharmony_ci				unsigned fnr, unsigned bnr,
17062306a36Sopenharmony_ci				enum cachefiles_has_space_for reason);
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/*
17362306a36Sopenharmony_ci * daemon.c
17462306a36Sopenharmony_ci */
17562306a36Sopenharmony_ciextern const struct file_operations cachefiles_daemon_fops;
17662306a36Sopenharmony_ciextern void cachefiles_get_unbind_pincount(struct cachefiles_cache *cache);
17762306a36Sopenharmony_ciextern void cachefiles_put_unbind_pincount(struct cachefiles_cache *cache);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/*
18062306a36Sopenharmony_ci * error_inject.c
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_ci#ifdef CONFIG_CACHEFILES_ERROR_INJECTION
18362306a36Sopenharmony_ciextern unsigned int cachefiles_error_injection_state;
18462306a36Sopenharmony_ciextern int cachefiles_register_error_injection(void);
18562306a36Sopenharmony_ciextern void cachefiles_unregister_error_injection(void);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci#else
18862306a36Sopenharmony_ci#define cachefiles_error_injection_state 0
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic inline int cachefiles_register_error_injection(void)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	return 0;
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic inline void cachefiles_unregister_error_injection(void)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci#endif
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic inline int cachefiles_inject_read_error(void)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	return cachefiles_error_injection_state & 2 ? -EIO : 0;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic inline int cachefiles_inject_write_error(void)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	return cachefiles_error_injection_state & 2 ? -EIO :
20962306a36Sopenharmony_ci		cachefiles_error_injection_state & 1 ? -ENOSPC :
21062306a36Sopenharmony_ci		0;
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic inline int cachefiles_inject_remove_error(void)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	return cachefiles_error_injection_state & 2 ? -EIO : 0;
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/*
21962306a36Sopenharmony_ci * interface.c
22062306a36Sopenharmony_ci */
22162306a36Sopenharmony_ciextern const struct fscache_cache_ops cachefiles_cache_ops;
22262306a36Sopenharmony_ciextern void cachefiles_see_object(struct cachefiles_object *object,
22362306a36Sopenharmony_ci				  enum cachefiles_obj_ref_trace why);
22462306a36Sopenharmony_ciextern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object,
22562306a36Sopenharmony_ci							enum cachefiles_obj_ref_trace why);
22662306a36Sopenharmony_ciextern void cachefiles_put_object(struct cachefiles_object *object,
22762306a36Sopenharmony_ci				  enum cachefiles_obj_ref_trace why);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci/*
23062306a36Sopenharmony_ci * io.c
23162306a36Sopenharmony_ci */
23262306a36Sopenharmony_ciextern bool cachefiles_begin_operation(struct netfs_cache_resources *cres,
23362306a36Sopenharmony_ci				       enum fscache_want_state want_state);
23462306a36Sopenharmony_ciextern int __cachefiles_prepare_write(struct cachefiles_object *object,
23562306a36Sopenharmony_ci				      struct file *file,
23662306a36Sopenharmony_ci				      loff_t *_start, size_t *_len,
23762306a36Sopenharmony_ci				      bool no_space_allocated_yet);
23862306a36Sopenharmony_ciextern int __cachefiles_write(struct cachefiles_object *object,
23962306a36Sopenharmony_ci			      struct file *file,
24062306a36Sopenharmony_ci			      loff_t start_pos,
24162306a36Sopenharmony_ci			      struct iov_iter *iter,
24262306a36Sopenharmony_ci			      netfs_io_terminated_t term_func,
24362306a36Sopenharmony_ci			      void *term_func_priv);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci/*
24662306a36Sopenharmony_ci * key.c
24762306a36Sopenharmony_ci */
24862306a36Sopenharmony_ciextern bool cachefiles_cook_key(struct cachefiles_object *object);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci/*
25162306a36Sopenharmony_ci * main.c
25262306a36Sopenharmony_ci */
25362306a36Sopenharmony_ciextern struct kmem_cache *cachefiles_object_jar;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/*
25662306a36Sopenharmony_ci * namei.c
25762306a36Sopenharmony_ci */
25862306a36Sopenharmony_ciextern void cachefiles_unmark_inode_in_use(struct cachefiles_object *object,
25962306a36Sopenharmony_ci					   struct file *file);
26062306a36Sopenharmony_ciextern int cachefiles_bury_object(struct cachefiles_cache *cache,
26162306a36Sopenharmony_ci				  struct cachefiles_object *object,
26262306a36Sopenharmony_ci				  struct dentry *dir,
26362306a36Sopenharmony_ci				  struct dentry *rep,
26462306a36Sopenharmony_ci				  enum fscache_why_object_killed why);
26562306a36Sopenharmony_ciextern int cachefiles_delete_object(struct cachefiles_object *object,
26662306a36Sopenharmony_ci				    enum fscache_why_object_killed why);
26762306a36Sopenharmony_ciextern bool cachefiles_look_up_object(struct cachefiles_object *object);
26862306a36Sopenharmony_ciextern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
26962306a36Sopenharmony_ci					       struct dentry *dir,
27062306a36Sopenharmony_ci					       const char *name,
27162306a36Sopenharmony_ci					       bool *_is_new);
27262306a36Sopenharmony_ciextern void cachefiles_put_directory(struct dentry *dir);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ciextern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
27562306a36Sopenharmony_ci			   char *filename);
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ciextern int cachefiles_check_in_use(struct cachefiles_cache *cache,
27862306a36Sopenharmony_ci				   struct dentry *dir, char *filename);
27962306a36Sopenharmony_ciextern struct file *cachefiles_create_tmpfile(struct cachefiles_object *object);
28062306a36Sopenharmony_ciextern bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
28162306a36Sopenharmony_ci				      struct cachefiles_object *object);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci/*
28462306a36Sopenharmony_ci * ondemand.c
28562306a36Sopenharmony_ci */
28662306a36Sopenharmony_ci#ifdef CONFIG_CACHEFILES_ONDEMAND
28762306a36Sopenharmony_ciextern ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
28862306a36Sopenharmony_ci					char __user *_buffer, size_t buflen);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ciextern int cachefiles_ondemand_copen(struct cachefiles_cache *cache,
29162306a36Sopenharmony_ci				     char *args);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ciextern int cachefiles_ondemand_init_object(struct cachefiles_object *object);
29462306a36Sopenharmony_ciextern void cachefiles_ondemand_clean_object(struct cachefiles_object *object);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ciextern int cachefiles_ondemand_read(struct cachefiles_object *object,
29762306a36Sopenharmony_ci				    loff_t pos, size_t len);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci#else
30062306a36Sopenharmony_cistatic inline ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
30162306a36Sopenharmony_ci					char __user *_buffer, size_t buflen)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	return -EOPNOTSUPP;
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic inline int cachefiles_ondemand_init_object(struct cachefiles_object *object)
30762306a36Sopenharmony_ci{
30862306a36Sopenharmony_ci	return 0;
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic inline void cachefiles_ondemand_clean_object(struct cachefiles_object *object)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic inline int cachefiles_ondemand_read(struct cachefiles_object *object,
31662306a36Sopenharmony_ci					   loff_t pos, size_t len)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	return -EOPNOTSUPP;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci#endif
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci/*
32362306a36Sopenharmony_ci * security.c
32462306a36Sopenharmony_ci */
32562306a36Sopenharmony_ciextern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
32662306a36Sopenharmony_ciextern int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
32762306a36Sopenharmony_ci					       struct dentry *root,
32862306a36Sopenharmony_ci					       const struct cred **_saved_cred);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_cistatic inline void cachefiles_begin_secure(struct cachefiles_cache *cache,
33162306a36Sopenharmony_ci					   const struct cred **_saved_cred)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	*_saved_cred = override_creds(cache->cache_cred);
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic inline void cachefiles_end_secure(struct cachefiles_cache *cache,
33762306a36Sopenharmony_ci					 const struct cred *saved_cred)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	revert_creds(saved_cred);
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci/*
34362306a36Sopenharmony_ci * volume.c
34462306a36Sopenharmony_ci */
34562306a36Sopenharmony_civoid cachefiles_acquire_volume(struct fscache_volume *volume);
34662306a36Sopenharmony_civoid cachefiles_free_volume(struct fscache_volume *volume);
34762306a36Sopenharmony_civoid cachefiles_withdraw_volume(struct cachefiles_volume *volume);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci/*
35062306a36Sopenharmony_ci * xattr.c
35162306a36Sopenharmony_ci */
35262306a36Sopenharmony_ciextern int cachefiles_set_object_xattr(struct cachefiles_object *object);
35362306a36Sopenharmony_ciextern int cachefiles_check_auxdata(struct cachefiles_object *object,
35462306a36Sopenharmony_ci				    struct file *file);
35562306a36Sopenharmony_ciextern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
35662306a36Sopenharmony_ci					  struct cachefiles_object *object,
35762306a36Sopenharmony_ci					  struct dentry *dentry);
35862306a36Sopenharmony_ciextern void cachefiles_prepare_to_write(struct fscache_cookie *cookie);
35962306a36Sopenharmony_ciextern bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume);
36062306a36Sopenharmony_ciextern int cachefiles_check_volume_xattr(struct cachefiles_volume *volume);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci/*
36362306a36Sopenharmony_ci * Error handling
36462306a36Sopenharmony_ci */
36562306a36Sopenharmony_ci#define cachefiles_io_error(___cache, FMT, ...)		\
36662306a36Sopenharmony_cido {							\
36762306a36Sopenharmony_ci	pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__);	\
36862306a36Sopenharmony_ci	fscache_io_error((___cache)->cache);		\
36962306a36Sopenharmony_ci	set_bit(CACHEFILES_DEAD, &(___cache)->flags);	\
37062306a36Sopenharmony_ci} while (0)
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci#define cachefiles_io_error_obj(object, FMT, ...)			\
37362306a36Sopenharmony_cido {									\
37462306a36Sopenharmony_ci	struct cachefiles_cache *___cache;				\
37562306a36Sopenharmony_ci									\
37662306a36Sopenharmony_ci	___cache = (object)->volume->cache;				\
37762306a36Sopenharmony_ci	cachefiles_io_error(___cache, FMT " [o=%08x]", ##__VA_ARGS__,	\
37862306a36Sopenharmony_ci			    (object)->debug_id);			\
37962306a36Sopenharmony_ci} while (0)
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci/*
38362306a36Sopenharmony_ci * Debug tracing
38462306a36Sopenharmony_ci */
38562306a36Sopenharmony_ciextern unsigned cachefiles_debug;
38662306a36Sopenharmony_ci#define CACHEFILES_DEBUG_KENTER	1
38762306a36Sopenharmony_ci#define CACHEFILES_DEBUG_KLEAVE	2
38862306a36Sopenharmony_ci#define CACHEFILES_DEBUG_KDEBUG	4
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci#define dbgprintk(FMT, ...) \
39162306a36Sopenharmony_ci	printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__)
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci#define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__)
39462306a36Sopenharmony_ci#define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
39562306a36Sopenharmony_ci#define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__)
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci#if defined(__KDEBUG)
39962306a36Sopenharmony_ci#define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__)
40062306a36Sopenharmony_ci#define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__)
40162306a36Sopenharmony_ci#define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__)
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci#elif defined(CONFIG_CACHEFILES_DEBUG)
40462306a36Sopenharmony_ci#define _enter(FMT, ...)				\
40562306a36Sopenharmony_cido {							\
40662306a36Sopenharmony_ci	if (cachefiles_debug & CACHEFILES_DEBUG_KENTER)	\
40762306a36Sopenharmony_ci		kenter(FMT, ##__VA_ARGS__);		\
40862306a36Sopenharmony_ci} while (0)
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci#define _leave(FMT, ...)				\
41162306a36Sopenharmony_cido {							\
41262306a36Sopenharmony_ci	if (cachefiles_debug & CACHEFILES_DEBUG_KLEAVE)	\
41362306a36Sopenharmony_ci		kleave(FMT, ##__VA_ARGS__);		\
41462306a36Sopenharmony_ci} while (0)
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci#define _debug(FMT, ...)				\
41762306a36Sopenharmony_cido {							\
41862306a36Sopenharmony_ci	if (cachefiles_debug & CACHEFILES_DEBUG_KDEBUG)	\
41962306a36Sopenharmony_ci		kdebug(FMT, ##__VA_ARGS__);		\
42062306a36Sopenharmony_ci} while (0)
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci#else
42362306a36Sopenharmony_ci#define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__)
42462306a36Sopenharmony_ci#define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
42562306a36Sopenharmony_ci#define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
42662306a36Sopenharmony_ci#endif
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci#if 1 /* defined(__KDEBUGALL) */
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci#define ASSERT(X)							\
43162306a36Sopenharmony_cido {									\
43262306a36Sopenharmony_ci	if (unlikely(!(X))) {						\
43362306a36Sopenharmony_ci		pr_err("\n");						\
43462306a36Sopenharmony_ci		pr_err("Assertion failed\n");		\
43562306a36Sopenharmony_ci		BUG();							\
43662306a36Sopenharmony_ci	}								\
43762306a36Sopenharmony_ci} while (0)
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci#define ASSERTCMP(X, OP, Y)						\
44062306a36Sopenharmony_cido {									\
44162306a36Sopenharmony_ci	if (unlikely(!((X) OP (Y)))) {					\
44262306a36Sopenharmony_ci		pr_err("\n");						\
44362306a36Sopenharmony_ci		pr_err("Assertion failed\n");		\
44462306a36Sopenharmony_ci		pr_err("%lx " #OP " %lx is false\n",			\
44562306a36Sopenharmony_ci		       (unsigned long)(X), (unsigned long)(Y));		\
44662306a36Sopenharmony_ci		BUG();							\
44762306a36Sopenharmony_ci	}								\
44862306a36Sopenharmony_ci} while (0)
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci#define ASSERTIF(C, X)							\
45162306a36Sopenharmony_cido {									\
45262306a36Sopenharmony_ci	if (unlikely((C) && !(X))) {					\
45362306a36Sopenharmony_ci		pr_err("\n");						\
45462306a36Sopenharmony_ci		pr_err("Assertion failed\n");		\
45562306a36Sopenharmony_ci		BUG();							\
45662306a36Sopenharmony_ci	}								\
45762306a36Sopenharmony_ci} while (0)
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci#define ASSERTIFCMP(C, X, OP, Y)					\
46062306a36Sopenharmony_cido {									\
46162306a36Sopenharmony_ci	if (unlikely((C) && !((X) OP (Y)))) {				\
46262306a36Sopenharmony_ci		pr_err("\n");						\
46362306a36Sopenharmony_ci		pr_err("Assertion failed\n");		\
46462306a36Sopenharmony_ci		pr_err("%lx " #OP " %lx is false\n",			\
46562306a36Sopenharmony_ci		       (unsigned long)(X), (unsigned long)(Y));		\
46662306a36Sopenharmony_ci		BUG();							\
46762306a36Sopenharmony_ci	}								\
46862306a36Sopenharmony_ci} while (0)
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci#else
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci#define ASSERT(X)			do {} while (0)
47362306a36Sopenharmony_ci#define ASSERTCMP(X, OP, Y)		do {} while (0)
47462306a36Sopenharmony_ci#define ASSERTIF(C, X)			do {} while (0)
47562306a36Sopenharmony_ci#define ASSERTIFCMP(C, X, OP, Y)	do {} while (0)
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci#endif
478