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