]> git.proxmox.com Git - mirror_qemu.git/blobdiff - nbd/server.c
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20180309a' into...
[mirror_qemu.git] / nbd / server.c
index 78b08f589130d11dc66f1a4a42a12e70e481ca0e..e714bfe6a1755021fbc6a2a21faa0b9d8579f162 100644 (file)
@@ -137,43 +137,29 @@ static void nbd_client_receive_next_request(NBDClient *client);
 
 */
 
+static inline void set_be_option_rep(NBDOptionReply *rep, uint32_t option,
+                                     uint32_t type, uint32_t length)
+{
+    stq_be_p(&rep->magic, NBD_REP_MAGIC);
+    stl_be_p(&rep->option, option);
+    stl_be_p(&rep->type, type);
+    stl_be_p(&rep->length, length);
+}
+
 /* Send a reply header, including length, but no payload.
  * Return -errno on error, 0 on success. */
 static int nbd_negotiate_send_rep_len(NBDClient *client, uint32_t type,
                                       uint32_t len, Error **errp)
 {
-    uint64_t magic;
-    QIOChannel *ioc = client->ioc;
-    uint32_t opt = client->opt;
+    NBDOptionReply rep;
 
-    trace_nbd_negotiate_send_rep_len(opt, nbd_opt_lookup(opt),
+    trace_nbd_negotiate_send_rep_len(client->opt, nbd_opt_lookup(client->opt),
                                      type, nbd_rep_lookup(type), len);
 
     assert(len < NBD_MAX_BUFFER_SIZE);
-    magic = cpu_to_be64(NBD_REP_MAGIC);
-    if (nbd_write(ioc, &magic, sizeof(magic), errp) < 0) {
-        error_prepend(errp, "write failed (rep magic): ");
-        return -EINVAL;
-    }
-
-    opt = cpu_to_be32(opt);
-    if (nbd_write(ioc, &opt, sizeof(opt), errp) < 0) {
-        error_prepend(errp, "write failed (rep opt): ");
-        return -EINVAL;
-    }
-
-    type = cpu_to_be32(type);
-    if (nbd_write(ioc, &type, sizeof(type), errp) < 0) {
-        error_prepend(errp, "write failed (rep type): ");
-        return -EINVAL;
-    }
 
-    len = cpu_to_be32(len);
-    if (nbd_write(ioc, &len, sizeof(len), errp) < 0) {
-        error_prepend(errp, "write failed (rep data length): ");
-        return -EINVAL;
-    }
-    return 0;
+    set_be_option_rep(&rep, client->opt, type, len);
+    return nbd_write(client->ioc, &rep, sizeof(rep), errp);
 }
 
 /* Send a reply header with default 0 length.
@@ -613,6 +599,7 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
     qio_channel_tls_handshake(tioc,
                               nbd_tls_handshake,
                               &data,
+                              NULL,
                               NULL);
 
     if (!data.complete) {
@@ -820,7 +807,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
 
             default:
                 ret = nbd_opt_drop(client, NBD_REP_ERR_UNSUP, errp,
-                                   "Unsupported option 0x%" PRIx32 " (%s)",
+                                   "Unsupported option %" PRIu32 " (%s)",
                                    option, nbd_opt_lookup(option));
                 break;
             }
@@ -836,7 +823,7 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
                                                         errp);
 
             default:
-                error_setg(errp, "Unsupported option 0x%" PRIx32 " (%s)",
+                error_setg(errp, "Unsupported option %" PRIu32 " (%s)",
                            option, nbd_opt_lookup(option));
                 return -EINVAL;
             }
@@ -1191,6 +1178,19 @@ void nbd_export_close(NBDExport *exp)
     nbd_export_put(exp);
 }
 
+void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp)
+{
+    if (mode == NBD_SERVER_REMOVE_MODE_HARD || QTAILQ_EMPTY(&exp->clients)) {
+        nbd_export_close(exp);
+        return;
+    }
+
+    assert(mode == NBD_SERVER_REMOVE_MODE_SAFE);
+
+    error_setg(errp, "export '%s' still in use", exp->name);
+    error_append_hint(errp, "Use mode='hard' to force client disconnect\n");
+}
+
 void nbd_export_get(NBDExport *exp)
 {
     assert(exp->refcount > 0);