Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/md/dm-linear.c
15109 views
1
/*
2
* Copyright (C) 2001-2003 Sistina Software (UK) Limited.
3
*
4
* This file is released under the GPL.
5
*/
6
7
#include "dm.h"
8
#include <linux/module.h>
9
#include <linux/init.h>
10
#include <linux/blkdev.h>
11
#include <linux/bio.h>
12
#include <linux/slab.h>
13
#include <linux/device-mapper.h>
14
15
#define DM_MSG_PREFIX "linear"
16
17
/*
18
* Linear: maps a linear range of a device.
19
*/
20
struct linear_c {
21
struct dm_dev *dev;
22
sector_t start;
23
};
24
25
/*
26
* Construct a linear mapping: <dev_path> <offset>
27
*/
28
static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
29
{
30
struct linear_c *lc;
31
unsigned long long tmp;
32
33
if (argc != 2) {
34
ti->error = "Invalid argument count";
35
return -EINVAL;
36
}
37
38
lc = kmalloc(sizeof(*lc), GFP_KERNEL);
39
if (lc == NULL) {
40
ti->error = "dm-linear: Cannot allocate linear context";
41
return -ENOMEM;
42
}
43
44
if (sscanf(argv[1], "%llu", &tmp) != 1) {
45
ti->error = "dm-linear: Invalid device sector";
46
goto bad;
47
}
48
lc->start = tmp;
49
50
if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
51
ti->error = "dm-linear: Device lookup failed";
52
goto bad;
53
}
54
55
ti->num_flush_requests = 1;
56
ti->num_discard_requests = 1;
57
ti->private = lc;
58
return 0;
59
60
bad:
61
kfree(lc);
62
return -EINVAL;
63
}
64
65
static void linear_dtr(struct dm_target *ti)
66
{
67
struct linear_c *lc = (struct linear_c *) ti->private;
68
69
dm_put_device(ti, lc->dev);
70
kfree(lc);
71
}
72
73
static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
74
{
75
struct linear_c *lc = ti->private;
76
77
return lc->start + dm_target_offset(ti, bi_sector);
78
}
79
80
static void linear_map_bio(struct dm_target *ti, struct bio *bio)
81
{
82
struct linear_c *lc = ti->private;
83
84
bio->bi_bdev = lc->dev->bdev;
85
if (bio_sectors(bio))
86
bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
87
}
88
89
static int linear_map(struct dm_target *ti, struct bio *bio,
90
union map_info *map_context)
91
{
92
linear_map_bio(ti, bio);
93
94
return DM_MAPIO_REMAPPED;
95
}
96
97
static int linear_status(struct dm_target *ti, status_type_t type,
98
char *result, unsigned int maxlen)
99
{
100
struct linear_c *lc = (struct linear_c *) ti->private;
101
102
switch (type) {
103
case STATUSTYPE_INFO:
104
result[0] = '\0';
105
break;
106
107
case STATUSTYPE_TABLE:
108
snprintf(result, maxlen, "%s %llu", lc->dev->name,
109
(unsigned long long)lc->start);
110
break;
111
}
112
return 0;
113
}
114
115
static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
116
unsigned long arg)
117
{
118
struct linear_c *lc = (struct linear_c *) ti->private;
119
return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg);
120
}
121
122
static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
123
struct bio_vec *biovec, int max_size)
124
{
125
struct linear_c *lc = ti->private;
126
struct request_queue *q = bdev_get_queue(lc->dev->bdev);
127
128
if (!q->merge_bvec_fn)
129
return max_size;
130
131
bvm->bi_bdev = lc->dev->bdev;
132
bvm->bi_sector = linear_map_sector(ti, bvm->bi_sector);
133
134
return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
135
}
136
137
static int linear_iterate_devices(struct dm_target *ti,
138
iterate_devices_callout_fn fn, void *data)
139
{
140
struct linear_c *lc = ti->private;
141
142
return fn(ti, lc->dev, lc->start, ti->len, data);
143
}
144
145
static struct target_type linear_target = {
146
.name = "linear",
147
.version = {1, 1, 0},
148
.module = THIS_MODULE,
149
.ctr = linear_ctr,
150
.dtr = linear_dtr,
151
.map = linear_map,
152
.status = linear_status,
153
.ioctl = linear_ioctl,
154
.merge = linear_merge,
155
.iterate_devices = linear_iterate_devices,
156
};
157
158
int __init dm_linear_init(void)
159
{
160
int r = dm_register_target(&linear_target);
161
162
if (r < 0)
163
DMERR("register failed %d", r);
164
165
return r;
166
}
167
168
void dm_linear_exit(void)
169
{
170
dm_unregister_target(&linear_target);
171
}
172
173