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
38 #define DPRINTK(_f, _a...) \
39 printk("(%s() file=%s, line=%d) " _f "\n", \
40 __PRETTY_FUNCTION__, __FILE__ , __LINE__ , ##_a )
43 #define MEDIA_PRESENT "media-present"
45 static void cdrom_media_changed(struct xenbus_watch *, const char **, unsigned int);
48 * Writes media-present=1 attribute for the given vbd device if not
51 static int cdrom_xenstore_write_media_present(struct backend_info *be)
53 struct xenbus_device *dev = be->dev;
54 struct xenbus_transaction xbt;
58 err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
61 DPRINTK("already written err%d", err);
67 err = xenbus_transaction_start(&xbt);
69 xenbus_dev_fatal(dev, err, "starting transaction");
73 err = xenbus_printf(xbt, dev->nodename, MEDIA_PRESENT, "%d", media_present );
75 xenbus_dev_fatal(dev, err, "writing %s/%s",
76 dev->nodename, MEDIA_PRESENT);
79 err = xenbus_transaction_end(xbt, 0);
83 xenbus_dev_fatal(dev, err, "ending transaction");
86 xenbus_transaction_end(xbt, 1);
93 static int cdrom_is_type(struct backend_info *be)
95 DPRINTK("type:%x", be->blkif->vbd.type );
96 return (be->blkif->vbd.type & VDISK_CDROM)
97 && (be->blkif->vbd.type & GENHD_FL_REMOVABLE);
103 void cdrom_add_media_watch(struct backend_info *be)
105 struct xenbus_device *dev = be->dev;
108 DPRINTK("nodename:%s", dev->nodename);
109 if (cdrom_is_type(be)) {
110 DPRINTK("is a cdrom");
111 if ( cdrom_xenstore_write_media_present(be) == 0 ) {
112 DPRINTK( "xenstore wrote OK");
113 err = xenbus_watch_path2(dev, dev->nodename, MEDIA_PRESENT,
114 &be->backend_cdrom_watch,
115 cdrom_media_changed);
117 DPRINTK( "media_present watch add failed" );
123 * Callback received when the "media_present" xenstore node is changed
125 static void cdrom_media_changed(struct xenbus_watch *watch,
126 const char **vec, unsigned int len)
129 unsigned media_present;
130 struct backend_info *be
131 = container_of(watch, struct backend_info, backend_cdrom_watch);
132 struct xenbus_device *dev = be->dev;
134 if (!cdrom_is_type(be)) {
135 DPRINTK("callback not for a cdrom" );
139 err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
141 if (err == 0 || err == -ENOENT) {
142 DPRINTK("xenbus_read of cdrom media_present node error:%d",err);
146 if (media_present == 0)
147 vbd_free(&be->blkif->vbd);
149 char *p = strrchr(dev->otherend, '/') + 1;
150 long handle = simple_strtoul(p, NULL, 0);
152 if (!be->blkif->vbd.bdev) {
153 err = vbd_create(be->blkif, handle, be->major, be->minor,
154 !strchr(be->mode, 'w'), 1);
156 be->major = be->minor = 0;
157 xenbus_dev_fatal(dev, err, "creating vbd structure");