101
static int alloc_ifreq(struct ifconf *ifc, int sock)
103
int ret, lastlen = ifc_last_len, len = ifc_buf_len;
104
char err_buf[MAX_ERR_BUF], *buf;
109
char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
110
logerr("malloc: %s", estr);
115
ifc->ifc_req = (struct ifreq *) buf;
117
ret = ioctl(sock, SIOCGIFCONF, ifc);
119
char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
120
logerr("ioctl: %s", estr);
125
if (ifc->ifc_len <= lastlen)
128
lastlen = ifc->ifc_len;
133
if (lastlen != ifc_last_len) {
134
ifc_last_len = lastlen;
98
141
static unsigned int get_proximity(const char *host_addr, int addr_len)
100
143
struct sockaddr_in *msk_addr, *if_addr;
122
165
fcntl(sock, F_SETFD, cl_flags);
125
ifc.ifc_len = sizeof(buf);
126
ifc.ifc_req = (struct ifreq *) buf;
127
ret = ioctl(sock, SIOCGIFCONF, &ifc);
129
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
130
logerr("ioctl: %s", estr);
168
if (!alloc_ifreq(&ifc, sock)) {
132
170
return PROXIMITY_ERROR;
139
177
ptr = (char *) &ifc.ifc_buf[0];
141
while (ptr < buf + ifc.ifc_len) {
179
while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
142
180
ifr = (struct ifreq *) ptr;
144
182
switch (ifr->ifr_addr.sa_family) {
163
202
ptr = (char *) &ifc.ifc_buf[0];
165
while (ptr < buf + ifc.ifc_len) {
204
while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
166
205
ifr = (struct ifreq *) ptr;
168
207
switch (ifr->ifr_addr.sa_family) {
225
268
return PROXIMITY_OTHER;
228
static struct host *new_host(const char *name, const char *addr, unsigned int proximity, unsigned int weight)
271
static struct host *new_host(const char *name,
272
const char *addr, size_t addr_len,
273
unsigned int proximity, unsigned int weight)
230
275
struct host *new;
231
276
char *tmp1, *tmp2;
400
447
double taken = 0;
401
448
int status, count = 0;
451
"called for host %s proto %s version 0x%x",
452
host->name, proto, version);
403
454
memset(&parms, 0, sizeof(struct pmap));
405
456
parms.pm_prog = NFS_PROGRAM;
424
475
status = rpc_ping_proto(rpc_info);
425
476
gettimeofday(&end, &tz);
427
if (random_selection)
479
if (random_selection) {
428
480
/* Random value between 0 and 1 */
429
taken += ((float) random())/((float) RAND_MAX+1);
431
taken += elapsed(start, end);;
481
reply = ((float) random())/((float) RAND_MAX+1);
483
"nfs v4 random selection time: %f", reply);
485
reply = elapsed(start, end);
486
debug(logopt, "nfs v4 rpc ping time: %f", reply);
433
490
supported = NFS4_SUPPORTED;
438
495
if (!have_port_opt) {
439
496
status = rpc_portmap_getclient(pm_info,
440
host->name, proto, RPC_CLOSE_DEFAULT);
497
host->name, host->addr, host->addr_len,
498
proto, RPC_CLOSE_DEFAULT);
465
523
status = rpc_ping_proto(rpc_info);
466
524
gettimeofday(&end, &tz);
468
if (random_selection)
527
if (random_selection) {
469
528
/* Random value between 0 and 1 */
470
taken += ((float) random())/((float) RAND_MAX+1);
472
taken += elapsed(start, end);;
529
reply = ((float) random())/((float) RAND_MAX+1);
531
"nfs v3 random selection time: %f", reply);
533
reply = elapsed(start, end);
534
debug(logopt, "nfs v3 rpc ping time: %f", reply);
474
538
supported |= NFS3_SUPPORTED;
499
563
status = rpc_ping_proto(rpc_info);
500
564
gettimeofday(&end, &tz);
502
if (random_selection)
567
if (random_selection) {
503
568
/* Random value between 0 and 1 */
504
taken += ((float) random())/((float) RAND_MAX+1);
506
taken += elapsed(start, end);;
569
reply = ((float) random())/((float) RAND_MAX+1);
571
"nfs v2 random selection time: %f", reply);
573
reply = elapsed(start, end);;
574
debug(logopt, "nfs v2 rpc ping time: %f", reply);
508
578
supported |= NFS2_SUPPORTED;
528
598
/* Allow for user bias */
529
599
if (host->weight)
530
600
host->cost *= (host->weight + 1);
602
debug(logopt, "host %s cost %ld weight %d",
603
host->name, host->cost, host->weight);
533
606
return supported;
548
621
if (host->proximity == PROXIMITY_NET)
549
622
timeout = RPC_TIMEOUT * 2;
550
else if (host->proximity == PROXIMITY_NET)
623
else if (host->proximity == PROXIMITY_OTHER)
551
624
timeout = RPC_TIMEOUT * 8;
553
626
rpc_info.host = host->name;
627
rpc_info.addr = host->addr;
628
rpc_info.addr_len = host->addr_len;
554
629
rpc_info.program = NFS_PROGRAM;
555
630
rpc_info.timeout.tv_sec = timeout;
556
631
rpc_info.close_option = RPC_CLOSE_DEFAULT;
596
671
time_t timeout = RPC_TIMEOUT;
675
"called with host %s version 0x%x", host->name, version);
599
677
memset(&pm_info, 0, sizeof(struct conn_info));
600
678
memset(&rpc_info, 0, sizeof(struct conn_info));
601
679
memset(&parms, 0, sizeof(struct pmap));
603
681
if (host->proximity == PROXIMITY_NET)
604
682
timeout = RPC_TIMEOUT * 2;
605
else if (host->proximity == PROXIMITY_NET)
683
else if (host->proximity == PROXIMITY_OTHER)
606
684
timeout = RPC_TIMEOUT * 8;
608
686
rpc_info.host = host->name;
687
rpc_info.addr = host->addr;
688
rpc_info.addr_len = host->addr_len;
609
689
rpc_info.program = NFS_PROGRAM;
610
690
rpc_info.timeout.tv_sec = timeout;
611
691
rpc_info.close_option = RPC_CLOSE_DEFAULT;
654
734
int ret = rpc_portmap_getclient(&pm_info,
655
host->name, proto, RPC_CLOSE_DEFAULT);
735
host->name, host->addr, host->addr_len,
736
proto, RPC_CLOSE_DEFAULT);
671
752
status = rpc_ping_proto(&rpc_info);
672
753
gettimeofday(&end, &tz);
674
if (random_selection)
755
if (random_selection) {
675
756
/* Random value between 0 and 1 */
676
757
taken = ((float) random())/((float) RAND_MAX+1);
758
debug(logopt, "random selection time %f", taken);
678
760
taken = elapsed(start, end);
761
debug(logopt, "rpc ping time %f", taken);
848
* The list of hosts that aren't proximity local may now
849
* be empty if we haven't been able probe any so we need
850
* to check again for a list containing only proximity
763
858
/* Select NFS version of highest number of closest servers */
792
887
max_udp_count = mmax(v4_udp_count, v3_udp_count, v2_udp_count);
793
888
max_count = max(max_tcp_count, max_udp_count);
795
if (max_count == v4_tcp_count)
890
if (max_count == v4_tcp_count) {
796
891
selected_version = NFS4_TCP_SUPPORTED;
797
else if (max_count == v3_tcp_count)
893
"selected subset of hosts that support NFS4 over TCP");
894
} else if (max_count == v3_tcp_count) {
798
895
selected_version = NFS3_TCP_SUPPORTED;
799
else if (max_count == v2_tcp_count)
897
"selected subset of hosts that support NFS3 over TCP");
898
} else if (max_count == v2_tcp_count) {
800
899
selected_version = NFS2_TCP_SUPPORTED;
801
else if (max_count == v4_udp_count)
901
"selected subset of hosts that support NFS2 over TCP");
902
} else if (max_count == v4_udp_count) {
802
903
selected_version = NFS4_UDP_SUPPORTED;
803
else if (max_count == v3_udp_count)
905
"selected subset of hosts that support NFS4 over UDP");
906
} else if (max_count == v3_udp_count) {
804
907
selected_version = NFS3_UDP_SUPPORTED;
805
else if (max_count == v2_udp_count)
909
"selected subset of hosts that support NFS3 over UDP");
910
} else if (max_count == v2_udp_count) {
806
911
selected_version = NFS2_UDP_SUPPORTED;
913
"selected subset of hosts that support NFS2 over UDP");
808
916
/* Add local and hosts with selected version to new list */
868
976
if (prx == PROXIMITY_ERROR)
871
if (!(new = new_host(host, thost, prx, weight)))
979
if (!(new = new_host(host, thost, sizeof(saddr.sin_addr), prx, weight)))
874
982
if (!add_host(list, new))
893
1001
for (haddr = phe->h_addr_list; *haddr; haddr++) {
894
1004
prx = get_proximity(*haddr, phe->h_length);
895
1005
if (prx == PROXIMITY_ERROR)
898
if (!(new = new_host(host, *haddr, prx, weight)))
1008
memcpy(&tt, *haddr, sizeof(struct in_addr));
1009
if (!(new = new_host(host, *haddr, phe->h_length, prx, weight)))
901
1012
if (!add_host(list, new)) {