hammer2 / kern_dmsg - Fix bugs
authorMatthew Dillon <dillon@apollo.backplane.com>
Sat, 28 Feb 2015 16:13:49 +0000 (08:13 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sat, 28 Feb 2015 16:13:49 +0000 (08:13 -0800)
* Fix header size limt check.

* Do not free the message data out from under a running I/O.
  Introduce an API for detaching aux_data from a msg.

* Increase DMSG_AUX_MAX to 1MB to ensure that xdisk (remote disks)
  work with any filesystem.

  Theoretically we can break up READ and WRITE messages into pieces
  in order to allow DMSG_AUX_MAX to be made smaller (which is easier
  to manage in-kernel), but for now the implementation just uses a
  single message transaction.

* Adjust some comments.

sys/kern/kern_dmsg.c
sys/kern/subr_diskiocom.c
sys/sys/dmsg.h
sys/vfs/hammer2/hammer2_cluster.c
sys/vfs/hammer2/hammer2_vfsops.c

index dd94fbe..51ca941 100644 (file)
@@ -293,7 +293,7 @@ kdmsg_iocom_thread_rd(void *arg)
                        break;
                }
                hbytes = (hdr.cmd & DMSGF_SIZE) * DMSG_ALIGN;
-               if (hbytes < sizeof(hdr) || hbytes > DMSG_AUX_MAX) {
+               if (hbytes < sizeof(hdr) || hbytes > DMSG_HDR_MAX) {
                        kprintf("kdmsg: bad header size %zd\n", hbytes);
                        error = EINVAL;
                        break;
@@ -1497,6 +1497,28 @@ kdmsg_msg_free(kdmsg_msg_t *msg)
        kfree(msg, iocom->mmsg);
 }
 
+void
+kdmsg_detach_aux_data(kdmsg_msg_t *msg, kdmsg_data_t *data)
+{
+       if (msg->flags & KDMSG_FLAG_AUXALLOC) {
+               data->aux_data = msg->aux_data;
+               data->aux_size = msg->aux_size;
+               data->iocom = msg->state->iocom;
+               msg->flags &= ~KDMSG_FLAG_AUXALLOC;
+       } else {
+               data->aux_data = NULL;
+               data->aux_size = 0;
+               data->iocom = msg->state->iocom;
+       }
+}
+
+void
+kdmsg_free_aux_data(kdmsg_data_t *data)
+{
+       if (data->aux_data)
+               kfree(data->aux_data, data->iocom->mmsg);
+}
+
 /*
  * Indexed messages are stored in a red-black tree indexed by their
  * msgid.  Only persistent messages are indexed.
index 448e84a..3cc5ee4 100644 (file)
@@ -67,6 +67,7 @@ struct dios_open {
 struct dios_io {
        int     count;
        int     eof;
+       kdmsg_data_t data;
 };
 
 static MALLOC_DEFINE(M_DMSG_DISK, "dmsg_disk", "disk dmsg");
@@ -417,10 +418,12 @@ disk_blk_write(struct disk *dp, kdmsg_msg_t *msg)
                bp->b_resid = bp->b_bcount;
                if (msg->aux_size >= msg->any.blk_write.bytes) {
                        bp->b_data = msg->aux_data;
+                       kdmsg_detach_aux_data(msg, &iost->data);
                } else {
                        bcopy(msg->aux_data, bp->b_data, msg->aux_size);
                        bzero(bp->b_data + msg->aux_size,
                              msg->any.blk_write.bytes - msg->aux_size);
+                       bzero(&iost->data, sizeof(iost->data));
                }
                bio->bio_offset = msg->any.blk_write.offset;
                bio->bio_caller_info1.ptr = msg->state;
@@ -578,6 +581,7 @@ diskiodone(struct bio *bio)
                        error = 0;
                        resid = bp->b_resid;
                }
+               kdmsg_free_aux_data(&iost->data);
                break;
        case BUF_CMD_FLUSH:
        case BUF_CMD_FREEBLKS:
index c18af20..f7f2a41 100644 (file)
@@ -229,9 +229,17 @@ typedef struct dmsg_hdr dmsg_hdr_t;
 
 /*
  * Administrative protocol limits.
+ *
+ * NOTE: A dmsg header must completely fit in the (fifo) buffer, but
+ *      dmsg aux data does not have to completely fit.  The dmsg
+ *      structure allows headers up to 255*64 = 16320 bytes.  There
+ *      is no real limit on the aux_data other than what we deem
+ *      reasonable and defenseable (i.e. not run processes or the
+ *      kernel out of memory).  But it should be able to handle at
+ *      least MAXPHYS bytes which is typically 128KB or 256KB.
  */
-#define DMSG_HDR_MAX           2048    /* <= 65535 */
-#define DMSG_AUX_MAX           65536   /* <= 1MB */
+#define DMSG_HDR_MAX           2048            /* <= 8192 */
+#define DMSG_AUX_MAX           (1024*1024)     /* <= 1MB */
 #define DMSG_BUF_SIZE          (DMSG_HDR_MAX * 4)
 #define DMSG_BUF_MASK          (DMSG_BUF_SIZE - 1)
 
@@ -692,6 +700,7 @@ struct xa_softc;
 struct kdmsg_iocom;
 struct kdmsg_state;
 struct kdmsg_msg;
+struct kdmsg_data;
 
 /*
  * msg_ctl flags (atomic)
@@ -748,11 +757,18 @@ struct kdmsg_msg {
        dmsg_any_t      any;                    /* variable sized */
 };
 
+struct kdmsg_data {
+       char            *aux_data;
+       size_t          aux_size;
+       struct kdmsg_iocom *iocom;
+};
+
 #define KDMSG_FLAG_AUXALLOC    0x0001
 
 typedef struct kdmsg_link kdmsg_link_t;
 typedef struct kdmsg_state kdmsg_state_t;
 typedef struct kdmsg_msg kdmsg_msg_t;
+typedef struct kdmsg_data kdmsg_data_t;
 
 struct kdmsg_state_tree;
 int kdmsg_state_cmp(kdmsg_state_t *state1, kdmsg_state_t *state2);
@@ -823,6 +839,8 @@ void kdmsg_msg_reply(kdmsg_msg_t *msg, uint32_t error);
 void kdmsg_msg_result(kdmsg_msg_t *msg, uint32_t error);
 void kdmsg_state_reply(kdmsg_state_t *state, uint32_t error);
 void kdmsg_state_result(kdmsg_state_t *state, uint32_t error);
+void kdmsg_detach_aux_data(kdmsg_msg_t *msg, kdmsg_data_t *data);
+void kdmsg_free_aux_data(kdmsg_data_t *data);
 
 #endif
 
index 9d25a24..5a0c6f5 100644 (file)
@@ -1269,7 +1269,7 @@ hammer2_cluster_load_async(hammer2_cluster_t *cluster,
  *
  * Each resynchronization pass virtually snapshots the PFS on the good nodes
  * and synchronizes using that snapshot against the target node.  This
- * ensures a consistent chain topology and also avoid interference between
+ * ensures a consistent chain topology and also avoids interference between
  * the resynchronization thread and frontend operations.
  *
  * Since these are per-node threads it is possible to resynchronize several
index 80072c4..3b7cd2f 100644 (file)
@@ -656,9 +656,7 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
                 *
                 * Automatic LNK_CONN
                 * Automatic handling of received LNK_SPAN
-                * Automatic handling of received LNK_CIRC
                 * No automatic LNK_SPAN generation - we do this ourselves
-                * No automatic LNK_CIRC generation - we do this ourselves
                 */
                kdmsg_iocom_init(&hmp->iocom, hmp,
                                 KDMSG_IOCOMF_AUTOCONN |