1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /* General netfs cache on cache files internal defs
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #ifdef pr_fmt
9*4882a593Smuzhiyun #undef pr_fmt
10*4882a593Smuzhiyun #endif
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #define pr_fmt(fmt) "CacheFiles: " fmt
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/fscache-cache.h>
16*4882a593Smuzhiyun #include <linux/timer.h>
17*4882a593Smuzhiyun #include <linux/wait_bit.h>
18*4882a593Smuzhiyun #include <linux/cred.h>
19*4882a593Smuzhiyun #include <linux/workqueue.h>
20*4882a593Smuzhiyun #include <linux/security.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun struct cachefiles_cache;
23*4882a593Smuzhiyun struct cachefiles_object;
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun extern unsigned cachefiles_debug;
26*4882a593Smuzhiyun #define CACHEFILES_DEBUG_KENTER 1
27*4882a593Smuzhiyun #define CACHEFILES_DEBUG_KLEAVE 2
28*4882a593Smuzhiyun #define CACHEFILES_DEBUG_KDEBUG 4
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define cachefiles_gfp (__GFP_RECLAIM | __GFP_NORETRY | __GFP_NOMEMALLOC)
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun * node records
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun struct cachefiles_object {
36*4882a593Smuzhiyun struct fscache_object fscache; /* fscache handle */
37*4882a593Smuzhiyun struct cachefiles_lookup_data *lookup_data; /* cached lookup data */
38*4882a593Smuzhiyun struct dentry *dentry; /* the file/dir representing this object */
39*4882a593Smuzhiyun struct dentry *backer; /* backing file */
40*4882a593Smuzhiyun loff_t i_size; /* object size */
41*4882a593Smuzhiyun unsigned long flags;
42*4882a593Smuzhiyun #define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */
43*4882a593Smuzhiyun atomic_t usage; /* object usage count */
44*4882a593Smuzhiyun uint8_t type; /* object type */
45*4882a593Smuzhiyun uint8_t new; /* T if object new */
46*4882a593Smuzhiyun spinlock_t work_lock;
47*4882a593Smuzhiyun struct rb_node active_node; /* link in active tree (dentry is key) */
48*4882a593Smuzhiyun };
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun extern struct kmem_cache *cachefiles_object_jar;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /*
53*4882a593Smuzhiyun * Cache files cache definition
54*4882a593Smuzhiyun */
55*4882a593Smuzhiyun struct cachefiles_cache {
56*4882a593Smuzhiyun struct fscache_cache cache; /* FS-Cache record */
57*4882a593Smuzhiyun struct vfsmount *mnt; /* mountpoint holding the cache */
58*4882a593Smuzhiyun struct dentry *graveyard; /* directory into which dead objects go */
59*4882a593Smuzhiyun struct file *cachefilesd; /* manager daemon handle */
60*4882a593Smuzhiyun const struct cred *cache_cred; /* security override for accessing cache */
61*4882a593Smuzhiyun struct mutex daemon_mutex; /* command serialisation mutex */
62*4882a593Smuzhiyun wait_queue_head_t daemon_pollwq; /* poll waitqueue for daemon */
63*4882a593Smuzhiyun struct rb_root active_nodes; /* active nodes (can't be culled) */
64*4882a593Smuzhiyun rwlock_t active_lock; /* lock for active_nodes */
65*4882a593Smuzhiyun atomic_t gravecounter; /* graveyard uniquifier */
66*4882a593Smuzhiyun atomic_t f_released; /* number of objects released lately */
67*4882a593Smuzhiyun atomic_long_t b_released; /* number of blocks released lately */
68*4882a593Smuzhiyun unsigned frun_percent; /* when to stop culling (% files) */
69*4882a593Smuzhiyun unsigned fcull_percent; /* when to start culling (% files) */
70*4882a593Smuzhiyun unsigned fstop_percent; /* when to stop allocating (% files) */
71*4882a593Smuzhiyun unsigned brun_percent; /* when to stop culling (% blocks) */
72*4882a593Smuzhiyun unsigned bcull_percent; /* when to start culling (% blocks) */
73*4882a593Smuzhiyun unsigned bstop_percent; /* when to stop allocating (% blocks) */
74*4882a593Smuzhiyun unsigned bsize; /* cache's block size */
75*4882a593Smuzhiyun unsigned bshift; /* min(ilog2(PAGE_SIZE / bsize), 0) */
76*4882a593Smuzhiyun uint64_t frun; /* when to stop culling */
77*4882a593Smuzhiyun uint64_t fcull; /* when to start culling */
78*4882a593Smuzhiyun uint64_t fstop; /* when to stop allocating */
79*4882a593Smuzhiyun sector_t brun; /* when to stop culling */
80*4882a593Smuzhiyun sector_t bcull; /* when to start culling */
81*4882a593Smuzhiyun sector_t bstop; /* when to stop allocating */
82*4882a593Smuzhiyun unsigned long flags;
83*4882a593Smuzhiyun #define CACHEFILES_READY 0 /* T if cache prepared */
84*4882a593Smuzhiyun #define CACHEFILES_DEAD 1 /* T if cache dead */
85*4882a593Smuzhiyun #define CACHEFILES_CULLING 2 /* T if cull engaged */
86*4882a593Smuzhiyun #define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */
87*4882a593Smuzhiyun char *rootdirname; /* name of cache root directory */
88*4882a593Smuzhiyun char *secctx; /* LSM security context */
89*4882a593Smuzhiyun char *tag; /* cache binding tag */
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun * backing file read tracking
94*4882a593Smuzhiyun */
95*4882a593Smuzhiyun struct cachefiles_one_read {
96*4882a593Smuzhiyun wait_queue_entry_t monitor; /* link into monitored waitqueue */
97*4882a593Smuzhiyun struct page *back_page; /* backing file page we're waiting for */
98*4882a593Smuzhiyun struct page *netfs_page; /* netfs page we're going to fill */
99*4882a593Smuzhiyun struct fscache_retrieval *op; /* retrieval op covering this */
100*4882a593Smuzhiyun struct list_head op_link; /* link in op's todo list */
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /*
104*4882a593Smuzhiyun * backing file write tracking
105*4882a593Smuzhiyun */
106*4882a593Smuzhiyun struct cachefiles_one_write {
107*4882a593Smuzhiyun struct page *netfs_page; /* netfs page to copy */
108*4882a593Smuzhiyun struct cachefiles_object *object;
109*4882a593Smuzhiyun struct list_head obj_link; /* link in object's lists */
110*4882a593Smuzhiyun fscache_rw_complete_t end_io_func;
111*4882a593Smuzhiyun void *context;
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /*
115*4882a593Smuzhiyun * auxiliary data xattr buffer
116*4882a593Smuzhiyun */
117*4882a593Smuzhiyun struct cachefiles_xattr {
118*4882a593Smuzhiyun uint16_t len;
119*4882a593Smuzhiyun uint8_t type;
120*4882a593Smuzhiyun uint8_t data[];
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun #include <trace/events/cachefiles.h>
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /*
126*4882a593Smuzhiyun * note change of state for daemon
127*4882a593Smuzhiyun */
cachefiles_state_changed(struct cachefiles_cache * cache)128*4882a593Smuzhiyun static inline void cachefiles_state_changed(struct cachefiles_cache *cache)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun set_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
131*4882a593Smuzhiyun wake_up_all(&cache->daemon_pollwq);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /*
135*4882a593Smuzhiyun * bind.c
136*4882a593Smuzhiyun */
137*4882a593Smuzhiyun extern int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args);
138*4882a593Smuzhiyun extern void cachefiles_daemon_unbind(struct cachefiles_cache *cache);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /*
141*4882a593Smuzhiyun * daemon.c
142*4882a593Smuzhiyun */
143*4882a593Smuzhiyun extern const struct file_operations cachefiles_daemon_fops;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun extern int cachefiles_has_space(struct cachefiles_cache *cache,
146*4882a593Smuzhiyun unsigned fnr, unsigned bnr);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun /*
149*4882a593Smuzhiyun * interface.c
150*4882a593Smuzhiyun */
151*4882a593Smuzhiyun extern const struct fscache_cache_ops cachefiles_cache_ops;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /*
154*4882a593Smuzhiyun * key.c
155*4882a593Smuzhiyun */
156*4882a593Smuzhiyun extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /*
159*4882a593Smuzhiyun * namei.c
160*4882a593Smuzhiyun */
161*4882a593Smuzhiyun extern void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
162*4882a593Smuzhiyun struct cachefiles_object *object,
163*4882a593Smuzhiyun blkcnt_t i_blocks);
164*4882a593Smuzhiyun extern int cachefiles_delete_object(struct cachefiles_cache *cache,
165*4882a593Smuzhiyun struct cachefiles_object *object);
166*4882a593Smuzhiyun extern int cachefiles_walk_to_object(struct cachefiles_object *parent,
167*4882a593Smuzhiyun struct cachefiles_object *object,
168*4882a593Smuzhiyun const char *key,
169*4882a593Smuzhiyun struct cachefiles_xattr *auxdata);
170*4882a593Smuzhiyun extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
171*4882a593Smuzhiyun struct dentry *dir,
172*4882a593Smuzhiyun const char *name);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
175*4882a593Smuzhiyun char *filename);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun extern int cachefiles_check_in_use(struct cachefiles_cache *cache,
178*4882a593Smuzhiyun struct dentry *dir, char *filename);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /*
181*4882a593Smuzhiyun * proc.c
182*4882a593Smuzhiyun */
183*4882a593Smuzhiyun #ifdef CONFIG_CACHEFILES_HISTOGRAM
184*4882a593Smuzhiyun extern atomic_t cachefiles_lookup_histogram[HZ];
185*4882a593Smuzhiyun extern atomic_t cachefiles_mkdir_histogram[HZ];
186*4882a593Smuzhiyun extern atomic_t cachefiles_create_histogram[HZ];
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun extern int __init cachefiles_proc_init(void);
189*4882a593Smuzhiyun extern void cachefiles_proc_cleanup(void);
190*4882a593Smuzhiyun static inline
cachefiles_hist(atomic_t histogram[],unsigned long start_jif)191*4882a593Smuzhiyun void cachefiles_hist(atomic_t histogram[], unsigned long start_jif)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun unsigned long jif = jiffies - start_jif;
194*4882a593Smuzhiyun if (jif >= HZ)
195*4882a593Smuzhiyun jif = HZ - 1;
196*4882a593Smuzhiyun atomic_inc(&histogram[jif]);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #else
200*4882a593Smuzhiyun #define cachefiles_proc_init() (0)
201*4882a593Smuzhiyun #define cachefiles_proc_cleanup() do {} while (0)
202*4882a593Smuzhiyun #define cachefiles_hist(hist, start_jif) do {} while (0)
203*4882a593Smuzhiyun #endif
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /*
206*4882a593Smuzhiyun * rdwr.c
207*4882a593Smuzhiyun */
208*4882a593Smuzhiyun extern int cachefiles_read_or_alloc_page(struct fscache_retrieval *,
209*4882a593Smuzhiyun struct page *, gfp_t);
210*4882a593Smuzhiyun extern int cachefiles_read_or_alloc_pages(struct fscache_retrieval *,
211*4882a593Smuzhiyun struct list_head *, unsigned *,
212*4882a593Smuzhiyun gfp_t);
213*4882a593Smuzhiyun extern int cachefiles_allocate_page(struct fscache_retrieval *, struct page *,
214*4882a593Smuzhiyun gfp_t);
215*4882a593Smuzhiyun extern int cachefiles_allocate_pages(struct fscache_retrieval *,
216*4882a593Smuzhiyun struct list_head *, unsigned *, gfp_t);
217*4882a593Smuzhiyun extern int cachefiles_write_page(struct fscache_storage *, struct page *);
218*4882a593Smuzhiyun extern void cachefiles_uncache_page(struct fscache_object *, struct page *);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /*
221*4882a593Smuzhiyun * security.c
222*4882a593Smuzhiyun */
223*4882a593Smuzhiyun extern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
224*4882a593Smuzhiyun extern int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
225*4882a593Smuzhiyun struct dentry *root,
226*4882a593Smuzhiyun const struct cred **_saved_cred);
227*4882a593Smuzhiyun
cachefiles_begin_secure(struct cachefiles_cache * cache,const struct cred ** _saved_cred)228*4882a593Smuzhiyun static inline void cachefiles_begin_secure(struct cachefiles_cache *cache,
229*4882a593Smuzhiyun const struct cred **_saved_cred)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun *_saved_cred = override_creds(cache->cache_cred);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
cachefiles_end_secure(struct cachefiles_cache * cache,const struct cred * saved_cred)234*4882a593Smuzhiyun static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
235*4882a593Smuzhiyun const struct cred *saved_cred)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun revert_creds(saved_cred);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /*
241*4882a593Smuzhiyun * xattr.c
242*4882a593Smuzhiyun */
243*4882a593Smuzhiyun extern int cachefiles_check_object_type(struct cachefiles_object *object);
244*4882a593Smuzhiyun extern int cachefiles_set_object_xattr(struct cachefiles_object *object,
245*4882a593Smuzhiyun struct cachefiles_xattr *auxdata);
246*4882a593Smuzhiyun extern int cachefiles_update_object_xattr(struct cachefiles_object *object,
247*4882a593Smuzhiyun struct cachefiles_xattr *auxdata);
248*4882a593Smuzhiyun extern int cachefiles_check_auxdata(struct cachefiles_object *object);
249*4882a593Smuzhiyun extern int cachefiles_check_object_xattr(struct cachefiles_object *object,
250*4882a593Smuzhiyun struct cachefiles_xattr *auxdata);
251*4882a593Smuzhiyun extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
252*4882a593Smuzhiyun struct dentry *dentry);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /*
256*4882a593Smuzhiyun * error handling
257*4882a593Smuzhiyun */
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun #define cachefiles_io_error(___cache, FMT, ...) \
260*4882a593Smuzhiyun do { \
261*4882a593Smuzhiyun pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__); \
262*4882a593Smuzhiyun fscache_io_error(&(___cache)->cache); \
263*4882a593Smuzhiyun set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
264*4882a593Smuzhiyun } while (0)
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun #define cachefiles_io_error_obj(object, FMT, ...) \
267*4882a593Smuzhiyun do { \
268*4882a593Smuzhiyun struct cachefiles_cache *___cache; \
269*4882a593Smuzhiyun \
270*4882a593Smuzhiyun ___cache = container_of((object)->fscache.cache, \
271*4882a593Smuzhiyun struct cachefiles_cache, cache); \
272*4882a593Smuzhiyun cachefiles_io_error(___cache, FMT, ##__VA_ARGS__); \
273*4882a593Smuzhiyun } while (0)
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /*
277*4882a593Smuzhiyun * debug tracing
278*4882a593Smuzhiyun */
279*4882a593Smuzhiyun #define dbgprintk(FMT, ...) \
280*4882a593Smuzhiyun printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__)
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun #define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__)
283*4882a593Smuzhiyun #define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
284*4882a593Smuzhiyun #define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__)
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun #if defined(__KDEBUG)
288*4882a593Smuzhiyun #define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__)
289*4882a593Smuzhiyun #define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__)
290*4882a593Smuzhiyun #define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__)
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun #elif defined(CONFIG_CACHEFILES_DEBUG)
293*4882a593Smuzhiyun #define _enter(FMT, ...) \
294*4882a593Smuzhiyun do { \
295*4882a593Smuzhiyun if (cachefiles_debug & CACHEFILES_DEBUG_KENTER) \
296*4882a593Smuzhiyun kenter(FMT, ##__VA_ARGS__); \
297*4882a593Smuzhiyun } while (0)
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun #define _leave(FMT, ...) \
300*4882a593Smuzhiyun do { \
301*4882a593Smuzhiyun if (cachefiles_debug & CACHEFILES_DEBUG_KLEAVE) \
302*4882a593Smuzhiyun kleave(FMT, ##__VA_ARGS__); \
303*4882a593Smuzhiyun } while (0)
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun #define _debug(FMT, ...) \
306*4882a593Smuzhiyun do { \
307*4882a593Smuzhiyun if (cachefiles_debug & CACHEFILES_DEBUG_KDEBUG) \
308*4882a593Smuzhiyun kdebug(FMT, ##__VA_ARGS__); \
309*4882a593Smuzhiyun } while (0)
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun #else
312*4882a593Smuzhiyun #define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__)
313*4882a593Smuzhiyun #define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
314*4882a593Smuzhiyun #define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
315*4882a593Smuzhiyun #endif
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun #if 1 /* defined(__KDEBUGALL) */
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun #define ASSERT(X) \
320*4882a593Smuzhiyun do { \
321*4882a593Smuzhiyun if (unlikely(!(X))) { \
322*4882a593Smuzhiyun pr_err("\n"); \
323*4882a593Smuzhiyun pr_err("Assertion failed\n"); \
324*4882a593Smuzhiyun BUG(); \
325*4882a593Smuzhiyun } \
326*4882a593Smuzhiyun } while (0)
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun #define ASSERTCMP(X, OP, Y) \
329*4882a593Smuzhiyun do { \
330*4882a593Smuzhiyun if (unlikely(!((X) OP (Y)))) { \
331*4882a593Smuzhiyun pr_err("\n"); \
332*4882a593Smuzhiyun pr_err("Assertion failed\n"); \
333*4882a593Smuzhiyun pr_err("%lx " #OP " %lx is false\n", \
334*4882a593Smuzhiyun (unsigned long)(X), (unsigned long)(Y)); \
335*4882a593Smuzhiyun BUG(); \
336*4882a593Smuzhiyun } \
337*4882a593Smuzhiyun } while (0)
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun #define ASSERTIF(C, X) \
340*4882a593Smuzhiyun do { \
341*4882a593Smuzhiyun if (unlikely((C) && !(X))) { \
342*4882a593Smuzhiyun pr_err("\n"); \
343*4882a593Smuzhiyun pr_err("Assertion failed\n"); \
344*4882a593Smuzhiyun BUG(); \
345*4882a593Smuzhiyun } \
346*4882a593Smuzhiyun } while (0)
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun #define ASSERTIFCMP(C, X, OP, Y) \
349*4882a593Smuzhiyun do { \
350*4882a593Smuzhiyun if (unlikely((C) && !((X) OP (Y)))) { \
351*4882a593Smuzhiyun pr_err("\n"); \
352*4882a593Smuzhiyun pr_err("Assertion failed\n"); \
353*4882a593Smuzhiyun pr_err("%lx " #OP " %lx is false\n", \
354*4882a593Smuzhiyun (unsigned long)(X), (unsigned long)(Y)); \
355*4882a593Smuzhiyun BUG(); \
356*4882a593Smuzhiyun } \
357*4882a593Smuzhiyun } while (0)
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun #else
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun #define ASSERT(X) do {} while (0)
362*4882a593Smuzhiyun #define ASSERTCMP(X, OP, Y) do {} while (0)
363*4882a593Smuzhiyun #define ASSERTIF(C, X) do {} while (0)
364*4882a593Smuzhiyun #define ASSERTIFCMP(C, X, OP, Y) do {} while (0)
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun #endif
367