diff options
author | Stefan Weinhuber <wein@de.ibm.com> | 2011-01-05 06:48:04 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2011-01-05 06:47:30 -0500 |
commit | 5a27e60dec59a95bd7f8ae9a19ae2ede4f76395b (patch) | |
tree | 20595cba0caebf7a8a5f0afac9785c7d717f3e8c /drivers/s390/block/dasd_devmap.c | |
parent | a4d26c6aeceea330ee5e0fb6b017d57e3b252d29 (diff) |
[S390] dasd: Improve handling of stolen DASD reservation
If a DASD device has been reserved by a Linux system, and later
this reservation is ‘stolen’ by a second system by means of an
unconditional reserve, then the first system receives a
notification about this fact. With this patch such an event can
be either ignored, as before, or it can be used to let the device
fail all I/O request, so that the device will not block anymore.
Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd_devmap.c')
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 0001df8ad3e6..47fc88692494 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -1127,6 +1127,103 @@ dasd_expires_store(struct device *dev, struct device_attribute *attr, | |||
1127 | 1127 | ||
1128 | static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store); | 1128 | static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store); |
1129 | 1129 | ||
1130 | static ssize_t dasd_reservation_policy_show(struct device *dev, | ||
1131 | struct device_attribute *attr, | ||
1132 | char *buf) | ||
1133 | { | ||
1134 | struct dasd_devmap *devmap; | ||
1135 | int rc = 0; | ||
1136 | |||
1137 | devmap = dasd_find_busid(dev_name(dev)); | ||
1138 | if (IS_ERR(devmap)) { | ||
1139 | rc = snprintf(buf, PAGE_SIZE, "ignore\n"); | ||
1140 | } else { | ||
1141 | spin_lock(&dasd_devmap_lock); | ||
1142 | if (devmap->features & DASD_FEATURE_FAILONSLCK) | ||
1143 | rc = snprintf(buf, PAGE_SIZE, "fail\n"); | ||
1144 | else | ||
1145 | rc = snprintf(buf, PAGE_SIZE, "ignore\n"); | ||
1146 | spin_unlock(&dasd_devmap_lock); | ||
1147 | } | ||
1148 | return rc; | ||
1149 | } | ||
1150 | |||
1151 | static ssize_t dasd_reservation_policy_store(struct device *dev, | ||
1152 | struct device_attribute *attr, | ||
1153 | const char *buf, size_t count) | ||
1154 | { | ||
1155 | struct dasd_devmap *devmap; | ||
1156 | int rc; | ||
1157 | |||
1158 | devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); | ||
1159 | if (IS_ERR(devmap)) | ||
1160 | return PTR_ERR(devmap); | ||
1161 | rc = 0; | ||
1162 | spin_lock(&dasd_devmap_lock); | ||
1163 | if (sysfs_streq("ignore", buf)) | ||
1164 | devmap->features &= ~DASD_FEATURE_FAILONSLCK; | ||
1165 | else if (sysfs_streq("fail", buf)) | ||
1166 | devmap->features |= DASD_FEATURE_FAILONSLCK; | ||
1167 | else | ||
1168 | rc = -EINVAL; | ||
1169 | if (devmap->device) | ||
1170 | devmap->device->features = devmap->features; | ||
1171 | spin_unlock(&dasd_devmap_lock); | ||
1172 | if (rc) | ||
1173 | return rc; | ||
1174 | else | ||
1175 | return count; | ||
1176 | } | ||
1177 | |||
1178 | static DEVICE_ATTR(reservation_policy, 0644, | ||
1179 | dasd_reservation_policy_show, dasd_reservation_policy_store); | ||
1180 | |||
1181 | static ssize_t dasd_reservation_state_show(struct device *dev, | ||
1182 | struct device_attribute *attr, | ||
1183 | char *buf) | ||
1184 | { | ||
1185 | struct dasd_device *device; | ||
1186 | int rc = 0; | ||
1187 | |||
1188 | device = dasd_device_from_cdev(to_ccwdev(dev)); | ||
1189 | if (IS_ERR(device)) | ||
1190 | return snprintf(buf, PAGE_SIZE, "none\n"); | ||
1191 | |||
1192 | if (test_bit(DASD_FLAG_IS_RESERVED, &device->flags)) | ||
1193 | rc = snprintf(buf, PAGE_SIZE, "reserved\n"); | ||
1194 | else if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags)) | ||
1195 | rc = snprintf(buf, PAGE_SIZE, "lost\n"); | ||
1196 | else | ||
1197 | rc = snprintf(buf, PAGE_SIZE, "none\n"); | ||
1198 | dasd_put_device(device); | ||
1199 | return rc; | ||
1200 | } | ||
1201 | |||
1202 | static ssize_t dasd_reservation_state_store(struct device *dev, | ||
1203 | struct device_attribute *attr, | ||
1204 | const char *buf, size_t count) | ||
1205 | { | ||
1206 | struct dasd_device *device; | ||
1207 | int rc = 0; | ||
1208 | |||
1209 | device = dasd_device_from_cdev(to_ccwdev(dev)); | ||
1210 | if (IS_ERR(device)) | ||
1211 | return -ENODEV; | ||
1212 | if (sysfs_streq("reset", buf)) | ||
1213 | clear_bit(DASD_FLAG_LOCK_STOLEN, &device->flags); | ||
1214 | else | ||
1215 | rc = -EINVAL; | ||
1216 | dasd_put_device(device); | ||
1217 | |||
1218 | if (rc) | ||
1219 | return rc; | ||
1220 | else | ||
1221 | return count; | ||
1222 | } | ||
1223 | |||
1224 | static DEVICE_ATTR(last_known_reservation_state, 0644, | ||
1225 | dasd_reservation_state_show, dasd_reservation_state_store); | ||
1226 | |||
1130 | static struct attribute * dasd_attrs[] = { | 1227 | static struct attribute * dasd_attrs[] = { |
1131 | &dev_attr_readonly.attr, | 1228 | &dev_attr_readonly.attr, |
1132 | &dev_attr_discipline.attr, | 1229 | &dev_attr_discipline.attr, |
@@ -1139,6 +1236,8 @@ static struct attribute * dasd_attrs[] = { | |||
1139 | &dev_attr_erplog.attr, | 1236 | &dev_attr_erplog.attr, |
1140 | &dev_attr_failfast.attr, | 1237 | &dev_attr_failfast.attr, |
1141 | &dev_attr_expires.attr, | 1238 | &dev_attr_expires.attr, |
1239 | &dev_attr_reservation_policy.attr, | ||
1240 | &dev_attr_last_known_reservation_state.attr, | ||
1142 | NULL, | 1241 | NULL, |
1143 | }; | 1242 | }; |
1144 | 1243 | ||