UBUNTU: ubuntu: iscsitarget -- version 1.4.20.1
[linux-flexiantxendom0-natty.git] / ubuntu / iscsitarget / block-io.c
1 /*
2  * Target device block I/O.
3  *
4  * Based on file I/O driver from FUJITA Tomonori
5  * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
6  * (C) 2006 Andre Brinkmann <brinkman at hni dot upb dot de>
7  * (C) 2007 Ross Walker <rswwalker at hotmail dot com>
8  * (C) 2007 Ming Zhang <blackmagic02881 at gmail dot com>
9  * This code is licenced under the GPL.
10  */
11
12 #include <linux/types.h>
13 #include <linux/blkdev.h>
14 #include <linux/parser.h>
15 #include <linux/buffer_head.h>
16
17 #include "iscsi.h"
18 #include "iscsi_dbg.h"
19 #include "iotype.h"
20
21 struct blockio_data {
22         char *path;
23         struct block_device *bdev;
24 };
25
26 struct tio_work {
27         atomic_t error;
28         atomic_t bios_remaining;
29         struct completion tio_complete;
30 };
31
32 static void blockio_bio_endio(struct bio *bio, int error)
33 {
34         struct tio_work *tio_work = bio->bi_private;
35
36         error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO;
37
38         if (error)
39                 atomic_set(&tio_work->error, error);
40
41         /* If last bio signal completion */
42         if (atomic_dec_and_test(&tio_work->bios_remaining))
43                 complete(&tio_work->tio_complete);
44
45         bio_put(bio);
46 }
47
48 /*
49  * Blockio_make_request(): The function translates an iscsi-request into
50  * a number of requests to the corresponding block device.
51  */
52 static int
53 blockio_make_request(struct iet_volume *volume, struct tio *tio, int rw)
54 {
55         struct blockio_data *bio_data = volume->private;
56         struct request_queue *bdev_q = bdev_get_queue(bio_data->bdev);
57         struct tio_work *tio_work;
58         struct bio *tio_bio = NULL, *bio = NULL, *biotail = NULL;
59
60         u32 offset = tio->offset;
61         u32 size = tio->size;
62         u32 tio_index = 0;
63
64         int max_pages = 1;
65         int err = 0;
66
67         loff_t ppos = ((loff_t) tio->idx << PAGE_SHIFT) + offset;
68
69         /* Calculate max_pages for bio_alloc (memory saver) */
70         if (bdev_q)
71                 max_pages = bio_get_nr_vecs(bio_data->bdev);
72
73         tio_work = kzalloc(sizeof (*tio_work), GFP_KERNEL);
74         if (!tio_work)
75                 return -ENOMEM;
76
77         atomic_set(&tio_work->error, 0);
78         atomic_set(&tio_work->bios_remaining, 0);
79         init_completion(&tio_work->tio_complete);
80
81         /* Main processing loop, allocate and fill all bios */
82         while (tio_index < tio->pg_cnt) {
83                 bio = bio_alloc(GFP_KERNEL, min(max_pages, BIO_MAX_PAGES));
84                 if (!bio) {
85                         err = -ENOMEM;
86                         goto out;
87                 }
88
89                 /* bi_sector is ALWAYS in units of 512 bytes */
90                 bio->bi_sector = ppos >> 9;
91                 bio->bi_bdev = bio_data->bdev;
92                 bio->bi_end_io = blockio_bio_endio;
93                 bio->bi_private = tio_work;
94
95                 if (tio_bio)
96                         biotail = biotail->bi_next = bio;
97                 else
98                         tio_bio = biotail = bio;
99
100                 atomic_inc(&tio_work->bios_remaining);
101
102                 /* Loop for filling bio */
103                 while (tio_index < tio->pg_cnt) {
104                         unsigned int bytes = PAGE_SIZE - offset;
105
106                         if (bytes > size)
107                                 bytes = size;
108
109                         if (!bio_add_page(bio, tio->pvec[tio_index], bytes, offset))
110                                 break;
111
112                         size -= bytes;
113                         ppos += bytes;
114
115                         offset = 0;
116
117                         tio_index++;
118                 }
119         }
120
121         /* Walk the list, submitting bios 1 by 1 */
122         while (tio_bio) {
123                 bio = tio_bio;
124                 tio_bio = tio_bio->bi_next;
125                 bio->bi_next = NULL;
126
127                 submit_bio(rw, bio);
128         }
129
130         if (bdev_q && bdev_q->unplug_fn)
131                 bdev_q->unplug_fn(bdev_q);
132
133         wait_for_completion(&tio_work->tio_complete);
134
135         err = atomic_read(&tio_work->error);
136
137         kfree(tio_work);
138
139         return err;
140 out:
141         while (tio_bio) {
142                 bio = tio_bio;
143                 tio_bio = tio_bio->bi_next;
144
145                 bio_put(bio);
146         }
147
148         kfree(tio_work);
149
150         return err;
151 }
152
153 static int
154 blockio_open_path(struct iet_volume *volume, const char *path)
155 {
156         struct blockio_data *bio_data = volume->private;
157         struct block_device *bdev;
158         int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
159         int err = 0;
160
161         bio_data->path = kstrdup(path, GFP_KERNEL);
162         if (!bio_data->path)
163                 return -ENOMEM;
164
165         bdev = open_bdev_exclusive(path, flags, THIS_MODULE);
166         if (IS_ERR(bdev)) {
167                 err = PTR_ERR(bdev);
168                 eprintk("Can't open device %s, error %d\n", path, err);
169                 bio_data->bdev = NULL;
170         } else {
171                 bio_data->bdev = bdev;
172                 fsync_bdev(bio_data->bdev);
173         }
174
175         return err;
176 }
177
178 /* Create an enumeration of our accepted actions */
179 enum
180 {
181         opt_path, opt_ignore, opt_err,
182 };
183
184 /* Create a match table using our action enums and their matching options */
185 static match_table_t tokens = {
186         {opt_path, "path=%s"},
187         {opt_ignore, "scsiid=%s"},
188         {opt_ignore, "scsisn=%s"},
189         {opt_ignore, "type=%s"},
190         {opt_ignore, "iomode=%s"},
191         {opt_ignore, "blocksize=%s"},
192         {opt_err, NULL},
193 };
194
195 static int
196 parse_blockio_params(struct iet_volume *volume, char *params)
197 {
198         struct blockio_data *info = volume->private;
199         int err = 0;
200         char *p, *q;
201
202         /* Loop through parameters separated by commas, look up our
203          * parameter in match table, return enumeration and arguments
204          * select case based on the returned enum and run the action */
205         while ((p = strsep(&params, ",")) != NULL) {
206                 substring_t args[MAX_OPT_ARGS];
207                 int token;
208                 if (!*p)
209                         continue;
210                 iet_strtolower(p);
211                 token = match_token(p, tokens, args);
212                 switch (token) {
213                 case opt_path:
214                         if (info->path) {
215                                 iprintk("Target %s, LUN %u: "
216                                         "duplicate \"Path\" param\n",
217                                         volume->target->name, volume->lun);
218                                 err = -EINVAL;
219                                 goto out;
220                         }
221                         if (!(q = match_strdup(&args[0]))) {
222                                 err = -ENOMEM;
223                                 goto out;
224                         }
225                         err = blockio_open_path(volume, q);
226                         kfree(q);
227                         if (err < 0)
228                                 goto out;
229                         break;
230                 case opt_ignore:
231                         break;
232                 default:
233                         iprintk("Target %s, LUN %u: unknown param %s\n",
234                                 volume->target->name, volume->lun, p);
235                         return -EINVAL;
236                 }
237         }
238
239         if (!info->path) {
240                 iprintk("Target %s, LUN %u: missing \"Path\" param\n",
241                         volume->target->name, volume->lun);
242                 err = -EINVAL;
243         }
244
245   out:
246         return err;
247 }
248
249 static void
250 blockio_detach(struct iet_volume *volume)
251 {
252         struct blockio_data *bio_data = volume->private;
253         int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
254
255         if (bio_data->bdev)
256                 close_bdev_exclusive(bio_data->bdev, flags);
257         kfree(bio_data->path);
258
259         kfree(volume->private);
260 }
261
262 static int
263 blockio_attach(struct iet_volume *volume, char *args)
264 {
265         struct blockio_data *bio_data;
266         int err = 0;
267
268         if (volume->private) {
269                 eprintk("Lun %u already attached on Target %s \n",
270                         volume->lun, volume->target->name);
271                 return -EBUSY;
272         }
273
274         bio_data = kzalloc(sizeof (*bio_data), GFP_KERNEL);
275         if (!bio_data)
276                 return -ENOMEM;
277
278         volume->private = bio_data;
279
280         err = parse_blockio_params(volume, args);
281         if (!err) {
282                 /* see Documentation/ABI/testing/sysfs-block */
283                 unsigned bsz = bdev_logical_block_size(bio_data->bdev);
284                 if (!volume->blk_shift)
285                         volume->blk_shift = ilog2(bsz);
286                 else if (volume->blk_shift < ilog2(bsz)) {
287                         eprintk("Specified block size (%u) smaller than "
288                                 "device %s logical block size (%u)\n",
289                                 (1 << volume->blk_shift), bio_data->path, bsz);
290                         err = -EINVAL;
291                 }
292         }
293         if (err < 0) {
294                 eprintk("Error attaching Lun %u to Target %s \n",
295                         volume->lun, volume->target->name);
296                 goto out;
297         }
298
299         volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift;
300
301         /* Offer neither write nor read caching */
302         ClearLURCache(volume);
303         ClearLUWCache(volume);
304
305   out:
306         if (err < 0)
307                 blockio_detach(volume);
308
309         return err;
310 }
311
312 static void
313 blockio_show(struct iet_volume *volume, struct seq_file *seq)
314 {
315         struct blockio_data *bio_data = volume->private;
316
317         /* Used to display blockio volume info in /proc/net/iet/volumes */
318         seq_printf(seq, " path:%s\n", bio_data->path);
319 }
320
321 struct iotype blockio = {
322         .name = "blockio",
323         .attach = blockio_attach,
324         .make_request = blockio_make_request,
325         .detach = blockio_detach,
326         .show = blockio_show,
327 };