You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
6.0 KiB
252 lines
6.0 KiB
From 49e7c0e7c8c9a982fd3aa69bbed4e306a1dcb331 Mon Sep 17 00:00:00 2001 |
|
From: Hangbin Liu <haliu@redhat.com> |
|
Date: Wed, 8 Nov 2017 14:39:12 +0800 |
|
Subject: [PATCH] lib/libnetlink: re malloc buff if size is not enough |
|
|
|
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1380803 |
|
Upstream Status: iproute2.git net-next commit 2d34851cd341 |
|
|
|
commit 2d34851cd341f0e1b3fc17ca3e6e874229f3a1f8 |
|
Author: Hangbin Liu <liuhangbin@gmail.com> |
|
Date: Thu Oct 26 09:41:46 2017 +0800 |
|
|
|
lib/libnetlink: re malloc buff if size is not enough |
|
|
|
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 <liuhangbin@gmail.com> |
|
Signed-off-by: Phil Sutter <phil@nwl.cc> |
|
|
|
Signed-off-by: Hangbin Liu <haliu@redhat.com> |
|
--- |
|
lib/libnetlink.c | 114 ++++++++++++++++++++++++++++++++++++++----------------- |
|
1 file changed, 80 insertions(+), 34 deletions(-) |
|
|
|
diff --git a/lib/libnetlink.c b/lib/libnetlink.c |
|
index a057831..446c960 100644 |
|
--- a/lib/libnetlink.c |
|
+++ b/lib/libnetlink.c |
|
@@ -386,6 +386,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) |
|
{ |
|
@@ -397,31 +455,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); |
|
@@ -446,8 +491,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 */ |
|
@@ -455,19 +502,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) |
|
@@ -527,7 +578,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; |
|
|
|
@@ -540,22 +591,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", |
|
@@ -569,6 +610,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, |
|
@@ -595,6 +637,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; |
|
} |
|
|
|
@@ -603,12 +646,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; |
|
} |
|
|
|
@@ -617,6 +662,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"); |
|
-- |
|
1.8.3.1 |
|
|
|
|