2010-12-28 17:29:24

by Tejun Heo

[permalink] [raw]
Subject: [PATCHSET] block: convert block drivers to ->check_events()

This patchset converts all in-kernel block drivers from
->media_changed() to ->check_events(). Most conversions are fairly
mechanical. The only notable exceptions are,

* 0014-umem: media_changed was dummy. As ->check_events() can be
omitted, just drop it.

* 0015-pktcdvd: inherits and forwards ->check_events() instead of
->media_changed() from the underlying device.

0001-block-don-t-implicitly-trigger-event-check-on-disk_u.patch
0002-block-don-t-check-events-on-close-unless-it-was-bloc.patch
0003-block-don-t-check-events-while-open-is-in-progress.patch
0004-ide-convert-to-bdops-check_events.patch
0005-floppy-ami-ata-flop-convert-to-bdops-check_events.patch
0006-gdrom-viocd-convert-to-bdops-check_events.patch
0007-paride-convert-to-bdops-check_events.patch
0008-dac960-convert-to-bdops-check_events.patch
0009-swim-3-convert-to-bdops-check_events.patch
0010-ub-convert-to-bdops-check_events.patch
0011-xsysace-convert-to-bdops-check_events.patch
0012-i2o_block-convert-to-bdops-check_events.patch
0013-s390-tape_block-convert-to-bdops-check_events.patch
0014-umem-drop-dummy-media_changed.patch
0015-pktcdvd-convert-to-bdops-check_events.patch
0016-staging-convert-to-bdops-check_events.patch

0001-0003 prepare for further conversions. Some of the conversions
are not very well behaved in that they may generate spurious events
and allow event polling between event clearing check and the actual
clearing. These three patches modify the disk event check behavior
such that such faults can be tolerated.

0004-0016 convert all block drivers. Conversions are mostly
mechanical, all changes except for one of the staging driver are
compile-tested and ide is verified to behave correctly after the
conversion.

We should be able to remove ->media_changed() in the next devel cycle
once the scsi bits and the block branch get merged.

This patchset is on top of the current linux-2.6-block/event-handling
(fcc57045d53edc35bcce456e60ac4aa802712934) and is available in the
following git branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git disk-event-convert

and contains the following changes.

block/genhd.c | 2 -
drivers/block/DAC960.c | 8 +++--
drivers/block/amiflop.c | 9 +++---
drivers/block/ataflop.c | 14 +++++----
drivers/block/floppy.c | 10 ++++--
drivers/block/paride/pcd.c | 18 +++++++-----
drivers/block/paride/pd.c | 7 ++--
drivers/block/paride/pf.c | 10 ++++--
drivers/block/pktcdvd.c | 13 ++++++--
drivers/block/swim.c | 8 +++--
drivers/block/swim3.c | 11 ++++---
drivers/block/ub.c | 10 ++++--
drivers/block/umem.c | 10 ------
drivers/block/xsysace.c | 9 +++---
drivers/cdrom/gdrom.c | 16 ++++++----
drivers/cdrom/viocd.c | 17 ++++++-----
drivers/ide/ide-cd.c | 10 ++++--
drivers/ide/ide-cd.h | 3 +-
drivers/ide/ide-cd_ioctl.c | 8 ++---
drivers/ide/ide-gd.c | 14 +++++----
drivers/message/i2o/i2o_block.c | 11 ++++---
drivers/s390/char/tape_block.c | 11 ++++---
drivers/staging/hv/blkvsc_drv.c | 11 ++++---
drivers/staging/westbridge/astoria/block/cyasblkdev_block.c | 11 ++++---
fs/block_dev.c | 11 ++++---
25 files changed, 152 insertions(+), 110 deletions(-)

Thanks.

--
tejun


2010-12-28 17:29:26

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 02/16] block: don't check events on close unless it was blocked

The block event mechanism currently always checks events when the
device is being closed regardless of the open mode. The intention was
to allow detection of EJECT_REQUEST when a device is closed whether
disk event polling is enabled or not.

This is unnecessary as, for devices of interest, events are checked
from either userland or kernel and in the former case ->check_events()
is performed on open of each poll attempt anyway. Furthermore, this
unconditional event check on close makes the code susceptible to event
loop if the block driver doesn't clear reported events correctly - an
event triggers userland to open and close the device which in turn
causes another event, rinse and repeat.

Check events on close only if it was blocked by excl write open.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
---
fs/block_dev.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index c620628..58026da 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1379,13 +1379,11 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
disk_unblock_events(bdev->bd_disk);
disk_check_events(bdev->bd_disk);
bdev->bd_write_holder = false;
- } else
- disk_check_events(bdev->bd_disk);
+ }
}

mutex_unlock(&bdev->bd_mutex);
- } else
- disk_check_events(bdev->bd_disk);
+ }

return __blkdev_put(bdev, mode, 0);
}
--
1.7.1

2010-12-28 17:29:38

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 11/16] xsysace: convert to bdops->check_events()

Convert from ->media_changed() to ->check_events().

xsysace buffers media changed state and clears it on revalidation. It
will behave correctly with kernel event polling.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Grant Likely <[email protected]>
---
drivers/block/xsysace.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 829161e..16a2fa9 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -867,12 +867,12 @@ static void ace_request(struct request_queue * q)
}
}

-static int ace_media_changed(struct gendisk *gd)
+static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
{
struct ace_device *ace = gd->private_data;
- dev_dbg(ace->dev, "ace_media_changed(): %i\n", ace->media_change);
+ dev_dbg(ace->dev, "ace_check_events(): %i\n", ace->media_change);

- return ace->media_change;
+ return ace->media_change ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static int ace_revalidate_disk(struct gendisk *gd)
@@ -953,7 +953,7 @@ static const struct block_device_operations ace_fops = {
.owner = THIS_MODULE,
.open = ace_open,
.release = ace_release,
- .media_changed = ace_media_changed,
+ .check_events = ace_check_events,
.revalidate_disk = ace_revalidate_disk,
.getgeo = ace_getgeo,
};
@@ -1005,6 +1005,7 @@ static int __devinit ace_setup(struct ace_device *ace)
ace->gd->major = ace_major;
ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
ace->gd->fops = &ace_fops;
+ ace->gd->events = DISK_EVENT_MEDIA_CHANGE;
ace->gd->queue = ace->queue;
ace->gd->private_data = ace;
snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
--
1.7.1

2010-12-28 17:29:41

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 13/16] s390/tape_block: convert to bdops->check_events()

Convert from ->media_changed() to ->check_events().

s390/tape_block buffers media changed state and clears it on
revalidation. It will behave correctly with kernel event polling.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Martin Schwidefsky <[email protected]>
Cc: Heiko Carstens <[email protected]>
---
drivers/s390/char/tape_block.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index f0fa9ca..cfd2082 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -48,14 +48,14 @@
static DEFINE_MUTEX(tape_block_mutex);
static int tapeblock_open(struct block_device *, fmode_t);
static int tapeblock_release(struct gendisk *, fmode_t);
-static int tapeblock_medium_changed(struct gendisk *);
+static unsigned int tapeblock_check_events(struct gendisk *, unsigned int);
static int tapeblock_revalidate_disk(struct gendisk *);

static const struct block_device_operations tapeblock_fops = {
.owner = THIS_MODULE,
.open = tapeblock_open,
.release = tapeblock_release,
- .media_changed = tapeblock_medium_changed,
+ .check_events = tapeblock_check_events,
.revalidate_disk = tapeblock_revalidate_disk,
};

@@ -237,6 +237,7 @@ tapeblock_setup_device(struct tape_device * device)
disk->major = tapeblock_major;
disk->first_minor = device->first_minor;
disk->fops = &tapeblock_fops;
+ disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = tape_get_device(device);
disk->queue = blkdat->request_queue;
set_capacity(disk, 0);
@@ -340,8 +341,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
return 0;
}

-static int
-tapeblock_medium_changed(struct gendisk *disk)
+static unsigned int
+tapeblock_check_events(struct gendisk *disk, unsigned int clearing)
{
struct tape_device *device;

@@ -349,7 +350,7 @@ tapeblock_medium_changed(struct gendisk *disk)
DBF_LH(6, "tapeblock_medium_changed(%p) = %d\n",
device, device->blk_data.medium_changed);

- return device->blk_data.medium_changed;
+ return device->blk_data.medium_changed ? DISK_EVENT_MEDIA_CHANGE : 0;
}

/*
--
1.7.1

2010-12-28 17:29:44

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 15/16] pktcdvd: convert to bdops->check_events()

Convert from ->media_changed() to ->check_events().

pktcdvd needs to forward all event related operations to the
underlying device. Forward ->check_events() instead of
->media_changed() and inherit disk->[async_]events.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Peter Osterlund <[email protected]>
---
drivers/block/pktcdvd.c | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 77d70ee..a077db2 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2796,7 +2796,8 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
return ret;
}

-static int pkt_media_changed(struct gendisk *disk)
+static unsigned int pkt_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct pktcdvd_device *pd = disk->private_data;
struct gendisk *attached_disk;
@@ -2806,9 +2807,9 @@ static int pkt_media_changed(struct gendisk *disk)
if (!pd->bdev)
return 0;
attached_disk = pd->bdev->bd_disk;
- if (!attached_disk)
+ if (!attached_disk || !attached_disk->fops->check_events)
return 0;
- return attached_disk->fops->media_changed(attached_disk);
+ return attached_disk->fops->check_events(attached_disk, clearing);
}

static const struct block_device_operations pktcdvd_ops = {
@@ -2816,7 +2817,7 @@ static const struct block_device_operations pktcdvd_ops = {
.open = pkt_open,
.release = pkt_close,
.ioctl = pkt_ioctl,
- .media_changed = pkt_media_changed,
+ .check_events = pkt_check_events,
};

static char *pktcdvd_devnode(struct gendisk *gd, mode_t *mode)
@@ -2889,6 +2890,10 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
if (ret)
goto out_new_dev;

+ /* inherit events of the host device */
+ disk->events = pd->bdev->bd_disk->events;
+ disk->async_events = pd->bdev->bd_disk->async_events;
+
add_disk(disk);

pkt_sysfs_dev_new(pd);
--
1.7.1

2010-12-28 17:30:20

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 14/16] umem: drop dummy ->media_changed()

umem doesn't implement media changed detection and there's no need to
implement dummy callback anymore. Remove it.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
---
drivers/block/umem.c | 10 ----------
1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 8be5715..9b102ab 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -779,20 +779,10 @@ static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}

-/*
- * Future support for removable devices
- */
-static int mm_check_change(struct gendisk *disk)
-{
-/* struct cardinfo *dev = disk->private_data; */
- return 0;
-}
-
static const struct block_device_operations mm_fops = {
.owner = THIS_MODULE,
.getgeo = mm_getgeo,
.revalidate_disk = mm_revalidate,
- .media_changed = mm_check_change,
};

static int __devinit mm_pci_probe(struct pci_dev *dev,
--
1.7.1

2010-12-28 17:29:53

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 16/16] staging: convert to bdops->check_events()

Convert two staging drivers - blkvsc_drv and cyasblkdev_block - from
->media_changed() to ->check_events(). The former always indicated
media changed while the latter always indicated media not changed.
Not sure what the drivers are trying to achieve but keep the original
behavior.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
---
drivers/staging/hv/blkvsc_drv.c | 11 +++++++----
.../westbridge/astoria/block/cyasblkdev_block.c | 11 +++++++----
2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index 3f81ca5..9944385 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -131,7 +131,8 @@ static void blkvsc_shutdown(struct device *device);

static int blkvsc_open(struct block_device *bdev, fmode_t mode);
static int blkvsc_release(struct gendisk *disk, fmode_t mode);
-static int blkvsc_media_changed(struct gendisk *gd);
+static unsigned int blkvsc_check_events(struct gendisk *gd,
+ unsigned int clearing);
static int blkvsc_revalidate_disk(struct gendisk *gd);
static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg);
static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
@@ -162,7 +163,7 @@ static const struct block_device_operations block_ops = {
.owner = THIS_MODULE,
.open = blkvsc_open,
.release = blkvsc_release,
- .media_changed = blkvsc_media_changed,
+ .check_events = blkvsc_check_events,
.revalidate_disk = blkvsc_revalidate_disk,
.getgeo = blkvsc_getgeo,
.ioctl = blkvsc_ioctl,
@@ -367,6 +368,7 @@ static int blkvsc_probe(struct device *device)
else
blkdev->gd->first_minor = 0;
blkdev->gd->fops = &block_ops;
+ blkdev->gd->events = DISK_EVENT_MEDIA_CHANGE;
blkdev->gd->private_data = blkdev;
sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum);

@@ -1346,10 +1348,11 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode)
return 0;
}

-static int blkvsc_media_changed(struct gendisk *gd)
+static unsigned int blkvsc_check_events(struct gendisk *gd,
+ unsigned int clearing)
{
DPRINT_DBG(BLKVSC_DRV, "- enter\n");
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}

static int blkvsc_revalidate_disk(struct gendisk *gd)
diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c
index e1851f0..842cd92 100644
--- a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c
+++ b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c
@@ -381,10 +381,10 @@ static int cyasblkdev_blk_ioctl(
return -ENOTTY;
}

-/* Media_changed block_device opp
+/* check_events block_device opp
* this one is called by kernel to confirm if the media really changed
* as we indicated by issuing check_disk_change() call */
-int cyasblkdev_media_changed(struct gendisk *gd)
+unsigned int cyasblkdev_check_events(struct gendisk *gd, unsigned int clearing)
{
struct cyasblkdev_blk_data *bd;

@@ -402,7 +402,7 @@ int cyasblkdev_media_changed(struct gendisk *gd)
#endif
}

- /* return media change state "1" yes, 0 no */
+ /* return media change state - DISK_EVENT_MEDIA_CHANGE yes, 0 no */
return 0;
}

@@ -432,7 +432,7 @@ static struct block_device_operations cyasblkdev_bdops = {
.ioctl = cyasblkdev_blk_ioctl,
/* .getgeo = cyasblkdev_blk_getgeo, */
/* added to support media removal( real and simulated) media */
- .media_changed = cyasblkdev_media_changed,
+ .check_events = cyasblkdev_check_events,
/* added to support media removal( real and simulated) media */
.revalidate_disk = cyasblkdev_revalidate_disk,
.owner = THIS_MODULE,
@@ -1090,6 +1090,7 @@ static int cyasblkdev_add_disks(int bus_num,
bd->user_disk_0->first_minor = devidx << CYASBLKDEV_SHIFT;
bd->user_disk_0->minors = 8;
bd->user_disk_0->fops = &cyasblkdev_bdops;
+ bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE;
bd->user_disk_0->private_data = bd;
bd->user_disk_0->queue = bd->queue.queue;
bd->dbgprn_flags = DBGPRN_RD_RQ;
@@ -1190,6 +1191,7 @@ static int cyasblkdev_add_disks(int bus_num,
bd->user_disk_1->first_minor = (devidx + 1) << CYASBLKDEV_SHIFT;
bd->user_disk_1->minors = 8;
bd->user_disk_1->fops = &cyasblkdev_bdops;
+ bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE;
bd->user_disk_1->private_data = bd;
bd->user_disk_1->queue = bd->queue.queue;
bd->dbgprn_flags = DBGPRN_RD_RQ;
@@ -1278,6 +1280,7 @@ static int cyasblkdev_add_disks(int bus_num,
(devidx + 2) << CYASBLKDEV_SHIFT;
bd->system_disk->minors = 8;
bd->system_disk->fops = &cyasblkdev_bdops;
+ bd->system_disk->events = DISK_EVENT_MEDIA_CHANGE;
bd->system_disk->private_data = bd;
bd->system_disk->queue = bd->queue.queue;
/* don't search for vfat
--
1.7.1

2010-12-28 17:30:44

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 12/16] i2o_block: convert to bdops->check_events()

Convert from ->media_changed() to ->check_events().

i2o_block buffers media changed state and clears it after reporting.
It will behave correctly with kernel event polling.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Markus Lidel <[email protected]>
---
drivers/message/i2o/i2o_block.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index f87a9d4..729d3b6 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -695,20 +695,22 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,
};

/**
- * i2o_block_media_changed - Have we seen a media change?
+ * i2o_block_check_events - Have we seen a media change?
* @disk: gendisk which should be verified
+ * @clearing: events being cleared
*
* Verifies if the media has changed.
*
* Returns 1 if the media was changed or 0 otherwise.
*/
-static int i2o_block_media_changed(struct gendisk *disk)
+static unsigned int i2o_block_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct i2o_block_device *p = disk->private_data;

if (p->media_change_flag) {
p->media_change_flag = 0;
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}
return 0;
}
@@ -950,7 +952,7 @@ static const struct block_device_operations i2o_block_fops = {
.ioctl = i2o_block_ioctl,
.compat_ioctl = i2o_block_ioctl,
.getgeo = i2o_block_getgeo,
- .media_changed = i2o_block_media_changed
+ .check_events = i2o_block_check_events,
};

/**
@@ -1002,6 +1004,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
gd->major = I2O_MAJOR;
gd->queue = queue;
gd->fops = &i2o_block_fops;
+ gd->events = DISK_EVENT_MEDIA_CHANGE;
gd->private_data = dev;

dev->gd = gd;
--
1.7.1

2010-12-28 17:29:37

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 09/16] swim[3]: convert to bdops->check_events()

Convert from ->media_changed() to ->check_events().

Both swim and swim3 buffer media changed state and clear it on
revalidation. They will behave correctly with kernel event polling.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Laurent Vivier <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
---
drivers/block/swim.c | 8 +++++---
drivers/block/swim3.c | 11 +++++++----
2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 75333d0..24a482f 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -741,11 +741,12 @@ static int floppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}

-static int floppy_check_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct floppy_state *fs = disk->private_data;

- return fs->ejected;
+ return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static int floppy_revalidate(struct gendisk *disk)
@@ -772,7 +773,7 @@ static const struct block_device_operations floppy_fops = {
.release = floppy_release,
.ioctl = floppy_ioctl,
.getgeo = floppy_getgeo,
- .media_changed = floppy_check_change,
+ .check_events = floppy_check_events,
.revalidate_disk = floppy_revalidate,
};

@@ -857,6 +858,7 @@ static int __devinit swim_floppy_init(struct swim_priv *swd)
swd->unit[drive].disk->first_minor = drive;
sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
swd->unit[drive].disk->fops = &floppy_fops;
+ swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE;
swd->unit[drive].disk->private_data = &swd->unit[drive];
swd->unit[drive].disk->queue = swd->queue;
set_capacity(swd->unit[drive].disk, 2880);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index bf3a5b8..4c10f56 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -250,7 +250,8 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long param);
static int floppy_open(struct block_device *bdev, fmode_t mode);
static int floppy_release(struct gendisk *disk, fmode_t mode);
-static int floppy_check_change(struct gendisk *disk);
+static unsigned int floppy_check_events(struct gendisk *disk,
+ unsigned int clearing);
static int floppy_revalidate(struct gendisk *disk);

static bool swim3_end_request(int err, unsigned int nr_bytes)
@@ -975,10 +976,11 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
return 0;
}

-static int floppy_check_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct floppy_state *fs = disk->private_data;
- return fs->ejected;
+ return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static int floppy_revalidate(struct gendisk *disk)
@@ -1025,7 +1027,7 @@ static const struct block_device_operations floppy_fops = {
.open = floppy_unlocked_open,
.release = floppy_release,
.ioctl = floppy_ioctl,
- .media_changed = floppy_check_change,
+ .check_events = floppy_check_events,
.revalidate_disk= floppy_revalidate,
};

@@ -1161,6 +1163,7 @@ static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device
disk->major = FLOPPY_MAJOR;
disk->first_minor = i;
disk->fops = &floppy_fops;
+ disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = &floppy_states[i];
disk->queue = swim3_queue;
disk->flags |= GENHD_FL_REMOVABLE;
--
1.7.1

2010-12-28 17:29:35

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 08/16] dac960: convert to bdops->check_events()

Convert from ->media_changed() to ->check_events().

DAC960 media change notification seems to be one way (once set, never
cleared) and will generate spurious events when polled once the
condition triggers.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
---
drivers/block/DAC960.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 1f286ab..7988210 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -140,13 +140,14 @@ static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}

-static int DAC960_media_changed(struct gendisk *disk)
+static unsigned int DAC960_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
DAC960_Controller_T *p = disk->queue->queuedata;
int drive_nr = (long)disk->private_data;

if (!p->LogicalDriveInitiallyAccessible[drive_nr])
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
return 0;
}

@@ -163,7 +164,7 @@ static const struct block_device_operations DAC960_BlockDeviceOperations = {
.owner = THIS_MODULE,
.open = DAC960_open,
.getgeo = DAC960_getgeo,
- .media_changed = DAC960_media_changed,
+ .check_events = DAC960_check_events,
.revalidate_disk = DAC960_revalidate_disk,
};

@@ -2546,6 +2547,7 @@ static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
disk->major = MajorNumber;
disk->first_minor = n << DAC960_MaxPartitionsBits;
disk->fops = &DAC960_BlockDeviceOperations;
+ disk->events = DISK_EVENT_MEDIA_CHANGE;
}
/*
Indicate the Block Device Registration completed successfully,
--
1.7.1

2010-12-28 17:31:05

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 10/16] ub: convert to bdops->check_events()

Convert from ->media_changed() to ->check_events().

ub buffers media changed state and clears it on revalidation. It will
behave correctly with kernel event polling.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Pete Zaitcev <[email protected]>
---
drivers/block/ub.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 9ae3bb7..68b9430 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1788,7 +1788,8 @@ static int ub_bd_revalidate(struct gendisk *disk)
*
* The return code is bool!
*/
-static int ub_bd_media_changed(struct gendisk *disk)
+static unsigned int ub_bd_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct ub_lun *lun = disk->private_data;

@@ -1806,10 +1807,10 @@ static int ub_bd_media_changed(struct gendisk *disk)
*/
if (ub_sync_tur(lun->udev, lun) != 0) {
lun->changed = 1;
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}

- return lun->changed;
+ return lun->changed ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static const struct block_device_operations ub_bd_fops = {
@@ -1817,7 +1818,7 @@ static const struct block_device_operations ub_bd_fops = {
.open = ub_bd_unlocked_open,
.release = ub_bd_release,
.ioctl = ub_bd_ioctl,
- .media_changed = ub_bd_media_changed,
+ .check_events = ub_bd_check_events,
.revalidate_disk = ub_bd_revalidate,
};

@@ -2333,6 +2334,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
disk->major = UB_MAJOR;
disk->first_minor = lun->id * UB_PARTS_PER_LUN;
disk->fops = &ub_bd_fops;
+ disk->events = DISK_EVENT_MEDIA_CHANGE;
disk->private_data = lun;
disk->driverfs_dev = &sc->intf->dev;

--
1.7.1

2010-12-28 17:29:32

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 04/16] ide: convert to bdops->check_events()

Convert ->media_changed() to the new ->check_events() method. The
conversion is mostly mechanical. The only notable change is that
cdrom now doesn't generate any event if @slot_nr isn't CDSL_CURRENT.
It used to return -EINVAL which would be treated as media changed. As
media changer isn't supported anyway, this doesn't make any
difference.

This makes ide emit the standard disk events and allows kernel event
polling. Currently, only MEDIA_CHANGE event is implemented. Adding
support for EJECT_REQUEST shouldn't be difficult; however, given that
ide driver is already deprecated, it probably is best to leave it
alone.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: [email protected]
---
drivers/ide/ide-cd.c | 10 ++++++----
drivers/ide/ide-cd.h | 3 ++-
drivers/ide/ide-cd_ioctl.c | 8 ++++----
drivers/ide/ide-gd.c | 14 ++++++++------
4 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 0c73fe3..a2e2909 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1177,7 +1177,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
.open = ide_cdrom_open_real,
.release = ide_cdrom_release_real,
.drive_status = ide_cdrom_drive_status,
- .media_changed = ide_cdrom_check_media_change_real,
+ .check_events = ide_cdrom_check_events_real,
.tray_move = ide_cdrom_tray_move,
.lock_door = ide_cdrom_lock_door,
.select_speed = ide_cdrom_select_speed,
@@ -1702,10 +1702,11 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode,
}


-static int idecd_media_changed(struct gendisk *disk)
+static unsigned int idecd_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
- return cdrom_media_changed(&info->devinfo);
+ return cdrom_check_events(&info->devinfo, clearing);
}

static int idecd_revalidate_disk(struct gendisk *disk)
@@ -1723,7 +1724,7 @@ static const struct block_device_operations idecd_ops = {
.open = idecd_open,
.release = idecd_release,
.ioctl = idecd_ioctl,
- .media_changed = idecd_media_changed,
+ .check_events = idecd_check_events,
.revalidate_disk = idecd_revalidate_disk
};

@@ -1790,6 +1791,7 @@ static int ide_cd_probe(ide_drive_t *drive)
ide_cd_read_toc(drive, &sense);
g->fops = &idecd_ops;
g->flags |= GENHD_FL_REMOVABLE;
+ g->events = DISK_EVENT_MEDIA_CHANGE;
add_disk(g);
return 0;

diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 93a3cf1..1efc936 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -111,7 +111,8 @@ int cdrom_check_status(ide_drive_t *, struct request_sense *);
int ide_cdrom_open_real(struct cdrom_device_info *, int);
void ide_cdrom_release_real(struct cdrom_device_info *);
int ide_cdrom_drive_status(struct cdrom_device_info *, int);
-int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int);
+unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *,
+ unsigned int clearing, int slot_nr);
int ide_cdrom_tray_move(struct cdrom_device_info *, int);
int ide_cdrom_lock_door(struct cdrom_device_info *, int);
int ide_cdrom_select_speed(struct cdrom_device_info *, int);
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 766b3de..2a6bc50 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -79,8 +79,8 @@ int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr)
return CDS_DRIVE_NOT_READY;
}

-int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
- int slot_nr)
+unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *cdi,
+ unsigned int clearing, int slot_nr)
{
ide_drive_t *drive = cdi->handle;
int retval;
@@ -89,9 +89,9 @@ int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
(void) cdrom_check_status(drive, NULL);
retval = (drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED) ? 1 : 0;
drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
- return retval;
+ return retval ? DISK_EVENT_MEDIA_CHANGE : 0;
} else {
- return -EINVAL;
+ return 0;
}
}

diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 35c4b43..c4ffd48 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -285,11 +285,12 @@ static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}

-static int ide_gd_media_changed(struct gendisk *disk)
+static unsigned int ide_gd_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
ide_drive_t *drive = idkp->drive;
- int ret;
+ bool ret;

/* do not scan partitions twice if this is a removable device */
if (drive->dev_flags & IDE_DFLAG_ATTACH) {
@@ -297,10 +298,10 @@ static int ide_gd_media_changed(struct gendisk *disk)
return 0;
}

- ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
+ ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;

- return ret;
+ return ret ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static void ide_gd_unlock_native_capacity(struct gendisk *disk)
@@ -318,7 +319,7 @@ static int ide_gd_revalidate_disk(struct gendisk *disk)
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
ide_drive_t *drive = idkp->drive;

- if (ide_gd_media_changed(disk))
+ if (ide_gd_check_events(disk, 0))
drive->disk_ops->get_capacity(drive);

set_capacity(disk, ide_gd_capacity(drive));
@@ -340,7 +341,7 @@ static const struct block_device_operations ide_gd_ops = {
.release = ide_gd_release,
.ioctl = ide_gd_ioctl,
.getgeo = ide_gd_getgeo,
- .media_changed = ide_gd_media_changed,
+ .check_events = ide_gd_check_events,
.unlock_native_capacity = ide_gd_unlock_native_capacity,
.revalidate_disk = ide_gd_revalidate_disk
};
@@ -412,6 +413,7 @@ static int ide_gd_probe(ide_drive_t *drive)
if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
g->flags = GENHD_FL_REMOVABLE;
g->fops = &ide_gd_ops;
+ g->events = DISK_EVENT_MEDIA_CHANGE;
add_disk(g);
return 0;

--
1.7.1

2010-12-28 17:31:37

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 06/16] gdrom,viocd: convert to bdops->check_events()

Convert gdrom and viocd from ->media_changed() to ->check_events().

It's unclear how the conditions are cleared and it's possible that it
may generate spurious events when polled.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
---
drivers/cdrom/gdrom.c | 16 ++++++++++------
drivers/cdrom/viocd.c | 17 ++++++++++-------
2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index de65915..e560c43 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -395,10 +395,12 @@ static int gdrom_drivestatus(struct cdrom_device_info *cd_info, int ignore)
return CDS_NO_INFO;
}

-static int gdrom_mediachanged(struct cdrom_device_info *cd_info, int ignore)
+static unsigned int gdrom_check_events(struct cdrom_device_info *cd_info,
+ unsigned int clearing, int ignore)
{
/* check the sense key */
- return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60;
+ return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60 ?
+ DISK_EVENT_MEDIA_CHANGE : 0;
}

/* reset the G1 bus */
@@ -483,7 +485,7 @@ static struct cdrom_device_ops gdrom_ops = {
.open = gdrom_open,
.release = gdrom_release,
.drive_status = gdrom_drivestatus,
- .media_changed = gdrom_mediachanged,
+ .check_events = gdrom_check_events,
.get_last_session = gdrom_get_last_session,
.reset = gdrom_hardreset,
.audio_ioctl = gdrom_audio_ioctl,
@@ -509,9 +511,10 @@ static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode)
return 0;
}

-static int gdrom_bdops_mediachanged(struct gendisk *disk)
+static unsigned int gdrom_bdops_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
- return cdrom_media_changed(gd.cd_info);
+ return cdrom_check_events(gd.cd_info, clearing);
}

static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode,
@@ -530,7 +533,7 @@ static const struct block_device_operations gdrom_bdops = {
.owner = THIS_MODULE,
.open = gdrom_bdops_open,
.release = gdrom_bdops_release,
- .media_changed = gdrom_bdops_mediachanged,
+ .check_events = gdrom_bdops_check_events,
.ioctl = gdrom_bdops_ioctl,
};

@@ -800,6 +803,7 @@ static int __devinit probe_gdrom(struct platform_device *devptr)
goto probe_fail_cdrom_register;
}
gd.disk->fops = &gdrom_bdops;
+ gd.disk->events = DISK_EVENT_MEDIA_CHANGE;
/* latch on to the interrupt */
err = gdrom_set_interrupt_handlers();
if (err)
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index be73a9b..4e874c5 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -186,10 +186,11 @@ static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode,
return ret;
}

-static int viocd_blk_media_changed(struct gendisk *disk)
+static unsigned int viocd_blk_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct disk_info *di = disk->private_data;
- return cdrom_media_changed(&di->viocd_info);
+ return cdrom_check_events(&di->viocd_info, clearing);
}

static const struct block_device_operations viocd_fops = {
@@ -197,7 +198,7 @@ static const struct block_device_operations viocd_fops = {
.open = viocd_blk_open,
.release = viocd_blk_release,
.ioctl = viocd_blk_ioctl,
- .media_changed = viocd_blk_media_changed,
+ .check_events = viocd_blk_check_events,
};

static int viocd_open(struct cdrom_device_info *cdi, int purpose)
@@ -320,7 +321,8 @@ static void do_viocd_request(struct request_queue *q)
}
}

-static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+static unsigned int viocd_check_events(struct cdrom_device_info *cdi,
+ unsigned int clearing, int disc_nr)
{
struct viocd_waitevent we;
HvLpEvent_Rc hvrc;
@@ -340,7 +342,7 @@ static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
if (hvrc != 0) {
pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n",
(int)hvrc);
- return -EIO;
+ return 0;
}

wait_for_completion(&we.com);
@@ -354,7 +356,7 @@ static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
return 0;
}

- return we.changed;
+ return we.changed ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static int viocd_lock_door(struct cdrom_device_info *cdi, int locking)
@@ -550,7 +552,7 @@ static int viocd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
static struct cdrom_device_ops viocd_dops = {
.open = viocd_open,
.release = viocd_release,
- .media_changed = viocd_media_changed,
+ .check_events = viocd_check_events,
.lock_door = viocd_lock_door,
.generic_packet = viocd_packet,
.audio_ioctl = viocd_audio_ioctl,
@@ -624,6 +626,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
gendisk->queue = q;
gendisk->fops = &viocd_fops;
gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE;
+ gendisk->events = DISK_EVENT_MEDIA_CHANGE;
set_capacity(gendisk, 0);
gendisk->private_data = d;
d->viocd_disk = gendisk;
--
1.7.1

2010-12-28 17:31:38

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 07/16] paride: convert to bdops->check_events()

Convert paride drivers from ->media_changed() to ->check_events().

pcd and pd buffer and clear events after reporting; however, pf
unconditionally reports MEDIA_CHANGE and will generate spurious events
when polled.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
Cc: Tim Waugh <[email protected]>
---
drivers/block/paride/pcd.c | 18 +++++++++++-------
drivers/block/paride/pd.c | 7 ++++---
drivers/block/paride/pf.c | 10 ++++++----
3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 62cec6a..2f2ccf6 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -172,7 +172,8 @@ module_param_array(drive3, int, NULL, 0);
static int pcd_open(struct cdrom_device_info *cdi, int purpose);
static void pcd_release(struct cdrom_device_info *cdi);
static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
-static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
+static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
+ unsigned int clearing, int slot_nr);
static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
static int pcd_drive_reset(struct cdrom_device_info *cdi);
@@ -257,10 +258,11 @@ static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
return ret;
}

-static int pcd_block_media_changed(struct gendisk *disk)
+static unsigned int pcd_block_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct pcd_unit *cd = disk->private_data;
- return cdrom_media_changed(&cd->info);
+ return cdrom_check_events(&cd->info, clearing);
}

static const struct block_device_operations pcd_bdops = {
@@ -268,14 +270,14 @@ static const struct block_device_operations pcd_bdops = {
.open = pcd_block_open,
.release = pcd_block_release,
.ioctl = pcd_block_ioctl,
- .media_changed = pcd_block_media_changed,
+ .check_events = pcd_block_check_events,
};

static struct cdrom_device_ops pcd_dops = {
.open = pcd_open,
.release = pcd_release,
.drive_status = pcd_drive_status,
- .media_changed = pcd_media_changed,
+ .check_events = pcd_check_events,
.tray_move = pcd_tray_move,
.lock_door = pcd_lock_door,
.get_mcn = pcd_get_mcn,
@@ -318,6 +320,7 @@ static void pcd_init_units(void)
disk->first_minor = unit;
strcpy(disk->disk_name, cd->name); /* umm... */
disk->fops = &pcd_bdops;
+ disk->events = DISK_EVENT_MEDIA_CHANGE;
}
}

@@ -502,13 +505,14 @@ static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc)

#define DBMSG(msg) ((verbose>1)?(msg):NULL)

-static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
+static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
+ unsigned int clearing, int slot_nr)
{
struct pcd_unit *cd = cdi->handle;
int res = cd->changed;
if (res)
cd->changed = 0;
- return res;
+ return res ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index c0ee155..21dfdb7 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -794,7 +794,7 @@ static int pd_release(struct gendisk *p, fmode_t mode)
return 0;
}

-static int pd_check_media(struct gendisk *p)
+static unsigned int pd_check_events(struct gendisk *p, unsigned int clearing)
{
struct pd_unit *disk = p->private_data;
int r;
@@ -803,7 +803,7 @@ static int pd_check_media(struct gendisk *p)
pd_special_command(disk, pd_media_check);
r = disk->changed;
disk->changed = 0;
- return r;
+ return r ? DISK_EVENT_MEDIA_CHANGE : 0;
}

static int pd_revalidate(struct gendisk *p)
@@ -822,7 +822,7 @@ static const struct block_device_operations pd_fops = {
.release = pd_release,
.ioctl = pd_ioctl,
.getgeo = pd_getgeo,
- .media_changed = pd_check_media,
+ .check_events = pd_check_events,
.revalidate_disk= pd_revalidate
};

@@ -837,6 +837,7 @@ static void pd_probe_drive(struct pd_unit *disk)
p->fops = &pd_fops;
p->major = major;
p->first_minor = (disk - pd) << PD_BITS;
+ p->events = DISK_EVENT_MEDIA_CHANGE;
disk->gd = p;
p->private_data = disk;
p->queue = pd_queue;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 635f25d..7adeb1e 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -243,7 +243,8 @@ static struct pf_unit units[PF_UNITS];
static int pf_identify(struct pf_unit *pf);
static void pf_lock(struct pf_unit *pf, int func);
static void pf_eject(struct pf_unit *pf);
-static int pf_check_media(struct gendisk *disk);
+static unsigned int pf_check_events(struct gendisk *disk,
+ unsigned int clearing);

static char pf_scratch[512]; /* scratch block buffer */

@@ -270,7 +271,7 @@ static const struct block_device_operations pf_fops = {
.release = pf_release,
.ioctl = pf_ioctl,
.getgeo = pf_getgeo,
- .media_changed = pf_check_media,
+ .check_events = pf_check_events,
};

static void __init pf_init_units(void)
@@ -293,6 +294,7 @@ static void __init pf_init_units(void)
disk->first_minor = unit;
strcpy(disk->disk_name, pf->name);
disk->fops = &pf_fops;
+ disk->events = DISK_EVENT_MEDIA_CHANGE;
if (!(*drives[unit])[D_PRT])
pf_drive_count++;
}
@@ -377,9 +379,9 @@ static int pf_release(struct gendisk *disk, fmode_t mode)

}

-static int pf_check_media(struct gendisk *disk)
+static unsigned int pf_check_events(struct gendisk *disk, unsigned int clearing)
{
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}

static inline int status_reg(struct pf_unit *pf)
--
1.7.1

2010-12-28 17:29:30

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 05/16] floppy,{ami|ata}flop: convert to bdops->check_events()

Convert the floppy drivers from ->media_changed() to ->check_events().
Both floppy and ataflop buffer media changed state bit and clear them
on revalidation and will behave correctly with kernel event polling.

I can't tell how amiflop clears its event and it's possible that it
may generate spurious events when polled.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
---
drivers/block/amiflop.c | 9 +++++----
drivers/block/ataflop.c | 14 ++++++++------
drivers/block/floppy.c | 10 ++++++----
3 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index a1725e6..b988cb2 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1658,12 +1658,12 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
}

/*
- * floppy-change is never called from an interrupt, so we can relax a bit
+ * check_events is never called from an interrupt, so we can relax a bit
* here, sleep etc. Note that floppy-on tries to set current_DOR to point
* to the desired drive, but it will probably not survive the sleep if
* several floppies are used at the same time: thus the loop.
*/
-static int amiga_floppy_change(struct gendisk *disk)
+static unsigned amiga_check_events(struct gendisk *disk, unsigned int clearing)
{
struct amiga_floppy_struct *p = disk->private_data;
int drive = p - unit;
@@ -1686,7 +1686,7 @@ static int amiga_floppy_change(struct gendisk *disk)
p->dirty = 0;
writepending = 0; /* if this was true before, too bad! */
writefromint = 0;
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}
return 0;
}
@@ -1697,7 +1697,7 @@ static const struct block_device_operations floppy_fops = {
.release = floppy_release,
.ioctl = fd_ioctl,
.getgeo = fd_getgeo,
- .media_changed = amiga_floppy_change,
+ .check_events = amiga_check_events,
};

static int __init fd_probe_drives(void)
@@ -1736,6 +1736,7 @@ static int __init fd_probe_drives(void)
disk->major = FLOPPY_MAJOR;
disk->first_minor = drive;
disk->fops = &floppy_fops;
+ disk->events = DISK_EVENT_MEDIA_CHANGE;
sprintf(disk->disk_name, "fd%d", drive);
disk->private_data = &unit[drive];
set_capacity(disk, 880*2);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 4e4cc6c..0fce4c3 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1324,23 +1324,24 @@ static void finish_fdc_done( int dummy )
* due to unrecognised disk changes.
*/

-static int check_floppy_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
struct atari_floppy_struct *p = disk->private_data;
unsigned int drive = p - unit;
if (test_bit (drive, &fake_change)) {
/* simulated change (e.g. after formatting) */
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}
if (test_bit (drive, &changed_floppies)) {
/* surely changed (the WP signal changed at least once) */
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}
if (UD.wpstat) {
/* WP is on -> could be changed: to be sure, buffers should be
* invalidated...
*/
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
}

return 0;
@@ -1570,7 +1571,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
* or the next access will revalidate - and clear UDT :-(
*/

- if (check_floppy_change(disk))
+ if (floppy_check_events(disk, 0))
floppy_revalidate(disk);

if (UD.flags & FTD_MSG)
@@ -1904,7 +1905,7 @@ static const struct block_device_operations floppy_fops = {
.open = floppy_unlocked_open,
.release = floppy_release,
.ioctl = fd_ioctl,
- .media_changed = check_floppy_change,
+ .check_events = floppy_check_events,
.revalidate_disk= floppy_revalidate,
};

@@ -1963,6 +1964,7 @@ static int __init atari_floppy_init (void)
unit[i].disk->first_minor = i;
sprintf(unit[i].disk->disk_name, "fd%d", i);
unit[i].disk->fops = &floppy_fops;
+ unit[i].disk->events = DISK_EVENT_MEDIA_CHANGE;
unit[i].disk->private_data = &unit[i];
unit[i].disk->queue = blk_init_queue(do_fd_request,
&ataflop_lock);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 3951020..317db28 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3765,13 +3765,14 @@ out2:
/*
* Check if the disk has been changed or if a change has been faked.
*/
-static int check_floppy_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+ unsigned int clearing)
{
int drive = (long)disk->private_data;

if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
test_bit(FD_VERIFY_BIT, &UDRS->flags))
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;

if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
lock_fdc(drive, false);
@@ -3783,7 +3784,7 @@ static int check_floppy_change(struct gendisk *disk)
test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
test_bit(drive, &fake_change) ||
(!ITYPE(UDRS->fd_device) && !current_type[drive]))
- return 1;
+ return DISK_EVENT_MEDIA_CHANGE;
return 0;
}

@@ -3893,7 +3894,7 @@ static const struct block_device_operations floppy_fops = {
.release = floppy_release,
.ioctl = fd_ioctl,
.getgeo = fd_getgeo,
- .media_changed = check_floppy_change,
+ .check_events = floppy_check_events,
.revalidate_disk = floppy_revalidate,
};

@@ -4200,6 +4201,7 @@ static int __init floppy_init(void)
disks[dr]->major = FLOPPY_MAJOR;
disks[dr]->first_minor = TOMINOR(dr);
disks[dr]->fops = &floppy_fops;
+ disks[dr]->events = DISK_EVENT_MEDIA_CHANGE;
sprintf(disks[dr]->disk_name, "fd%d", dr);

init_timer(&motor_off_timer[dr]);
--
1.7.1

2010-12-28 17:32:14

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 03/16] block: don't check events while open is in progress

Not all block drivers clear events immediately after reporting. Some
do so in ->revalidate_disk() or other steps during ->open(). There is
a slim chance event poll may happen between the clearing event check
from check_disk_change() and the actual clearing of the events which
would result in spurious events.

Block event checks while block device open is in progress. There is
no need to kick explicit event check afterwards as events are always
checked during open.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
---
fs/block_dev.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 58026da..f6390fd 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1016,6 +1016,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (!disk)
goto out;

+ disk_block_events(disk);
mutex_lock_nested(&bdev->bd_mutex, for_part);
if (!bdev->bd_openers) {
bdev->bd_disk = disk;
@@ -1041,6 +1042,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
put_disk(disk);
bdev->bd_disk = NULL;
mutex_unlock(&bdev->bd_mutex);
+ disk_unblock_events(disk);
goto restart;
}
if (ret)
@@ -1094,6 +1096,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (for_part)
bdev->bd_part_count++;
mutex_unlock(&bdev->bd_mutex);
+ disk_unblock_events(disk);
return 0;

out_clear:
@@ -1106,6 +1109,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
bdev->bd_contains = NULL;
out_unlock_bdev:
mutex_unlock(&bdev->bd_mutex);
+ disk_unblock_events(disk);
out:
if (disk)
module_put(disk->fops->owner);
--
1.7.1

2010-12-28 17:32:38

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 01/16] block: don't implicitly trigger event check on disk_unblock_events()

Currently, disk_unblock_events() implicitly kick event check if the
block count reaches zero. This behavior is not described in the
comment and hinders with future changes. Make the unblocker
explicitly check events by calling disk_check_events() as necessary.

This patch doesn't cause any behavior difference.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Kay Sievers <[email protected]>
---
block/genhd.c | 2 +-
fs/block_dev.c | 1 +
2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index 5465a82..a1d41dc 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1492,7 +1492,7 @@ void disk_block_events(struct gendisk *disk)
void disk_unblock_events(struct gendisk *disk)
{
if (disk->ev)
- __disk_unblock_events(disk, true);
+ __disk_unblock_events(disk, false);
}

/**
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 6017389..c620628 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1377,6 +1377,7 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
bd_unlink_disk_holder(bdev);
if (bdev->bd_write_holder) {
disk_unblock_events(bdev->bd_disk);
+ disk_check_events(bdev->bd_disk);
bdev->bd_write_holder = false;
} else
disk_check_events(bdev->bd_disk);
--
1.7.1

2010-12-28 18:39:53

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 16/16] staging: convert to bdops->check_events()

On Tue, Dec 28, 2010 at 06:29:12PM +0100, Tejun Heo wrote:
> Convert two staging drivers - blkvsc_drv and cyasblkdev_block - from
> ->media_changed() to ->check_events(). The former always indicated
> media changed while the latter always indicated media not changed.
> Not sure what the drivers are trying to achieve but keep the original
> behavior.
>
> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Jens Axboe <[email protected]>
> Cc: Kay Sievers <[email protected]>
> Cc: Greg Kroah-Hartman <[email protected]>

Acked-by: Greg Kroah-Hartman <[email protected]>

2010-12-28 19:00:41

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 04/16] ide: convert to bdops->check_events()

From: Tejun Heo <[email protected]>
Date: Tue, 28 Dec 2010 18:29:00 +0100

> Convert ->media_changed() to the new ->check_events() method. The
> conversion is mostly mechanical. The only notable change is that
> cdrom now doesn't generate any event if @slot_nr isn't CDSL_CURRENT.
> It used to return -EINVAL which would be treated as media changed. As
> media changer isn't supported anyway, this doesn't make any
> difference.
>
> This makes ide emit the standard disk events and allows kernel event
> polling. Currently, only MEDIA_CHANGE event is implemented. Adding
> support for EJECT_REQUEST shouldn't be difficult; however, given that
> ide driver is already deprecated, it probably is best to leave it
> alone.
>
> Signed-off-by: Tejun Heo <[email protected]>

Acked-by: David S. Miller <[email protected]>

2010-12-28 20:04:37

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCHSET] block: convert block drivers to ->check_events()

On 12/28/2010 12:28 PM, Tejun Heo wrote:
> This patchset converts all in-kernel block drivers from
> ->media_changed() to ->check_events(). Most conversions are fairly
> mechanical. The only notable exceptions are,

Even though this does not directly touch libata, I feel compelled to add
an 'ACK' to this patch series. Good stuff.

2010-12-29 06:37:48

by Grant Likely

[permalink] [raw]
Subject: Re: [PATCH 11/16] xsysace: convert to bdops->check_events()

On Tue, Dec 28, 2010 at 06:29:07PM +0100, Tejun Heo wrote:
> Convert from ->media_changed() to ->check_events().
>
> xsysace buffers media changed state and clears it on revalidation. It
> will behave correctly with kernel event polling.
>
> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Jens Axboe <[email protected]>
> Cc: Kay Sievers <[email protected]>
> Cc: Grant Likely <[email protected]>

Acked-by: Grant Likely <[email protected]>

g.

> ---
> drivers/block/xsysace.c | 9 +++++----
> 1 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
> index 829161e..16a2fa9 100644
> --- a/drivers/block/xsysace.c
> +++ b/drivers/block/xsysace.c
> @@ -867,12 +867,12 @@ static void ace_request(struct request_queue * q)
> }
> }
>
> -static int ace_media_changed(struct gendisk *gd)
> +static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
> {
> struct ace_device *ace = gd->private_data;
> - dev_dbg(ace->dev, "ace_media_changed(): %i\n", ace->media_change);
> + dev_dbg(ace->dev, "ace_check_events(): %i\n", ace->media_change);
>
> - return ace->media_change;
> + return ace->media_change ? DISK_EVENT_MEDIA_CHANGE : 0;
> }
>
> static int ace_revalidate_disk(struct gendisk *gd)
> @@ -953,7 +953,7 @@ static const struct block_device_operations ace_fops = {
> .owner = THIS_MODULE,
> .open = ace_open,
> .release = ace_release,
> - .media_changed = ace_media_changed,
> + .check_events = ace_check_events,
> .revalidate_disk = ace_revalidate_disk,
> .getgeo = ace_getgeo,
> };
> @@ -1005,6 +1005,7 @@ static int __devinit ace_setup(struct ace_device *ace)
> ace->gd->major = ace_major;
> ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
> ace->gd->fops = &ace_fops;
> + ace->gd->events = DISK_EVENT_MEDIA_CHANGE;
> ace->gd->queue = ace->queue;
> ace->gd->private_data = ace;
> snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
> --
> 1.7.1
>

2010-12-29 15:53:46

by Pete Zaitcev

[permalink] [raw]
Subject: Re: [PATCH 10/16] ub: convert to bdops->check_events()

On Tue, 28 Dec 2010 18:29:06 +0100
Tejun Heo <[email protected]> wrote:

> Convert from ->media_changed() to ->check_events().
>
> ub buffers media changed state and clears it on revalidation. It will
> behave correctly with kernel event polling.

If you say so, I don't mind. I reserve the right to come back to you
if I find breakage in testing (I have a ZIP drive that has a real
media change).

-- Pete

2010-12-29 16:02:11

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 10/16] ub: convert to bdops->check_events()

On Wed, Dec 29, 2010 at 08:53:29AM -0700, Pete Zaitcev wrote:
> On Tue, 28 Dec 2010 18:29:06 +0100
> Tejun Heo <[email protected]> wrote:
>
> > Convert from ->media_changed() to ->check_events().
> >
> > ub buffers media changed state and clears it on revalidation. It will
> > behave correctly with kernel event polling.
>
> If you say so, I don't mind. I reserve the right to come back to you
> if I find breakage in testing (I have a ZIP drive that has a real
> media change).

Sure. :-)

--
tejun

2011-02-01 10:31:49

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCHSET] block: convert block drivers to ->check_events()

On Tue, Jan 25, 2011 at 02:06:38PM +0100, Tejun Heo wrote:
> Hello, Jens.
>
> On Tue, Dec 28, 2010 at 06:28:56PM +0100, Tejun Heo wrote:
> > 0001-block-don-t-implicitly-trigger-event-check-on-disk_u.patch
> > 0002-block-don-t-check-events-on-close-unless-it-was-bloc.patch
> > 0003-block-don-t-check-events-while-open-is-in-progress.patch
> > 0004-ide-convert-to-bdops-check_events.patch
> > 0005-floppy-ami-ata-flop-convert-to-bdops-check_events.patch
> > 0006-gdrom-viocd-convert-to-bdops-check_events.patch
> > 0007-paride-convert-to-bdops-check_events.patch
> > 0008-dac960-convert-to-bdops-check_events.patch
> > 0009-swim-3-convert-to-bdops-check_events.patch
> > 0010-ub-convert-to-bdops-check_events.patch
> > 0011-xsysace-convert-to-bdops-check_events.patch
> > 0012-i2o_block-convert-to-bdops-check_events.patch
> > 0013-s390-tape_block-convert-to-bdops-check_events.patch
> > 0014-umem-drop-dummy-media_changed.patch
> > 0015-pktcdvd-convert-to-bdops-check_events.patch
> > 0016-staging-convert-to-bdops-check_events.patch
>
> This series seems to have been forgotten. I think 0001-0003 better go
> in for 2.6.38 as they affect user-visible behavior (in not too
> significant way but still).
>
> The other patches can go in for 2.6.39. 0005 gets an easy-to-resolve
> context conflict but all other patches apply as-is. I'll post the
> refreshed version of 0005 as a reply to the original patch. If you
> want the whole series reposted, please let me know.

This will now create some minor conflicts on top of the mainline.
Please let me know when you're ready to apply this. I'll refresh and
repost.

Thank you.

--
tejun

2011-03-05 10:41:03

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCHSET] block: convert block drivers to ->check_events()

On Tue, Feb 01, 2011 at 11:31:43AM +0100, Tejun Heo wrote:
> This will now create some minor conflicts on top of the mainline.
> Please let me know when you're ready to apply this. I'll refresh and
> repost.

Ping?

--
tejun

2011-03-07 08:08:20

by Jens Axboe

[permalink] [raw]
Subject: Re: [PATCHSET] block: convert block drivers to ->check_events()

On 2011-03-05 11:40, Tejun Heo wrote:
> On Tue, Feb 01, 2011 at 11:31:43AM +0100, Tejun Heo wrote:
>> This will now create some minor conflicts on top of the mainline.
>> Please let me know when you're ready to apply this. I'll refresh and
>> repost.
>
> Ping?

I'm good to pull it in, so just let me know.

--
Jens Axboe