Drivers: hv: allocate the exact needed memory for messages
authorVitaly Kuznetsov <vkuznets@redhat.com>
Mon, 6 Apr 2020 10:41:51 +0000 (12:41 +0200)
committerWei Liu <wei.liu@kernel.org>
Thu, 23 Apr 2020 13:17:10 +0000 (13:17 +0000)
When we need to pass a buffer with Hyper-V message we don't need to always
allocate 256 bytes for the message: the real message length is known from
the header. Change 'struct onmessage_work_context' to make it possible to
not over-allocate.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/20200406104154.45010-3-vkuznets@redhat.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
drivers/hv/vmbus_drv.c

index 183a5b0..e356ea4 100644 (file)
@@ -1019,7 +1019,10 @@ static struct bus_type  hv_bus = {
 
 struct onmessage_work_context {
        struct work_struct work;
-       struct hv_message msg;
+       struct {
+               struct hv_message_header header;
+               u8 payload[];
+       } msg;
 };
 
 static void vmbus_onmessage_work(struct work_struct *work)
@@ -1072,7 +1075,8 @@ void vmbus_on_msg_dpc(unsigned long data)
                goto msg_handled;
 
        if (entry->handler_type == VMHT_BLOCKING) {
-               ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+               ctx = kmalloc(sizeof(*ctx) + msg->header.payload_size,
+                             GFP_ATOMIC);
                if (ctx == NULL)
                        return;
 
@@ -1126,10 +1130,11 @@ static void vmbus_force_channel_rescinded(struct vmbus_channel *channel)
        WARN_ON(!is_hvsock_channel(channel));
 
        /*
-        * sizeof(*ctx) is small and the allocation should really not fail,
+        * Allocation size is small and the allocation should really not fail,
         * otherwise the state of the hv_sock connections ends up in limbo.
         */
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | __GFP_NOFAIL);
+       ctx = kzalloc(sizeof(*ctx) + sizeof(*rescind),
+                     GFP_KERNEL | __GFP_NOFAIL);
 
        /*
         * So far, these are not really used by Linux. Just set them to the
@@ -1139,7 +1144,7 @@ static void vmbus_force_channel_rescinded(struct vmbus_channel *channel)
        ctx->msg.header.payload_size = sizeof(*rescind);
 
        /* These values are actually used by Linux. */
-       rescind = (struct vmbus_channel_rescind_offer *)ctx->msg.u.payload;
+       rescind = (struct vmbus_channel_rescind_offer *)ctx->msg.payload;
        rescind->header.msgtype = CHANNELMSG_RESCIND_CHANNELOFFER;
        rescind->child_relid = channel->offermsg.child_relid;