Skip to content

Commit 99d639c

Browse files
committed
Added s-block STL template.
1 parent ac22361 commit 99d639c

File tree

2 files changed

+243
-1
lines changed

2 files changed

+243
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module := sadc
1+
module := sblock
22
obj-m := dm-$(module).o
33
KDIR := /lib/modules/$(shell uname -r)/build
44
PWD := $(shell pwd)

dm-sblock.c

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
#include <linux/device-mapper.h>
2+
#include <linux/module.h>
3+
#include <linux/init.h>
4+
#include <linux/bio.h>
5+
#include <linux/completion.h>
6+
#include <linux/string_helpers.h>
7+
8+
#define DM_MSG_PREFIX "sblock"
9+
10+
#define MIN_SBLOCK_SIZE (1 << 20)
11+
#define MAX_SBLOCK_SIZE (50 << 20)
12+
13+
#define MIN_NR_SECTIONS 2
14+
#define MAX_NR_SECTIONS 100
15+
16+
#define MIN_CACHE_PERCENT 1
17+
#define MAX_CACHE_PERCENT 10
18+
19+
#define MIN_OP_SBLOCK_PERCENT 1
20+
#define MAX_OP_SBLOCK_PERCENT 10
21+
22+
#define MIN_DISK_SIZE (76LL << 10)
23+
#define MAX_DISK_SIZE (10LL << 40)
24+
25+
typedef sector_t lba_t;
26+
typedef int32_t pba_t;
27+
28+
struct sblock_ctx {
29+
struct dm_dev *dev;
30+
31+
int64_t disk_size;
32+
int32_t cache_percent;
33+
int32_t op_sblock_percent;
34+
int32_t nr_sections;
35+
int32_t sblock_size;
36+
37+
int64_t section_usable_size;
38+
int64_t section_cache_size;
39+
int32_t section_nr_sblocks;
40+
int32_t section_nr_op_sblocks;
41+
int64_t total_usable_size;
42+
};
43+
44+
static char *readable(u64 size)
45+
{
46+
static char buf[10];
47+
48+
string_get_size(size, STRING_UNITS_2, buf, sizeof(buf));
49+
50+
return buf;
51+
}
52+
53+
static bool get_args(struct dm_target *ti, struct sblock_ctx *sc,
54+
int argc, char **argv)
55+
{
56+
unsigned long long tmp;
57+
char d;
58+
59+
if (argc != 6) {
60+
ti->error = "dm-sblock: Invalid argument count.";
61+
return false;
62+
}
63+
64+
if (sscanf(argv[1], "%llu%c", &tmp, &d) != 1 || tmp & 0xfff ||
65+
(tmp < MIN_SBLOCK_SIZE || tmp > MAX_SBLOCK_SIZE)) {
66+
ti->error = "dm-sblock: Invalid s-block size.";
67+
return false;
68+
}
69+
sc->sblock_size = tmp;
70+
71+
if (sscanf(argv[2], "%llu%c", &tmp, &d) != 1 ||
72+
tmp < MIN_NR_SECTIONS || tmp > MAX_NR_SECTIONS) {
73+
ti->error = "dm-sblock: Invalid section count.";
74+
return false;
75+
}
76+
sc->nr_sections = tmp;
77+
78+
if (sscanf(argv[3], "%llu%c", &tmp, &d) != 1 ||
79+
tmp < MIN_OP_SBLOCK_PERCENT || tmp > MAX_OP_SBLOCK_PERCENT) {
80+
ti->error = "dm-sblock: Invalid over-provisioned sblock percent.";
81+
return false;
82+
}
83+
sc->op_sblock_percent = tmp;
84+
85+
if (sscanf(argv[4], "%llu%c", &tmp, &d) != 1 ||
86+
tmp < MIN_CACHE_PERCENT || tmp > MAX_CACHE_PERCENT) {
87+
ti->error = "dm-sblock: Invalid cache percent.";
88+
return false;
89+
}
90+
sc->cache_percent = tmp;
91+
92+
if (sscanf(argv[5], "%llu%c", &tmp, &d) != 1 ||
93+
tmp < MIN_DISK_SIZE || tmp > MAX_DISK_SIZE) {
94+
ti->error = "dm-sblock: Invalid disk size.";
95+
return false;
96+
}
97+
sc->disk_size = tmp;
98+
99+
return true;
100+
}
101+
102+
static void calc_params(struct sblock_ctx *sc)
103+
{
104+
int64_t s = sc->disk_size / sc->nr_sections;
105+
106+
sc->section_cache_size = s * sc->cache_percent / 100;
107+
s -= sc->section_cache_size;
108+
sc->section_nr_sblocks = s / sc->sblock_size;
109+
sc->section_nr_op_sblocks = sc->section_nr_sblocks * sc->op_sblock_percent / 100;
110+
sc->section_nr_sblocks -= sc->section_nr_op_sblocks;
111+
112+
sc->section_usable_size = sc->section_nr_sblocks * (int64_t) sc->sblock_size;
113+
sc->total_usable_size = sc->section_usable_size * sc->nr_sections;
114+
}
115+
116+
static void print_params(struct sblock_ctx *sc)
117+
{
118+
DMINFO("Disk size: %s", readable(sc->disk_size));
119+
DMINFO("S-block size: %s", readable(sc->sblock_size));
120+
DMINFO("Cache size/section: %s", readable(sc->section_cache_size));
121+
DMINFO("S-blocks/section: %d", sc->section_nr_sblocks);
122+
DMINFO("OP s-blocks/section: %d", sc->section_nr_op_sblocks);
123+
DMINFO("Usable section size: %s", readable(sc->section_usable_size));
124+
DMINFO("Total usable size: %s", readable(sc->total_usable_size));
125+
}
126+
127+
static void sblock_dtr(struct dm_target *ti)
128+
{
129+
struct sblock_ctx *sc = (struct sblock_ctx *) ti->private;
130+
131+
DMINFO("Destructing...");
132+
133+
ti->private = NULL;
134+
135+
if (!sc)
136+
return;
137+
kzfree(sc);
138+
}
139+
140+
static int sblock_ctr(struct dm_target *ti, unsigned int argc, char **argv)
141+
{
142+
struct sblock_ctx *sc;
143+
int32_t ret;
144+
145+
DMINFO("Constructing...");
146+
147+
sc = kzalloc(sizeof(*sc), GFP_KERNEL);
148+
if (!sc) {
149+
ti->error = "dm-sblock: Cannot allocate sblock context.";
150+
return -ENOMEM;
151+
}
152+
ti->private = sc;
153+
154+
if (!get_args(ti, sc, argc, argv)) {
155+
kzfree(sc);
156+
return -EINVAL;
157+
}
158+
159+
calc_params(sc);
160+
print_params(sc);
161+
162+
ret = -EINVAL;
163+
if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &sc->dev)) {
164+
ti->error = "dm-sblock: Device lookup failed.";
165+
return -1;
166+
}
167+
168+
/* TODO: Reconsider proper values for these. */
169+
ti->num_flush_bios = 1;
170+
ti->num_discard_bios = 1;
171+
ti->num_write_same_bios = 1;
172+
173+
return 0;
174+
}
175+
176+
static int sblock_map(struct dm_target *ti, struct bio *bio)
177+
{
178+
return DM_MAPIO_REMAPPED;
179+
}
180+
181+
static void sblock_status(struct dm_target *ti, status_type_t type,
182+
unsigned status_flags, char *result, unsigned maxlen)
183+
{
184+
struct sblock_ctx *sc = (struct sblock_ctx *) ti->private;
185+
186+
switch (type) {
187+
case STATUSTYPE_INFO:
188+
result[0] = '\0';
189+
break;
190+
191+
/* TODO: get string representation of device name.*/
192+
case STATUSTYPE_TABLE:
193+
snprintf(result, maxlen, "%s cache: %%%d, over-provisioned sblock: %%%d, sections %d, sblock size: %d",
194+
sc->dev->name,
195+
sc->cache_percent,
196+
sc->op_sblock_percent,
197+
sc->nr_sections,
198+
sc->sblock_size);
199+
break;
200+
}
201+
}
202+
203+
static int sblock_iterate_devices(struct dm_target *ti,
204+
iterate_devices_callout_fn fn, void *data)
205+
{
206+
struct sblock_ctx *sc = ti->private;
207+
208+
return fn(ti, sc->dev, 0, ti->len, data);
209+
}
210+
211+
static struct target_type sblock_target = {
212+
.name = "sblock",
213+
.version = {1, 0, 0},
214+
.module = THIS_MODULE,
215+
.ctr = sblock_ctr,
216+
.dtr = sblock_dtr,
217+
.map = sblock_map,
218+
.status = sblock_status,
219+
.iterate_devices = sblock_iterate_devices,
220+
};
221+
222+
static int __init sblock_init(void)
223+
{
224+
int r = dm_register_target(&sblock_target);
225+
226+
if (r < 0)
227+
DMERR("register failed %d", r);
228+
229+
return r;
230+
}
231+
232+
static void __exit sblock_exit(void)
233+
{
234+
dm_unregister_target(&sblock_target);
235+
}
236+
237+
module_init(sblock_init);
238+
module_exit(sblock_exit);
239+
240+
MODULE_AUTHOR("Abutalib Aghayev <[email protected]>");
241+
MODULE_DESCRIPTION(DM_NAME " S-block STL emulator target");
242+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)