diff options
Diffstat (limited to 'fs/aufs/module.h')
-rw-r--r-- | fs/aufs/module.h | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/fs/aufs/module.h b/fs/aufs/module.h index 1383e3da9..681dc75f5 100644 --- a/fs/aufs/module.h +++ b/fs/aufs/module.h @@ -12,6 +12,7 @@ #ifdef __KERNEL__ #include <linux/slab.h> +#include "debug.h" struct path; struct seq_file; @@ -38,7 +39,7 @@ AuStubVoid(au_procfs_fin, void); /* ---------------------------------------------------------------------- */ -/* kmem cache */ +/* kmem cache and delayed free */ enum { AuCache_DINFO, AuCache_ICNTNR, @@ -49,19 +50,54 @@ enum { AuCache_Last }; +enum { + AU_DFREE_KFREE, + AU_DFREE_FREE_PAGE, + AU_DFREE_Last +}; + +struct au_cache { + struct kmem_cache *cache; + struct llist_head llist; /* delayed free */ +}; + +/* + * in order to reduce the cost of the internal timer, consolidate all the + * delayed free works into a single delayed_work. + */ +struct au_dfree { + struct au_cache cache[AuCache_Last]; + struct llist_head llist[AU_DFREE_Last]; + struct delayed_work dwork; +}; + +extern struct au_dfree au_dfree; + #define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) #define AuCache(type) KMEM_CACHE(type, AuCacheFlags) #define AuCacheCtor(type, ctor) \ kmem_cache_create(#type, sizeof(struct type), \ __alignof__(struct type), AuCacheFlags, ctor) -extern struct kmem_cache *au_cachep[]; +#define AU_DFREE_DELAY msecs_to_jiffies(10) +#define AU_DFREE_BODY(lnode, llist) do { \ + if (llist_add(lnode, llist)) \ + schedule_delayed_work(&au_dfree.dwork, \ + AU_DFREE_DELAY); \ + } while (0) +#define AU_CACHE_DFREE_FUNC(name, idx, lnode) \ + void au_cache_dfree_##name(struct au_##name *p) \ + { \ + struct au_cache *cp = au_dfree.cache + AuCache_##idx; \ + AU_DFREE_BODY(&p->lnode, &cp->llist); \ + } #define AuCacheFuncs(name, index) \ static inline struct au_##name *au_cache_alloc_##name(void) \ -{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \ +{ return kmem_cache_alloc(au_dfree.cache[AuCache_##index].cache, GFP_NOFS); } \ static inline void au_cache_free_##name(struct au_##name *p) \ -{ kmem_cache_free(au_cachep[AuCache_##index], p); } +{ kmem_cache_free(au_dfree.cache[AuCache_##index].cache, p); } \ +void au_cache_dfree_##name(struct au_##name *p) AuCacheFuncs(dinfo, DINFO); AuCacheFuncs(icntnr, ICNTNR); @@ -72,5 +108,24 @@ AuCacheFuncs(vdir_dehstr, DEHSTR); AuCacheFuncs(hnotify, HNOTIFY); #endif +static inline void au_delayed_kfree(const void *p) +{ + AuDebugOn(!p); + AuDebugOn(ksize(p) < sizeof(struct llist_node)); + + AU_DFREE_BODY((void *)p, au_dfree.llist + AU_DFREE_KFREE); +} + +/* cast only */ +static inline void au_free_page(void *p) +{ + free_page((unsigned long)p); +} + +static inline void au_delayed_free_page(unsigned long addr) +{ + AU_DFREE_BODY((void *)addr, au_dfree.llist + AU_DFREE_FREE_PAGE); +} + #endif /* __KERNEL__ */ #endif /* __AUFS_MODULE_H__ */ |