diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2020-03-04 22:27:16 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2020-03-04 22:27:16 +0000 |
commit | 8cd9718f0b29edf380e35ac462773c26ab2a729c (patch) | |
tree | ce9cf895f3d884b29cd79aa1e3720e411cfdb255 /sbin/mount_nfs | |
parent | defa7daf890401a5a220bcf098571d336691ab5a (diff) | |
download | src-8cd9718f0b29edf380e35ac462773c26ab2a729c.tar.gz src-8cd9718f0b29edf380e35ac462773c26ab2a729c.zip |
Notes
Diffstat (limited to 'sbin/mount_nfs')
-rw-r--r-- | sbin/mount_nfs/mount_nfs.c | 62 |
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); |