1 /* Xenbus code for blkif backend
2 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
3 Copyright (C) 2005 XenSource Ltd
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <linux/module.h>
22 #include <linux/kthread.h>
26 #define DPRINTK(fmt, args...) \
27 pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \
28 __FUNCTION__, __LINE__, ##args)
32 struct xenbus_device
*dev
;
34 struct xenbus_watch backend_watch
;
40 static void connect(struct backend_info
*);
41 static int connect_ring(struct backend_info
*);
42 static void backend_changed(struct xenbus_watch
*, const char **,
45 struct xenbus_device
*blkback_xenbus(struct backend_info
*be
)
50 static int blkback_name(blkif_t
*blkif
, char *buf
)
52 char *devpath
, *devname
;
53 struct xenbus_device
*dev
= blkif
->be
->dev
;
55 devpath
= xenbus_read(XBT_NIL
, dev
->nodename
, "dev", NULL
);
57 return PTR_ERR(devpath
);
59 if ((devname
= strstr(devpath
, "/dev/")) != NULL
)
60 devname
+= strlen("/dev/");
64 snprintf(buf
, TASK_COMM_LEN
, "blkback.%d.%s", blkif
->domid
, devname
);
70 static void update_blkif_status(blkif_t
*blkif
)
73 char name
[TASK_COMM_LEN
];
75 /* Not ready to connect? */
76 if (!blkif
->irq
|| !blkif
->vbd
.bdev
)
79 /* Already connected? */
80 if (blkif
->be
->dev
->state
== XenbusStateConnected
)
83 /* Attempt to connect: exit if we fail to. */
85 if (blkif
->be
->dev
->state
!= XenbusStateConnected
)
88 err
= blkback_name(blkif
, name
);
90 xenbus_dev_error(blkif
->be
->dev
, err
, "get blkback dev name");
94 err
= filemap_write_and_wait(blkif
->vbd
.bdev
->bd_inode
->i_mapping
);
96 xenbus_dev_error(blkif
->be
->dev
, err
, "block flush");
99 invalidate_inode_pages2(blkif
->vbd
.bdev
->bd_inode
->i_mapping
);
101 blkif
->xenblkd
= kthread_run(blkif_schedule
, blkif
, name
);
102 if (IS_ERR(blkif
->xenblkd
)) {
103 err
= PTR_ERR(blkif
->xenblkd
);
104 blkif
->xenblkd
= NULL
;
105 xenbus_dev_error(blkif
->be
->dev
, err
, "start xenblkd");
111 * sysfs interface for VBD I/O requests
114 #define VBD_SHOW(name, format, args...) \
115 static ssize_t show_##name(struct device *_dev, \
116 struct device_attribute *attr, \
119 struct xenbus_device *dev = to_xenbus_device(_dev); \
120 struct backend_info *be = dev_get_drvdata(&dev->dev); \
122 return sprintf(buf, format, ##args); \
124 static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
126 VBD_SHOW(oo_req
, "%d\n", be
->blkif
->st_oo_req
);
127 VBD_SHOW(rd_req
, "%d\n", be
->blkif
->st_rd_req
);
128 VBD_SHOW(wr_req
, "%d\n", be
->blkif
->st_wr_req
);
129 VBD_SHOW(br_req
, "%d\n", be
->blkif
->st_br_req
);
130 VBD_SHOW(rd_sect
, "%d\n", be
->blkif
->st_rd_sect
);
131 VBD_SHOW(wr_sect
, "%d\n", be
->blkif
->st_wr_sect
);
133 static struct attribute
*vbdstat_attrs
[] = {
134 &dev_attr_oo_req
.attr
,
135 &dev_attr_rd_req
.attr
,
136 &dev_attr_wr_req
.attr
,
137 &dev_attr_br_req
.attr
,
138 &dev_attr_rd_sect
.attr
,
139 &dev_attr_wr_sect
.attr
,
143 static struct attribute_group vbdstat_group
= {
144 .name
= "statistics",
145 .attrs
= vbdstat_attrs
,
148 VBD_SHOW(physical_device
, "%x:%x\n", be
->major
, be
->minor
);
149 VBD_SHOW(mode
, "%s\n", be
->mode
);
151 int xenvbd_sysfs_addif(struct xenbus_device
*dev
)
155 error
= device_create_file(&dev
->dev
, &dev_attr_physical_device
);
159 error
= device_create_file(&dev
->dev
, &dev_attr_mode
);
163 error
= sysfs_create_group(&dev
->dev
.kobj
, &vbdstat_group
);
169 fail3
: sysfs_remove_group(&dev
->dev
.kobj
, &vbdstat_group
);
170 fail2
: device_remove_file(&dev
->dev
, &dev_attr_mode
);
171 fail1
: device_remove_file(&dev
->dev
, &dev_attr_physical_device
);
175 void xenvbd_sysfs_delif(struct xenbus_device
*dev
)
177 sysfs_remove_group(&dev
->dev
.kobj
, &vbdstat_group
);
178 device_remove_file(&dev
->dev
, &dev_attr_mode
);
179 device_remove_file(&dev
->dev
, &dev_attr_physical_device
);
182 static int blkback_remove(struct xenbus_device
*dev
)
184 struct backend_info
*be
= dev_get_drvdata(&dev
->dev
);
188 if (be
->major
|| be
->minor
)
189 xenvbd_sysfs_delif(dev
);
191 if (be
->backend_watch
.node
) {
192 unregister_xenbus_watch(&be
->backend_watch
);
193 kfree(be
->backend_watch
.node
);
194 be
->backend_watch
.node
= NULL
;
198 blkif_disconnect(be
->blkif
);
199 vbd_free(&be
->blkif
->vbd
);
200 blkif_free(be
->blkif
);
205 dev_set_drvdata(&dev
->dev
, NULL
);
209 int blkback_barrier(struct xenbus_transaction xbt
,
210 struct backend_info
*be
, int state
)
212 struct xenbus_device
*dev
= be
->dev
;
215 err
= xenbus_printf(xbt
, dev
->nodename
, "feature-barrier",
218 xenbus_dev_fatal(dev
, err
, "writing feature-barrier");
224 * Entry point to this code when a new device is created. Allocate the basic
225 * structures, and watch the store waiting for the hotplug scripts to tell us
226 * the device's physical major and minor numbers. Switch to InitWait.
228 static int blkback_probe(struct xenbus_device
*dev
,
229 const struct xenbus_device_id
*id
)
232 struct backend_info
*be
= kzalloc(sizeof(struct backend_info
),
235 xenbus_dev_fatal(dev
, -ENOMEM
,
236 "allocating backend structure");
240 dev_set_drvdata(&dev
->dev
, be
);
242 be
->blkif
= blkif_alloc(dev
->otherend_id
);
243 if (IS_ERR(be
->blkif
)) {
244 err
= PTR_ERR(be
->blkif
);
246 xenbus_dev_fatal(dev
, err
, "creating block interface");
250 /* setup back pointer */
253 err
= xenbus_watch_pathfmt(dev
, &be
->backend_watch
, backend_changed
,
254 "%s/%s", dev
->nodename
, "physical-device");
258 err
= xenbus_switch_state(dev
, XenbusStateInitWait
);
272 * Callback received when the hotplug scripts have placed the physical-device
273 * node. Read it and the mode node, and create a vbd. If the frontend is
276 static void backend_changed(struct xenbus_watch
*watch
,
277 const char **vec
, unsigned int len
)
282 struct backend_info
*be
283 = container_of(watch
, struct backend_info
, backend_watch
);
284 struct xenbus_device
*dev
= be
->dev
;
290 err
= xenbus_scanf(XBT_NIL
, dev
->nodename
, "physical-device", "%x:%x",
292 if (XENBUS_EXIST_ERR(err
)) {
293 /* Since this watch will fire once immediately after it is
294 registered, we expect this. Ignore it, and wait for the
299 xenbus_dev_fatal(dev
, err
, "reading physical-device");
303 if ((be
->major
|| be
->minor
) &&
304 ((be
->major
!= major
) || (be
->minor
!= minor
))) {
306 "blkback: changing physical device (from %x:%x to "
307 "%x:%x) not supported.\n", be
->major
, be
->minor
,
312 be
->mode
= xenbus_read(XBT_NIL
, dev
->nodename
, "mode", NULL
);
313 if (IS_ERR(be
->mode
)) {
314 err
= PTR_ERR(be
->mode
);
316 xenbus_dev_fatal(dev
, err
, "reading mode");
320 device_type
= xenbus_read(XBT_NIL
, dev
->otherend
, "device-type", NULL
);
321 if (!IS_ERR(device_type
)) {
322 cdrom
= strcmp(device_type
, "cdrom") == 0;
326 if (be
->major
== 0 && be
->minor
== 0) {
327 /* Front end dir is a number, which is used as the handle. */
329 char *p
= strrchr(dev
->otherend
, '/') + 1;
330 long handle
= simple_strtoul(p
, NULL
, 0);
335 err
= vbd_create(be
->blkif
, handle
, major
, minor
,
336 (NULL
== strchr(be
->mode
, 'w')), cdrom
);
338 be
->major
= be
->minor
= 0;
339 xenbus_dev_fatal(dev
, err
, "creating vbd structure");
343 err
= xenvbd_sysfs_addif(dev
);
345 vbd_free(&be
->blkif
->vbd
);
346 be
->major
= be
->minor
= 0;
347 xenbus_dev_fatal(dev
, err
, "creating sysfs entries");
351 /* We're potentially connected now */
352 update_blkif_status(be
->blkif
);
358 * Callback received when the frontend's state changes.
360 static void frontend_changed(struct xenbus_device
*dev
,
361 enum xenbus_state frontend_state
)
363 struct backend_info
*be
= dev_get_drvdata(&dev
->dev
);
366 DPRINTK("%s", xenbus_strstate(frontend_state
));
368 switch (frontend_state
) {
369 case XenbusStateInitialising
:
370 if (dev
->state
== XenbusStateClosed
) {
371 printk(KERN_INFO
"%s: %s: prepare for reconnect\n",
372 __FUNCTION__
, dev
->nodename
);
373 xenbus_switch_state(dev
, XenbusStateInitWait
);
377 case XenbusStateInitialised
:
378 case XenbusStateConnected
:
379 /* Ensure we connect even when two watches fire in
380 close successsion and we miss the intermediate value
381 of frontend_state. */
382 if (dev
->state
== XenbusStateConnected
)
385 /* Enforce precondition before potential leak point.
386 * blkif_disconnect() is idempotent.
388 blkif_disconnect(be
->blkif
);
390 err
= connect_ring(be
);
393 update_blkif_status(be
->blkif
);
396 case XenbusStateClosing
:
397 blkif_disconnect(be
->blkif
);
398 xenbus_switch_state(dev
, XenbusStateClosing
);
401 case XenbusStateClosed
:
402 xenbus_switch_state(dev
, XenbusStateClosed
);
403 if (xenbus_dev_is_online(dev
))
405 /* fall through if not online */
406 case XenbusStateUnknown
:
407 /* implies blkif_disconnect() via blkback_remove() */
408 device_unregister(&dev
->dev
);
412 xenbus_dev_fatal(dev
, -EINVAL
, "saw state %d at frontend",
419 /* ** Connection ** */
423 * Write the physical details regarding the block device to the store, and
424 * switch to Connected state.
426 static void connect(struct backend_info
*be
)
428 struct xenbus_transaction xbt
;
430 struct xenbus_device
*dev
= be
->dev
;
432 DPRINTK("%s", dev
->otherend
);
434 /* Supply the information about the device the frontend needs */
436 err
= xenbus_transaction_start(&xbt
);
438 xenbus_dev_fatal(dev
, err
, "starting transaction");
442 err
= blkback_barrier(xbt
, be
, 1);
446 err
= xenbus_printf(xbt
, dev
->nodename
, "sectors", "%llu",
447 vbd_size(&be
->blkif
->vbd
));
449 xenbus_dev_fatal(dev
, err
, "writing %s/sectors",
454 /* FIXME: use a typename instead */
455 err
= xenbus_printf(xbt
, dev
->nodename
, "info", "%u",
456 vbd_info(&be
->blkif
->vbd
));
458 xenbus_dev_fatal(dev
, err
, "writing %s/info",
462 err
= xenbus_printf(xbt
, dev
->nodename
, "sector-size", "%lu",
463 vbd_secsize(&be
->blkif
->vbd
));
465 xenbus_dev_fatal(dev
, err
, "writing %s/sector-size",
470 err
= xenbus_transaction_end(xbt
, 0);
474 xenbus_dev_fatal(dev
, err
, "ending transaction");
476 err
= xenbus_switch_state(dev
, XenbusStateConnected
);
478 xenbus_dev_fatal(dev
, err
, "switching to Connected state",
483 xenbus_transaction_end(xbt
, 1);
487 static int connect_ring(struct backend_info
*be
)
489 struct xenbus_device
*dev
= be
->dev
;
490 unsigned long ring_ref
;
492 char protocol
[64] = "";
495 DPRINTK("%s", dev
->otherend
);
497 err
= xenbus_gather(XBT_NIL
, dev
->otherend
, "ring-ref", "%lu", &ring_ref
,
498 "event-channel", "%u", &evtchn
, NULL
);
500 xenbus_dev_fatal(dev
, err
,
501 "reading %s/ring-ref and event-channel",
506 be
->blkif
->blk_protocol
= BLKIF_PROTOCOL_NATIVE
;
507 err
= xenbus_gather(XBT_NIL
, dev
->otherend
, "protocol",
508 "%63s", protocol
, NULL
);
510 strcpy(protocol
, "unspecified, assuming native");
511 else if (0 == strcmp(protocol
, XEN_IO_PROTO_ABI_NATIVE
))
512 be
->blkif
->blk_protocol
= BLKIF_PROTOCOL_NATIVE
;
513 else if (0 == strcmp(protocol
, XEN_IO_PROTO_ABI_X86_32
))
514 be
->blkif
->blk_protocol
= BLKIF_PROTOCOL_X86_32
;
515 else if (0 == strcmp(protocol
, XEN_IO_PROTO_ABI_X86_64
))
516 be
->blkif
->blk_protocol
= BLKIF_PROTOCOL_X86_64
;
518 xenbus_dev_fatal(dev
, err
, "unknown fe protocol %s", protocol
);
522 "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
523 ring_ref
, evtchn
, be
->blkif
->blk_protocol
, protocol
);
525 /* Map the shared frame, irq etc. */
526 err
= blkif_map(be
->blkif
, ring_ref
, evtchn
);
528 xenbus_dev_fatal(dev
, err
, "mapping ring-ref %lu port %u",
537 /* ** Driver Registration ** */
540 static const struct xenbus_device_id blkback_ids
[] = {
546 static struct xenbus_driver blkback
= {
548 .owner
= THIS_MODULE
,
550 .probe
= blkback_probe
,
551 .remove
= blkback_remove
,
552 .otherend_changed
= frontend_changed
556 int blkif_xenbus_init(void)
558 return xenbus_register_backend(&blkback
);