05bba0
From 8f412efbb8bb57fde0f924a7ad084f1c536c4a0b Mon Sep 17 00:00:00 2001
05bba0
From: Fam Zheng <famz@redhat.com>
05bba0
Date: Tue, 20 Jan 2015 03:42:13 +0100
05bba0
Subject: [PATCH 06/16] iscsi: Refuse to open as writable if the LUN is write
05bba0
 protected
05bba0
05bba0
Message-id: <1421725333-27072-1-git-send-email-famz@redhat.com>
05bba0
Patchwork-id: 63370
05bba0
O-Subject: [RHEL-7.2 qemu-kvm PATCH v2] iscsi: Refuse to open as writable if the LUN is write protected
05bba0
Bugzilla: 1032412
05bba0
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
05bba0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
05bba0
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
05bba0
05bba0
Before, when a write protected iSCSI target is attached as scsi-disk
05bba0
with BDRV_O_RDWR, we report it as writable, while in fact all writes
05bba0
will fail.
05bba0
05bba0
One way to improve this is to report write protect flag as true to
05bba0
guest, but a even better way is to refuse using a write protected LUN to
05bba0
guest.
05bba0
05bba0
Target write protect flag is checked with a mode sense query.
05bba0
05bba0
Signed-off-by: Fam Zheng <famz@redhat.com>
05bba0
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
05bba0
(cherry picked from commit c1d4096b0f033d0a52c542f0948403783c3682e9)
05bba0
Signed-off-by: Fam Zheng <famz@redhat.com>
05bba0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
05bba0
05bba0
Conflicts:
05bba0
	block/iscsi.c
05bba0
05bba0
Trivial context conflict: AioContext attach/detach functions are not
05bba0
present in downstream.
05bba0
---
05bba0
 block/iscsi.c | 43 +++++++++++++++++++++++++++++++++++++++++++
05bba0
 1 file changed, 43 insertions(+)
05bba0
05bba0
diff --git a/block/iscsi.c b/block/iscsi.c
05bba0
index 4f42f29..3d61dd7 100644
05bba0
--- a/block/iscsi.c
05bba0
+++ b/block/iscsi.c
05bba0
@@ -1290,6 +1290,41 @@ fail:
05bba0
     return NULL;
05bba0
 }
05bba0
 
05bba0
+
05bba0
+static bool iscsi_is_write_protected(IscsiLun *iscsilun)
05bba0
+{
05bba0
+    struct scsi_task *task;
05bba0
+    struct scsi_mode_sense *ms = NULL;
05bba0
+    bool wrprotected = false;
05bba0
+
05bba0
+    task = iscsi_modesense6_sync(iscsilun->iscsi, iscsilun->lun,
05bba0
+                                 1, SCSI_MODESENSE_PC_CURRENT,
05bba0
+                                 0x3F, 0, 255);
05bba0
+    if (task == NULL) {
05bba0
+        error_report("iSCSI: Failed to send MODE_SENSE(6) command: %s",
05bba0
+                     iscsi_get_error(iscsilun->iscsi));
05bba0
+        goto out;
05bba0
+    }
05bba0
+
05bba0
+    if (task->status != SCSI_STATUS_GOOD) {
05bba0
+        error_report("iSCSI: Failed MODE_SENSE(6), LUN assumed writable");
05bba0
+        goto out;
05bba0
+    }
05bba0
+    ms = scsi_datain_unmarshall(task);
05bba0
+    if (!ms) {
05bba0
+        error_report("iSCSI: Failed to unmarshall MODE_SENSE(6) data: %s",
05bba0
+                     iscsi_get_error(iscsilun->iscsi));
05bba0
+        goto out;
05bba0
+    }
05bba0
+    wrprotected = ms->device_specific_parameter & 0x80;
05bba0
+
05bba0
+out:
05bba0
+    if (task) {
05bba0
+        scsi_free_scsi_task(task);
05bba0
+    }
05bba0
+    return wrprotected;
05bba0
+}
05bba0
+
05bba0
 /*
05bba0
  * We support iscsi url's on the form
05bba0
  * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
05bba0
@@ -1405,6 +1440,14 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
05bba0
     scsi_free_scsi_task(task);
05bba0
     task = NULL;
05bba0
 
05bba0
+    /* Check the write protect flag of the LUN if we want to write */
05bba0
+    if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
05bba0
+        iscsi_is_write_protected(iscsilun)) {
05bba0
+        error_setg(errp, "Cannot open a write protected LUN as read-write");
05bba0
+        ret = -EACCES;
05bba0
+        goto out;
05bba0
+    }
05bba0
+
05bba0
     iscsi_readcapacity_sync(iscsilun, &local_err);
05bba0
     if (local_err != NULL) {
05bba0
         error_propagate(errp, local_err);
05bba0
-- 
05bba0
1.8.3.1
05bba0