|
@@ -26,6 +26,7 @@
|
|
|
#include <asm/ebcdic.h>
|
|
|
#include <asm/idals.h>
|
|
|
#include <asm/itcw.h>
|
|
|
+#include <asm/diag.h>
|
|
|
|
|
|
/* This is ugly... */
|
|
|
#define PRINTK_HEADER "dasd:"
|
|
@@ -2212,6 +2213,13 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ if ((mode & FMODE_WRITE) &&
|
|
|
+ (test_bit(DASD_FLAG_DEVICE_RO, &base->flags) ||
|
|
|
+ (base->features & DASD_FEATURE_READONLY))) {
|
|
|
+ rc = -EROFS;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
out:
|
|
@@ -2289,6 +2297,34 @@ dasd_exit(void)
|
|
|
* SECTION: common functions for ccw_driver use
|
|
|
*/
|
|
|
|
|
|
+/*
|
|
|
+ * Is the device read-only?
|
|
|
+ * Note that this function does not report the setting of the
|
|
|
+ * readonly device attribute, but how it is configured in z/VM.
|
|
|
+ */
|
|
|
+int dasd_device_is_ro(struct dasd_device *device)
|
|
|
+{
|
|
|
+ struct ccw_dev_id dev_id;
|
|
|
+ struct diag210 diag_data;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (!MACHINE_IS_VM)
|
|
|
+ return 0;
|
|
|
+ ccw_device_get_id(device->cdev, &dev_id);
|
|
|
+ memset(&diag_data, 0, sizeof(diag_data));
|
|
|
+ diag_data.vrdcdvno = dev_id.devno;
|
|
|
+ diag_data.vrdclen = sizeof(diag_data);
|
|
|
+ rc = diag210(&diag_data);
|
|
|
+ if (rc == 0 || rc == 2) {
|
|
|
+ return diag_data.vrdcvfla & 0x80;
|
|
|
+ } else {
|
|
|
+ DBF_EVENT(DBF_WARNING, "diag210 failed for dev=%04x with rc=%d",
|
|
|
+ dev_id.devno, rc);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(dasd_device_is_ro);
|
|
|
+
|
|
|
static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
|
|
|
{
|
|
|
struct ccw_device *cdev = data;
|