@@ -1437,11 +1437,13 @@ struct disk_events {
static const char *disk_events_strs[] = {
[ilog2(DISK_EVENT_MEDIA_CHANGE)] = "media_change",
[ilog2(DISK_EVENT_EJECT_REQUEST)] = "eject_request",
+ [ilog2(DISK_EVENT_LOWAT)] = "low_water_mark",
};
static char *disk_uevents[] = {
[ilog2(DISK_EVENT_MEDIA_CHANGE)] = "DISK_MEDIA_CHANGE=1",
[ilog2(DISK_EVENT_EJECT_REQUEST)] = "DISK_EJECT_REQUEST=1",
+ [ilog2(DISK_EVENT_LOWAT)] = "DISK_LOW_WATER_MARK=1",
};
/* list of all disk_events */
@@ -2683,7 +2683,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
EXPORT_SYMBOL(scsi_device_set_state);
/**
- * sdev_evt_emit - emit a single SCSI device uevent
+ * sdev_evt_emit - emit a single SCSI device uevent
* @sdev: associated SCSI device
* @evt: event to emit
*
@@ -2711,7 +2711,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
envp[idx++] = "SDEV_UA=CAPACITY_DATA_HAS_CHANGED";
break;
case SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED:
- envp[idx++] = "SDEV_UA=THIN_PROVISIONING_SOFT_THRESHOLD_REACHED";
+ envp[idx++] = "SDEV_UA=THIN_PROVISIONING_SOFT_THRESHOLD_REACHED";
break;
case SDEV_EVT_MODE_PARAMETER_CHANGE_REPORTED:
envp[idx++] = "SDEV_UA=MODE_PARAMETERS_CHANGED";
@@ -2733,7 +2733,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
}
/**
- * sdev_evt_thread - send a uevent for each scsi event
+ * sdev_evt_thread - send a uevent for each scsi event
* @work: work struct for scsi_device
*
* Dispatch queued events to their associated scsi_device kobjects
@@ -2773,7 +2773,7 @@ void scsi_evt_thread(struct work_struct *work)
}
/**
- * sdev_evt_send - send asserted event to uevent thread
+ * sdev_evt_send - send asserted event to uevent thread
* @sdev: scsi_device event occurred on
* @evt: event to send
*
@@ -2791,7 +2791,7 @@ void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt)
EXPORT_SYMBOL_GPL(sdev_evt_send);
/**
- * sdev_evt_alloc - allocate a new scsi event
+ * sdev_evt_alloc - allocate a new scsi event
* @evt_type: type of event to allocate
* @gfpflags: GFP flags for allocation
*
@@ -1425,6 +1425,16 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
return DISK_EVENT_MEDIA_CHANGE;
}
+ if (sdkp->tp_lowat) {
+ /*
+ * Thin Provisioning Low Watermark reached;
+ * don't send TEST_UNIT_READY but rather return
+ * immediately.
+ */
+ sdkp->tp_lowat = false;
+ return DISK_EVENT_LOWAT;
+ }
+
/*
* Using TEST_UNIT_READY enables differentiation between drive with
* no cartridge loaded - NOT READY, drive with changed cartridge -
@@ -1729,6 +1739,9 @@ static void sd_ua_event(struct scsi_device *sdev, enum scsi_device_event evt)
if (evt == SDEV_EVT_MEDIA_CHANGE) {
sdev->changed = 1;
disk_clear_events(sdkp->disk, DISK_EVENT_MEDIA_CHANGE);
+ } else if (evt == SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED) {
+ sdkp->tp_lowat = true;
+ disk_clear_events(sdkp->disk, DISK_EVENT_LOWAT);
}
}
@@ -3044,6 +3057,12 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
gd->flags |= GENHD_FL_REMOVABLE;
gd->events |= DISK_EVENT_MEDIA_CHANGE;
}
+ if (sdkp->lbpme) {
+ gd->events |= DISK_EVENT_LOWAT;
+ gd->async_events |= DISK_EVENT_LOWAT;
+ set_bit(SDEV_EVT_SOFT_THRESHOLD_REACHED_REPORTED,
+ sdp->supported_events);
+ }
blk_pm_runtime_init(sdp->request_queue, dev);
add_disk(gd);
@@ -94,6 +94,7 @@ struct scsi_disk {
unsigned lbpvpd : 1;
unsigned ws10 : 1;
unsigned ws16 : 1;
+ unsigned tp_lowat : 1; /* TP soft threshold reached */
};
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
@@ -143,6 +143,7 @@ struct hd_struct {
enum {
DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */
DISK_EVENT_EJECT_REQUEST = 1 << 1, /* eject requested */
+ DISK_EVENT_LOWAT = 1 << 2, /* Low watermark reached */
};
#define BLK_SCSI_MAX_CMDS (256)
Add a disk event for a 'low water mark' condition, signalling when a device is about to run out of space. This event is mapped to a Thin Provisioning Soft Threshold Reached UA. Signed-off-by: Hannes Reinecke <hare@suse.com> --- block/genhd.c | 2 ++ drivers/scsi/scsi_lib.c | 10 +++++----- drivers/scsi/sd.c | 19 +++++++++++++++++++ drivers/scsi/sd.h | 1 + include/linux/genhd.h | 1 + 5 files changed, 28 insertions(+), 5 deletions(-)