aboutsummaryrefslogtreecommitdiff
path: root/sbin/mount_nfs
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2020-03-04 22:27:16 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2020-03-04 22:27:16 +0000
commit8cd9718f0b29edf380e35ac462773c26ab2a729c (patch)
treece9cf895f3d884b29cd79aa1e3720e411cfdb255 /sbin/mount_nfs
parentdefa7daf890401a5a220bcf098571d336691ab5a (diff)
downloadsrc-8cd9718f0b29edf380e35ac462773c26ab2a729c.tar.gz
src-8cd9718f0b29edf380e35ac462773c26ab2a729c.zip
Notes
Diffstat (limited to 'sbin/mount_nfs')
-rw-r--r--sbin/mount_nfs/mount_nfs.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c
index 1c15f505d8ec..8d8ddac62224 100644
--- a/sbin/mount_nfs/mount_nfs.c
+++ b/sbin/mount_nfs/mount_nfs.c
@@ -65,6 +65,8 @@ __FBSDID("$FreeBSD$");
#include <fs/nfs/nfsv4_errstr.h>
#include <arpa/inet.h>
+#include <net/route.h>
+#include <net/if.h>
#include <ctype.h>
#include <err.h>
@@ -505,6 +507,59 @@ sec_num_to_name(int flavor)
return (NULL);
}
+/*
+ * Wait for RTM_IFINFO message with interface that is IFF_UP and with
+ * link on, or until timeout expires. Returns seconds left.
+ */
+static time_t
+rtm_ifinfo_sleep(time_t sec)
+{
+ char buf[2048];
+ fd_set rfds;
+ struct timeval tv, start;
+ ssize_t nread;
+ int n, s;
+
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s < 0)
+ err(EX_OSERR, "socket");
+ (void)gettimeofday(&start, NULL);
+
+ for (tv.tv_sec = sec, tv.tv_usec = 0;
+ tv.tv_sec > 0;
+ (void)gettimeofday(&tv, NULL),
+ tv.tv_sec = sec - (tv.tv_sec - start.tv_sec)) {
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+ n = select(s + 1, &rfds, NULL, NULL, &tv);
+ if (n == 0)
+ continue;
+ if (n == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ err(EX_SOFTWARE, "select");
+ }
+ nread = read(s, buf, 2048);
+ if (nread < 0)
+ err(EX_OSERR, "read");
+ if ((size_t)nread >= sizeof(struct if_msghdr)) {
+ struct if_msghdr *ifm;
+
+ ifm = (struct if_msghdr *)buf;
+ if (ifm->ifm_version == RTM_VERSION &&
+ ifm->ifm_type == RTM_IFINFO &&
+ (ifm->ifm_flags & IFF_UP) &&
+ ifm->ifm_data.ifi_link_state != LINK_STATE_DOWN)
+ break;
+ }
+ }
+
+ close(s);
+
+ return (tv.tv_sec);
+}
+
static int
getnfsargs(char *spec, struct iovec **iov, int *iovlen)
{
@@ -638,7 +693,12 @@ getnfsargs(char *spec, struct iovec **iov, int *iovlen)
if (daemon(0, 0) != 0)
err(1, "daemon");
}
- sleep(60);
+ /*
+ * If rtm_ifinfo_sleep() returns non-zero, don't count
+ * that as a retry attempt.
+ */
+ if (rtm_ifinfo_sleep(60) && retrycnt != 0)
+ retrycnt++;
}
freeaddrinfo(ai_nfs);