platform: add a new function nmp_utils_open_sysctl()
A race condition may happen when NetworkManager opens sysfs and udev renames interface name at the same time. Thomas Haller provides a new function [1] which can avoid the race condition when opening sysfs. This patch is a direct copy from [1]. [1] https://mail.gnome.org/archives/networkmanager-list/2016-December/msg00004.html Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
This commit is contained in:

committed by
Thomas Haller

parent
99e1e4d6a1
commit
713c74f6e4
@@ -31,6 +31,7 @@
|
||||
#include <linux/mii.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "nm-utils.h"
|
||||
#include "nm-setting-wired.h"
|
||||
@@ -47,6 +48,7 @@
|
||||
G_STMT_START { (pedata)->speed = (guint16) (speed); } G_STMT_END
|
||||
#endif
|
||||
|
||||
extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
|
||||
|
||||
static gboolean
|
||||
ethtool_get (const char *name, gpointer edata)
|
||||
@@ -623,3 +625,51 @@ nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
nmp_utils_open_sysctl(int ifindex, const char *ifname)
|
||||
{
|
||||
#define SYS_CLASS_NET "/sys/class/net/"
|
||||
char ifname_buf[IFNAMSIZ];
|
||||
guint try_count = 0;
|
||||
char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ + 1] = SYS_CLASS_NET;
|
||||
char fd_buf[256];
|
||||
int fd;
|
||||
int fd_ifindex;
|
||||
ssize_t nn;
|
||||
|
||||
while (++try_count < 4) {
|
||||
if (!ifname) {
|
||||
ifname = if_indextoname (ifindex, ifname_buf);
|
||||
if (!ifname)
|
||||
return -1;
|
||||
}
|
||||
|
||||
nm_utils_ifname_cpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], ifname);
|
||||
fd = open (sysdir, O_DIRECTORY);
|
||||
if (fd < 0)
|
||||
goto next;
|
||||
fd_ifindex = openat (fd, "ifindex", 0);
|
||||
if (fd_ifindex < 0) {
|
||||
close (fd);
|
||||
goto next;
|
||||
}
|
||||
/* read ifindex file, and compare it to @ifindex. If match, return fd. */
|
||||
nn = nm_utils_fd_read_loop (fd_ifindex, fd_buf, sizeof (fd_buf) - 1, FALSE);
|
||||
if (nn < 0) {
|
||||
close (fd);
|
||||
close (fd_ifindex);
|
||||
goto next;
|
||||
}
|
||||
fd_buf[sizeof (fd_buf) - 1] = '\0';
|
||||
|
||||
if (ifindex != _nm_utils_ascii_str_to_int64 (fd_buf, 10, 1, G_MAXINT, -1)) {
|
||||
close (fd);
|
||||
close (fd_ifindex);
|
||||
goto next;
|
||||
}
|
||||
return fd;
|
||||
next:
|
||||
ifname = NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@@ -61,4 +61,6 @@ NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource
|
||||
NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source) _nm_const;
|
||||
const char * nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len);
|
||||
|
||||
int nmp_utils_open_sysctl(int ifindex, const char *ifname);
|
||||
|
||||
#endif /* __NM_PLATFORM_UTILS_H__ */
|
||||
|
Reference in New Issue
Block a user