All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: jeff@garzik.org, linux-ide@vger.kernel.org, axboe@kernel.dk,
	linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org,
	kay.sievers@vrfy.org, jack@suse.cz,
	James.Bottomley@HansenPartnership.com
Cc: Tejun Heo <tj@kernel.org>
Subject: [PATCH 4/8] cdrom: add ->check_events() support
Date: Wed,  8 Dec 2010 20:57:38 +0100	[thread overview]
Message-ID: <1291838262-21274-5-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1291838262-21274-1-git-send-email-tj@kernel.org>

In principle, cdrom just needs to pass through ->check_events() but
CDROM_MEDIA_CHANGED ioctl makes things a bit more complex.  Just as
with ->media_changed() support, cdrom code needs to buffer the events
and serve them to ioctl and vfs as requested.

As the code has to deal with both ->check_events() and
->media_changed(), and vfs and ioctl event buffering, this patch adds
check_events caching on top of the existing cdi->mc_flags buffering.

It may be a good idea to deprecate CDROM_MEDIA_CHANGED ioctl and
remove all this mess.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
 drivers/cdrom/cdrom.c |   55 ++++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/cdrom.h |    6 +++++
 2 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index af13c62..1ea8f8d 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1348,7 +1348,10 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
 	if (!CDROM_CAN(CDC_SELECT_DISC))
 		return -EDRIVE_CANT_DO_THIS;
 
-	(void) cdi->ops->media_changed(cdi, slot);
+	if (cdi->ops->check_events)
+		cdi->ops->check_events(cdi, 0, slot);
+	else
+		cdi->ops->media_changed(cdi, slot);
 
 	if (slot == CDSL_NONE) {
 		/* set media changed bits, on both queues */
@@ -1392,6 +1395,41 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
 	return slot;
 }
 
+/*
+ * As cdrom implements an extra ioctl consumer for media changed
+ * event, it needs to buffer ->check_events() output, such that event
+ * is not lost for both the usual VFS and ioctl paths.
+ * cdi->{vfs|ioctl}_events are used to buffer pending events for each
+ * path.
+ *
+ * XXX: Locking is non-existent.  cdi->ops->check_events() can be
+ * called in parallel and buffering fields are accessed without any
+ * exclusion.  The original media_changed code had the same problem.
+ * It might be better to simply deprecate CDROM_MEDIA_CHANGED ioctl
+ * and remove this cruft altogether.  It doesn't have much usefulness
+ * at this point.
+ */
+static void cdrom_update_events(struct cdrom_device_info *cdi,
+				unsigned int clearing)
+{
+	unsigned int events;
+
+	events = cdi->ops->check_events(cdi, clearing, CDSL_CURRENT);
+	cdi->vfs_events |= events;
+	cdi->ioctl_events |= events;
+}
+
+unsigned int cdrom_check_events(struct cdrom_device_info *cdi,
+				unsigned int clearing)
+{
+	unsigned int events;
+
+	cdrom_update_events(cdi, clearing);
+	events = cdi->vfs_events;
+	cdi->vfs_events = 0;
+	return events;
+}
+
 /* We want to make media_changed accessible to the user through an
  * ioctl. The main problem now is that we must double-buffer the
  * low-level implementation, to assure that the VFS and the user both
@@ -1403,15 +1441,26 @@ int media_changed(struct cdrom_device_info *cdi, int queue)
 {
 	unsigned int mask = (1 << (queue & 1));
 	int ret = !!(cdi->mc_flags & mask);
+	bool changed;
 
 	if (!CDROM_CAN(CDC_MEDIA_CHANGED))
-	    return ret;
+		return ret;
+
 	/* changed since last call? */
-	if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) {
+	if (cdi->ops->check_events) {
+		BUG_ON(!queue);	/* shouldn't be called from VFS path */
+		cdrom_update_events(cdi, DISK_EVENT_MEDIA_CHANGE);
+		changed = cdi->ioctl_events & DISK_EVENT_MEDIA_CHANGE;
+		cdi->ioctl_events = 0;
+	} else
+		changed = cdi->ops->media_changed(cdi, CDSL_CURRENT);
+
+	if (changed) {
 		cdi->mc_flags = 0x3;    /* set bit on both queues */
 		ret |= 1;
 		cdi->media_written = 0;
 	}
+
 	cdi->mc_flags &= ~mask;         /* clear bit */
 	return ret;
 }
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index 78e9047..35eae4b 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -946,6 +946,8 @@ struct cdrom_device_info {
 /* device-related storage */
 	unsigned int options	: 30;	/* options flags */
 	unsigned mc_flags	: 2;	/* media change buffer flags */
+	unsigned int vfs_events;	/* cached events for vfs path */
+	unsigned int ioctl_events;	/* cached events for ioctl path */
     	int use_count;                  /* number of times device opened */
     	char name[20];                  /* name of the device type */
 /* per-device flags */
@@ -965,6 +967,8 @@ struct cdrom_device_ops {
 	int (*open) (struct cdrom_device_info *, int);
 	void (*release) (struct cdrom_device_info *);
 	int (*drive_status) (struct cdrom_device_info *, int);
+	unsigned int (*check_events) (struct cdrom_device_info *cdi,
+				      unsigned int clearing, int slot);
 	int (*media_changed) (struct cdrom_device_info *, int);
 	int (*tray_move) (struct cdrom_device_info *, int);
 	int (*lock_door) (struct cdrom_device_info *, int);
@@ -993,6 +997,8 @@ extern int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
 extern void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode);
 extern int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
 		       fmode_t mode, unsigned int cmd, unsigned long arg);
+extern unsigned int cdrom_check_events(struct cdrom_device_info *cdi,
+				       unsigned int clearing);
 extern int cdrom_media_changed(struct cdrom_device_info *);
 
 extern int register_cdrom(struct cdrom_device_info *cdi);
-- 
1.7.1

  parent reply	other threads:[~2010-12-08 19:57 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-08 19:57 [PATCHSET] block/SCSI: implement in-kernel disk event handling, take#2 Tejun Heo
2010-12-08 19:57 ` [PATCH 1/8] block: kill genhd_media_change_notify() Tejun Heo
2010-12-08 19:57 ` [PATCH 2/8] block: move register_disk() and del_gendisk() to block/genhd.c Tejun Heo
2010-12-08 19:57 ` [PATCH 3/8] implement in-kernel gendisk events handling Tejun Heo
2010-12-08 19:57 ` Tejun Heo [this message]
2010-12-08 19:57 ` [PATCH 5/8] scsi: fix TUR error handling in sr_media_change() Tejun Heo
2010-12-08 20:14   ` Rolf Eike Beer
2010-12-09 10:18   ` [PATCH UPDATED " Tejun Heo
2010-12-09 18:20   ` [PATCH " Sergei Shtylyov
2010-12-09 18:53     ` Tejun Heo
2010-12-08 19:57 ` [PATCH 6/8] scsi: replace sr_test_unit_ready() with scsi_test_unit_ready() Tejun Heo
2010-12-08 19:57 ` [PATCH 7/8] sr: implement sr_check_events() Tejun Heo
2011-01-30  1:26   ` Simon Arlott
2011-01-30  1:31     ` [PATCH] cdrom: support devices that have check_events but not media_changed Simon Arlott
2011-01-31 10:12       ` Tejun Heo
2011-01-31 18:26         ` [PATCH (v2)] " Simon Arlott
2011-01-31 11:22       ` [PATCH] " Sergei Shtylyov
2011-02-10 17:30     ` [PATCH 7/8] sr: implement sr_check_events() ael
2010-12-08 19:57 ` [PATCH 8/8] sd: implement sd_check_events() Tejun Heo
2010-12-16 16:31 ` [PATCHSET] block/SCSI: implement in-kernel disk event handling, take#2 Tejun Heo
2010-12-16 16:36   ` Jens Axboe
2010-12-16 16:38     ` James Bottomley
2010-12-16 16:44       ` Kay Sievers
2010-12-16 16:44         ` Kay Sievers
2010-12-16 16:41     ` Kay Sievers
2010-12-16 16:43       ` Jens Axboe
2010-12-16 16:45         ` Tejun Heo
2010-12-16 17:00           ` Jens Axboe
2010-12-16 18:11             ` Tejun Heo
2010-12-16 16:55         ` Jens Axboe
2010-12-16 16:55           ` Jens Axboe
2010-12-16 17:00   ` Christoph Hellwig
2010-12-16 18:04     ` Tejun Heo

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=1291838262-21274-5-git-send-email-tj@kernel.org \
    --to=tj@kernel.org \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=axboe@kernel.dk \
    --cc=jack@suse.cz \
    --cc=jeff@garzik.org \
    --cc=kay.sievers@vrfy.org \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.