nbd: add FUA op support
authorShaun McDowell <shaunjmcdowell@gmail.com>
Fri, 26 May 2017 03:55:54 +0000 (23:55 -0400)
committerJens Axboe <axboe@fb.com>
Tue, 30 May 2017 14:20:25 +0000 (08:20 -0600)
NBD userland client and server have FUA (forced unit access) support
and flags defined. Make NBD kernel module recognize NBD_FLAG_SEND_FUA,
enable FUA on the queue, and forward FUA requests to the server.

Signed-off-by: Shaun McDowell <shaunjmcdowell@gmail.com>
Reviewed-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/block/nbd.c
include/uapi/linux/nbd.h

index 9a7bb2c2944772cad8124a965bacc17d0aa8f935..c5e52f66d3d44b2fdf4e3726d51870a7c7c49441 100644 (file)
@@ -400,6 +400,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
        unsigned long size = blk_rq_bytes(req);
        struct bio *bio;
        u32 type;
+       u32 nbd_cmd_flags = 0;
        u32 tag = blk_mq_unique_tag(req);
        int sent = nsock->sent, skip = 0;
 
@@ -429,6 +430,9 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
                return -EIO;
        }
 
+       if (req->cmd_flags & REQ_FUA)
+               nbd_cmd_flags |= NBD_CMD_FLAG_FUA;
+
        /* We did a partial send previously, and we at least sent the whole
         * request struct, so just go and send the rest of the pages in the
         * request.
@@ -442,7 +446,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
        }
        cmd->index = index;
        cmd->cookie = nsock->cookie;
-       request.type = htonl(type);
+       request.type = htonl(type | nbd_cmd_flags);
        if (type != NBD_CMD_FLUSH) {
                request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
                request.len = htonl(size);
@@ -965,8 +969,12 @@ static void nbd_parse_flags(struct nbd_device *nbd)
                set_disk_ro(nbd->disk, false);
        if (config->flags & NBD_FLAG_SEND_TRIM)
                queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
-       if (config->flags & NBD_FLAG_SEND_FLUSH)
-               blk_queue_write_cache(nbd->disk->queue, true, false);
+       if (config->flags & NBD_FLAG_SEND_FLUSH) {
+               if (config->flags & NBD_FLAG_SEND_FUA)
+                       blk_queue_write_cache(nbd->disk->queue, true, true);
+               else
+                       blk_queue_write_cache(nbd->disk->queue, true, false);
+       }
        else
                blk_queue_write_cache(nbd->disk->queue, false, false);
 }
@@ -1309,6 +1317,8 @@ static int nbd_dbg_flags_show(struct seq_file *s, void *unused)
                seq_puts(s, "NBD_FLAG_READ_ONLY\n");
        if (flags & NBD_FLAG_SEND_FLUSH)
                seq_puts(s, "NBD_FLAG_SEND_FLUSH\n");
+       if (flags & NBD_FLAG_SEND_FUA)
+               seq_puts(s, "NBD_FLAG_SEND_FUA\n");
        if (flags & NBD_FLAG_SEND_TRIM)
                seq_puts(s, "NBD_FLAG_SEND_TRIM\n");
 
index 155e33f819134a3aecdccf3c139974ef0c54c68c..a50527ebf671e010715d542f614331f7c49e4294 100644 (file)
@@ -41,10 +41,14 @@ enum {
 #define NBD_FLAG_HAS_FLAGS     (1 << 0) /* nbd-server supports flags */
 #define NBD_FLAG_READ_ONLY     (1 << 1) /* device is read-only */
 #define NBD_FLAG_SEND_FLUSH    (1 << 2) /* can flush writeback cache */
+#define NBD_FLAG_SEND_FUA      (1 << 3) /* send FUA (forced unit access) */
 /* there is a gap here to match userspace */
 #define NBD_FLAG_SEND_TRIM     (1 << 5) /* send trim/discard */
 #define NBD_FLAG_CAN_MULTI_CONN        (1 << 8)        /* Server supports multiple connections per export. */
 
+/* values for cmd flags in the upper 16 bits of request type */
+#define NBD_CMD_FLAG_FUA       (1 << 16) /* FUA (forced unit access) op */
+
 /* These are client behavior specific flags. */
 #define NBD_CFLAG_DESTROY_ON_DISCONNECT        (1 << 0) /* delete the nbd device on
                                                    disconnect. */