]>
Commit | Line | Data |
---|---|---|
74cc6069 | 1 | diff -Nurp autofs-4.1.4.orig/modules/mount_nfs.c autofs-4.1.4/modules/mount_nfs.c |
2 | --- autofs-4.1.4.orig/modules/mount_nfs.c 2005-04-25 10:55:27.000000000 +0800 | |
3 | +++ autofs-4.1.4/modules/mount_nfs.c 2005-04-25 10:56:15.000000000 +0800 | |
4 | @@ -31,6 +31,7 @@ | |
5 | #include <netinet/in.h> | |
6 | #include <linux/nfs.h> | |
7 | #include <linux/nfs2.h> | |
8 | +#include <ctype.h> | |
9 | ||
10 | #define MODULE_MOUNT | |
11 | #include "automount.h" | |
12 | @@ -105,28 +106,117 @@ int is_local_addr(const char *host, cons | |
13 | ||
14 | return 1; | |
15 | } | |
16 | + | |
17 | +/* | |
18 | + * If the entry doesn't contain a ',' or doesn't contain more than | |
19 | + * one ':' then @what is not a replicated server entry. | |
20 | + */ | |
21 | +static int inline is_replicated_entry(char *what) | |
22 | +{ | |
23 | + return strchr(what, ',') || | |
24 | + (strchr(what, ':') != strrchr(what, ':')); | |
25 | +} | |
26 | + | |
27 | +/* | |
28 | + * Check to see if the 'host:path' or 'host' is on the local machine | |
29 | + * Returns < 0 if there is a host lookup problem, otherwise returns 0 | |
30 | + * if it's not a local mount, and returns > 0 if it is a local mount. | |
31 | + */ | |
32 | +int is_local_mount(const char *hostpath) | |
33 | +{ | |
34 | + struct hostent *he; | |
35 | + char **haddr; | |
36 | + char *delim; | |
37 | + char *hostname; | |
38 | + int hostnamelen; | |
39 | + int local = 0; | |
40 | + | |
41 | + debug(MODPREFIX "is_local_mount: %s", hostpath); | |
42 | + delim = strpbrk(hostpath,":"); | |
43 | + | |
44 | + if (delim) | |
45 | + hostnamelen = delim - hostpath; | |
46 | + else | |
47 | + hostnamelen = strlen(hostpath); | |
48 | + | |
49 | + hostname = malloc(hostnamelen+1); | |
50 | + strncpy(hostname, hostpath, hostnamelen); | |
51 | + hostname[hostnamelen] = '\0'; | |
52 | + he = gethostbyname(hostname); | |
53 | + if (!he) { | |
54 | + error(MODPREFIX "host %s: lookup failure", hostname); | |
55 | + return -1; | |
56 | + } | |
57 | + | |
58 | + for (haddr = he->h_addr_list; *haddr; haddr++) { | |
59 | + local = is_local_addr(hostname, *haddr, he->h_length); | |
60 | + if (local < 0) | |
61 | + return local; | |
62 | + if (local) { | |
63 | + debug(MODPREFIX "host %s: is localhost", | |
64 | + hostname); | |
65 | + return local; | |
66 | + } | |
67 | + } | |
68 | + return 0; | |
69 | +} | |
70 | + | |
71 | /* | |
72 | * Given a mount string, return (in the same string) the | |
73 | - * best mount to use based on weight/locality/rpctime | |
74 | + * best mount to use based on locality/weight/rpctime. | |
75 | + * | |
76 | + * If longtimeout is set to 0 then we only do 100 ms pings to hosts. In | |
77 | + * the event that this fails, we call ourself recursively with the | |
78 | + * longtimeout option set to 1. In this case we ping for up to 10s and | |
79 | + * skip logic for detecting if a localhost has been passed. (if a local | |
80 | + * host had been passed, we would have returned that mount as the best | |
81 | + * mount. The skipping of local maps in this case is an optimization). | |
82 | + * | |
83 | * - return -1 and what = '\0' on error, | |
84 | * 1 and what = local mount path if local bind, | |
85 | * else 0 and what = remote mount path | |
86 | */ | |
87 | -int get_best_mount(char *what, const char *original, int longtimeout, int skiplocal) | |
88 | +int get_best_mount(char *what, const char *original, int longtimeout) | |
89 | { | |
90 | char *p = what; | |
91 | char *winner = NULL; | |
92 | int winner_weight = INT_MAX, local = 0; | |
93 | double winner_time = 0; | |
94 | - char *delim; | |
95 | + char *delim, *pstrip; | |
96 | int sec = (longtimeout) ? 10 : 0; | |
97 | int micros = (longtimeout) ? 0 : 100000; | |
98 | + int skiplocal = longtimeout; /* clearly local is not available */ | |
99 | ||
100 | if (!p) { | |
101 | *what = '\0'; | |
102 | return -1; | |
103 | } | |
104 | ||
105 | + /* | |
106 | + * If only one mountpoint has been passed in, we don't need to | |
107 | + * do anything except strip whitespace from the end of the string. | |
108 | + */ | |
109 | + if (!is_replicated_entry(p)) { | |
110 | + for (pstrip = p+strlen(p) - 1; pstrip >= p; pstrip--) | |
111 | + if (isspace(*pstrip)) | |
112 | + *pstrip = '\0'; | |
113 | + | |
114 | + /* Check if the host is the localhost */ | |
115 | + if (is_local_mount(p) > 0) { | |
116 | + debug(MODPREFIX "host %s: is localhost", p); | |
117 | + | |
118 | + /* Strip off hostname and ':' */ | |
119 | + delim = strchr(p,':'); | |
120 | + while (delim && *delim != '\0') { | |
121 | + delim++; | |
122 | + *what = *delim; | |
123 | + what++; | |
124 | + } | |
125 | + return 1; | |
126 | + } | |
127 | + return 0; | |
128 | + } | |
129 | + | |
130 | while (p && *p) { | |
131 | char *next; | |
132 | unsigned int ping_stat = 0; | |
133 | @@ -171,37 +261,17 @@ int get_best_mount(char *what, const cha | |
134 | /* p points to a server, "next is our next parse point */ | |
135 | if (!skiplocal) { | |
136 | /* Check if it's localhost */ | |
137 | - struct hostent *he; | |
138 | - char **haddr; | |
139 | - | |
140 | - he = gethostbyname(p); | |
141 | - if (!he) { | |
142 | - error(MODPREFIX "host %s: lookup failure", p); | |
143 | - p = next; | |
144 | - continue; | |
145 | - } | |
146 | - | |
147 | - /* Check each host in round robin list */ | |
148 | - for (haddr = he->h_addr_list; *haddr; haddr++) { | |
149 | - local = is_local_addr(p, *haddr, he->h_length); | |
150 | - | |
151 | - if (local < 0) | |
152 | - continue; | |
153 | - | |
154 | - if (local) { | |
155 | - winner = p; | |
156 | - break; | |
157 | - } | |
158 | - } | |
159 | - | |
160 | + local = is_local_mount(p); | |
161 | if (local < 0) { | |
162 | local = 0; | |
163 | p = next; | |
164 | continue; | |
165 | } | |
166 | ||
167 | - if (local) | |
168 | + if (local) { | |
169 | + winner = p; | |
170 | break; | |
171 | + } | |
172 | } | |
173 | ||
174 | /* ping each (or the) entry to see if it's alive. */ | |
175 | @@ -214,6 +284,7 @@ int get_best_mount(char *what, const cha | |
176 | /* First unweighted or only host is alive so set winner */ | |
177 | if (!winner) { | |
178 | winner = p; | |
179 | + winner_time = 1; | |
180 | /* No more to check, return it */ | |
181 | if (!next || !*next) | |
182 | break; | |
183 | @@ -256,7 +327,7 @@ int get_best_mount(char *what, const cha | |
184 | */ | |
185 | if (!local && winner_weight == INT_MAX) { | |
186 | /* We had more than one contender and none responded in time */ | |
187 | - if (winner_time != 0 && winner_time > 500) { | |
188 | + if (winner_time == 0 || winner_time > 500) { | |
189 | /* We've already tried a longer timeout */ | |
190 | if (!longtimeout) { | |
191 | /* Reset string and try again */ | |
192 | @@ -267,16 +338,14 @@ int get_best_mount(char *what, const cha | |
193 | "retrying with longer timeout", | |
194 | original); | |
195 | ||
196 | - return get_best_mount(what, original, 1, 1); | |
197 | + return get_best_mount(what, original, 1); | |
198 | } | |
199 | } | |
200 | } | |
201 | ||
202 | - /* No winner found so bail */ | |
203 | - if (!winner) { | |
204 | - *what = '\0'; | |
205 | - return 0; | |
206 | - } | |
207 | + /* No winner found so return first */ | |
208 | + if (!winner) | |
209 | + winner = what; | |
210 | ||
211 | /* | |
212 | * We now have our winner, copy it to the front of the string, | |
213 | @@ -395,7 +464,7 @@ int mount_mount(const char *root, const | |
214 | /* No colon, take this as a bind (local) entry */ | |
215 | local = 1; | |
216 | } else if (!nosymlink) { | |
217 | - local = get_best_mount(whatstr, what, 0, 0); | |
218 | + local = get_best_mount(whatstr, what, 0); | |
219 | if (!*whatstr) { | |
220 | warn(MODPREFIX "no host elected"); | |
221 | return 1; |