2021-10-20 21:34:41 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/* Internal definitions for FS-Cache
|
|
|
|
*
|
|
|
|
* Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
|
|
|
|
* Written by David Howells (dhowells@redhat.com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef pr_fmt
|
|
|
|
#undef pr_fmt
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define pr_fmt(fmt) "FS-Cache: " fmt
|
|
|
|
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/fscache-cache.h>
|
|
|
|
#include <trace/events/fscache.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
|
2021-10-20 22:00:26 +08:00
|
|
|
/*
|
|
|
|
* cache.c
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
extern const struct seq_operations fscache_caches_seq_ops;
|
|
|
|
#endif
|
2021-10-20 22:00:26 +08:00
|
|
|
bool fscache_begin_cache_access(struct fscache_cache *cache, enum fscache_access_trace why);
|
|
|
|
void fscache_end_cache_access(struct fscache_cache *cache, enum fscache_access_trace why);
|
2021-10-20 22:00:26 +08:00
|
|
|
struct fscache_cache *fscache_lookup_cache(const char *name, bool is_cache);
|
|
|
|
void fscache_put_cache(struct fscache_cache *cache, enum fscache_cache_trace where);
|
|
|
|
|
|
|
|
static inline enum fscache_cache_state fscache_cache_state(const struct fscache_cache *cache)
|
|
|
|
{
|
|
|
|
return smp_load_acquire(&cache->state);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool fscache_cache_is_live(const struct fscache_cache *cache)
|
|
|
|
{
|
|
|
|
return fscache_cache_state(cache) == FSCACHE_CACHE_IS_ACTIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void fscache_set_cache_state(struct fscache_cache *cache,
|
|
|
|
enum fscache_cache_state new_state)
|
|
|
|
{
|
|
|
|
smp_store_release(&cache->state, new_state);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool fscache_set_cache_state_maybe(struct fscache_cache *cache,
|
|
|
|
enum fscache_cache_state old_state,
|
|
|
|
enum fscache_cache_state new_state)
|
|
|
|
{
|
|
|
|
return try_cmpxchg_release(&cache->state, &old_state, new_state);
|
|
|
|
}
|
|
|
|
|
fscache: Implement cookie registration
Add functions to the fscache API to allow data file cookies to be acquired
and relinquished by the network filesystem. It is intended that the
filesystem will create such cookies per-inode under a volume.
To request a cookie, the filesystem should call:
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)
The filesystem must first have created a volume cookie, which is passed in
here. If it passes in NULL then the function will just return a NULL
cookie.
A binary key should be passed in index_key and is of size index_key_len.
This is saved in the cookie and is used to locate the associated data in
the cache.
A coherency data buffer of size aux_data_len will be allocated and
initialised from the buffer pointed to by aux_data. This is used to
validate cache objects when they're opened and is stored on disk with them
when they're committed. The data is stored in the cookie and will be
updateable by various functions in later patches.
The object_size must also be given. This is also used to perform a
coherency check and to size the backing storage appropriately.
This function disallows a cookie from being acquired twice in parallel,
though it will cause the second user to wait if the first is busy
relinquishing its cookie.
When a network filesystem has finished with a cookie, it should call:
void
fscache_relinquish_cookie(struct fscache_volume *volume,
bool retire)
If retire is true, any backing data will be discarded immediately.
Changes
=======
ver #3:
- fscache_hash()'s size parameter is now in bytes. Use __le32 as the unit
to round up to.
- When comparing cookies, simply see if the attributes are the same rather
than subtracting them to produce a strcmp-style return[1].
- Add a check to see if the cookie is still hashed at the point of
freeing.
ver #2:
- Don't hold n_accesses elevated whilst cache is bound to a cookie, but
rather add a flag that prevents the state machine from being queued when
n_accesses reaches 0.
- Remove the unused cookie pointer field from the fscache_acquire
tracepoint.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/CAHk-=whtkzB446+hX0zdLsdcUJsJ=8_-0S1mE_R+YurThfUbLA@mail.gmail.com/ [1]
Link: https://lore.kernel.org/r/163819590658.215744.14934902514281054323.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906891983.143852.6219772337558577395.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967088507.1823006.12659006350221417165.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021498432.640689.12743483856927722772.stgit@warthog.procyon.org.uk/ # v4
2021-10-20 22:53:34 +08:00
|
|
|
/*
|
|
|
|
* cookie.c
|
|
|
|
*/
|
|
|
|
extern struct kmem_cache *fscache_cookie_jar;
|
|
|
|
extern const struct seq_operations fscache_cookies_seq_ops;
|
|
|
|
|
|
|
|
extern void fscache_print_cookie(struct fscache_cookie *cookie, char prefix);
|
|
|
|
static inline void fscache_see_cookie(struct fscache_cookie *cookie,
|
|
|
|
enum fscache_cookie_trace where)
|
|
|
|
{
|
|
|
|
trace_fscache_cookie(cookie->debug_id, refcount_read(&cookie->ref),
|
|
|
|
where);
|
|
|
|
}
|
|
|
|
|
2021-10-20 21:34:41 +08:00
|
|
|
/*
|
|
|
|
* main.c
|
|
|
|
*/
|
|
|
|
extern unsigned fscache_debug;
|
|
|
|
|
2021-10-20 22:45:28 +08:00
|
|
|
extern unsigned int fscache_hash(unsigned int salt, const void *data, size_t len);
|
|
|
|
|
2021-10-20 21:34:41 +08:00
|
|
|
/*
|
|
|
|
* proc.c
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
extern int __init fscache_proc_init(void);
|
|
|
|
extern void fscache_proc_cleanup(void);
|
|
|
|
#else
|
|
|
|
#define fscache_proc_init() (0)
|
|
|
|
#define fscache_proc_cleanup() do {} while (0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* stats.c
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_FSCACHE_STATS
|
fscache: Implement volume registration
Add functions to the fscache API to allow volumes to be acquired and
relinquished by the network filesystem. A volume is an index of data
storage cache objects. A volume is represented by a volume cookie in the
API. A filesystem would typically create a volume for a superblock and
then create per-inode cookies within it.
To request a volume, the filesystem calls:
struct fscache_volume *
fscache_acquire_volume(const char *volume_key,
const char *cache_name,
const void *coherency_data,
size_t coherency_len)
The volume_key is a printable string used to match the volume in the cache.
It should not contain any '/' characters. For AFS, for example, this would
be "afs,<cellname>,<volume_id>", e.g. "afs,example.com,523001".
The cache_name can be NULL, but if not it should be a string indicating the
name of the cache to use if there's more than one available.
The coherency data, if given, is an arbitrarily-sized blob that's attached
to the volume and is compared when the volume is looked up. If it doesn't
match, the old volume is judged to be out of date and it and everything
within it is discarded.
Acquiring a volume twice concurrently is disallowed, though the function
will wait if an old volume cookie is being relinquishing.
When a network filesystem has finished with a volume, it should return the
volume cookie by calling:
void
fscache_relinquish_volume(struct fscache_volume *volume,
const void *coherency_data,
bool invalidate)
If invalidate is true, the entire volume will be discarded; if false, the
volume will be synced and the coherency data will be updated.
Changes
=======
ver #4:
- Removed an extraneous param from kdoc on fscache_relinquish_volume()[3].
ver #3:
- fscache_hash()'s size parameter is now in bytes. Use __le32 as the unit
to round up to.
- When comparing cookies, simply see if the attributes are the same rather
than subtracting them to produce a strcmp-style return[2].
- Make the coherency data an arbitrary blob rather than a u64, but don't
store it for the moment.
ver #2:
- Fix error check[1].
- Make a fscache_acquire_volume() return errors, including EBUSY if a
conflicting volume cookie already exists. No error is printed now -
that's left to the netfs.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/20211203095608.GC2480@kili/ [1]
Link: https://lore.kernel.org/r/CAHk-=whtkzB446+hX0zdLsdcUJsJ=8_-0S1mE_R+YurThfUbLA@mail.gmail.com/ [2]
Link: https://lore.kernel.org/r/20211220224646.30e8205c@canb.auug.org.au/ [3]
Link: https://lore.kernel.org/r/163819588944.215744.1629085755564865996.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906890630.143852.13972180614535611154.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967086836.1823006.8191672796841981763.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021495816.640689.4403156093668590217.stgit@warthog.procyon.org.uk/ # v4
2021-10-20 22:26:17 +08:00
|
|
|
extern atomic_t fscache_n_volumes;
|
|
|
|
extern atomic_t fscache_n_volumes_collision;
|
|
|
|
extern atomic_t fscache_n_volumes_nomem;
|
fscache: Implement cookie registration
Add functions to the fscache API to allow data file cookies to be acquired
and relinquished by the network filesystem. It is intended that the
filesystem will create such cookies per-inode under a volume.
To request a cookie, the filesystem should call:
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)
The filesystem must first have created a volume cookie, which is passed in
here. If it passes in NULL then the function will just return a NULL
cookie.
A binary key should be passed in index_key and is of size index_key_len.
This is saved in the cookie and is used to locate the associated data in
the cache.
A coherency data buffer of size aux_data_len will be allocated and
initialised from the buffer pointed to by aux_data. This is used to
validate cache objects when they're opened and is stored on disk with them
when they're committed. The data is stored in the cookie and will be
updateable by various functions in later patches.
The object_size must also be given. This is also used to perform a
coherency check and to size the backing storage appropriately.
This function disallows a cookie from being acquired twice in parallel,
though it will cause the second user to wait if the first is busy
relinquishing its cookie.
When a network filesystem has finished with a cookie, it should call:
void
fscache_relinquish_cookie(struct fscache_volume *volume,
bool retire)
If retire is true, any backing data will be discarded immediately.
Changes
=======
ver #3:
- fscache_hash()'s size parameter is now in bytes. Use __le32 as the unit
to round up to.
- When comparing cookies, simply see if the attributes are the same rather
than subtracting them to produce a strcmp-style return[1].
- Add a check to see if the cookie is still hashed at the point of
freeing.
ver #2:
- Don't hold n_accesses elevated whilst cache is bound to a cookie, but
rather add a flag that prevents the state machine from being queued when
n_accesses reaches 0.
- Remove the unused cookie pointer field from the fscache_acquire
tracepoint.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/CAHk-=whtkzB446+hX0zdLsdcUJsJ=8_-0S1mE_R+YurThfUbLA@mail.gmail.com/ [1]
Link: https://lore.kernel.org/r/163819590658.215744.14934902514281054323.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906891983.143852.6219772337558577395.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967088507.1823006.12659006350221417165.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021498432.640689.12743483856927722772.stgit@warthog.procyon.org.uk/ # v4
2021-10-20 22:53:34 +08:00
|
|
|
extern atomic_t fscache_n_cookies;
|
|
|
|
|
|
|
|
extern atomic_t fscache_n_acquires;
|
|
|
|
extern atomic_t fscache_n_acquires_ok;
|
|
|
|
extern atomic_t fscache_n_acquires_oom;
|
|
|
|
|
|
|
|
extern atomic_t fscache_n_relinquishes;
|
|
|
|
extern atomic_t fscache_n_relinquishes_retire;
|
|
|
|
extern atomic_t fscache_n_relinquishes_dropped;
|
2021-10-20 21:34:41 +08:00
|
|
|
|
|
|
|
static inline void fscache_stat(atomic_t *stat)
|
|
|
|
{
|
|
|
|
atomic_inc(stat);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void fscache_stat_d(atomic_t *stat)
|
|
|
|
{
|
|
|
|
atomic_dec(stat);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define __fscache_stat(stat) (stat)
|
|
|
|
|
|
|
|
int fscache_stats_show(struct seq_file *m, void *v);
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define __fscache_stat(stat) (NULL)
|
|
|
|
#define fscache_stat(stat) do {} while (0)
|
|
|
|
#define fscache_stat_d(stat) do {} while (0)
|
|
|
|
#endif
|
|
|
|
|
fscache: Implement volume registration
Add functions to the fscache API to allow volumes to be acquired and
relinquished by the network filesystem. A volume is an index of data
storage cache objects. A volume is represented by a volume cookie in the
API. A filesystem would typically create a volume for a superblock and
then create per-inode cookies within it.
To request a volume, the filesystem calls:
struct fscache_volume *
fscache_acquire_volume(const char *volume_key,
const char *cache_name,
const void *coherency_data,
size_t coherency_len)
The volume_key is a printable string used to match the volume in the cache.
It should not contain any '/' characters. For AFS, for example, this would
be "afs,<cellname>,<volume_id>", e.g. "afs,example.com,523001".
The cache_name can be NULL, but if not it should be a string indicating the
name of the cache to use if there's more than one available.
The coherency data, if given, is an arbitrarily-sized blob that's attached
to the volume and is compared when the volume is looked up. If it doesn't
match, the old volume is judged to be out of date and it and everything
within it is discarded.
Acquiring a volume twice concurrently is disallowed, though the function
will wait if an old volume cookie is being relinquishing.
When a network filesystem has finished with a volume, it should return the
volume cookie by calling:
void
fscache_relinquish_volume(struct fscache_volume *volume,
const void *coherency_data,
bool invalidate)
If invalidate is true, the entire volume will be discarded; if false, the
volume will be synced and the coherency data will be updated.
Changes
=======
ver #4:
- Removed an extraneous param from kdoc on fscache_relinquish_volume()[3].
ver #3:
- fscache_hash()'s size parameter is now in bytes. Use __le32 as the unit
to round up to.
- When comparing cookies, simply see if the attributes are the same rather
than subtracting them to produce a strcmp-style return[2].
- Make the coherency data an arbitrary blob rather than a u64, but don't
store it for the moment.
ver #2:
- Fix error check[1].
- Make a fscache_acquire_volume() return errors, including EBUSY if a
conflicting volume cookie already exists. No error is printed now -
that's left to the netfs.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/20211203095608.GC2480@kili/ [1]
Link: https://lore.kernel.org/r/CAHk-=whtkzB446+hX0zdLsdcUJsJ=8_-0S1mE_R+YurThfUbLA@mail.gmail.com/ [2]
Link: https://lore.kernel.org/r/20211220224646.30e8205c@canb.auug.org.au/ [3]
Link: https://lore.kernel.org/r/163819588944.215744.1629085755564865996.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906890630.143852.13972180614535611154.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967086836.1823006.8191672796841981763.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021495816.640689.4403156093668590217.stgit@warthog.procyon.org.uk/ # v4
2021-10-20 22:26:17 +08:00
|
|
|
/*
|
|
|
|
* volume.c
|
|
|
|
*/
|
|
|
|
extern const struct seq_operations fscache_volumes_seq_ops;
|
|
|
|
|
|
|
|
struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
|
|
|
|
enum fscache_volume_trace where);
|
|
|
|
void fscache_put_volume(struct fscache_volume *volume,
|
|
|
|
enum fscache_volume_trace where);
|
fscache: Implement volume-level access helpers
Add a pair of helper functions to manage access to a volume, pinning the
volume in place for the duration to prevent cache withdrawal from removing
it:
bool fscache_begin_volume_access(struct fscache_volume *volume,
enum fscache_access_trace why);
void fscache_end_volume_access(struct fscache_volume *volume,
enum fscache_access_trace why);
The way the access gate on the volume works/will work is:
(1) If the cache tests as not live (state is not FSCACHE_CACHE_IS_ACTIVE),
then we return false to indicate access was not permitted.
(2) If the cache tests as live, then we increment the volume's n_accesses
count and then recheck the cache liveness, ending the access if it
ceased to be live.
(3) When we end the access, we decrement the volume's n_accesses and wake
up the any waiters if it reaches 0.
(4) Whilst the cache is caching, the volume's n_accesses is kept
artificially incremented to prevent wakeups from happening.
(5) When the cache is taken offline, the state is changed to prevent new
accesses, the volume's n_accesses is decremented and we wait for it to
become 0.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/163819594158.215744.8285859817391683254.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906894315.143852.5454793807544710479.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967095028.1823006.9173132503876627466.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021501546.640689.9631510472149608443.stgit@warthog.procyon.org.uk/ # v4
2021-10-20 22:26:17 +08:00
|
|
|
bool fscache_begin_volume_access(struct fscache_volume *volume,
|
|
|
|
struct fscache_cookie *cookie,
|
|
|
|
enum fscache_access_trace why);
|
fscache: Implement volume registration
Add functions to the fscache API to allow volumes to be acquired and
relinquished by the network filesystem. A volume is an index of data
storage cache objects. A volume is represented by a volume cookie in the
API. A filesystem would typically create a volume for a superblock and
then create per-inode cookies within it.
To request a volume, the filesystem calls:
struct fscache_volume *
fscache_acquire_volume(const char *volume_key,
const char *cache_name,
const void *coherency_data,
size_t coherency_len)
The volume_key is a printable string used to match the volume in the cache.
It should not contain any '/' characters. For AFS, for example, this would
be "afs,<cellname>,<volume_id>", e.g. "afs,example.com,523001".
The cache_name can be NULL, but if not it should be a string indicating the
name of the cache to use if there's more than one available.
The coherency data, if given, is an arbitrarily-sized blob that's attached
to the volume and is compared when the volume is looked up. If it doesn't
match, the old volume is judged to be out of date and it and everything
within it is discarded.
Acquiring a volume twice concurrently is disallowed, though the function
will wait if an old volume cookie is being relinquishing.
When a network filesystem has finished with a volume, it should return the
volume cookie by calling:
void
fscache_relinquish_volume(struct fscache_volume *volume,
const void *coherency_data,
bool invalidate)
If invalidate is true, the entire volume will be discarded; if false, the
volume will be synced and the coherency data will be updated.
Changes
=======
ver #4:
- Removed an extraneous param from kdoc on fscache_relinquish_volume()[3].
ver #3:
- fscache_hash()'s size parameter is now in bytes. Use __le32 as the unit
to round up to.
- When comparing cookies, simply see if the attributes are the same rather
than subtracting them to produce a strcmp-style return[2].
- Make the coherency data an arbitrary blob rather than a u64, but don't
store it for the moment.
ver #2:
- Fix error check[1].
- Make a fscache_acquire_volume() return errors, including EBUSY if a
conflicting volume cookie already exists. No error is printed now -
that's left to the netfs.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/20211203095608.GC2480@kili/ [1]
Link: https://lore.kernel.org/r/CAHk-=whtkzB446+hX0zdLsdcUJsJ=8_-0S1mE_R+YurThfUbLA@mail.gmail.com/ [2]
Link: https://lore.kernel.org/r/20211220224646.30e8205c@canb.auug.org.au/ [3]
Link: https://lore.kernel.org/r/163819588944.215744.1629085755564865996.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906890630.143852.13972180614535611154.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967086836.1823006.8191672796841981763.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021495816.640689.4403156093668590217.stgit@warthog.procyon.org.uk/ # v4
2021-10-20 22:26:17 +08:00
|
|
|
void fscache_create_volume(struct fscache_volume *volume, bool wait);
|
|
|
|
|
2021-10-20 21:34:41 +08:00
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/*
|
|
|
|
* debug tracing
|
|
|
|
*/
|
|
|
|
#define dbgprintk(FMT, ...) \
|
|
|
|
printk("[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__)
|
|
|
|
#define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
|
|
|
|
#define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define kjournal(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#ifdef __KDEBUG
|
|
|
|
#define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__)
|
|
|
|
#define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__)
|
|
|
|
#define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#elif defined(CONFIG_FSCACHE_DEBUG)
|
|
|
|
#define _enter(FMT, ...) \
|
|
|
|
do { \
|
|
|
|
if (__do_kdebug(ENTER)) \
|
|
|
|
kenter(FMT, ##__VA_ARGS__); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define _leave(FMT, ...) \
|
|
|
|
do { \
|
|
|
|
if (__do_kdebug(LEAVE)) \
|
|
|
|
kleave(FMT, ##__VA_ARGS__); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define _debug(FMT, ...) \
|
|
|
|
do { \
|
|
|
|
if (__do_kdebug(DEBUG)) \
|
|
|
|
kdebug(FMT, ##__VA_ARGS__); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#else
|
|
|
|
#define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__)
|
|
|
|
#define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
|
|
|
|
#define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* determine whether a particular optional debugging point should be logged
|
|
|
|
* - we need to go through three steps to persuade cpp to correctly join the
|
|
|
|
* shorthand in FSCACHE_DEBUG_LEVEL with its prefix
|
|
|
|
*/
|
|
|
|
#define ____do_kdebug(LEVEL, POINT) \
|
|
|
|
unlikely((fscache_debug & \
|
|
|
|
(FSCACHE_POINT_##POINT << (FSCACHE_DEBUG_ ## LEVEL * 3))))
|
|
|
|
#define ___do_kdebug(LEVEL, POINT) \
|
|
|
|
____do_kdebug(LEVEL, POINT)
|
|
|
|
#define __do_kdebug(POINT) \
|
|
|
|
___do_kdebug(FSCACHE_DEBUG_LEVEL, POINT)
|
|
|
|
|
|
|
|
#define FSCACHE_DEBUG_CACHE 0
|
|
|
|
#define FSCACHE_DEBUG_COOKIE 1
|
|
|
|
#define FSCACHE_DEBUG_OBJECT 2
|
|
|
|
#define FSCACHE_DEBUG_OPERATION 3
|
|
|
|
|
|
|
|
#define FSCACHE_POINT_ENTER 1
|
|
|
|
#define FSCACHE_POINT_LEAVE 2
|
|
|
|
#define FSCACHE_POINT_DEBUG 4
|
|
|
|
|
|
|
|
#ifndef FSCACHE_DEBUG_LEVEL
|
|
|
|
#define FSCACHE_DEBUG_LEVEL CACHE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* assertions
|
|
|
|
*/
|
|
|
|
#if 1 /* defined(__KDEBUGALL) */
|
|
|
|
|
|
|
|
#define ASSERT(X) \
|
|
|
|
do { \
|
|
|
|
if (unlikely(!(X))) { \
|
|
|
|
pr_err("\n"); \
|
|
|
|
pr_err("Assertion failed\n"); \
|
|
|
|
BUG(); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ASSERTCMP(X, OP, Y) \
|
|
|
|
do { \
|
|
|
|
if (unlikely(!((X) OP (Y)))) { \
|
|
|
|
pr_err("\n"); \
|
|
|
|
pr_err("Assertion failed\n"); \
|
|
|
|
pr_err("%lx " #OP " %lx is false\n", \
|
|
|
|
(unsigned long)(X), (unsigned long)(Y)); \
|
|
|
|
BUG(); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ASSERTIF(C, X) \
|
|
|
|
do { \
|
|
|
|
if (unlikely((C) && !(X))) { \
|
|
|
|
pr_err("\n"); \
|
|
|
|
pr_err("Assertion failed\n"); \
|
|
|
|
BUG(); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ASSERTIFCMP(C, X, OP, Y) \
|
|
|
|
do { \
|
|
|
|
if (unlikely((C) && !((X) OP (Y)))) { \
|
|
|
|
pr_err("\n"); \
|
|
|
|
pr_err("Assertion failed\n"); \
|
|
|
|
pr_err("%lx " #OP " %lx is false\n", \
|
|
|
|
(unsigned long)(X), (unsigned long)(Y)); \
|
|
|
|
BUG(); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define ASSERT(X) do {} while (0)
|
|
|
|
#define ASSERTCMP(X, OP, Y) do {} while (0)
|
|
|
|
#define ASSERTIF(C, X) do {} while (0)
|
|
|
|
#define ASSERTIFCMP(C, X, OP, Y) do {} while (0)
|
|
|
|
|
|
|
|
#endif /* assert or not */
|