Print this page
5910 libnisdb won't build with modern GCC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnisdb/yptol/lock_update.c
+++ new/usr/src/lib/libnisdb/yptol/lock_update.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 + * Copyright 2015 Gary Mills
23 24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 25 * Use is subject to license terms.
25 26 */
26 27
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 28 /*
30 29 * DESCRIPTION: Contains code supporting the 'update in progress' flag. This is
31 30 * a near copy of lock flag code (in
32 31 * usr/src/cmd/ypcmd/shared/lockmp.c) If we implement a clean
33 32 * version of the locking code this file will probably disappear.
34 33 *
35 34 * These locks are held while a map is being updated from the
36 35 * DIT. They prevent a second update being started while this is
37 36 * in progress. This is independant from the `lockmap` mechanism
38 37 * which protects maps, generally for a much shorter period,
39 38 * while their control structures are modified.
40 39 */
41 40
42 41 #include <unistd.h>
43 42 #include <syslog.h>
44 43 #include <sys/mman.h>
45 44 #include <thread.h>
46 45 #include <synch.h>
47 46 #include <ndbm.h>
48 47 #include <strings.h>
49 48 #include "ypsym.h"
50 49 #include "shim.h"
51 50 #include "yptol.h"
52 51 #include "../ldap_util.h"
53 52
54 53 #define LOCKFILE "/var/run/yp_mapupdate"
55 54 struct updatearray {
56 55 mutex_t updatenode[MAXHASH];
57 56 };
58 57 typedef struct updatearray updatearray;
59 58
60 59 /*
61 60 * Cross-process robust mutex locks.
62 61 * Provide synchronization between YP processes
63 62 * by implementing an exclusive locking mechanism
64 63 * via a memory-mapped file.
65 64 */
66 65 static struct updatearray *shmupdatearray;
67 66 static int lockfile;
68 67
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
69 68 bool_t
70 69 init_update_locks_mem()
71 70 {
72 71 int iiter, rc;
73 72 int ebusy_cnt = 0;
74 73
75 74 /*
76 75 * Initialize cross-process locks in memory-mapped file.
77 76 */
78 77 for (iiter = 0; iiter < MAXHASH; iiter++) {
79 - if (rc = mutex_init(&(shmupdatearray->updatenode[iiter]),
80 - USYNC_PROCESS | LOCK_ROBUST, 0)) {
78 + if ((rc = mutex_init(&(shmupdatearray->updatenode[iiter]),
79 + USYNC_PROCESS | LOCK_ROBUST, 0)) != 0) {
81 80 if (rc == EBUSY) {
82 81 ebusy_cnt++;
83 82 } else {
84 83 logmsg(MSG_NOTIMECHECK, LOG_ERR,
85 84 "init_update_locks_mem():mutex_init():"
86 85 "error=%d", rc);
87 86 return (FALSE);
88 87 }
89 88 }
90 89 }
91 90
92 91 /*
93 92 * EBUSY for all locks OK, it means another process
94 93 * has already initialized locks.
95 94 */
96 95 if ((ebusy_cnt > 0) && (ebusy_cnt != MAXHASH)) {
97 96 logmsg(MSG_NOTIMECHECK, LOG_ERR,
98 97 "%s inconsistent. Remove this file and restart NIS (YP)",
99 98 LOCKFILE);
100 99 return (FALSE);
101 100 }
102 101 return (TRUE);
103 102 }
104 103
105 104 bool_t
106 105 init_update_lock_map()
107 106 {
108 107 char buff[ sizeof (updatearray) ];
109 108 int write_cnt, lf_size;
110 109 struct stat fdata;
111 110
112 111 /*
113 112 * Locking file initialization algorithm, with recovery mechanism.
114 113 * This mechanism has been devised to ensure proper creation
115 114 * of a memory-mapped lock file containing mutexes for robust,
116 115 * inter-process communication.
117 116 * File name is /var/run/yp_mapupate (LOCKFILE). It might or might
118 117 * not exist.
119 118 *
120 119 * Algorithm:
121 120 * Try to open the file. If file doesn't exist, or size is too small,
122 121 * create/rewrite the file, m-map it into memory and initialize the
123 122 * mutexes in it.
124 123 * If file exists and size is at least large enough, assume it's a
125 124 * good file, and m-map the lock structure directly to it.
126 125 *
127 126 * Recovery from inconsistent state is easy - simply delete the file
128 127 * and restart NIS (YP).
129 128 */
130 129
131 130 lockfile = open(LOCKFILE, O_RDWR|O_CREAT, 0600);
132 131 if (lockfile != -1) {
133 132 if (lockf(lockfile, F_LOCK, 0) == 0) {
134 133 if (fstat(lockfile, &fdata) == 0) {
135 134 lf_size = fdata.st_size;
136 135 if (lf_size < sizeof (updatearray)) {
137 136 bzero(buff, sizeof (buff));
138 137 if ((write_cnt = write(lockfile, buff,
139 138 sizeof (buff)) != sizeof (buff))) {
140 139 if (write_cnt < 0) {
141 140 logmsg(MSG_NOTIMECHECK,
142 141 LOG_ERR,
143 142 "write(%s) => errno=%d",
144 143 LOCKFILE, errno);
145 144 } else {
146 145 logmsg(MSG_NOTIMECHECK,
147 146 LOG_ERR,
148 147 "write(%s) => %d!=%d: wrong number of bytes written",
149 148 LOCKFILE,
150 149 write_cnt,
151 150 sizeof (buff));
152 151 }
153 152 lockf(lockfile, F_ULOCK, 0);
154 153 close(lockfile);
155 154 return (FALSE);
156 155 }
157 156 }
158 157 } else {
159 158 logmsg(MSG_NOTIMECHECK, LOG_ERR,
160 159 "fstat(%s) => errno=%d", LOCKFILE, errno);
161 160 lockf(lockfile, F_ULOCK, 0);
162 161 close(lockfile);
163 162 return (FALSE);
164 163 }
165 164 } else {
166 165 logmsg(MSG_NOTIMECHECK, LOG_ERR,
167 166 "lockf(%s,F_LOCK) => errno=%d", LOCKFILE, errno);
168 167 close(lockfile);
169 168 return (FALSE);
170 169 }
171 170 } else {
172 171 logmsg(MSG_NOTIMECHECK, LOG_ERR,
173 172 "open(%s) => errno=%d", LOCKFILE, errno);
174 173 return (FALSE);
175 174 }
176 175
177 176 /*
178 177 * File exists with correct size, is open, and we're holding
179 178 * the file lock.
180 179 */
181 180 shmupdatearray = (updatearray *)mmap((caddr_t)0, sizeof (updatearray),
182 181 PROT_READ | PROT_WRITE, MAP_SHARED, lockfile, 0);
183 182 if (shmupdatearray == MAP_FAILED) {
184 183 logmsg(MSG_NOTIMECHECK, LOG_ERR,
185 184 "mmap(%s) => errno=%d", LOCKFILE, errno);
186 185 lockf(lockfile, F_ULOCK, 0);
187 186 close(lockfile);
188 187 return (FALSE);
189 188 }
190 189
191 190 /*
192 191 * If we wrote zeroes to the file, we also need to initialize
193 192 * the mutex locks.
194 193 */
195 194 if (lf_size < sizeof (updatearray)) {
196 195 if (init_update_locks_mem() == FALSE) {
197 196 lockf(lockfile, F_ULOCK, 0);
198 197 close(lockfile);
199 198 if (remove(LOCKFILE) != 0) {
200 199 logmsg(MSG_NOTIMECHECK, LOG_ERR,
201 200 "remove(%s) => errno=%d: Please delete file",
202 201 LOCKFILE, errno);
203 202 }
204 203 return (FALSE);
205 204 }
206 205 }
207 206
208 207 if (lockf(lockfile, F_ULOCK, 0) != 0) {
209 208 logmsg(MSG_NOTIMECHECK, LOG_ERR,
210 209 "lockf(%s,F_ULOCK) => errno=%d", LOCKFILE, errno);
211 210 close(lockfile);
212 211 return (FALSE);
213 212 }
214 213
215 214 if (close(lockfile) == 0) {
216 215 return (TRUE);
217 216 } else {
218 217 logmsg(MSG_NOTIMECHECK, LOG_ERR,
219 218 "close(%s) => errno=%d", LOCKFILE, errno);
220 219 return (FALSE);
221 220 }
222 221 }
223 222
224 223 suc_code
225 224 lock_map_update(map_ctrl *map)
226 225 {
227 226 int hashval = map->hash_val;
228 227 int rc;
229 228
230 229 /*
231 230 * Robust, cross-process lock implementation
232 231 */
233 232 rc = mutex_lock(&(shmupdatearray->updatenode[hashval]));
234 233 while (rc != 0) {
235 234 switch (rc) {
236 235 case EOWNERDEAD:
237 236 /*
238 237 * Previous lock owner died, resetting lock
239 238 * to recover from error.
240 239 */
241 240 rc = mutex_consistent(
242 241 &(shmupdatearray->updatenode[hashval]));
243 242 if (rc != 0) {
244 243 logmsg(MSG_NOTIMECHECK, LOG_ERR,
245 244 "mutex_consistent(): error=%d", rc);
246 245 return (FAILURE);
247 246 }
248 247 rc = mutex_unlock(
249 248 &(shmupdatearray->updatenode[hashval]));
250 249 if (rc != 0) {
251 250 logmsg(MSG_NOTIMECHECK, LOG_ERR,
252 251 "mutex_unlock(): error=%d", rc);
253 252 return (FAILURE);
254 253 }
255 254 break;
256 255 default:
257 256 /*
258 257 * Unrecoverable problem - nothing to do
259 258 * but exit YP and delete lock file.
260 259 */
261 260 logmsg(MSG_NOTIMECHECK, LOG_ERR,
262 261 "mutex_lock(): error=%d", rc);
263 262 logmsg(MSG_NOTIMECHECK, LOG_ERR,
264 263 "Please restart NIS (ypstop/ypstart)");
265 264 if (remove(LOCKFILE) != 0) {
266 265 logmsg(MSG_NOTIMECHECK, LOG_ERR,
267 266 "remove(%s) => errno=%d: Please delete file",
268 267 LOCKFILE, errno);
269 268 }
270 269 return (FAILURE);
271 270 }
272 271 rc = mutex_lock(&(shmupdatearray->updatenode[hashval]));
273 272 }
274 273
275 274 /* Success */
276 275 return (SUCCESS);
277 276 }
278 277
279 278
280 279 suc_code
281 280 unlock_map_update(map_ctrl *map)
282 281 {
283 282 int hashval = map->hash_val;
284 283 int rc;
285 284
286 285 rc = mutex_unlock(&(shmupdatearray->updatenode[hashval]));
287 286 if (rc != 0) {
288 287 logmsg(MSG_NOTIMECHECK, LOG_ERR,
289 288 "mutex_unlock(): error=%d", rc);
290 289 logmsg(MSG_NOTIMECHECK, LOG_ERR,
291 290 "Please restart NIS (ypstop/ypstart)");
292 291 if (remove(LOCKFILE) != 0) {
293 292 logmsg(MSG_NOTIMECHECK, LOG_ERR,
294 293 "remove(%s) => errno=%d: Please delete file",
295 294 LOCKFILE, errno);
296 295 }
297 296 return (FAILURE);
298 297 }
299 298
300 299 /* Success */
301 300 return (SUCCESS);
302 301 }
303 302
304 303 /*
305 304 * FUNCTION : is_map_updating()
306 305 *
307 306 * DESCRIPTION: Determines if a map is currently locked for update
308 307 *
309 308 * GIVEN : Pointer to map_ctrl structure
310 309 *
311 310 * RETURNS : TRUE = Map is locked
312 311 * FALSE = Map is not locked
313 312 */
314 313 bool_t
315 314 is_map_updating(map_ctrl *map)
316 315 {
317 316 int ret;
318 317
319 318 /* It appears not to be possible to just read a mutex. Try to lock it */
320 319 ret = mutex_trylock(&(shmupdatearray->updatenode[map->hash_val]));
321 320
322 321 if (0 != ret) {
323 322 /* Didn't get the lock ... was already locked */
324 323 return (TRUE);
325 324 }
326 325
327 326 /* Didn't need the lock so free it again */
328 327 mutex_unlock(&(shmupdatearray->updatenode[map->hash_val]));
329 328 return (FALSE);
330 329 }
331 330
332 331 /*
333 332 * FUNCTION : try_lock_map_update()
334 333 *
335 334 * DESCRIPTION: Tries to to lock a map for update.
336 335 *
337 336 * GIVEN : Pointer to the map to lock
338 337 *
339 338 * RETURNS : 0 = The map is now locked
340 339 * EBUSY = The map was already locked lock not obtained.
341 340 * Other = There was an error
342 341 */
343 342 int
344 343 try_lock_map_update(map_ctrl *map)
345 344 {
346 345 int hashval = map->hash_val;
347 346 int rc;
348 347
349 348 /*
350 349 * Robust, cross-process lock implementation
351 350 *
352 351 * Keep trying until either lock is obtained or somebody else gets it.
353 352 */
354 353 while (1) {
355 354 rc = mutex_trylock(&(shmupdatearray->updatenode[hashval]));
356 355
357 356 switch (rc) {
358 357
359 358 case 0:
360 359 case EBUSY:
361 360 /* Either got it or somebody else has it */
362 361 return (rc);
363 362
364 363 case EOWNERDEAD:
365 364 /*
366 365 * Previous lock owner died, resetting lock
367 366 * to recover from error.
368 367 */
369 368 rc = mutex_consistent(
370 369 &(shmupdatearray->updatenode[hashval]));
371 370 if (rc != 0) {
372 371 logmsg(MSG_NOTIMECHECK, LOG_ERR,
373 372 "mutex_consistent(): error=%d", rc);
374 373 return (rc);
375 374 }
376 375 rc = mutex_unlock(
377 376 &(shmupdatearray->updatenode[hashval]));
378 377 if (rc != 0) {
379 378 logmsg(MSG_NOTIMECHECK, LOG_ERR,
380 379 "mutex_unlock(): error=%d", rc);
381 380 return (rc);
382 381 }
383 382 break;
384 383 default:
385 384 /*
386 385 * Unrecoverable problem - nothing to do
387 386 * but exit YP and delete lock file.
388 387 */
389 388 logmsg(MSG_NOTIMECHECK, LOG_ERR,
390 389 "mutex_lock(): error=%d", rc);
391 390 logmsg(MSG_NOTIMECHECK, LOG_ERR,
392 391 "Please restart NIS (ypstop/ypstart)");
393 392 if (remove(LOCKFILE) != 0) {
394 393 logmsg(MSG_NOTIMECHECK, LOG_ERR,
395 394 "remove(%s) => errno=%d: Please delete file",
396 395 LOCKFILE, errno);
397 396 }
398 397 return (rc);
399 398 }
400 399 }
401 400 }
↓ open down ↓ |
311 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX