]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
SPARC64: Virtual Disk Device (vdsdev) Read-Only Option (options=ro) not working
authorGeorge Kennedy <george.kennedy@oracle.com>
Wed, 22 Mar 2017 17:39:32 +0000 (13:39 -0400)
committerChuck Anderson <chuck.anderson@oracle.com>
Mon, 24 Apr 2017 04:43:21 +0000 (21:43 -0700)
Add read-only (options=ro) support to virtual disk server (VDS).

Signed-off-by: George Kennedy <george.kennedy@oracle.com>
Reviewed-by: Alexandre Chartre <Alexandre.Chartre@oracle.com>
Orabug: 23623853
Signed-off-by: Allen Pais <allen.pais@oracle.com>
drivers/block/vds/vds.h
drivers/block/vds/vds_main.c

index 362c78ca3535dab7de03bf5abaf428092ecdd099..fb249c638a01edae4f138f208b6e0675ac69fc7c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vds.h: LDOM Virtual Disk Server.
  *
- * Copyright (C) 2014, 2015 Oracle. All rights reserved.
+ * Copyright (C) 2014, 2017 Oracle. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -62,6 +62,7 @@ struct vds_port {
 
 #define        VDS_PORT_SEQ            0x1
 #define        VDS_PORT_FINI           0x2
+#define        VDS_PORT_READ_ONLY      0x4
 
 static inline struct vds_port *to_vds_port(struct vio_driver_state *vio)
 {
index 9119864d20a5afa20869ef78fe72d1f020cfabe5..4d94471e858510b9ea258386787d627f51efb2fc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vds_main.c: LDOM Virtual Disk Server.
  *
- * Copyright (C) 2014, 2015 Oracle. All rights reserved.
+ * Copyright (C) 2014, 2017 Oracle. All rights reserved.
  */
 
 #include "vds.h"
@@ -82,6 +82,24 @@ static struct vio_version vds_versions[] = {
        { .major = 1, .minor = 0 },
 };
 
+struct vds_operation {
+       int operation;
+       int rw;
+       int (*function)(struct vds_io *);
+};
+
+static struct vds_operation vds_operations[] = {
+       { VD_OP_BREAD, READ, vd_op_rw },
+       { VD_OP_BWRITE, WRITE, vd_op_rw },
+       { VD_OP_GET_VTOC, READ, vd_op_get_vtoc },
+       { VD_OP_SET_VTOC, WRITE, vd_op_set_vtoc },
+       { VD_OP_GET_DISKGEOM, READ, vd_op_get_geom },
+       { VD_OP_SET_DISKGEOM, WRITE, vd_op_set_geom },
+       { VD_OP_GET_EFI, READ, vd_op_get_efi },
+       { VD_OP_SET_EFI, WRITE, vd_op_set_efi },
+       { VD_OP_FLUSH, WRITE, vd_op_flush }
+};
+
 static inline int vds_version_supp(struct vds_port *port, u16 major, u16 minor)
 {
        return port->vio.ver.major == major && port->vio.ver.minor >= minor;
@@ -392,7 +410,8 @@ static void vds_bh_io(struct work_struct *work)
        struct vds_io *io = container_of(work, struct vds_io, vds_work);
        struct vio_driver_state *vio = io->vio;
        struct vds_port *port = to_vds_port(vio);
-       int err;
+       struct vds_operation *op;
+       int err, i;
 
        BUG_ON(in_interrupt());
 
@@ -402,38 +421,22 @@ static void vds_bh_io(struct work_struct *work)
        io->ack = VIO_SUBTYPE_ACK;
        io->error = 0;
 
-       switch (io->desc->operation) {
-       case VD_OP_BREAD:
-               err = vd_op_rw(io);
-               break;
-       case VD_OP_BWRITE:
-               io->rw = WRITE;
-               err = vd_op_rw(io);
-               break;
-       case VD_OP_GET_VTOC:
-               err = vd_op_get_vtoc(io);
-               break;
-       case VD_OP_SET_VTOC:
-               err = vd_op_set_vtoc(io);
-               break;
-       case VD_OP_GET_DISKGEOM:
-               err = vd_op_get_geom(io);
-               break;
-       case VD_OP_SET_DISKGEOM:
-               err = vd_op_set_geom(io);
-               break;
-       case VD_OP_GET_EFI:
-               err = vd_op_get_efi(io);
-               break;
-       case VD_OP_SET_EFI:
-               err = vd_op_set_efi(io);
-               break;
-       case VD_OP_FLUSH:
-               err = vd_op_flush(io);
-               break;
-       default:
+       for (i = 0, op = NULL; i < ARRAY_SIZE(vds_operations); i++) {
+               if (io->desc->operation == vds_operations[i].operation) {
+                       op = &vds_operations[i];
+                       break;
+               }
+       }
+
+       if (op != NULL) {
+               if ((port->flags & VDS_PORT_READ_ONLY) && op->rw != READ) {
+                       err = -EROFS;
+               } else {
+                       io->rw = op->rw;
+                       err = (*op->function)(io);
+               }
+       } else {
                err = -ENOTSUPP;
-               break;
        }
 
        if (io->ack == VIO_SUBTYPE_ACK && err != 0 && io->error == 0)
@@ -490,7 +493,7 @@ static void vds_reset(struct vds_io *io)
        vds_vio_lock(vio, flags);
        vio_link_state_change(vio, LDC_EVENT_RESET);
 
-       port->flags = 0;
+       port->flags &= ~(VDS_PORT_FINI | VDS_PORT_SEQ);
        kfree(port->msgbuf);
        port->msglen = LDC_PACKET_SIZE;
        port->msgbuf = kzalloc(port->msglen, GFP_ATOMIC);
@@ -868,9 +871,9 @@ static int vds_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        struct mdesc_handle *hp;
        struct vds_port *port;
        struct vio_driver_state *vio;
-       const char *path;
+       const char *path, *prop;
        u64 node;
-       int err;
+       int err, len;
 
        print_version();
 
@@ -918,6 +921,19 @@ static int vds_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
                goto free_ldc;
        }
        port->path = kstrdup(path, GFP_KERNEL);
+       prop = mdesc_get_property(hp, node, "vds-block-device-opts", &len);
+       if (prop != NULL) {
+               while (len > 0) {
+                       if (strcmp(prop, "ro") == 0) {
+                               port->flags |= VDS_PORT_READ_ONLY;
+                               vdsdbg(IOC,
+                                   "%s is read-only\n", port->path);
+                               break;
+                       }
+                       len -= strlen(prop) + 1;
+                       prop += strlen(prop) + 1;
+               }
+       }
        mdesc_release(hp);
        vdsdbg(INIT, "path=%s\n", path);
        port->vtoc = kzalloc(roundup(sizeof(*port->vtoc), 8), GFP_KERNEL);