[S390] dasd: automatic recognition of read-only devices
[safe/jmp/linux-2.6] / drivers / s390 / block / dasd.c
index 4951aa8..bbea90b 100644 (file)
@@ -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;