1 /******************************************************************************
4 * Routines for managing cdrom watch and media-present attribute of a
5 * cdrom type virtual block device (VBD).
7 * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
8 * Copyright (c) 2007 Pat Campbell
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation; or, when distributed
13 * separately from the Linux kernel or incorporated into other
14 * software packages, subject to the following license:
16 * Permission is hereby granted, free of charge, to any person obtaining a copy
17 * of this source file (the "Software"), to deal in the Software without
18 * restriction, including without limitation the rights to use, copy, modify,
19 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
20 * and to permit persons to whom the Software is furnished to do so, subject to
21 * the following conditions:
23 * The above copyright notice and this permission notice shall be included in
24 * all copies or substantial portions of the Software.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
37 #define MEDIA_PRESENT "media-present"
39 static void cdrom_media_changed(struct xenbus_watch *, const char **, unsigned int);
42 * Writes media-present=1 attribute for the given vbd device if not
45 static int cdrom_xenstore_write_media_present(struct backend_info *be)
47 struct xenbus_device *dev = be->dev;
48 struct xenbus_transaction xbt;
52 err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
55 DPRINTK("already written err%d", err);
58 media_present = !!be->blkif->vbd.bdev;
61 err = xenbus_transaction_start(&xbt);
63 xenbus_dev_fatal(dev, err, "starting transaction");
67 err = xenbus_printf(xbt, dev->nodename, MEDIA_PRESENT, "%d", media_present );
69 xenbus_dev_fatal(dev, err, "writing %s/%s",
70 dev->nodename, MEDIA_PRESENT);
73 err = xenbus_transaction_end(xbt, 0);
77 xenbus_dev_fatal(dev, err, "ending transaction");
80 xenbus_transaction_end(xbt, 1);
87 static int cdrom_is_type(struct backend_info *be)
89 DPRINTK("type:%x", be->blkif->vbd.type );
90 return (be->blkif->vbd.type & VDISK_CDROM)
91 && (be->blkif->vbd.type & GENHD_FL_REMOVABLE);
97 void cdrom_add_media_watch(struct backend_info *be)
99 struct xenbus_device *dev = be->dev;
102 DPRINTK("nodename:%s", dev->nodename);
103 if (cdrom_is_type(be)) {
104 DPRINTK("is a cdrom");
105 if (cdrom_xenstore_write_media_present(be) == 0) {
106 DPRINTK("xenstore wrote OK");
107 err = xenbus_watch_path2(dev, dev->nodename, MEDIA_PRESENT,
109 cdrom_media_changed);
111 DPRINTK(MEDIA_PRESENT " watch add failed");
117 * Callback received when the MEDIA_PRESENT xenstore node is changed
119 static void cdrom_media_changed(struct xenbus_watch *watch,
120 const char **vec, unsigned int len)
122 int err, media_present;
123 struct backend_info *be
124 = container_of(watch, struct backend_info, cdrom_watch);
125 struct xenbus_device *dev = be->dev;
127 if (!cdrom_is_type(be)) {
128 DPRINTK("callback not for a cdrom" );
132 err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
135 DPRINTK("read of " MEDIA_PRESENT " node error:%d", err);
140 vbd_free(&be->blkif->vbd);
141 else if (!be->blkif->vbd.bdev) {
142 char *p = strrchr(dev->otherend, '/') + 1;
143 long handle = simple_strtoul(p, NULL, 0);
145 err = vbd_create(be->blkif, handle, be->major, be->minor,
146 be->blkif->vbd.mode, true);
147 if (err && err != -ENOMEDIUM) {
148 be->major = be->minor = 0;
149 xenbus_dev_fatal(dev, err, "creating vbd structure");
152 vbd_resize(be->blkif);