add cleanup sysfs method in xsegbd. plus some typos fixes
[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         xq_append_head(&xsegbd_dev->blk_queue_pending, blkreq_idx, 1);
521         
522         goto out;
523 }
524
525 static void xseg_callback(xport portno)
526 {
527         struct xsegbd_device *xsegbd_dev;
528         struct xseg_request *xreq;
529         struct request *blkreq;
530         struct xsegbd_pending *pending;
531         unsigned long flags;
532         xqindex blkreq_idx, ridx;
533         int err;
534         void *data;
535
536         xsegbd_dev  = __xsegbd_get_dev(portno);
537         if (!xsegbd_dev) {
538                 XSEGLOG("portno: %u has no xsegbd device assigned", portno);
539                 WARN_ON(1);
540                 return;
541         }
542
543         for (;;) {
544                 xseg_prepare_wait(xsegbd_dev->xseg, xsegbd_dev->src_portno);
545                 xreq = xseg_receive(xsegbd_dev->xseg, portno);
546                 if (!xreq)
547                         break;
548
549                 xseg_cancel_wait(xsegbd_dev->xseg, xsegbd_dev->src_portno);
550
551                 blkreq_idx = (xqindex) xreq->priv;
552                 if (blkreq_idx >= xsegbd_dev->nr_requests) {
553                         WARN_ON(1);
554                         //FIXME maybe put request?
555                         continue;
556                 }
557
558                 pending = &xsegbd_dev->blk_req_pending[blkreq_idx];
559                 if (pending->comp) {
560                         /* someone is blocking on this request
561                            and will handle it when we wake them up. */
562                         complete(pending->comp);
563                         /* the request is blocker's responsibility so
564                            we will not put_request(); */
565                         continue;
566                 }
567
568                 /* this is now treated as a block I/O request to end */
569                 blkreq = pending->request;
570                 pending->request = NULL;
571                 if (xsegbd_dev != pending->dev) {
572                         //FIXME maybe put request?
573                         XSEGLOG("xsegbd_dev != pending->dev");
574                         BUG_ON(1);
575                         continue;
576                 }
577                 pending->dev = NULL;
578                 if (!blkreq){
579                         //FIXME maybe put request?
580                         XSEGLOG("blkreq does not exist");
581                         BUG_ON(1);
582                         continue;
583                 }
584
585                 err = -EIO;
586                 if (!(xreq->state & XS_SERVED))
587                         goto blk_end;
588
589                 if (xreq->serviced != blk_rq_bytes(blkreq))
590                         goto blk_end;
591
592                 err = 0;
593                 /* unlock for data transfer? */
594                 if (!rq_data_dir(blkreq)){
595                         xseg_to_blk(xsegbd_dev->xseg, xreq, blkreq);
596                 }       
597 blk_end:
598                 blk_end_request_all(blkreq, err);
599                 
600                 ridx = xq_append_head(&xsegbd_dev->blk_queue_pending, 
601                                         blkreq_idx, xsegbd_dev->src_portno);
602                 if (ridx == Noneidx) {
603                         XSEGLOG("couldnt append blkreq_idx");
604                         WARN_ON(1);
605                 }
606
607                 if (xseg_put_request(xsegbd_dev->xseg, xreq, 
608                                                 xsegbd_dev->src_portno) < 0){
609                         XSEGLOG("couldn't put req");
610                         BUG_ON(1);
611                 }
612         }
613
614         if (xsegbd_dev) {
615                 spin_lock_irqsave(&xsegbd_dev->rqlock, flags);
616                 xseg_request_fn(xsegbd_dev->blk_queue);
617                 spin_unlock_irqrestore(&xsegbd_dev->rqlock, flags);
618         }
619 }
620
621
622 /* sysfs interface */
623
624 static struct bus_type xsegbd_bus_type = {
625         .name   = "xsegbd",
626 };
627
628 static ssize_t xsegbd_size_show(struct device *dev,
629                                         struct device_attribute *attr, char *buf)
630 {
631         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
632
633         return sprintf(buf, "%llu\n", (unsigned long long) xsegbd_dev->sectors * 512ULL);
634 }
635
636 static ssize_t xsegbd_major_show(struct device *dev,
637                                         struct device_attribute *attr, char *buf)
638 {
639         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
640
641         return sprintf(buf, "%d\n", xsegbd_dev->major);
642 }
643
644 static ssize_t xsegbd_srcport_show(struct device *dev,
645                                         struct device_attribute *attr, char *buf)
646 {
647         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
648
649         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->src_portno);
650 }
651
652 static ssize_t xsegbd_dstport_show(struct device *dev,
653                                         struct device_attribute *attr, char *buf)
654 {
655         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
656
657         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->dst_portno);
658 }
659
660 static ssize_t xsegbd_id_show(struct device *dev,
661                                         struct device_attribute *attr, char *buf)
662 {
663         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
664
665         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->id);
666 }
667
668 static ssize_t xsegbd_reqs_show(struct device *dev,
669                                         struct device_attribute *attr, char *buf)
670 {
671         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
672
673         return sprintf(buf, "%u\n", (unsigned) xsegbd_dev->nr_requests);
674 }
675
676 static ssize_t xsegbd_target_show(struct device *dev,
677                                         struct device_attribute *attr, char *buf)
678 {
679         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
680
681         return sprintf(buf, "%s\n", xsegbd_dev->target);
682 }
683
684 static ssize_t xsegbd_image_refresh(struct device *dev,
685                                         struct device_attribute *attr,
686                                         const char *buf,
687                                         size_t size)
688 {
689         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
690         int rc, ret = size;
691
692         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
693
694         rc = xsegbd_get_size(xsegbd_dev);
695         if (rc < 0) {
696                 ret = rc;
697                 goto out;
698         }
699
700         set_capacity(xsegbd_dev->gd, xsegbd_dev->sectors);
701
702 out:
703         mutex_unlock(&xsegbd_mutex);
704         return ret;
705 }
706
707 static ssize_t xsegbd_cleanup(struct device *dev,
708                                         struct device_attribute *attr,
709                                         const char *buf,
710                                         size_t size)
711 {
712         struct xsegbd_device *xsegbd_dev = dev_to_xsegbd(dev);
713         int ret = size, i;
714         struct request *blkreq = NULL;
715         struct xsegbd_pending *pending = NULL;
716         struct completion *comp = NULL;
717
718         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
719         for (i = 0; i < xsegbd_dev->nr_requests; i++) {
720                 xlock_acquire(&xsegbd_dev->blk_queue_pending.lock, 
721                                 xsegbd_dev->src_portno);
722                 if (!__xq_check(&xsegbd_dev->blk_queue_pending, i)) {
723                         pending = &xsegbd_dev->blk_req_pending[i];
724                         blkreq = pending->request;
725                         pending->request = NULL;
726                         comp = pending->comp;
727                         pending->comp = NULL;
728                 }
729                 if (blkreq)
730                         blk_end_request_all(blkreq, -EIO);
731                 if (comp)
732                         complete(comp);
733                 xlock_release(&xsegbd_dev->blk_queue_pending.lock);
734         }
735
736         mutex_unlock(&xsegbd_mutex);
737         return ret;
738 }
739
740 static DEVICE_ATTR(size, S_IRUGO, xsegbd_size_show, NULL);
741 static DEVICE_ATTR(major, S_IRUGO, xsegbd_major_show, NULL);
742 static DEVICE_ATTR(srcport, S_IRUGO, xsegbd_srcport_show, NULL);
743 static DEVICE_ATTR(dstport, S_IRUGO, xsegbd_dstport_show, NULL);
744 static DEVICE_ATTR(id , S_IRUGO, xsegbd_id_show, NULL);
745 static DEVICE_ATTR(reqs , S_IRUGO, xsegbd_reqs_show, NULL);
746 static DEVICE_ATTR(target, S_IRUGO, xsegbd_target_show, NULL);
747 static DEVICE_ATTR(refresh , S_IWUSR, NULL, xsegbd_image_refresh);
748 static DEVICE_ATTR(cleanup , S_IWUSR, NULL, xsegbd_cleanup);
749
750 static struct attribute *xsegbd_attrs[] = {
751         &dev_attr_size.attr,
752         &dev_attr_major.attr,
753         &dev_attr_srcport.attr,
754         &dev_attr_dstport.attr,
755         &dev_attr_id.attr,
756         &dev_attr_reqs.attr,
757         &dev_attr_target.attr,
758         &dev_attr_refresh.attr,
759         &dev_attr_cleanup.attr,
760         NULL
761 };
762
763 static struct attribute_group xsegbd_attr_group = {
764         .attrs = xsegbd_attrs,
765 };
766
767 static const struct attribute_group *xsegbd_attr_groups[] = {
768         &xsegbd_attr_group,
769         NULL
770 };
771
772 static void xsegbd_sysfs_dev_release(struct device *dev)
773 {
774 }
775
776 static struct device_type xsegbd_device_type = {
777         .name           = "xsegbd",
778         .groups         = xsegbd_attr_groups,
779         .release        = xsegbd_sysfs_dev_release,
780 };
781
782 static void xsegbd_root_dev_release(struct device *dev)
783 {
784 }
785
786 static struct device xsegbd_root_dev = {
787         .init_name      = "xsegbd",
788         .release        = xsegbd_root_dev_release,
789 };
790
791 static int xsegbd_bus_add_dev(struct xsegbd_device *xsegbd_dev)
792 {
793         int ret = -ENOMEM;
794         struct device *dev;
795
796         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
797         dev = &xsegbd_dev->dev;
798
799         dev->bus = &xsegbd_bus_type;
800         dev->type = &xsegbd_device_type;
801         dev->parent = &xsegbd_root_dev;
802         dev->release = xsegbd_dev_release;
803         dev_set_name(dev, "%d", xsegbd_dev->id);
804
805         ret = device_register(dev);
806
807         mutex_unlock(&xsegbd_mutex);
808         return ret;
809 }
810
811 static void xsegbd_bus_del_dev(struct xsegbd_device *xsegbd_dev)
812 {
813         device_unregister(&xsegbd_dev->dev);
814 }
815
816 static ssize_t xsegbd_add(struct bus_type *bus, const char *buf, size_t count)
817 {
818         struct xsegbd_device *xsegbd_dev;
819         struct xseg_port *port;
820         ssize_t ret = -ENOMEM;
821
822         if (!try_module_get(THIS_MODULE))
823                 return -ENODEV;
824
825         xsegbd_dev = kzalloc(sizeof(*xsegbd_dev), GFP_KERNEL);
826         if (!xsegbd_dev)
827                 goto out;
828
829         spin_lock_init(&xsegbd_dev->rqlock);
830         INIT_LIST_HEAD(&xsegbd_dev->node);
831
832         /* parse cmd */
833         if (sscanf(buf, "%" __stringify(XSEGBD_TARGET_NAMELEN) "s "
834                         "%d:%d:%d", xsegbd_dev->target, &xsegbd_dev->src_portno,
835                         &xsegbd_dev->dst_portno, &xsegbd_dev->nr_requests) < 3) {
836                 ret = -EINVAL;
837                 goto out_dev;
838         }
839         xsegbd_dev->targetlen = strlen(xsegbd_dev->target);
840
841         spin_lock(&xsegbd_devices_lock);
842         if (xsegbd_devices[xsegbd_dev->src_portno] != NULL) {
843                 ret = -EINVAL;
844                 goto out_unlock;
845         }
846         xsegbd_devices[xsegbd_dev->src_portno] = xsegbd_dev;
847         xsegbd_dev->id = xsegbd_dev->src_portno;
848         spin_unlock(&xsegbd_devices_lock);
849
850         XSEGLOG("registering block device major %d", major);
851         ret = register_blkdev(major, XSEGBD_NAME);
852         if (ret < 0) {
853                 XSEGLOG("cannot register block device!");
854                 ret = -EBUSY;
855                 goto out_delentry;
856         }
857         xsegbd_dev->major = ret;
858         XSEGLOG("registered block device major %d", xsegbd_dev->major);
859
860         ret = xsegbd_bus_add_dev(xsegbd_dev);
861         if (ret)
862                 goto out_blkdev;
863
864         if (!xq_alloc_seq(&xsegbd_dev->blk_queue_pending, 
865                                 xsegbd_dev->nr_requests,
866                                 xsegbd_dev->nr_requests))
867                 goto out_bus;
868
869         xsegbd_dev->blk_req_pending = kzalloc(
870                         xsegbd_dev->nr_requests *sizeof(struct xsegbd_pending),
871                                    GFP_KERNEL);
872         if (!xsegbd_dev->blk_req_pending)
873                 goto out_freeq;
874
875         
876         XSEGLOG("joining segment");
877         //FIXME use xsebd module config for now
878         xsegbd_dev->xseg = xseg_join(   xsegbd.config.type,
879                                         xsegbd.config.name,
880                                         "segdev",
881                                         xseg_callback           );
882         if (!xsegbd_dev->xseg)
883                 goto out_freepending;
884         
885
886         XSEGLOG("binding to source port %u (destination %u)",
887                         xsegbd_dev->src_portno, xsegbd_dev->dst_portno);
888         port = xseg_bind_port(xsegbd_dev->xseg, xsegbd_dev->src_portno);
889         if (!port) {
890                 XSEGLOG("cannot bind to port");
891                 ret = -EFAULT;
892
893                 goto out_xseg;
894         }
895         
896         if (xsegbd_dev->src_portno != xseg_portno(xsegbd_dev->xseg, port)) {
897                 XSEGLOG("portno != xsegbd_dev->src_portno");
898                 BUG_ON(1);
899                 ret = -EFAULT;
900                 goto out_xseg;
901         }
902         
903         /* make sure we don't get any requests until we're ready to handle them */
904         xseg_cancel_wait(xsegbd_dev->xseg, xseg_portno(xsegbd_dev->xseg, port));
905
906         ret = xsegbd_dev_init(xsegbd_dev);
907         if (ret)
908                 goto out_xseg;
909
910         xseg_prepare_wait(xsegbd_dev->xseg, xseg_portno(xsegbd_dev->xseg, port));
911         return count;
912
913 out_xseg:
914         xseg_leave(xsegbd_dev->xseg);
915         
916 out_freepending:
917         kfree(xsegbd_dev->blk_req_pending);
918
919 out_freeq:
920         xq_free(&xsegbd_dev->blk_queue_pending);
921
922 out_bus:
923         xsegbd_bus_del_dev(xsegbd_dev);
924         return ret;
925
926 out_blkdev:
927         unregister_blkdev(xsegbd_dev->major, XSEGBD_NAME);
928
929 out_delentry:
930         spin_lock(&xsegbd_devices_lock);
931         xsegbd_devices[xsegbd_dev->src_portno] = NULL;
932
933 out_unlock:
934         spin_unlock(&xsegbd_devices_lock);
935
936 out_dev:
937         kfree(xsegbd_dev);
938
939 out:
940         return ret;
941 }
942
943 static ssize_t xsegbd_remove(struct bus_type *bus, const char *buf, size_t count)
944 {
945         struct xsegbd_device *xsegbd_dev = NULL;
946         int id, ret;
947         unsigned long ul_id;
948
949         ret = strict_strtoul(buf, 10, &ul_id);
950         if (ret)
951                 return ret;
952
953         id = (int) ul_id;
954         if (id != ul_id)
955                 return -EINVAL;
956
957         mutex_lock_nested(&xsegbd_mutex, SINGLE_DEPTH_NESTING);
958
959         ret = count;
960         xsegbd_dev = __xsegbd_get_dev(id);
961         if (!xsegbd_dev) {
962                 ret = -ENOENT;
963                 goto out_unlock;
964         }
965         xsegbd_bus_del_dev(xsegbd_dev);
966
967 out_unlock:
968         mutex_unlock(&xsegbd_mutex);
969         return ret;
970 }
971
972 static struct bus_attribute xsegbd_bus_attrs[] = {
973         __ATTR(add, S_IWUSR, NULL, xsegbd_add),
974         __ATTR(remove, S_IWUSR, NULL, xsegbd_remove),
975         __ATTR_NULL
976 };
977
978 static int xsegbd_sysfs_init(void)
979 {
980         int ret;
981
982         ret = device_register(&xsegbd_root_dev);
983         if (ret < 0)
984                 return ret;
985
986         xsegbd_bus_type.bus_attrs = xsegbd_bus_attrs;
987         ret = bus_register(&xsegbd_bus_type);
988         if (ret < 0)
989                 device_unregister(&xsegbd_root_dev);
990
991         return ret;
992 }
993
994 static void xsegbd_sysfs_cleanup(void)
995 {
996         bus_unregister(&xsegbd_bus_type);
997         device_unregister(&xsegbd_root_dev);
998 }
999
1000 /* *************************** */
1001 /* ** Module Initialization ** */
1002 /* *************************** */
1003
1004 static int __init xsegbd_init(void)
1005 {
1006         int ret = -ENOMEM;
1007         xsegbd_devices = kzalloc(max_dev * sizeof(struct xsegbd_devices *), GFP_KERNEL);
1008         if (!xsegbd_devices)
1009                 goto out;
1010
1011         spin_lock_init(&xsegbd_devices_lock);
1012
1013         ret = -ENOSYS;
1014         ret = xsegbd_xseg_init();
1015         if (ret)
1016                 goto out_free;
1017
1018         ret = xsegbd_sysfs_init();
1019         if (ret)
1020                 goto out_xseg;
1021
1022         XSEGLOG("initialization complete");
1023
1024 out:
1025         return ret;
1026
1027 out_xseg:
1028         xsegbd_xseg_quit();
1029         
1030 out_free:
1031         kfree(xsegbd_devices);
1032
1033         goto out;
1034 }
1035
1036 static void __exit xsegbd_exit(void)
1037 {
1038         xsegbd_sysfs_cleanup();
1039         xsegbd_xseg_quit();
1040 }
1041
1042 module_init(xsegbd_init);
1043 module_exit(xsegbd_exit);
1044