From eface65c336eff420d70beb0fb6787a732e05ffb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 18 Dec 2010 18:42:23 +0100 Subject: [SCSI] sd: implement sd_check_events() Replace sd_media_change() with sd_check_events(). * Move media removed logic into set_media_not_present() and media_not_present() and set sdev->changed iff an existing media is removed or the device indicates UNIT_ATTENTION. * Make sd_check_events() sets sdev->changed if previously missing media becomes present. * Event is reported only if sdev->changed is set. This makes media presence event reported if scsi_disk->media_present actually changed or the device indicated UNIT_ATTENTION. For backward compatibility, SDEV_EVT_MEDIA_CHANGE is generated each time sd_check_events() detects media change event. [jejb: fix boot failure] Signed-off-by: Tejun Heo Acked-by: Jens Axboe Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 104 ++++++++++++++++++++++++++++-------------------------- drivers/scsi/sd.h | 1 - 2 files changed, 53 insertions(+), 52 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b65e65a..7d25746 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -990,30 +990,51 @@ out: static void set_media_not_present(struct scsi_disk *sdkp) { - sdkp->media_present = 0; - sdkp->capacity = 0; - sdkp->device->changed = 1; + if (sdkp->media_present) + sdkp->device->changed = 1; + + if (sdkp->device->removable) { + sdkp->media_present = 0; + sdkp->capacity = 0; + } +} + +static int media_not_present(struct scsi_disk *sdkp, + struct scsi_sense_hdr *sshdr) +{ + if (!scsi_sense_valid(sshdr)) + return 0; + + /* not invoked for commands that could return deferred errors */ + switch (sshdr->sense_key) { + case UNIT_ATTENTION: + case NOT_READY: + /* medium not present */ + if (sshdr->asc == 0x3A) { + set_media_not_present(sdkp); + return 1; + } + } + return 0; } /** - * sd_media_changed - check if our medium changed - * @disk: kernel device descriptor + * sd_check_events - check media events + * @disk: kernel device descriptor + * @clearing: disk events currently being cleared * - * Returns 0 if not applicable or no change; 1 if change + * Returns mask of DISK_EVENT_*. * * Note: this function is invoked from the block subsystem. **/ -static int sd_media_changed(struct gendisk *disk) +static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) { struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; struct scsi_sense_hdr *sshdr = NULL; int retval; - SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n")); - - if (!sdp->removable) - return 0; + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n")); /* * If the device is offline, don't send any commands - just pretend as @@ -1043,40 +1064,37 @@ static int sd_media_changed(struct gendisk *disk) sshdr); } - if (retval) { + /* failed to execute TUR, assume media not present */ + if (host_byte(retval)) { set_media_not_present(sdkp); goto out; } + if (media_not_present(sdkp, sshdr)) + goto out; + /* * For removable scsi disk we have to recognise the presence - * of a disk in the drive. This is kept in the struct scsi_disk - * struct and tested at open ! Daniel Roche (dan@lectra.fr) + * of a disk in the drive. */ + if (!sdkp->media_present) + sdp->changed = 1; sdkp->media_present = 1; - out: /* - * Report a media change under the following conditions: + * sdp->changed is set under the following conditions: * - * Medium is present now and wasn't present before. - * Medium wasn't present before and is present now. - * Medium was present at all times, but it changed while - * we weren't looking (sdp->changed is set). + * Medium present state has changed in either direction. + * Device has indicated UNIT_ATTENTION. * - * If there was no medium before and there is no medium now then - * don't report a change, even if a medium was inserted and removed - * while we weren't looking. + * Report SDEV_EVT_MEDIA_CHANGE too for backward compatibility. */ - retval = (sdkp->media_present != sdkp->previous_state || - (sdkp->media_present && sdp->changed)); - if (retval) + if (sdp->changed) sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); - sdkp->previous_state = sdkp->media_present; - - /* sdp->changed indicates medium was changed or is not present */ - sdp->changed = !sdkp->media_present; kfree(sshdr); + + retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0; + sdp->changed = 0; return retval; } @@ -1169,7 +1187,7 @@ static const struct block_device_operations sd_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, #endif - .media_changed = sd_media_changed, + .check_events = sd_check_events, .revalidate_disk = sd_revalidate_disk, .unlock_native_capacity = sd_unlock_native_capacity, }; @@ -1312,23 +1330,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) return good_bytes; } -static int media_not_present(struct scsi_disk *sdkp, - struct scsi_sense_hdr *sshdr) -{ - - if (!scsi_sense_valid(sshdr)) - return 0; - /* not invoked for commands that could return deferred errors */ - if (sshdr->sense_key != NOT_READY && - sshdr->sense_key != UNIT_ATTENTION) - return 0; - if (sshdr->asc != 0x3A) /* medium not present */ - return 0; - - set_media_not_present(sdkp); - return 1; -} - /* * spinup disk - called only in sd_revalidate_disk() */ @@ -1503,7 +1504,7 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, */ if (sdp->removable && sense_valid && sshdr->sense_key == NOT_READY) - sdp->changed = 1; + set_media_not_present(sdkp); /* * We used to set media_present to 0 here to indicate no media @@ -2389,8 +2390,10 @@ static void sd_probe_async(void *data, async_cookie_t cookie) gd->driverfs_dev = &sdp->sdev_gendev; gd->flags = GENHD_FL_EXT_DEVT; - if (sdp->removable) + if (sdp->removable) { gd->flags |= GENHD_FL_REMOVABLE; + gd->events |= DISK_EVENT_MEDIA_CHANGE; + } add_disk(gd); sd_dif_config_host(sdkp); @@ -2472,7 +2475,6 @@ static int sd_probe(struct device *dev) sdkp->disk = gd; sdkp->index = index; atomic_set(&sdkp->openers, 0); - sdkp->previous_state = 1; if (!sdp->request_queue->rq_timeout) { if (sdp->type != TYPE_MOD) diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 55488fa..c9d8f6c 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -55,7 +55,6 @@ struct scsi_disk { u8 media_present; u8 write_prot; u8 protection_type;/* Data Integrity Field */ - unsigned previous_state : 1; unsigned ATO : 1; /* state of disk ATO bit */ unsigned WCE : 1; /* state of disk WCE bit */ unsigned RCD : 1; /* state of disk RCD bit, unused */ -- cgit v1.1 From 140e3008e7fe1526cbb12f8f07dbc273ac713b75 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 28 Dec 2010 16:20:47 +0100 Subject: [SCSI] sd,sr: kill compat SDEV_MEDIA_CHANGE event SDEV_MEDIA_CHANGE event was first added by commit a341cd0f (SCSI: add asynchronous event notification API) for SATA AN support and then extended to cover generic media change events by commit 285e9670 ([SCSI] sr,sd: send media state change modification events). This event was mapped to block device in userland with all properties stripped to simulate CHANGE event on the block device, which, in turn, was used to trigger further userspace action on media change. The recent addition of disk event framework kept this event for backward compatibility but it turns out to be unnecessary and causes erratic and inefficient behavior. The new disk event generates proper events on the block devices and the compat events are mapped to block device with all properties stripped, so the block device ends up generating multiple duplicate events for single actual event. This patch removes the compat event generation from both sr and sd as suggested by Kay Sievers. Both existing and newer versions of udev and the associated tools will behave better with the removal of these events as they from the beginning were expecting events on the block devices. Signed-off-by: Tejun Heo Acked-by: Kay Sievers Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 5 ----- drivers/scsi/sr.c | 4 ---- 2 files changed, 9 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7d25746..e567302 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1086,13 +1086,8 @@ out: * * Medium present state has changed in either direction. * Device has indicated UNIT_ATTENTION. - * - * Report SDEV_EVT_MEDIA_CHANGE too for backward compatibility. */ - if (sdp->changed) - sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); kfree(sshdr); - retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0; sdp->changed = 0; return retval; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index be6baf8..aefadc6 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -249,10 +249,6 @@ skip_tur: cd->device->changed = 0; } - /* for backward compatibility */ - if (events & DISK_EVENT_MEDIA_CHANGE) - sdev_evt_send_simple(cd->device, SDEV_EVT_MEDIA_CHANGE, - GFP_KERNEL); return events; } -- cgit v1.1 From e205117285d6035af135c9d6c34a30ee6b8d1f2e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 16 Jan 2011 21:11:25 +0000 Subject: configfs: change depends -> select SYSFS This patch changes configfs to select SYSFS to fix the following: warning: (TARGET_CORE && GFS2_FS) selects CONFIGFS_FS which has unmet direct dependencies (SYSFS) Reported-by: Randy Dunlap Signed-off-by: Nicholas A. Bellinger Acked-by: Joel Becker --- fs/configfs/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/configfs/Kconfig b/fs/configfs/Kconfig index 13587cc..9febcde 100644 --- a/fs/configfs/Kconfig +++ b/fs/configfs/Kconfig @@ -1,8 +1,8 @@ config CONFIGFS_FS tristate "Userspace-driven configuration filesystem" - depends on SYSFS + select SYSFS help - configfs is a ram-based filesystem that provides the converse + configfs is a RAM-based filesystem that provides the converse of sysfs's functionality. Where sysfs is a filesystem-based view of kernel objects, configfs is a filesystem-based manager of kernel objects, or config_items. -- cgit v1.1 From d9f9ab51e55e36379773752ffeaac677b080d469 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 16 Jan 2011 21:13:59 +0000 Subject: net: Make NETCONSOLE_DYNAMIC depend on CONFIGFS_FS This patch fixes the following kconfig error after changing CONFIGFS_FS -> select SYSFS: fs/sysfs/Kconfig:1:error: recursive dependency detected! fs/sysfs/Kconfig:1: symbol SYSFS is selected by CONFIGFS_FS fs/configfs/Kconfig:1: symbol CONFIGFS_FS is selected by NETCONSOLE_DYNAMIC drivers/net/Kconfig:3390: symbol NETCONSOLE_DYNAMIC depends on SYSFS Signed-off-by: Nicholas A. Bellinger Cc: Joel Becker Cc: Randy Dunlap Cc: Stephen Rothwell Cc: James Bottomley --- drivers/net/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4c8bfc9..16fe4f9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -3389,8 +3389,7 @@ config NETCONSOLE config NETCONSOLE_DYNAMIC bool "Dynamic reconfiguration of logging targets" - depends on NETCONSOLE && SYSFS - select CONFIGFS_FS + depends on NETCONSOLE && SYSFS && CONFIGFS_FS help This option enables the ability to dynamically reconfigure target parameters (interface, IP addresses, port numbers, MAC addresses) -- cgit v1.1 From 86c747d2a4f028fe2fdf091c3a81d0e187827682 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 16 Jan 2011 21:14:52 +0000 Subject: dlm: Make DLM depend on CONFIGFS_FS This patch fixes the following kconfig error after changing CONFIGFS_FS -> select SYSFS: fs/sysfs/Kconfig:1:error: recursive dependency detected! fs/sysfs/Kconfig:1: symbol SYSFS is selected by CONFIGFS_FS fs/configfs/Kconfig:1: symbol CONFIGFS_FS is selected by DLM fs/dlm/Kconfig:1: symbol DLM depends on SYSFS Signed-off-by: Nicholas A. Bellinger Cc: Joel Becker Cc: Randy Dunlap Cc: Stephen Rothwell Cc: James Bottomley --- fs/dlm/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig index 2dbb422..1897eb1b 100644 --- a/fs/dlm/Kconfig +++ b/fs/dlm/Kconfig @@ -1,8 +1,7 @@ menuconfig DLM tristate "Distributed Lock Manager (DLM)" depends on EXPERIMENTAL && INET - depends on SYSFS && (IPV6 || IPV6=n) - select CONFIGFS_FS + depends on SYSFS && CONFIGFS_FS && (IPV6 || IPV6=n) select IP_SCTP help A general purpose distributed lock manager for kernel or userspace -- cgit v1.1 From 7b1fff7e4fdf2805fce7afd6247912588d72d604 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 16 Jan 2011 21:16:07 +0000 Subject: ocfs2: Make OCFS2_FS depend on CONFIGFS_FS This patch fixes the following kconfig error after changing CONFIGFS_FS -> select SYSFS: fs/sysfs/Kconfig:1:error: recursive dependency detected! fs/sysfs/Kconfig:1: symbol SYSFS is selected by CONFIGFS_FS fs/configfs/Kconfig:1: symbol CONFIGFS_FS is selected by OCFS2_FS fs/ocfs2/Kconfig:1: symbol OCFS2_FS depends on SYSFS Signed-off-by: Nicholas A. Bellinger Cc: Joel Becker Cc: Randy Dunlap Cc: Stephen Rothwell Cc: James Bottomley --- fs/ocfs2/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ocfs2/Kconfig b/fs/ocfs2/Kconfig index ab152c0..77a8de5 100644 --- a/fs/ocfs2/Kconfig +++ b/fs/ocfs2/Kconfig @@ -1,7 +1,6 @@ config OCFS2_FS tristate "OCFS2 file system support" - depends on NET && SYSFS - select CONFIGFS_FS + depends on NET && SYSFS && CONFIGFS_FS select JBD2 select CRC32 select QUOTA -- cgit v1.1