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