From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: amit.shah@redhat.com, armbru@redhat.com
Subject: [Qemu-devel] [PATCH 3/5] raw-posix: keep complete control of door locking if possible
Date: Wed, 8 Feb 2012 18:37:34 +0100 [thread overview]
Message-ID: <1328722656-22856-4-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1328722656-22856-1-git-send-email-pbonzini@redhat.com>
Try to open the disk O_EXCL so that udev will not receive eject
request and media change events. These will work fine with SCSI
passthrough.
With IDE and scsi-disk the user will need to use the monitor in order
to eject the disk and put it back (respectively with the eject and
change commands). Fixing this would require (re)implementing polling
using CDROM_MEDIA_CHANGED ioctls.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
block/raw-posix.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 80 insertions(+), 9 deletions(-)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index d9b03a1..1b51bd4 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -127,6 +127,11 @@ typedef struct BDRVRawState {
int got_error;
int media_changed;
} fdd;
+ struct {
+ bool manage_door;
+ bool save_lock;
+ bool save_locked;
+ } cd;
};
#endif
#ifdef CONFIG_LINUX_AIO
@@ -1035,14 +1040,80 @@ static BlockDriver bdrv_host_floppy = {
.bdrv_eject = floppy_eject,
};
+static bool cdrom_get_options(int fd)
+{
+ /* CDROM_SET_OPTIONS with arg == 0 returns the current options! */
+ return ioctl(fd, CDROM_SET_OPTIONS, 0);
+}
+
+static int cdrom_is_locked(int fd)
+{
+ int opts = cdrom_get_options(fd);
+
+ /* This is the only way we have to probe the current status of
+ * CDROM_LOCKDOOR (EBUSY = locked). We use CDROM_SET_OPTIONS to
+ * reset the previous state in case the ioctl succeeds.
+ */
+ if (ioctl(fd, CDROMEJECT_SW, 0) == 0) {
+ ioctl(fd, CDROM_SET_OPTIONS, opts);
+ return false;
+ } else if (errno == EBUSY) {
+ return true;
+ } else {
+ return -errno;
+ }
+}
+
+
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
+ int rc;
s->type = FTYPE_CD;
- /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
- return raw_open_common(bs, filename, flags, O_NONBLOCK);
+ /* open will not fail even if no CD is inserted, so add O_NONBLOCK. First
+ * try with O_EXCL to see whether the CD is mounted.
+ */
+ rc = raw_open_common(bs, filename, flags, O_NONBLOCK | O_EXCL);
+ if (rc < 0 && rc != -EBUSY) {
+ return rc;
+ }
+
+ s->cd.manage_door = false;
+ if (rc == -EBUSY) {
+ /* The CD-ROM is mounted. No door support, because if we cannot use
+ * O_EXCL udev will always succeed in ejecting the medium under our
+ * feet.
+ */
+ rc = raw_open_common(bs, filename, flags, O_NONBLOCK);
+ } else if (rc == 0) {
+ /* We can handle the door ourselves. Save state so we can restore
+ * it when we exit.
+ */
+ int is_locked = cdrom_is_locked(s->fd);
+ if (is_locked >= 0 && ioctl(s->fd, CDROM_LOCKDOOR, 0) != -1) {
+ s->cd.save_lock = (cdrom_get_options(s->fd) & CDO_LOCK) != 0;
+ s->cd.save_locked = is_locked;
+ s->cd.manage_door = true;
+
+ ioctl(s->fd, CDROM_CLEAR_OPTIONS, CDO_LOCK);
+ }
+ }
+
+ return rc;
+}
+
+static void cdrom_close(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+ if (s->fd >= 0 && s->cd.manage_door) {
+ ioctl(s->fd, CDROM_LOCKDOOR, s->cd.save_locked);
+ if (s->cd.save_lock) {
+ ioctl(s->fd, CDROM_SET_OPTIONS, CDO_LOCK);
+ }
+ }
+ raw_close(bs);
}
static int cdrom_probe_device(const char *filename)
@@ -1086,6 +1157,10 @@ static void cdrom_eject(BlockDriverState *bs, int eject_flag)
{
BDRVRawState *s = bs->opaque;
+ if (!s->cd.manage_door) {
+ return;
+ }
+
if (eject_flag) {
if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
perror("CDROMEJECT");
@@ -1099,12 +1174,8 @@ static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
{
BDRVRawState *s = bs->opaque;
- if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
- /*
- * Note: an error can happen if the distribution automatically
- * mounts the CD-ROM
- */
- /* perror("CDROM_LOCKDOOR"); */
+ if (s->cd.manage_door) {
+ ioctl(s->fd, CDROM_LOCKDOOR, locked);
}
}
@@ -1114,7 +1185,7 @@ static BlockDriver bdrv_host_cdrom = {
.instance_size = sizeof(BDRVRawState),
.bdrv_probe_device = cdrom_probe_device,
.bdrv_file_open = cdrom_open,
- .bdrv_close = raw_close,
+ .bdrv_close = cdrom_close,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
.bdrv_has_zero_init = hdev_has_zero_init,
--
1.7.7.6
next prev parent reply other threads:[~2012-02-08 17:38 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-08 17:37 [Qemu-devel] [PATCH 0/5] Fix CD-ROM door with SCSI passthrough Paolo Bonzini
2012-02-08 17:37 ` [Qemu-devel] [PATCH 1/5] raw-posix: always prefer specific devices to hdev Paolo Bonzini
2012-02-10 12:49 ` Markus Armbruster
2012-02-08 17:37 ` [Qemu-devel] [PATCH 2/5] raw-posix: put Linux fd fields into a union Paolo Bonzini
2012-02-08 17:37 ` Paolo Bonzini [this message]
2012-02-10 12:49 ` [Qemu-devel] [PATCH 3/5] raw-posix: keep complete control of door locking if possible Markus Armbruster
2012-02-10 14:00 ` Paolo Bonzini
2012-02-10 14:56 ` Markus Armbruster
2012-02-10 15:19 ` Paolo Bonzini
2012-02-08 17:37 ` [Qemu-devel] [PATCH 4/5] configure: probe for dbus Paolo Bonzini
2012-02-08 17:37 ` [Qemu-devel] [PATCH 5/5] raw-posix: unmount CD-ROM filesystem via udisks Paolo Bonzini
2012-02-10 12:51 ` Markus Armbruster
2012-02-10 14:20 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1328722656-22856-4-git-send-email-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=amit.shah@redhat.com \
--cc=armbru@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).