From patchwork Thu Oct 26 01:41:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hangbin Liu X-Patchwork-Id: 830426 X-Patchwork-Delegate: shemminger@vyatta.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jgSMpz8e"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yMqWY2ygZz9t3p for ; Thu, 26 Oct 2017 12:42:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752086AbdJZBm2 (ORCPT ); Wed, 25 Oct 2017 21:42:28 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:52384 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751902AbdJZBmZ (ORCPT ); Wed, 25 Oct 2017 21:42:25 -0400 Received: by mail-pf0-f194.google.com with SMTP id e64so1313094pfk.9 for ; Wed, 25 Oct 2017 18:42:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=PU+q6iL3YwQjKnHc0xJvJbl9RY/W25i3z+coCMfjfuw=; b=jgSMpz8e5qF+SWC95YglVdlRh38GtwiVx2F9L35iqxs1EY3Msg2V1AD7ed4JFpubfX 4QH8KA//k5NhYvs+yBbfjap0FFdj/jfOxz0KeDhTy9fFBirts9tTaIyckvteRsRDmwHw RZYfDzAAkVhf1VyEy0MMgyoXGIvSAF6TUoXHZ3mK54w/BBK0skYzoModNNhLqr6OLohi T5bV3nTlH4O48WE81/rgXWrnCY/KcXUUqNX3/xWIoMvncnrp45mpeBcLFj6Gp5GgFQb9 rmte/bZfIXDad1B5eaqwP22DOkwE+IsF8TRzthDe0ajdQezpedK6CMt4CTw5ADpYSopp bPfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=PU+q6iL3YwQjKnHc0xJvJbl9RY/W25i3z+coCMfjfuw=; b=jSn/0vhNURwLU1Pr0v3yYhIIYR8xIxMVx4Gnu5gPWFWcz9Yumfr8u5+uBqQj9iCyL3 +Pake2zVDggc/oqmluybkUIr1wGo66tMYifWCtQ2Se6cffqwQgu+UtB3IaN/KQip1xnQ /TLlNaj/U57ETTftVlm+RAVTSK1VAbAJExoi+sj+9jjIYyJ8hOnwPtk2Cz3i8tsdWjGx OSJEF52h7QBG1zlXO1l+BNrcAJGq05oDP9HGWgHwpnA69T69g8NoPqUzlXsd8+NroeoP LyuoTYI+f/BbWOxusUBmI2yI8sibVJ3VB4j6P0iJQpVw9PIIWJ33660kdfJ83QcT0WHv s74g== X-Gm-Message-State: AMCzsaU23cO2OOr+MgA5YHPHOM4mAcwGcVOcA0SQGjSSTgbzX/0QWbGu IXGndn37Gc54Ij/N/83GqdnqzYME X-Google-Smtp-Source: ABhQp+QfbfXWCWi6s5XA5ThasRiOgRrVsrGgOQfmgXIZ+Dd9tAjpAiKVOC4XvLvDeAuvmpNf6RqchQ== X-Received: by 10.101.67.137 with SMTP id m9mr3609623pgp.63.1508982144849; Wed, 25 Oct 2017 18:42:24 -0700 (PDT) Received: from leo.usersys.redhat.com ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id r22sm7263460pfl.15.2017.10.25.18.42.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Oct 2017 18:42:24 -0700 (PDT) From: Hangbin Liu To: netdev@vger.kernel.org Cc: Stephen Hemminger , Michal Kubecek , Phil Sutter , Hangbin Liu Subject: [PATCHv5 iproute2 net-next 2/2] lib/libnetlink: re malloc buff if size is not enough Date: Thu, 26 Oct 2017 09:41:46 +0800 Message-Id: <1508982107-28474-2-git-send-email-liuhangbin@gmail.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1508982107-28474-1-git-send-email-liuhangbin@gmail.com> References: <1508982107-28474-1-git-send-email-liuhangbin@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org With commit 72b365e8e0fd ("libnetlink: Double the dump buffer size") we doubled the buffer size to support more VFs. But the VFs number is increasing all the time. Some customers even use more than 200 VFs now. We could not double it everytime when the buffer is not enough. Let's just not hard code the buffer size and malloc the correct number when running. Introduce function rtnl_recvmsg() to always return a newly allocated buffer. The caller need to free it after using. Signed-off-by: Hangbin Liu Signed-off-by: Phil Sutter --- lib/libnetlink.c | 114 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/lib/libnetlink.c b/lib/libnetlink.c index be7ac86..1847c0b 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -402,6 +402,64 @@ static void rtnl_dump_error(const struct rtnl_handle *rth, } } +static int __rtnl_recvmsg(int fd, struct msghdr *msg, int flags) +{ + int len; + + do { + len = recvmsg(fd, msg, flags); + } while (len < 0 && (errno == EINTR || errno == EAGAIN)); + + if (len < 0) { + fprintf(stderr, "netlink receive error %s (%d)\n", + strerror(errno), errno); + return -errno; + } + + if (len == 0) { + fprintf(stderr, "EOF on netlink\n"); + return -ENODATA; + } + + return len; +} + +static int rtnl_recvmsg(int fd, struct msghdr *msg, char **answer) +{ + struct iovec *iov = msg->msg_iov; + char *buf; + int len; + + iov->iov_base = NULL; + iov->iov_len = 0; + + len = __rtnl_recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC); + if (len < 0) + return len; + + buf = malloc(len); + if (!buf) { + fprintf(stderr, "malloc error: not enough buffer\n"); + return -ENOMEM; + } + + iov->iov_base = buf; + iov->iov_len = len; + + len = __rtnl_recvmsg(fd, msg, 0); + if (len < 0) { + free(buf); + return len; + } + + if (answer) + *answer = buf; + else + free(buf); + + return len; +} + int rtnl_dump_filter_l(struct rtnl_handle *rth, const struct rtnl_dump_filter_arg *arg) { @@ -413,31 +471,18 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, .msg_iov = &iov, .msg_iovlen = 1, }; - char buf[32768]; + char *buf; int dump_intr = 0; - iov.iov_base = buf; while (1) { int status; const struct rtnl_dump_filter_arg *a; int found_done = 0; int msglen = 0; - iov.iov_len = sizeof(buf); - status = recvmsg(rth->fd, &msg, 0); - - if (status < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - fprintf(stderr, "netlink receive error %s (%d)\n", - strerror(errno), errno); - return -1; - } - - if (status == 0) { - fprintf(stderr, "EOF on netlink\n"); - return -1; - } + status = rtnl_recvmsg(rth->fd, &msg, &buf); + if (status < 0) + return status; if (rth->dump_fp) fwrite(buf, 1, NLMSG_ALIGN(status), rth->dump_fp); @@ -462,8 +507,10 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, if (h->nlmsg_type == NLMSG_DONE) { err = rtnl_dump_done(h); - if (err < 0) + if (err < 0) { + free(buf); return -1; + } found_done = 1; break; /* process next filter */ @@ -471,19 +518,23 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, if (h->nlmsg_type == NLMSG_ERROR) { rtnl_dump_error(rth, h); + free(buf); return -1; } if (!rth->dump_fp) { err = a->filter(&nladdr, h, a->arg1); - if (err < 0) + if (err < 0) { + free(buf); return err; + } } skip_it: h = NLMSG_NEXT(h, msglen); } } + free(buf); if (found_done) { if (dump_intr) @@ -543,7 +594,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, .msg_iov = &iov, .msg_iovlen = 1, }; - char buf[32768] = {}; + char *buf; n->nlmsg_seq = seq = ++rtnl->seq; @@ -556,22 +607,12 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, return -1; } - iov.iov_base = buf; while (1) { - iov.iov_len = sizeof(buf); - status = recvmsg(rtnl->fd, &msg, 0); + status = rtnl_recvmsg(rtnl->fd, &msg, &buf); + + if (status < 0) + return status; - if (status < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - fprintf(stderr, "netlink receive error %s (%d)\n", - strerror(errno), errno); - return -1; - } - if (status == 0) { - fprintf(stderr, "EOF on netlink\n"); - return -1; - } if (msg.msg_namelen != sizeof(nladdr)) { fprintf(stderr, "sender address length == %d\n", @@ -585,6 +626,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, if (l < 0 || len > status) { if (msg.msg_flags & MSG_TRUNC) { fprintf(stderr, "Truncated message\n"); + free(buf); return -1; } fprintf(stderr, @@ -611,6 +653,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, if (answer) memcpy(answer, h, MIN(maxlen, h->nlmsg_len)); + free(buf); return 0; } @@ -619,12 +662,14 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, rtnl_talk_error(h, err, errfn); errno = -err->error; + free(buf); return -1; } if (answer) { memcpy(answer, h, MIN(maxlen, h->nlmsg_len)); + free(buf); return 0; } @@ -633,6 +678,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, status -= NLMSG_ALIGN(len); h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); } + free(buf); if (msg.msg_flags & MSG_TRUNC) { fprintf(stderr, "Message truncated\n");