978ae283ee80deeab927666e1ffe01dbfe5fef03
[mirror/scst/.git] / scst / src / scst_mem.h
1 /*
2  *  scst_mem.h
3  *
4  *  Copyright (C) 2006 - 2009 Vladislav Bolkhovitin <vst@vlnb.net>
5  *  Copyright (C) 2007 Krzysztof Blaszkowski <kb@sysmikro.com.pl>
6  *  Copyright (C) 2007 - 2009 ID7 Ltd.
7  *
8  *  This program is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU General Public License
10  *  as published by the Free Software Foundation, version 2
11  *  of the License.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  *  GNU General Public License for more details.
17  */
18
19 #include <linux/scatterlist.h>
20 #include <linux/workqueue.h>
21 #include <linux/seq_file.h>
22
23 #define SGV_POOL_ELEMENTS       11
24
25 /*
26  * sg_num is indexed by the page number, pg_count is indexed by the sg number.
27  * Made in one entry to simplify the code (eg all sizeof(*) parts) and save
28  * some CPU cache for non-clustered case.
29  */
30 struct trans_tbl_ent {
31         unsigned short sg_num;
32         unsigned short pg_count;
33 };
34
35 struct sgv_pool_obj {
36         /* if <0 - pages, >0 - order */
37         int order_or_pages;
38
39         struct {
40                 /* jiffies, protected by pool_mgr_lock */
41                 unsigned long time_stamp;
42                 struct list_head recycling_list_entry;
43                 struct list_head sorted_recycling_list_entry;
44         } recycle_entry;
45
46         struct sgv_pool *owner_pool;
47         int orig_sg;
48         int orig_length;
49         int sg_count;
50         void *allocator_priv;
51         struct trans_tbl_ent *trans_tbl;
52         struct scatterlist *sg_entries;
53         struct scatterlist sg_entries_data[0];
54 };
55
56 struct sgv_pool_acc {
57         u32 cached_pages, cached_entries;
58         atomic_t big_alloc, other_alloc;
59         atomic_t big_pages, other_pages;
60         atomic_t big_merged, other_merged;
61 };
62
63 struct sgv_pool_cache_acc {
64         atomic_t total_alloc, hit_alloc;
65         atomic_t merged;
66 };
67
68 struct sgv_pool_alloc_fns {
69         struct page *(*alloc_pages_fn)(struct scatterlist *sg, gfp_t gfp_mask,
70                 void *priv);
71         void (*free_pages_fn)(struct scatterlist *sg, int sg_count,
72                 void *priv);
73 };
74
75 struct sgv_pool {
76         enum sgv_clustering_types clustering_type;
77         struct sgv_pool_alloc_fns alloc_fns;
78         /* 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 */
79         struct kmem_cache *caches[SGV_POOL_ELEMENTS];
80
81         /* protected by pool_mgr_lock */
82         struct list_head recycling_lists[SGV_POOL_ELEMENTS];
83
84         struct sgv_pool_acc acc;
85         struct sgv_pool_cache_acc cache_acc[SGV_POOL_ELEMENTS];
86
87         /* SCST_MAX_NAME + few more bytes to match scst_user expectations */
88         char cache_names[SGV_POOL_ELEMENTS][SCST_MAX_NAME + 10];
89         char name[SCST_MAX_NAME + 10];
90         struct list_head sgv_pool_list_entry;
91 };
92
93 struct scst_sgv_pools_manager {
94         struct {
95                 struct sgv_pool norm_clust, norm;
96                 struct sgv_pool dma;
97         } default_set;
98
99         struct sgv_pool_mgr {
100                 spinlock_t pool_mgr_lock;
101                 /* protected by pool_mgr_lock */
102                 struct list_head sorted_recycling_list;
103                 /* protected by pool_mgr_lock */
104                 unsigned pitbool_running:1;
105
106                 struct sgv_mem_throttling {
107                         u32 inactive_pages_total;
108                         u32 active_pages_total;
109
110                         /*
111                          * compared against inactive_pages_total +
112                          *                  active_pages_total
113                          */
114                         u32 hi_wmk;
115                         /* compared against inactive_pages_total only */
116                         u32 lo_wmk;
117
118                         u32 releases_on_hiwmk;
119                         u32 releases_failed;
120                 } throttle; /* protected by pool_mgr_lock */
121
122 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23))
123                 struct shrinker *sgv_shrinker;
124 #else
125                 struct shrinker sgv_shrinker;
126 #endif
127
128 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))
129                 struct delayed_work apit_pool;
130 #else
131                 struct work_struct apit_pool;
132 #endif
133         } mgr;
134
135         int sgv_max_local_order, sgv_max_trans_order;
136
137         atomic_t sgv_other_total_alloc;
138         struct mutex scst_sgv_pool_mutex;
139         struct list_head scst_sgv_pool_list;
140 };
141
142 int sgv_pool_init(struct sgv_pool *pool, const char *name,
143         enum sgv_clustering_types clustering_type);
144 void sgv_pool_deinit(struct sgv_pool *pool);
145
146 static inline struct scatterlist *sgv_pool_sg(struct sgv_pool_obj *obj)
147 {
148         return obj->sg_entries;
149 }
150
151 extern int scst_sgv_pools_init(unsigned long mem_hwmark,
152                                unsigned long mem_lwmark);
153 extern void scst_sgv_pools_deinit(void);
154 extern int sgv_pool_procinfo_show(struct seq_file *seq, void *v);
155
156 void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev);
157 void scst_sgv_pool_use_norm_clust(struct scst_tgt_dev *tgt_dev);
158 void scst_sgv_pool_use_dma(struct scst_tgt_dev *tgt_dev);