remove double export of xseg symbols
[archipelago] / xseg / peers / kernel / xsegbd.c
1 /* xsegbd.c
2  *
3  */
4
5 #include <linux/module.h>
6 #include <linux/moduleparam.h>
7 #include <linux/init.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
11 #include <linux/fs.h>
12 #include <linux/errno.h>
13 #include <linux/timer.h>
14 #include <linux/types.h>
15 #include <linux/vmalloc.h>
16 #include <linux/genhd.h>
17 #include <linux/blkdev.h>
18 #include <linux/bio.h>
19 #include <linux/device.h>
20 #include <linux/completion.h>
21
22 #include <sys/kernel/segdev.h>
23 #include "xsegbd.h"
24
25 #define XSEGBD_MINORS 1
26 /* define max request size to be used in xsegbd */
27 //FIXME should we make this 4MB instead of 256KB ?
28 #define XSEGBD_MAX_REQUEST_SIZE 262144U
29
30 MODULE_DESCRIPTION("xsegbd");
31 MODULE_AUTHOR("XSEG");
32 MODULE_LICENSE("GPL");
33
34 static long sector_size = 0;
35 static long blksize = 512;
36 static int major = 0;
37 static int max_dev = 1024;
38 static char name[XSEGBD_SEGMENT_NAMELEN] = "xsegbd";
39 static char spec[256] = "segdev:xsegbd:4:1024:12";
40
41 module_param(sector_size, long, 0644);
42 module_param(blksize, long, 0644);
43 module_param(max_dev, int, 0644);
44 module_param(major, int, 0644);
45 module_param_string(name, name, sizeof(name), 0644);
46 module_param_string(spec, spec, sizeof(spec), 0644);
47
48 static struct xsegbd xsegbd;
49 static struct xsegbd_device **xsegbd_devices; /* indexed by portno */
50 static DEFINE_MUTEX(xsegbd_mutex);
51 static DEFINE_SPINLOCK(xsegbd_devices_lock);
52
53
54
55 static struct xsegbd_device *__xsegbd_get_dev(unsigned long id)
56 {
57         struct xsegbd_device *xsegbd_dev = NULL;
58
59         spin_lock(&xsegbd_devices_lock);
60         xsegbd_dev = xsegbd_devices[id];
61         spin_unlock(&xsegbd_devices_lock);
62
63         return xsegbd_dev;
64 }
65
66 /* ************************* */
67 /* ***** sysfs helpers ***** */
68 /* ************************* */
69
70 static struct xsegbd_device *dev_to_xsegbd(struct device *dev)
71 {
72         return container_of(dev, struct xsegbd_device, dev);
73 }
74
75 static struct device *xsegbd_get_dev(struct xsegbd_device *xsegbd_dev)
76 {
77         /* FIXME */
78         return get_device(&xsegbd_dev->dev);
79 }
80
81 static void xsegbd_put_dev(struct xsegbd_device *xsegbd_dev)
82 {
83         put_device(&xsegbd_dev->dev);
84 }
85
86 /* ************************* */
87 /* ** XSEG Initialization ** */
88 /* ************************* */
89
90 static void xseg_callback(uint32_t portno);
91
92 int xsegbd_xseg_init(void)
93 {
94         int r;
95
96         if (!xsegbd.name[0])
97                 strncpy(xsegbd.name, name, XSEGBD_SEGMENT_NAMELEN);
98
99         r = xseg_initialize();
100         if (r) {
101                 XSEGLOG("cannot initialize 'segdev' peer");
102                 goto err;
103         }
104
105         r = xseg_parse_spec(spec, &xsegbd.config);
106         if (r)
107                 goto err;
108
109         if (strncmp(xsegbd.config.type, "segdev", 16))
110                 XSEGLOG("WARNING: unexpected segment type '%s' vs 'segdev'",
111                          xsegbd.config.type);
112
113         /* leave it here for now */
114         XSEGLOG("joining segment");
115         xsegbd.xseg = xseg_join(        xsegbd.config.type,
116                                         xsegbd.config.name,
117                                         "segdev",
118                                         xseg_callback           );
119         if (!xsegbd.xseg) {
120                 XSEGLOG("cannot find segment");
121                 r = -ENODEV;
122                 goto err;
123         }
124
125         return 0;
126 err:
127         return r;
128
129 }
130
131 int xsegbd_xseg_quit(void)
132 {
133         struct segdev *segdev;
134
135         /* make sure to unmap the segment first */
136         segdev = segdev_get(0);
137         clear_bit(SEGDEV_RESERVED, &segdev->flags);
138         xsegbd.xseg->priv->segment_type.ops.unmap(xsegbd.xseg, xsegbd.xseg->segment_size);
139         segdev_put(segdev);
140
141         return 0;
142 }
143
144
145 /* ***************************** */
146 /* ** Block Device Operations ** */
147 /* ***************************** */
148
149 static int xsegbd_open(struct block_device *bdev, fmode_t mode)
150 {
151         struct gendisk *disk = bdev->bd_disk;
152         struct xsegbd_device *xsegbd_dev = disk->private_data;
153
154         xsegbd_get_dev(xsegbd_dev);
155
156         return 0;
157 }
158
159 static int xsegbd_release(struct gendisk *gd, fmode_t mode)
160 {
161         struct xsegbd_device *xsegbd_dev = gd->private_data;
162
163         xsegbd_put_dev(xsegbd_dev);
164
165         return 0;
166 }
167
168 static int xsegbd_ioctl(struct block_device *bdev, fmode_t mode,
169                         unsigned int cmd, unsigned long arg)
170 {
171         return -ENOTTY;
172 }
173
174 static const struct block_device_operations xsegbd_ops = {
175         .owner          = THIS_MODULE,
176         .open           = xsegbd_open,
177         .release        = xsegbd_release,
178         .ioctl          = xsegbd_ioctl 
179 };
180
181
182 /* *************************** */
183 /* ** Device Initialization ** */
184 /* *************************** */
185
186 static void xseg_request_fn(struct request_queue *rq);
187 static int xsegbd_get_size(struct xsegbd_device *xsegbd_dev);
188
189 static int xsegbd_dev_init(struct xsegbd_device *xsegbd_dev)
190 {
191         int ret = -ENOMEM;
192         struct gendisk *disk;
193         unsigned int max_request_size_bytes;
194
195         spin_lock_init(&xsegbd_dev->rqlock);
196
197         xsegbd_dev->xsegbd = &xsegbd;
198
199         xsegbd_dev->blk_queue = blk_alloc_queue(GFP_KERNEL);
200         if (!xsegbd_dev->blk_queue)
201                 goto out;
202
203         if (!blk_init_allocated_queue(xsegbd_dev->blk_queue, 
204                         xseg_request_fn, &xsegbd_dev->rqlock))
205                 goto outqueue;
206
207         xsegbd_dev->blk_queue->queuedata = xsegbd_dev;
208
209         blk_queue_flush(xsegbd_dev->blk_queue, REQ_FLUSH | REQ_FUA);
210         blk_queue_logical_block_size(xsegbd_dev->blk_queue, 512);
211         blk_queue_physical_block_size(xsegbd_dev->blk_queue, blksize);
212         blk_queue_bounce_limit(xsegbd_dev->blk_queue, BLK_BOUNCE_ANY);
213         
214         //blk_queue_max_segments(dev->blk_queue, 512);
215
216         max_request_size_bytes = XSEGBD_MAX_REQUEST_SIZE;
217         blk_queue_max_hw_sectors(xsegbd_dev->blk_queue, max_request_size_bytes >> 9);
218         blk_queue_max_segment_size(xsegbd_dev->blk_queue, max_request_size_bytes);
219         blk_queue_io_min(xsegbd_dev->blk_queue, max_request_size_bytes);
220         blk_queue_io_opt(xsegbd_dev->blk_queue, max_request_size_bytes);
221
222         queue_flag_set_unlocked(QUEUE_FLAG_NONROT, xsegbd_dev->blk_queue);
223
224         /* vkoukis says we don't need partitions */
225         xsegbd_dev->gd = disk = alloc_disk(1);
226         if (!disk)
227                 goto outqueue;
228
229         disk->major = xsegbd_dev->major;
230         disk->first_minor = 0; // id * XSEGBD_MINORS;
231         disk->fops = &xsegbd_ops;
232         disk->queue = xsegbd_dev->blk_queue;
233         disk->private_data = xsegbd_dev;
234         disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
235         snprintf(disk->disk_name, 32, "xsegbd%u", xsegbd_dev->id);
236
237         ret = 0;
238         
239         /* allow a non-zero sector_size parameter to override the disk size */
240         if (sector_size)
241                 xsegbd_dev->sectors = sector_size;
242         else {
243                 ret = xsegbd_get_size(xsegbd_dev);
244                 if (ret)
245                         goto outdisk;
246         }
247
248         set_capacity(disk, xsegbd_dev->sectors);
249         XSEGLOG("xsegbd active...");
250         add_disk(disk); /* immediately activates the device */
251
252         return 0;
253
254
255 outdisk:
256         put_disk(xsegbd_dev->gd);
257 outqueue:
258         blk_cleanup_queue(xsegbd_dev->blk_queue);
259 out:
260         xsegbd_dev->gd = NULL;
261         return ret;
262 }
263
264 static void xsegbd_dev_release(struct device *dev)
265 {
266         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
267         
268         xseg_cancel_wait(xsegbd_dev->xseg, xsegbd_dev->src_portno);
269
270         /* cleanup gendisk and blk_queue the right way */
271         if (xsegbd_dev->gd) {
272                 if (xsegbd_dev->gd->flags & GENHD_FL_UP)
273                         del_gendisk(xsegbd_dev->gd);
274
275                 blk_cleanup_queue(xsegbd_dev->blk_queue);
276                 put_disk(xsegbd_dev->gd);
277         }
278
279 //      if (xseg_free_requests(xsegbd_dev->xseg, 
280 //                      xsegbd_dev->src_portno, xsegbd_dev->nr_requests) < 0)
281 //              XSEGLOG("Error trying to free requests!\n");
282
283
284         unregister_blkdev(xsegbd_dev->major, XSEGBD_NAME);
285
286         spin_lock(&xsegbd_devices_lock);
287         BUG_ON(xsegbd_devices[xsegbd_dev->src_portno] != xsegbd_dev);
288         xsegbd_devices[xsegbd_dev->src_portno] = NULL;
289         spin_unlock(&xsegbd_devices_lock);
290
291         if (xsegbd_dev->blk_req_pending)
292                 kfree(xsegbd_dev->blk_req_pending);
293         xq_free(&xsegbd_dev->blk_queue_pending);
294
295         kfree(xsegbd_dev);
296
297         module_put(THIS_MODULE);
298 }
299
300 /* ******************* */
301 /* ** Critical Path ** */
302 /* ******************* */
303
304 static void blk_to_xseg(struct xseg *xseg, struct xseg_request *xreq,
305                         struct request *blkreq)
306 {
307         struct bio_vec *bvec;
308         struct req_iterator iter;
309         uint64_t off = 0;
310         char *data = xseg_get_data(xseg, xreq);
311         rq_for_each_segment(bvec, blkreq, iter) {
312                 char *bdata = kmap_atomic(bvec->bv_page) + bvec->bv_offset;
313                 memcpy(data + off, bdata, bvec->bv_len);
314                 off += bvec->bv_len;
315                 kunmap_atomic(bdata);
316         }
317 }
318
319 static void xseg_to_blk(struct xseg *xseg, struct xseg_request *xreq,
320                         struct request *blkreq)
321 {
322         struct bio_vec *bvec;
323         struct req_iterator iter;
324         uint64_t off = 0;
325         char *data = xseg_get_data(xseg, xreq);
326         rq_for_each_segment(bvec, blkreq, iter) {
327                 char *bdata = kmap_atomic(bvec->bv_page) + bvec->bv_offset;
328                 memcpy(bdata, data + off, bvec->bv_len);
329                 off += bvec->bv_len;
330                 kunmap_atomic(bdata);
331         }
332 }
333
334 static void xseg_request_fn(struct request_queue *rq)
335 {
336         struct xseg_request *xreq;
337         struct xsegbd_device *xsegbd_dev = rq->queuedata;
338         struct request *blkreq;
339         struct xsegbd_pending *pending;
340         xqindex blkreq_idx;
341         char *target;
342         uint64_t datalen;
343         xport p;
344         int r;
345
346         for (;;) {
347                 blkreq_idx = Noneidx;
348                 xreq = xseg_get_request(xsegbd_dev->xseg, xsegbd_dev->src_portno, 
349                                 xsegbd_dev->dst_portno, X_ALLOC);
350                 if (!xreq)
351                         break;
352
353                 blkreq_idx = xq_pop_head(&xsegbd_dev->blk_queue_pending, 
354                                                 xsegbd_dev->src_portno);
355                 if (blkreq_idx == Noneidx)
356                         break;
357                 
358                 if (blkreq_idx >= xsegbd_dev->nr_requests) {
359                         XSEGLOG("blkreq_idx >= xsegbd_dev->nr_requests");
360                         BUG_ON(1);
361                         break;
362                 }
363
364                 blkreq = blk_fetch_request(rq);
365                 if (!blkreq)
366                         break;
367
368                 if (blkreq->cmd_type != REQ_TYPE_FS) {
369                         //we lose xreq here
370                         XSEGLOG("non-fs cmd_type: %u. *shrug*", blkreq->cmd_type);
371                         __blk_end_request_all(blkreq, 0);
372                         continue;
373                 }
374
375                 datalen = blk_rq_bytes(blkreq);
376                 r = xseg_prep_request(xsegbd_dev->xseg, xreq, 
377                                         xsegbd_dev->targetlen, datalen);
378                 if (r < 0) {
379                         XSEGLOG("couldn't prep request");
380                         __blk_end_request_err(blkreq, r);
381                         BUG_ON(1);
382                         break;
383                 }
384                 r = -ENOMEM;
385                 if (xreq->bufferlen - xsegbd_dev->targetlen < datalen){
386                         XSEGLOG("malformed req buffers");
387                         __blk_end_request_err(blkreq, r);
388                         BUG_ON(1);
389                         break;
390                 }
391
392                 target = xseg_get_target(xsegbd_dev->xseg, xreq);
393                 strncpy(target, xsegbd_dev->target, xsegbd_dev->targetlen);
394
395                 pending = &xsegbd_dev->blk_req_pending[blkreq_idx];
396                 pending->dev = xsegbd_dev;
397                 pending->request = blkreq;
398                 pending->comp = NULL;
399                 
400                 xreq->size = datalen;
401                 xreq->offset = blk_rq_pos(blkreq) << 9;
402                 xreq->priv = (uint64_t) blkreq_idx;
403
404                 /*
405                 if (xreq->offset >= (sector_size << 9))
406                         XSEGLOG("sector offset: %lu > %lu, flush:%u, fua:%u",
407                                  blk_rq_pos(blkreq), sector_size,
408                                  blkreq->cmd_flags & REQ_FLUSH,
409                                  blkreq->cmd_flags & REQ_FUA);
410                 */
411
412                 if (blkreq->cmd_flags & REQ_FLUSH)
413                         xreq->flags |= XF_FLUSH;
414
415                 if (blkreq->cmd_flags & REQ_FUA)
416                         xreq->flags |= XF_FUA;
417
418                 if (rq_data_dir(blkreq)) {
419                         /* unlock for data transfers? */
420                         blk_to_xseg(xsegbd_dev->xseg, xreq, blkreq);
421                         xreq->op = X_WRITE;
422                 } else {
423                         xreq->op = X_READ;
424                 }
425
426
427                 r = -EIO;
428                 p = xseg_submit(xsegbd_dev->xseg, xreq, 
429                                         xsegbd_dev->src_portno, X_ALLOC);
430                 if (p == NoPort) {
431                         XSEGLOG("coundn't submit req");
432                         BUG_ON(1);
433                         __blk_end_request_err(blkreq, r);
434                         break;
435                 }
436                 WARN_ON(xseg_signal(xsegbd_dev->xsegbd->xseg, p) < 0);
437         }
438         if (xreq)
439                 BUG_ON(xseg_put_request(xsegbd_dev->xsegbd->xseg, xreq, 
440                                         xsegbd_dev->src_portno) == -1);
441         if (blkreq_idx != Noneidx)
442                 BUG_ON(xq_append_head(&xsegbd_dev->blk_queue_pending, 
443                                 blkreq_idx, xsegbd_dev->src_portno) == Noneidx);
444 }
445
446 int update_dev_sectors_from_request(    struct xsegbd_device *xsegbd_dev,
447                                         struct xseg_request *xreq       )
448 {
449         void *data;
450
451         if (xreq->state & XS_FAILED)
452                 return -ENOENT;
453
454         if (!(xreq->state & XS_SERVED))
455                 return -EIO;
456
457         data = xseg_get_data(xsegbd_dev->xseg, xreq);
458         xsegbd_dev->sectors = *((uint64_t *) data) / 512ULL;
459         return 0;
460 }
461
462 static int xsegbd_get_size(struct xsegbd_device *xsegbd_dev)
463 {
464         struct xseg_request *xreq;
465         char *target;
466         uint64_t datalen;
467         xqindex blkreq_idx;
468         struct xsegbd_pending *pending;
469         struct completion comp;
470         xport p;
471         void *data;
472         int ret = -EBUSY, r;
473         xreq = xseg_get_request(xsegbd_dev->xseg, xsegbd_dev->src_portno,
474                         xsegbd_dev->dst_portno, X_ALLOC);
475         if (!xreq)
476                 goto out;
477
478         datalen = sizeof(uint64_t);
479         BUG_ON(xseg_prep_request(xsegbd_dev->xseg, xreq, xsegbd_dev->targetlen, datalen));
480         BUG_ON(xreq->bufferlen - xsegbd_dev->targetlen < datalen);
481
482         init_completion(&comp);
483         blkreq_idx = xq_pop_head(&xsegbd_dev->blk_queue_pending, 1);
484         if (blkreq_idx == Noneidx)
485                 goto out;
486         
487         pending = &xsegbd_dev->blk_req_pending[blkreq_idx];
488         pending->dev = xsegbd_dev;
489         pending->request = NULL;
490         pending->comp = &comp;
491
492         
493         xreq->priv = (uint64_t) blkreq_idx;
494
495         target = xseg_get_target(xsegbd_dev->xseg, xreq);
496         strncpy(target, xsegbd_dev->target, xsegbd_dev->targetlen);
497         xreq->size = datalen;
498         xreq->offset = 0;
499         xreq->op = X_INFO;
500
501         xseg_prepare_wait(xsegbd_dev->xseg, xsegbd_dev->src_portno);
502         p = xseg_submit(xsegbd_dev->xseg, xreq, 
503                                 xsegbd_dev->src_portno, X_ALLOC);
504         if ( p == NoPort) {
505                 XSEGLOG("couldn't submit request");
506                 BUG_ON(1);
507                 goto out_queue;
508         }
509         WARN_ON(xseg_signal(xsegbd_dev->xseg, p) < 0);
510
511         wait_for_completion_interruptible(&comp);
512         //XSEGLOG("Woken up after wait_for_completion_interruptible()\n");
513         ret = update_dev_sectors_from_request(xsegbd_dev, xreq);
514         //XSEGLOG("get_size: sectors = %ld\n", (long)xsegbd_dev->sectors);
515 out:
516         BUG_ON(xseg_put_request(xsegbd_dev->xseg, xreq, xsegbd_dev->src_portno) == -1);
517         return ret;
518
519 out_queue:
520         pending->dev = NULL;
521         pending->comp = NULL;
522         xq_append_head(&xsegbd_dev->blk_queue_pending, blkreq_idx, 1);
523         
524         goto out;
525 }
526
527 static void xseg_callback(xport portno)
528 {
529         struct xsegbd_device *xsegbd_dev;
530         struct xseg_request *xreq;
531         struct request *blkreq;
532         struct xsegbd_pending *pending;
533         unsigned long flags;
534         xqindex blkreq_idx, ridx;
535         int err;
536         void *data;
537
538         xsegbd_dev  = __xsegbd_get_dev(portno);
539         if (!xsegbd_dev) {
540                 XSEGLOG("portno: %u has no xsegbd device assigned", portno);
541                 WARN_ON(1);
542                 return;
543         }
544
545         for (;;) {
546                 xseg_prepare_wait(xsegbd_dev->xseg, xsegbd_dev->src_portno);
547                 xreq = xseg_receive(xsegbd_dev->xseg, portno);
548                 if (!xreq)
549                         break;
550
551                 xseg_cancel_wait(xsegbd_dev->xseg, xsegbd_dev->src_portno);
552
553                 blkreq_idx = (xqindex) xreq->priv;
554                 if (blkreq_idx >= xsegbd_dev->nr_requests) {
555                         WARN_ON(1);
556                         //FIXME maybe put request?
557                         continue;
558                 }
559
560                 pending = &xsegbd_dev->blk_req_pending[blkreq_idx];
561                 if (pending->comp) {
562                         /* someone is blocking on this request
563                            and will handle it when we wake them up. */
564                         complete(pending->comp);
565                         /* the request is blocker's responsibility so
566                            we will not put_request(); */
567                         continue;
568                 }
569
570                 /* this is now treated as a block I/O request to end */
571                 blkreq = pending->request;
572                 pending->request = NULL;
573                 if (xsegbd_dev != pending->dev) {
574                         //FIXME maybe put request?
575                         XSEGLOG("xsegbd_dev != pending->dev");
576                         BUG_ON(1);
577                         continue;
578                 }
579                 pending->dev = NULL;
580                 if (!blkreq){
581                         //FIXME maybe put request?
582                         XSEGLOG("blkreq does not exist");
583                         BUG_ON(1);
584                         continue;
585                 }
586
587                 err = -EIO;
588                 if (!(xreq->state & XS_SERVED))
589                         goto blk_end;
590
591                 if (xreq->serviced != blk_rq_bytes(blkreq))
592                         goto blk_end;
593
594                 err = 0;
595                 /* unlock for data transfer? */
596                 if (!rq_data_dir(blkreq)){
597                         xseg_to_blk(xsegbd_dev->xseg, xreq, blkreq);
598                 }       
599 blk_end:
600                 blk_end_request_all(blkreq, err);
601                 
602                 ridx = xq_append_head(&xsegbd_dev->blk_queue_pending, 
603                                         blkreq_idx, xsegbd_dev->src_portno);
604                 if (ridx == Noneidx) {
605                         XSEGLOG("couldnt append blkreq_idx");
606                         WARN_ON(1);
607                 }
608
609                 if (xseg_put_request(xsegbd_dev->xseg, xreq, 
610                                                 xsegbd_dev->src_portno) < 0){
611                         XSEGLOG("couldn't put req");
612                         BUG_ON(1);
613                 }
614         }
615
616         if (xsegbd_dev) {
617                 spin_lock_irqsave(&xsegbd_dev->rqlock, flags);
618                 xseg_request_fn(xsegbd_dev->blk_queue);
619                 spin_unlock_irqrestore(&xsegbd_dev->rqlock, flags);
620         }
621 }
622
623
624 /* sysfs interface */
625
626 static struct bus_type xsegbd_bus_type = {
627         .name   = "xsegbd",
628 };
629
630 static ssize_t xsegbd_size_show(struct device *dev,
631                                         struct device_attribute *attr, char *buf)
632 {
633         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
634
635         return sprintf(buf, "%llu\n", (unsigned long long) xsegbd_dev->sectors * 512ULL);
636 }
637
638 static ssize_t xsegbd_major_show(struct device *dev,
639                                         struct device_attribute *attr, char *buf)
640 {
641         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
642
643         return sprintf(buf, "%d\n", xsegbd_dev->major);
644 }
645
646 static ssize_t xsegbd_srcport_show(struct device *dev,
647                                         struct device_attribute *attr, char *buf)
648 {
649         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
650
651         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->src_portno);
652 }
653
654 static ssize_t xsegbd_dstport_show(struct device *dev,
655                                         struct device_attribute *attr, char *buf)
656 {
657         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
658
659         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->dst_portno);
660 }
661
662 static ssize_t xsegbd_id_show(struct device *dev,
663                                         struct device_attribute *attr, char *buf)
664 {
665         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
666
667         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->id);
668 }
669
670 static ssize_t xsegbd_reqs_show(struct device *dev,
671                                         struct device_attribute *attr, char *buf)
672 {
673         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
674
675         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->nr_requests);
676 }
677
678 static ssize_t xsegbd_target_show(struct device *dev,
679                                         struct device_attribute *attr, char *buf)
680 {
681         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
682
683         return sprintf(buf, "%s\n", xsegbd_dev->target);
684 }
685
686 static ssize_t xsegbd_image_refresh(struct device *dev,
687                                         struct device_attribute *attr,
688                                         const char *buf,
689                                         size_t size)
690 {
691         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
692         int rc, ret = size;
693
694         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
695
696         rc = xsegbd_get_size(xsegbd_dev);
697         if (rc < 0) {
698                 ret = rc;
699                 goto out;
700         }
701
702         set_capacity(xsegbd_dev->gd, xsegbd_dev->sectors);
703
704 out:
705         mutex_unlock(&xsegbd_mutex);
706         return ret;
707 }
708
709 static ssize_t xsegbd_cleanup(struct device *dev,
710                                         struct device_attribute *attr,
711                                         const char *buf,
712                                         size_t size)
713 {
714         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
715         int ret = size, i;
716         struct request *blkreq = NULL;
717         struct xsegbd_pending *pending = NULL;
718         struct completion *comp = NULL;
719
720         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
721         for (i = 0; i < xsegbd_dev->nr_requests; i++) {
722                 xlock_acquire(&xsegbd_dev->blk_queue_pending.lock, 
723                                 xsegbd_dev->src_portno);
724                 if (!__xq_check(&xsegbd_dev->blk_queue_pending, i)) {
725                         pending = &xsegbd_dev->blk_req_pending[i];
726                         blkreq = pending->request;
727                         pending->request = NULL;
728                         comp = pending->comp;
729                         pending->comp = NULL;
730                 }
731                 if (blkreq)
732                         blk_end_request_all(blkreq, -EIO);
733                 if (comp)
734                         complete(comp);
735                 __xq_append_tail(&xsegbd_dev->blk_queue_pending, i);
736                 xlock_release(&xsegbd_dev->blk_queue_pending.lock);
737         }
738
739         mutex_unlock(&xsegbd_mutex);
740         return ret;
741 }
742
743 static DEVICE_ATTR(size, S_IRUGO, xsegbd_size_show, NULL);
744 static DEVICE_ATTR(major, S_IRUGO, xsegbd_major_show, NULL);
745 static DEVICE_ATTR(srcport, S_IRUGO, xsegbd_srcport_show, NULL);
746 static DEVICE_ATTR(dstport, S_IRUGO, xsegbd_dstport_show, NULL);
747 static DEVICE_ATTR(id , S_IRUGO, xsegbd_id_show, NULL);
748 static DEVICE_ATTR(reqs , S_IRUGO, xsegbd_reqs_show, NULL);
749 static DEVICE_ATTR(target, S_IRUGO, xsegbd_target_show, NULL);
750 static DEVICE_ATTR(refresh , S_IWUSR, NULL, xsegbd_image_refresh);
751 static DEVICE_ATTR(cleanup , S_IWUSR, NULL, xsegbd_cleanup);
752
753 static struct attribute *xsegbd_attrs[] = {
754         &dev_attr_size.attr,
755         &dev_attr_major.attr,
756         &dev_attr_srcport.attr,
757         &dev_attr_dstport.attr,
758         &dev_attr_id.attr,
759         &dev_attr_reqs.attr,
760         &dev_attr_target.attr,
761         &dev_attr_refresh.attr,
762         &dev_attr_cleanup.attr,
763         NULL
764 };
765
766 static struct attribute_group xsegbd_attr_group = {
767         .attrs = xsegbd_attrs,
768 };
769
770 static const struct attribute_group *xsegbd_attr_groups[] = {
771         &xsegbd_attr_group,
772         NULL
773 };
774
775 static void xsegbd_sysfs_dev_release(struct device *dev)
776 {
777 }
778
779 static struct device_type xsegbd_device_type = {
780         .name           = "xsegbd",
781         .groups         = xsegbd_attr_groups,
782         .release        = xsegbd_sysfs_dev_release,
783 };
784
785 static void xsegbd_root_dev_release(struct device *dev)
786 {
787 }
788
789 static struct device xsegbd_root_dev = {
790         .init_name      = "xsegbd",
791         .release        = xsegbd_root_dev_release,
792 };
793
794 static int xsegbd_bus_add_dev(struct xsegbd_device *xsegbd_dev)
795 {
796         int ret = -ENOMEM;
797         struct device *dev;
798
799         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
800         dev = &xsegbd_dev->dev;
801
802         dev->bus = &xsegbd_bus_type;
803         dev->type = &xsegbd_device_type;
804         dev->parent = &xsegbd_root_dev;
805         dev->release = xsegbd_dev_release;
806         dev_set_name(dev, "%d", xsegbd_dev->id);
807
808         ret = device_register(dev);
809
810         mutex_unlock(&xsegbd_mutex);
811         return ret;
812 }
813
814 static void xsegbd_bus_del_dev(struct xsegbd_device *xsegbd_dev)
815 {
816         device_unregister(&xsegbd_dev->dev);
817 }
818
819 static ssize_t xsegbd_add(struct bus_type *bus, const char *buf, size_t count)
820 {
821         struct xsegbd_device *xsegbd_dev;
822         struct xseg_port *port;
823         ssize_t ret = -ENOMEM;
824
825         if (!try_module_get(THIS_MODULE))
826                 return -ENODEV;
827
828         xsegbd_dev = kzalloc(sizeof(*xsegbd_dev), GFP_KERNEL);
829         if (!xsegbd_dev)
830                 goto out;
831
832         spin_lock_init(&xsegbd_dev->rqlock);
833         INIT_LIST_HEAD(&xsegbd_dev->node);
834
835         /* parse cmd */
836         if (sscanf(buf, "%" __stringify(XSEGBD_TARGET_NAMELEN) "s "
837                         "%d:%d:%d", xsegbd_dev->target, &xsegbd_dev->src_portno,
838                         &xsegbd_dev->dst_portno, &xsegbd_dev->nr_requests) < 3) {
839                 ret = -EINVAL;
840                 goto out_dev;
841         }
842         xsegbd_dev->targetlen = strlen(xsegbd_dev->target);
843
844         spin_lock(&xsegbd_devices_lock);
845         if (xsegbd_devices[xsegbd_dev->src_portno] != NULL) {
846                 ret = -EINVAL;
847                 goto out_unlock;
848         }
849         xsegbd_devices[xsegbd_dev->src_portno] = xsegbd_dev;
850         xsegbd_dev->id = xsegbd_dev->src_portno;
851         spin_unlock(&xsegbd_devices_lock);
852
853         XSEGLOG("registering block device major %d", major);
854         ret = register_blkdev(major, XSEGBD_NAME);
855         if (ret < 0) {
856                 XSEGLOG("cannot register block device!");
857                 ret = -EBUSY;
858                 goto out_delentry;
859         }
860         xsegbd_dev->major = ret;
861         XSEGLOG("registered block device major %d", xsegbd_dev->major);
862
863         ret = xsegbd_bus_add_dev(xsegbd_dev);
864         if (ret)
865                 goto out_blkdev;
866
867         if (!xq_alloc_seq(&xsegbd_dev->blk_queue_pending, 
868                                 xsegbd_dev->nr_requests,
869                                 xsegbd_dev->nr_requests))
870                 goto out_bus;
871
872         xsegbd_dev->blk_req_pending = kzalloc(
873                         xsegbd_dev->nr_requests *sizeof(struct xsegbd_pending),
874                                    GFP_KERNEL);
875         if (!xsegbd_dev->blk_req_pending)
876                 goto out_freeq;
877
878         
879         XSEGLOG("joining segment");
880         //FIXME use xsebd module config for now
881         xsegbd_dev->xseg = xseg_join(   xsegbd.config.type,
882                                         xsegbd.config.name,
883                                         "segdev",
884                                         xseg_callback           );
885         if (!xsegbd_dev->xseg)
886                 goto out_freepending;
887         
888
889         XSEGLOG("binding to source port %u (destination %u)",
890                         xsegbd_dev->src_portno, xsegbd_dev->dst_portno);
891         port = xseg_bind_port(xsegbd_dev->xseg, xsegbd_dev->src_portno);
892         if (!port) {
893                 XSEGLOG("cannot bind to port");
894                 ret = -EFAULT;
895
896                 goto out_xseg;
897         }
898         
899         if (xsegbd_dev->src_portno != xseg_portno(xsegbd_dev->xseg, port)) {
900                 XSEGLOG("portno != xsegbd_dev->src_portno");
901                 BUG_ON(1);
902                 ret = -EFAULT;
903                 goto out_xseg;
904         }
905         
906         /* make sure we don't get any requests until we're ready to handle them */
907         xseg_cancel_wait(xsegbd_dev->xseg, xseg_portno(xsegbd_dev->xseg, port));
908
909         ret = xsegbd_dev_init(xsegbd_dev);
910         if (ret)
911                 goto out_xseg;
912
913         xseg_prepare_wait(xsegbd_dev->xseg, xseg_portno(xsegbd_dev->xseg, port));
914         return count;
915
916 out_xseg:
917         xseg_leave(xsegbd_dev->xseg);
918         
919 out_freepending:
920         kfree(xsegbd_dev->blk_req_pending);
921
922 out_freeq:
923         xq_free(&xsegbd_dev->blk_queue_pending);
924
925 out_bus:
926         xsegbd_bus_del_dev(xsegbd_dev);
927         return ret;
928
929 out_blkdev:
930         unregister_blkdev(xsegbd_dev->major, XSEGBD_NAME);
931
932 out_delentry:
933         spin_lock(&xsegbd_devices_lock);
934         xsegbd_devices[xsegbd_dev->src_portno] = NULL;
935
936 out_unlock:
937         spin_unlock(&xsegbd_devices_lock);
938
939 out_dev:
940         kfree(xsegbd_dev);
941
942 out:
943         return ret;
944 }
945
946 static ssize_t xsegbd_remove(struct bus_type *bus, const char *buf, size_t count)
947 {
948         struct xsegbd_device *xsegbd_dev = NULL;
949         int id, ret;
950         unsigned long ul_id;
951
952         ret = strict_strtoul(buf, 10, &ul_id);
953         if (ret)
954                 return ret;
955
956         id = (int) ul_id;
957         if (id != ul_id)
958                 return -EINVAL;
959
960         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
961
962         ret = count;
963         xsegbd_dev = __xsegbd_get_dev(id);
964         if (!xsegbd_dev) {
965                 ret = -ENOENT;
966                 goto out_unlock;
967         }
968         xsegbd_bus_del_dev(xsegbd_dev);
969
970 out_unlock:
971         mutex_unlock(&xsegbd_mutex);
972         return ret;
973 }
974
975 static struct bus_attribute xsegbd_bus_attrs[] = {
976         __ATTR(add, S_IWUSR, NULL, xsegbd_add),
977         __ATTR(remove, S_IWUSR, NULL, xsegbd_remove),
978         __ATTR_NULL
979 };
980
981 static int xsegbd_sysfs_init(void)
982 {
983         int ret;
984
985         ret = device_register(&xsegbd_root_dev);
986         if (ret < 0)
987                 return ret;
988
989         xsegbd_bus_type.bus_attrs = xsegbd_bus_attrs;
990         ret = bus_register(&xsegbd_bus_type);
991         if (ret < 0)
992                 device_unregister(&xsegbd_root_dev);
993
994         return ret;
995 }
996
997 static void xsegbd_sysfs_cleanup(void)
998 {
999         bus_unregister(&xsegbd_bus_type);
1000         device_unregister(&xsegbd_root_dev);
1001 }
1002
1003 /* *************************** */
1004 /* ** Module Initialization ** */
1005 /* *************************** */
1006
1007 static int __init xsegbd_init(void)
1008 {
1009         int ret = -ENOMEM;
1010         xsegbd_devices = kzalloc(max_dev * sizeof(struct xsegbd_devices *), GFP_KERNEL);
1011         if (!xsegbd_devices)
1012                 goto out;
1013
1014         spin_lock_init(&xsegbd_devices_lock);
1015
1016         ret = -ENOSYS;
1017         ret = xsegbd_xseg_init();
1018         if (ret)
1019                 goto out_free;
1020
1021         ret = xsegbd_sysfs_init();
1022         if (ret)
1023                 goto out_xseg;
1024
1025         XSEGLOG("initialization complete");
1026
1027 out:
1028         return ret;
1029
1030 out_xseg:
1031         xsegbd_xseg_quit();
1032         
1033 out_free:
1034         kfree(xsegbd_devices);
1035
1036         goto out;
1037 }
1038
1039 static void __exit xsegbd_exit(void)
1040 {
1041         xsegbd_sysfs_cleanup();
1042         xsegbd_xseg_quit();
1043 }
1044
1045 module_init(xsegbd_init);
1046 module_exit(xsegbd_exit);
1047