Print this page
5253 kmem_alloc/kmem_zalloc won't fail with KM_SLEEP
5254 getrbuf won't fail with KM_SLEEP
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/avs/ns/rdc/rdc_bitmap.c
+++ new/usr/src/uts/common/avs/ns/rdc/rdc_bitmap.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 *
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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/ksynch.h>
28 28 #include <sys/cmn_err.h>
29 29 #include <sys/kmem.h>
30 30 #include <sys/stat.h>
31 31 #include <sys/errno.h>
32 32
33 33 #include "../solaris/nsc_thread.h"
34 34 #ifdef DS_DDICT
35 35 #include "../contract.h"
36 36 #endif
37 37 #include <sys/nsctl/nsctl.h>
38 38
39 39 #include <sys/kmem.h>
40 40 #include <sys/cmn_err.h>
41 41 #include <sys/ddi.h>
42 42
43 43 #include "rdc_io.h"
44 44 #include "rdc_bitmap.h"
45 45 #include "rdc_clnt.h"
46 46 #include "rdc_diskq.h"
47 47
48 48 #include <sys/unistat/spcs_s.h>
49 49 #include <sys/unistat/spcs_s_k.h>
50 50 #include <sys/unistat/spcs_errors.h>
51 51
52 52 #ifndef UINT8_MAX
53 53 #define UINT8_MAX 255
54 54 #endif
55 55
56 56 #ifndef UINT_MAX
57 57 #define UINT_MAX 0xffffffff
58 58 #endif
59 59
60 60 /*
61 61 * RDC bitmap functions.
62 62 */
63 63
64 64 /*
65 65 * RDC cluster integration notes.
66 66 *
67 67 * 1. Configuration
68 68 *
69 69 * 1.1. Change 'rdc_bitmap_mode' in /usr/kernel/drv/rdc.conf to '1'.
70 70 *
71 71 * 2. Operation
72 72 *
73 73 * 2.1. SunCluster ensures that only one physical host has any rdc
74 74 * controlled device imported at any one time. Hence rdc will
75 75 * only be active on a single node for any set at a time.
76 76 *
77 77 * 2.2. So operation from the kernel perspective looks just like
78 78 * operation on a single, standalone, node.
79 79 *
80 80 */
81 81
82 82 struct rdc_bitmap_ops *rdc_bitmap_ops; /* the bitmap ops switch */
83 83 static int rdc_wrflag; /* write flag for io */
84 84 int rdc_bitmap_delay = 0;
85 85 extern nsc_io_t *_rdc_io_hc;
86 86
87 87 int rdc_suspend_diskq(rdc_k_info_t *krdc);
88 88
89 89 /*
90 90 * rdc_ns_io
91 91 * Perform read or write on an underlying ns device
92 92 *
93 93 * fd - nsc file descriptor
94 94 * flag - nsc io direction and characteristics flag
95 95 * fba_pos - offset from beginning of device in FBAs
96 96 * io_addr - pointer to data buffer
97 97 * io_len - length of io in bytes
98 98 */
99 99
100 100 int
101 101 rdc_ns_io(nsc_fd_t *fd, int flag, nsc_off_t fba_pos, uchar_t *io_addr,
102 102 nsc_size_t io_len)
103 103 {
104 104 nsc_buf_t *tmp;
105 105 nsc_vec_t *vecp;
106 106 uchar_t *vaddr;
107 107 size_t copy_len;
108 108 int vlen;
109 109 int rc;
110 110 nsc_size_t fba_req, fba_len;
111 111 nsc_size_t maxfbas = 0;
112 112 nsc_size_t tocopy;
113 113 unsigned char *toaddr;
114 114
115 115 rc = nsc_maxfbas(fd, 0, &maxfbas);
116 116 if (!RDC_SUCCESS(rc)) {
117 117 #ifdef DEBUG
118 118 cmn_err(CE_WARN, "!rdc_ns_io: maxfbas failed (%d)", rc);
119 119 #endif
120 120 maxfbas = 256;
121 121 }
122 122 toaddr = io_addr;
123 123 fba_req = FBA_LEN(io_len);
124 124 loop:
125 125 tmp = NULL;
126 126 fba_len = min(fba_req, maxfbas);
127 127 tocopy = min(io_len, FBA_SIZE(fba_len));
128 128 ASSERT(tocopy < INT32_MAX);
129 129
130 130 rc = nsc_alloc_buf(fd, fba_pos, fba_len, flag, &tmp);
131 131 if (!RDC_SUCCESS(rc)) {
132 132 if (tmp) {
133 133 (void) nsc_free_buf(tmp);
134 134 }
135 135 return (EIO);
136 136 }
137 137
138 138 if ((flag & NSC_WRITE) != 0 && (flag & NSC_READ) == 0 &&
139 139 FBA_OFF(io_len) != 0) {
140 140 /*
141 141 * Not overwriting all of the last FBA, so read in the
142 142 * old contents now before we overwrite it with the new
143 143 * data.
144 144 */
145 145 rc = nsc_read(tmp, fba_pos+FBA_NUM(io_len), 1, 0);
146 146 if (!RDC_SUCCESS(rc)) {
147 147 (void) nsc_free_buf(tmp);
148 148 return (EIO);
149 149 }
150 150 }
151 151
152 152 vecp = tmp->sb_vec;
153 153 vlen = vecp->sv_len;
154 154 vaddr = vecp->sv_addr;
155 155
156 156 while (tocopy > 0) {
157 157 if (vecp->sv_addr == 0 || vecp->sv_len == 0) {
158 158 #ifdef DEBUG
159 159 cmn_err(CE_WARN, "!rdc_ns_io: ran off end of handle");
160 160 #endif
161 161 break;
162 162 }
163 163
164 164 copy_len = (size_t)min(vlen, (int)tocopy);
165 165
166 166 if (flag & NSC_WRITE)
167 167 bcopy(toaddr, vaddr, copy_len);
168 168 else
169 169 bcopy(vaddr, toaddr, copy_len);
170 170
171 171 toaddr += copy_len;
172 172 io_addr += copy_len; /* adjust position in callers buffer */
173 173 io_len -= copy_len; /* adjust total byte length remaining */
174 174 tocopy -= copy_len; /* adjust chunk byte length remaining */
175 175 vaddr += copy_len; /* adjust location in sv_vec_t */
176 176 vlen -= copy_len; /* adjust length left in sv_vec_t */
177 177
178 178 if (vlen <= 0) {
179 179 vecp++;
180 180 vaddr = vecp->sv_addr;
181 181 vlen = vecp->sv_len;
182 182 }
183 183 }
184 184
185 185 if (flag & NSC_WRITE) {
186 186 rc = nsc_write(tmp, tmp->sb_pos, tmp->sb_len, 0);
187 187 if (!RDC_SUCCESS(rc)) {
188 188 (void) nsc_free_buf(tmp);
189 189 return (rc);
190 190 }
191 191 }
192 192
193 193 (void) nsc_free_buf(tmp);
194 194
195 195 fba_pos += fba_len;
196 196 fba_req -= fba_len;
197 197 if (fba_req > 0)
198 198 goto loop;
199 199
200 200 return (0);
201 201 }
202 202
203 203 /*
204 204 * Must be called with krdc->bmapmutex held.
205 205 */
206 206 static void
207 207 rdc_fill_header(rdc_u_info_t *urdc, rdc_header_t *header)
208 208 {
209 209 rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
210 210 #ifdef DEBUG
211 211 ASSERT(MUTEX_HELD(&krdc->bmapmutex));
212 212 #endif
213 213
214 214 header->magic = RDC_HDR_MAGIC;
215 215 (void) strncpy(header->primary.file, urdc->primary.file, NSC_MAXPATH);
216 216 (void) strncpy(header->primary.bitmap, urdc->primary.bitmap,
217 217 NSC_MAXPATH);
218 218 (void) strncpy(header->secondary.file, urdc->secondary.file,
219 219 NSC_MAXPATH);
220 220 (void) strncpy(header->secondary.bitmap, urdc->secondary.bitmap,
221 221 NSC_MAXPATH);
222 222 header->flags = urdc->flags | urdc->sync_flags | urdc->bmap_flags;
223 223 header->autosync = urdc->autosync;
224 224 header->maxqfbas = urdc->maxqfbas;
225 225 header->maxqitems = urdc->maxqitems;
226 226 header->asyncthr = urdc->asyncthr;
227 227 header->syshostid = urdc->syshostid;
228 228 header->refcntsize = rdc_refcntsize(krdc);
229 229 #ifdef DEBUG_REFCNT
230 230 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
231 231 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
232 232 #endif
233 233 }
234 234
235 235 /*
236 236 * Must be called with krdc->bmapmutex held.
237 237 */
238 238 static int
239 239 rdc_read_header(rdc_k_info_t *krdc, rdc_header_t *header)
240 240 {
241 241 int sts;
242 242 rdc_u_info_t *urdc;
243 243 union {
244 244 rdc_header_t *current;
245 245 rdc_headerv4_t *v4;
246 246 } u_hdrp;
247 247
248 248 if (krdc == NULL) {
249 249 return (-1);
250 250 }
251 251
252 252 ASSERT(MUTEX_HELD(&krdc->bmapmutex));
253 253
254 254 urdc = &rdc_u_info[krdc->index];
255 255 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
256 256 return (-1);
257 257
258 258 if (krdc->bitmapfd == NULL) {
259 259 return (-1);
260 260 }
261 261 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
262 262 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
263 263 return (-1);
264 264 }
265 265
266 266 if (krdc->bmp_kstats) {
267 267 mutex_enter(krdc->bmp_kstats->ks_lock);
268 268 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
269 269 mutex_exit(krdc->bmp_kstats->ks_lock);
270 270 }
271 271
272 272 sts = rdc_ns_io(krdc->bitmapfd, NSC_RDBUF, 0, (uchar_t *)header,
273 273 sizeof (rdc_header_t));
274 274
275 275 if (krdc->bmp_kstats) {
276 276 mutex_enter(krdc->bmp_kstats->ks_lock);
277 277 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
278 278 mutex_exit(krdc->bmp_kstats->ks_lock);
279 279 KSTAT_IO_PTR(krdc->bmp_kstats)->reads++;
280 280 KSTAT_IO_PTR(krdc->bmp_kstats)->nread += sizeof (rdc_header_t);
281 281 }
282 282
283 283 if (!RDC_SUCCESS(sts)) {
284 284 cmn_err(CE_WARN, "!rdc_read_header: %s read failed %d",
285 285 urdc->primary.file, sts);
286 286 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "read header failed");
287 287 }
288 288
289 289 _rdc_rlse_devs(krdc, RDC_BMP);
290 290
291 291 if (!RDC_SUCCESS(sts))
292 292 return (-1);
293 293 switch (header->magic) {
294 294 case RDC_HDR_V4:
295 295 /*
296 296 * old header format - upgrade incore copy, disk copy will
297 297 * be changed when state is re-written.
298 298 */
299 299 #ifdef DEBUG
300 300 cmn_err(CE_NOTE, "!sndr: old style (V4) bit map header");
301 301 #endif
302 302 header->magic = RDC_HDR_MAGIC;
303 303 u_hdrp.current = header;
304 304 /* copy down items moved by new maxq??? sizes */
305 305 u_hdrp.current->asyncthr = u_hdrp.v4->asyncthr;
306 306 u_hdrp.current->syshostid = u_hdrp.v4->syshostid;
307 307 u_hdrp.current->maxqitems = u_hdrp.v4->maxqitems;
308 308 u_hdrp.current->maxqfbas = u_hdrp.v4->maxqfbas;
309 309 u_hdrp.current->refcntsize = 1; /* new field */
310 310 #ifdef DEBUG_REFCNT
311 311 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
312 312 (int)u_hdrp.current->refcntsize, __LINE__, __FILE__);
313 313 #endif
314 314 return (0);
315 315 case RDC_HDR_MAGIC:
316 316 /* current header type */
317 317 return (0);
318 318 default:
319 319 /* not a header we currently understand */
320 320 return (0);
321 321 }
322 322 }
323 323
324 324 /*
325 325 * Must be called with krdc->bmapmutex held.
326 326 */
327 327 static int
328 328 rdc_write_header(rdc_k_info_t *krdc, rdc_header_t *header)
329 329 {
330 330 rdc_u_info_t *urdc;
331 331 int sts;
332 332
333 333 if (krdc == NULL) {
334 334 return (-1);
335 335 }
336 336
337 337 ASSERT(MUTEX_HELD(&krdc->bmapmutex));
338 338
339 339 urdc = &rdc_u_info[krdc->index];
340 340 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
341 341 return (-1);
342 342
343 343 if (krdc->bitmapfd == NULL) {
344 344 return (-1);
345 345 }
346 346
347 347 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
348 348 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
349 349 return (-1);
350 350 }
351 351
352 352 if (krdc->bmp_kstats) {
353 353 mutex_enter(krdc->bmp_kstats->ks_lock);
354 354 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
355 355 mutex_exit(krdc->bmp_kstats->ks_lock);
356 356 }
357 357
358 358 sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, 0, (uchar_t *)header,
359 359 sizeof (rdc_header_t));
360 360
361 361 if (krdc->bmp_kstats) {
362 362 mutex_enter(krdc->bmp_kstats->ks_lock);
363 363 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
364 364 mutex_exit(krdc->bmp_kstats->ks_lock);
365 365 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
366 366 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten +=
367 367 sizeof (rdc_header_t);
368 368 }
369 369
370 370 if (!RDC_SUCCESS(sts)) {
371 371 cmn_err(CE_WARN, "!rdc_write_header: %s write failed %d",
372 372 urdc->primary.file, sts);
373 373 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
374 374 }
375 375
376 376 _rdc_rlse_devs(krdc, RDC_BMP);
377 377
378 378 if (!RDC_SUCCESS(sts))
379 379 return (-1);
380 380 else
381 381 return (0);
382 382 }
383 383
384 384 struct bm_ref_ops rdc_ref_byte_ops;
385 385 struct bm_ref_ops rdc_ref_int_ops;
386 386
387 387 static void
388 388 rdc_set_refcnt_ops(rdc_k_info_t *krdc, size_t refcntsize)
389 389 {
390 390 switch (refcntsize) {
391 391 default:
392 392 /* FALLTHRU */
393 393 case sizeof (unsigned char):
394 394 krdc->bm_refs = &rdc_ref_byte_ops;
395 395 break;
396 396 case sizeof (unsigned int):
397 397 krdc->bm_refs = &rdc_ref_int_ops;
398 398 break;
399 399 }
400 400 #ifdef DEBUG_REFCNT
401 401 cmn_err(CE_NOTE, "!sndr: set refcnt ops for refcntsize %d - %d:%s",
402 402 (int)refcntsize, __LINE__, __FILE__);
403 403 #endif
404 404 }
405 405
406 406 size_t
407 407 rdc_refcntsize(rdc_k_info_t *krdc)
408 408 {
409 409 if (krdc->bm_refs == &rdc_ref_int_ops)
410 410 return (sizeof (unsigned int));
411 411 return (sizeof (unsigned char));
412 412 }
413 413
414 414 int
415 415 rdc_read_state(rdc_k_info_t *krdc, int *statep, int *hostidp)
416 416 {
417 417 rdc_header_t header;
418 418 rdc_u_info_t *urdc;
419 419 int sts;
420 420
421 421 if (krdc == NULL) {
422 422 return (-1);
423 423 }
424 424
425 425 mutex_enter(&krdc->bmapmutex);
426 426
427 427 urdc = &rdc_u_info[krdc->index];
428 428 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
429 429 mutex_exit(&krdc->bmapmutex);
430 430 return (-1);
431 431 }
432 432
433 433 if (krdc->bitmapfd == NULL) {
434 434 mutex_exit(&krdc->bmapmutex);
435 435 return (-1);
436 436 }
437 437
438 438 sts = rdc_read_header(krdc, &header);
439 439 mutex_exit(&krdc->bmapmutex);
440 440
441 441 if (!RDC_SUCCESS(sts)) {
442 442 return (-1);
443 443 }
444 444
445 445 switch (header.magic) {
446 446 case RDC_HDR_MAGIC:
447 447 *statep = header.flags;
448 448 *hostidp = header.syshostid;
449 449 rdc_set_refcnt_ops(krdc, header.refcntsize);
450 450 #ifdef DEBUG_REFCNT
451 451 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
452 452 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
453 453 #endif
454 454 sts = 0;
455 455 break;
456 456 default:
457 457 sts = -1;
458 458 break;
459 459 }
460 460
461 461 return (sts);
462 462 }
463 463
464 464 int
465 465 rdc_clear_state(rdc_k_info_t *krdc)
466 466 {
467 467 rdc_u_info_t *urdc;
468 468 int sts;
469 469 rdc_header_t header;
470 470
471 471 if (krdc == NULL) {
472 472 return (-1);
473 473 }
474 474
475 475 mutex_enter(&krdc->bmapmutex);
476 476
477 477 urdc = &rdc_u_info[krdc->index];
478 478 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
479 479 mutex_exit(&krdc->bmapmutex);
480 480 return (-1);
481 481 }
482 482
483 483 if (krdc->bitmapfd == NULL) {
484 484 mutex_exit(&krdc->bmapmutex);
485 485 return (-1);
486 486 }
487 487
488 488 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
489 489 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
490 490 mutex_exit(&krdc->bmapmutex);
491 491 return (-1);
492 492 }
493 493
494 494 bzero(&header, sizeof (header));
495 495
496 496 if (krdc->bmp_kstats) {
497 497 mutex_enter(krdc->bmp_kstats->ks_lock);
498 498 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
499 499 mutex_exit(krdc->bmp_kstats->ks_lock);
500 500 }
501 501
502 502 sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, 0,
503 503 (uchar_t *)&header, sizeof (header));
504 504
505 505 if (krdc->bmp_kstats) {
506 506 mutex_enter(krdc->bmp_kstats->ks_lock);
507 507 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
508 508 mutex_exit(krdc->bmp_kstats->ks_lock);
509 509 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
510 510 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten +=
511 511 sizeof (rdc_header_t);
512 512 }
513 513
514 514 if (!RDC_SUCCESS(sts)) {
515 515 cmn_err(CE_WARN, "!rdc_clear_state: %s write failed",
516 516 urdc->primary.file);
517 517 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
518 518 }
519 519
520 520 _rdc_rlse_devs(krdc, RDC_BMP);
521 521 mutex_exit(&krdc->bmapmutex);
522 522
523 523 if (!RDC_SUCCESS(sts))
524 524 return (-1);
525 525 else
526 526 return (0);
527 527 }
528 528
529 529 void
530 530 rdc_write_state(rdc_u_info_t *urdc)
531 531 {
532 532 rdc_k_info_t *krdc;
533 533 int sts;
534 534 rdc_header_t header;
535 535
536 536 if (urdc == NULL) {
537 537 return;
538 538 }
539 539
540 540 krdc = &rdc_k_info[urdc->index];
541 541
542 542 mutex_enter(&krdc->bmapmutex);
543 543
544 544 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
545 545 mutex_exit(&krdc->bmapmutex);
546 546 return;
547 547 }
548 548
549 549 if (krdc->bitmapfd == NULL) {
550 550 mutex_exit(&krdc->bmapmutex);
551 551 return;
552 552 }
553 553
554 554 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
555 555 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
556 556 mutex_exit(&krdc->bmapmutex);
557 557 return;
558 558 }
559 559
560 560 if (krdc->bmp_kstats) {
561 561 mutex_enter(krdc->bmp_kstats->ks_lock);
562 562 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
563 563 mutex_exit(krdc->bmp_kstats->ks_lock);
564 564 }
565 565
566 566 sts = rdc_ns_io(krdc->bitmapfd, NSC_RDBUF, 0, (uchar_t *)&header,
567 567 sizeof (header));
568 568
569 569 if (krdc->bmp_kstats) {
570 570 mutex_enter(krdc->bmp_kstats->ks_lock);
571 571 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
572 572 mutex_exit(krdc->bmp_kstats->ks_lock);
573 573 KSTAT_IO_PTR(krdc->bmp_kstats)->reads++;
574 574 KSTAT_IO_PTR(krdc->bmp_kstats)->nread += sizeof (header);
575 575 }
576 576
577 577 if (!RDC_SUCCESS(sts)) {
578 578 cmn_err(CE_WARN, "!rdc_write_state: %s read failed",
579 579 urdc->primary.file);
580 580 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "read failed");
581 581 goto done;
582 582 }
583 583
584 584 rdc_fill_header(urdc, &header);
585 585
586 586 if (krdc->bmp_kstats) {
587 587 mutex_enter(krdc->bmp_kstats->ks_lock);
588 588 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
589 589 mutex_exit(krdc->bmp_kstats->ks_lock);
590 590 }
591 591
592 592 sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, 0,
593 593 (uchar_t *)&header, sizeof (header));
594 594
595 595 if (krdc->bmp_kstats) {
596 596 mutex_enter(krdc->bmp_kstats->ks_lock);
597 597 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
598 598 mutex_exit(krdc->bmp_kstats->ks_lock);
599 599 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
600 600 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += sizeof (header);
601 601 }
602 602
603 603 if (!RDC_SUCCESS(sts)) {
604 604 cmn_err(CE_WARN, "!rdc_write_state: %s write failed",
605 605 urdc->primary.file);
606 606 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
607 607 }
608 608
609 609 done:
610 610 _rdc_rlse_devs(krdc, RDC_BMP);
611 611 mutex_exit(&krdc->bmapmutex);
612 612 }
613 613
614 614
615 615 struct bitmapdata {
616 616 uchar_t *data;
617 617 size_t len;
618 618 };
619 619
620 620 static int
621 621 rdc_read_bitmap(rdc_k_info_t *krdc, struct bitmapdata *data)
622 622 {
↓ open down ↓ |
622 lines elided |
↑ open up ↑ |
623 623 rdc_u_info_t *urdc;
624 624 int sts;
625 625
626 626 if (krdc == NULL) {
627 627 return (-1);
628 628 }
629 629
630 630 if (data != NULL) {
631 631 data->data = kmem_alloc(krdc->bitmap_size, KM_SLEEP);
632 632 data->len = krdc->bitmap_size;
633 -
634 - if (data->data == NULL) {
635 - return (-1);
636 - }
637 633 }
638 634
639 635 mutex_enter(&krdc->bmapmutex);
640 636
641 637 urdc = &rdc_u_info[krdc->index];
642 638 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
643 639 mutex_exit(&krdc->bmapmutex);
644 640 return (-1);
645 641 }
646 642
647 643 if (krdc->bitmapfd == NULL) {
648 644 mutex_exit(&krdc->bmapmutex);
649 645 return (-1);
650 646 }
651 647
652 648 if (data == NULL && krdc->dcio_bitmap == NULL) {
653 649 mutex_exit(&krdc->bmapmutex);
654 650 return (-1);
655 651 }
656 652
657 653 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
658 654 cmn_err(CE_WARN, "!rdc_read_bitmap: %s reserve failed",
659 655 urdc->primary.file);
660 656 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
661 657 mutex_exit(&krdc->bmapmutex);
662 658 return (-1);
663 659 }
664 660
665 661 if (krdc->bmp_kstats) {
666 662 mutex_enter(krdc->bmp_kstats->ks_lock);
667 663 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
668 664 mutex_exit(krdc->bmp_kstats->ks_lock);
669 665 }
670 666
671 667 sts = rdc_ns_io(krdc->bitmapfd, NSC_RDBUF, RDC_BITMAP_FBA,
672 668 data ? data->data : krdc->dcio_bitmap, krdc->bitmap_size);
673 669
674 670 if (krdc->bmp_kstats) {
675 671 mutex_enter(krdc->bmp_kstats->ks_lock);
676 672 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
677 673 mutex_exit(krdc->bmp_kstats->ks_lock);
678 674 KSTAT_IO_PTR(krdc->bmp_kstats)->reads++;
679 675 KSTAT_IO_PTR(krdc->bmp_kstats)->nread += krdc->bitmap_size;
680 676 }
681 677
682 678 _rdc_rlse_devs(krdc, RDC_BMP);
683 679
684 680 if (!RDC_SUCCESS(sts)) {
685 681 cmn_err(CE_WARN, "!rdc_read_bitmap: %s read failed",
686 682 urdc->primary.file);
687 683 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "read failed");
688 684 mutex_exit(&krdc->bmapmutex);
689 685 return (-1);
690 686 }
691 687
692 688 mutex_exit(&krdc->bmapmutex);
693 689 return (0);
694 690 }
695 691
696 692 int
697 693 rdc_write_bitmap(rdc_k_info_t *krdc)
698 694 {
699 695 rdc_u_info_t *urdc;
700 696 int sts;
701 697
702 698 if (krdc == NULL) {
703 699 return (-1);
704 700 }
705 701
706 702 mutex_enter(&krdc->bmapmutex);
707 703
708 704 urdc = &rdc_u_info[krdc->index];
709 705 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
710 706 mutex_exit(&krdc->bmapmutex);
711 707 return (-1);
712 708 }
713 709
714 710 if (krdc->bitmapfd == NULL) {
715 711 mutex_exit(&krdc->bmapmutex);
716 712 return (-1);
717 713 }
718 714
719 715 if (krdc->dcio_bitmap == NULL) {
720 716 mutex_exit(&krdc->bmapmutex);
721 717 return (-1);
722 718 }
723 719
724 720 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
725 721 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
726 722 mutex_exit(&krdc->bmapmutex);
727 723 return (-1);
728 724 }
729 725
730 726 if (krdc->bmp_kstats) {
731 727 mutex_enter(krdc->bmp_kstats->ks_lock);
732 728 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
733 729 mutex_exit(krdc->bmp_kstats->ks_lock);
734 730 }
735 731
736 732 sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, RDC_BITMAP_FBA,
737 733 krdc->dcio_bitmap, krdc->bitmap_size);
738 734
739 735 if (krdc->bmp_kstats) {
740 736 mutex_enter(krdc->bmp_kstats->ks_lock);
741 737 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
742 738 mutex_exit(krdc->bmp_kstats->ks_lock);
743 739 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
744 740 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += krdc->bitmap_size;
745 741 }
746 742
747 743 _rdc_rlse_devs(krdc, RDC_BMP);
748 744
749 745 if (!RDC_SUCCESS(sts)) {
750 746 cmn_err(CE_WARN, "!rdc_write_bitmap: %s write failed",
751 747 urdc->primary.file);
752 748 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
753 749 mutex_exit(&krdc->bmapmutex);
754 750 return (-1);
755 751 }
756 752
757 753 mutex_exit(&krdc->bmapmutex);
758 754 return (0);
759 755 }
760 756
761 757 int
762 758 rdc_write_bitmap_fba(rdc_k_info_t *krdc, nsc_off_t fba)
763 759 {
764 760 rdc_u_info_t *urdc;
765 761 int sts;
766 762
767 763 if (krdc == NULL) {
768 764 return (-1);
769 765 }
770 766
771 767 mutex_enter(&krdc->bmapmutex);
772 768
773 769 urdc = &rdc_u_info[krdc->index];
774 770 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
775 771 mutex_exit(&krdc->bmapmutex);
776 772 return (-1);
777 773 }
778 774
779 775 if (krdc->bitmapfd == NULL) {
780 776 mutex_exit(&krdc->bmapmutex);
781 777 return (-1);
782 778 }
783 779
784 780 if (krdc->dcio_bitmap == NULL) {
785 781 mutex_exit(&krdc->bmapmutex);
786 782 return (-1);
787 783 }
788 784
789 785 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
790 786 cmn_err(CE_WARN, "!rdc_write_bitmap_fba: %s reserve failed",
791 787 urdc->primary.file);
792 788 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
793 789 mutex_exit(&krdc->bmapmutex);
794 790 return (-1);
795 791 }
796 792
797 793 if (krdc->bmp_kstats) {
798 794 mutex_enter(krdc->bmp_kstats->ks_lock);
799 795 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
800 796 mutex_exit(krdc->bmp_kstats->ks_lock);
801 797 }
802 798 sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, RDC_BITMAP_FBA + fba,
803 799 krdc->dcio_bitmap + fba * 512, 512);
804 800
805 801 if (krdc->bmp_kstats) {
806 802 mutex_enter(krdc->bmp_kstats->ks_lock);
807 803 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
808 804 mutex_exit(krdc->bmp_kstats->ks_lock);
809 805 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
810 806 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += 512;
811 807 }
812 808
813 809 _rdc_rlse_devs(krdc, RDC_BMP);
814 810
815 811 if (!RDC_SUCCESS(sts)) {
816 812 cmn_err(CE_WARN, "!rdc_write_bitmap_fba: %s write failed",
817 813 urdc->primary.file);
818 814 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
819 815 mutex_exit(&krdc->bmapmutex);
820 816 return (-1);
821 817 }
822 818
823 819 mutex_exit(&krdc->bmapmutex);
824 820 return (0);
825 821 }
826 822
827 823
828 824 static int
829 825 rdc_write_bitmap_pattern(rdc_k_info_t *krdc, const char pattern)
830 826 {
831 827 rdc_u_info_t *urdc;
832 828 char *buffer;
833 829 nsc_buf_t *h;
834 830 nsc_vec_t *v;
835 831 int rc;
836 832 size_t i;
837 833 nsc_size_t len;
838 834 int off;
839 835 size_t buffer_size;
840 836 size_t iolen;
841 837 nsc_size_t fba_req;
842 838 nsc_off_t fba_len, fba_pos;
843 839 nsc_size_t maxfbas = 0;
844 840 nsc_size_t tocopy;
845 841
846 842 if (krdc == NULL) {
847 843 return (-1);
848 844 }
849 845
850 846 mutex_enter(&krdc->bmapmutex);
851 847
852 848 urdc = &rdc_u_info[krdc->index];
853 849 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
854 850 mutex_exit(&krdc->bmapmutex);
855 851 return (-1);
856 852 }
857 853
858 854 if (krdc->bitmapfd == NULL) {
859 855 mutex_exit(&krdc->bmapmutex);
860 856 return (-1);
861 857 }
862 858
863 859 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
864 860 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
865 861 mutex_exit(&krdc->bmapmutex);
866 862 return (-1);
867 863 }
868 864
869 865 buffer_size = FBA_SIZE(1);
870 866 ASSERT(buffer_size < INT32_MAX);
871 867 buffer = kmem_alloc(buffer_size, KM_SLEEP);
872 868
873 869 for (i = 0; i < buffer_size; i++) {
874 870 buffer[i] = pattern;
875 871 }
876 872
877 873 rc = nsc_maxfbas(krdc->bitmapfd, 0, &maxfbas);
878 874 if (!RDC_SUCCESS(rc)) {
879 875 #ifdef DEBUG
880 876 cmn_err(CE_WARN,
881 877 "!rdc_write_bitmap_pattern: maxfbas failed (%d)", rc);
882 878 #endif
883 879 maxfbas = 256;
884 880 }
885 881
886 882 fba_req = FBA_LEN(krdc->bitmap_size); /* total FBAs left to copy */
887 883 fba_pos = RDC_BITMAP_FBA; /* current FBA position */
888 884 tocopy = krdc->bitmap_size; /* total bytes left to copy */
889 885 loop:
890 886 h = NULL;
891 887 fba_len = min(fba_req, maxfbas); /* FBAs to alloc this time */
892 888
893 889 rc = nsc_alloc_buf(krdc->bitmapfd, fba_pos, fba_len, rdc_wrflag, &h);
894 890 if (!RDC_SUCCESS(rc)) {
895 891 cmn_err(CE_WARN, "!rdc_write_bitmap_pattern: %s "
896 892 "write failed %d", urdc->primary.file, rc);
897 893 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "nsc_alloc_buf failed");
898 894 if (h) {
899 895 (void) nsc_free_handle(h);
900 896 }
901 897
902 898 _rdc_rlse_devs(krdc, RDC_BMP);
903 899 mutex_exit(&krdc->bmapmutex);
904 900 rc = -1;
905 901 goto finish;
906 902 }
907 903
908 904 /* bytes to copy this time */
909 905 len = min(tocopy, FBA_SIZE(fba_len));
910 906 v = h->sb_vec;
911 907 off = 0;
912 908
913 909 while (len) {
914 910 if (off >= v->sv_len) {
915 911 off = 0;
916 912 v++;
917 913 }
918 914
919 915 if (v->sv_addr == 0 || v->sv_len == 0) {
920 916 #ifdef DEBUG
921 917 cmn_err(CE_WARN,
922 918 "!rdc_write_bitmap_pattern: ran off end of handle");
923 919 #endif
924 920 break;
925 921 }
926 922
927 923 iolen = (size_t)min(len, buffer_size);
928 924
929 925 bcopy(buffer, (char *)(v->sv_addr + off), iolen);
930 926 off += iolen;
931 927 len -= iolen;
932 928 }
933 929
934 930 rc = nsc_write(h, h->sb_pos, h->sb_len, 0);
935 931 if (!RDC_SUCCESS(rc)) {
936 932 cmn_err(CE_WARN, "!rdc_write_bitmap_pattern: "
937 933 "%s write failed %d", urdc->primary.file, rc);
938 934 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
939 935 (void) nsc_free_buf(h);
940 936 _rdc_rlse_devs(krdc, RDC_BMP);
941 937 mutex_exit(&krdc->bmapmutex);
942 938 rc = -1;
943 939 goto finish;
944 940 }
945 941
946 942 (void) nsc_free_buf(h);
947 943
948 944 fba_pos += fba_len;
949 945 fba_req -= fba_len;
950 946 tocopy -= FBA_SIZE(fba_len); /* adjust byte length remaining */
951 947 if (fba_req > 0)
952 948 goto loop;
953 949
954 950 _rdc_rlse_devs(krdc, RDC_BMP);
955 951 mutex_exit(&krdc->bmapmutex);
956 952 rc = 0;
957 953 finish:
958 954 kmem_free(buffer, buffer_size);
959 955 return (rc);
960 956 }
961 957
962 958
963 959 /*
964 960 * rdc_write_bitmap_fill()
965 961 *
966 962 * Write a bitmap full of 1's out to disk without touching the
967 963 * in-memory bitmap.
968 964 */
969 965 int
970 966 rdc_write_bitmap_fill(rdc_k_info_t *krdc)
971 967 {
972 968 return (rdc_write_bitmap_pattern(krdc, 0xff));
973 969 }
974 970
975 971
976 972 void
977 973 rdc_merge_bitmaps(rdc_k_info_t *src, rdc_k_info_t *dst)
978 974 {
979 975 if (src->dcio_bitmap == NULL || dst->dcio_bitmap == NULL)
980 976 return;
981 977
982 978 rdc_lor(src->dcio_bitmap, dst->dcio_bitmap,
983 979 min(src->bitmap_size, dst->bitmap_size));
984 980 if (dst->bitmap_write > 0)
985 981 (void) rdc_write_bitmap(dst);
986 982 }
987 983
988 984
989 985 /*
990 986 * bitmap size in bytes, vol_size fba's
991 987 */
992 988
993 989 size_t
994 990 rdc_ref_size_possible(nsc_size_t bitmap_size, nsc_size_t vol_size)
995 991 {
996 992 nsc_size_t ref_size;
997 993 nsc_size_t bitmap_end_fbas;
998 994
999 995 bitmap_end_fbas = RDC_BITMAP_FBA + FBA_LEN(bitmap_size);
1000 996 ref_size = FBA_LEN(bitmap_size * BITS_IN_BYTE * sizeof (unsigned char));
1001 997 if (bitmap_end_fbas + ref_size > vol_size)
1002 998 return ((size_t)0);
1003 999
1004 1000 ref_size = FBA_LEN(bitmap_size * BITS_IN_BYTE * sizeof (unsigned int));
1005 1001 if (bitmap_end_fbas + ref_size > vol_size)
1006 1002 return (sizeof (unsigned char));
1007 1003 return (sizeof (unsigned int));
1008 1004 }
1009 1005
1010 1006 int
1011 1007 rdc_move_bitmap(rdc_k_info_t *krdc, char *newbitmap)
1012 1008 {
1013 1009 rdc_u_info_t *urdc;
1014 1010 nsc_fd_t *oldfd;
1015 1011 nsc_fd_t *newfd = NULL;
1016 1012 rdc_header_t header;
1017 1013 int sts;
1018 1014 nsc_size_t vol_size;
1019 1015 nsc_size_t req_size;
1020 1016 size_t ref_size;
1021 1017
1022 1018 if (krdc == NULL) {
1023 1019 return (-1);
1024 1020 }
1025 1021
1026 1022 if (krdc->bitmapfd == NULL) {
1027 1023 return (-1);
1028 1024 }
1029 1025
1030 1026 req_size = RDC_BITMAP_FBA + FBA_LEN(krdc->bitmap_size);
1031 1027 if (RDC_IS_DISKQ(krdc->group)) {
1032 1028 /* new volume must support at least the old refcntsize */
1033 1029 req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1034 1030 rdc_refcntsize(krdc));
1035 1031 #ifdef DEBUG_REFCNT
1036 1032 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1037 1033 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1038 1034 #endif
1039 1035 }
1040 1036
1041 1037 mutex_enter(&krdc->bmapmutex);
1042 1038
1043 1039 if (rdc_read_header(krdc, &header) < 0) {
1044 1040 #ifdef DEBUG
1045 1041 cmn_err(CE_WARN, "!rdc_move_bitmap: Read old header failed");
1046 1042 #endif
1047 1043 mutex_exit(&krdc->bmapmutex);
1048 1044 return (-1);
1049 1045 }
1050 1046
1051 1047 oldfd = krdc->bitmapfd;
1052 1048
1053 1049 newfd = nsc_open(newbitmap, NSC_RDCHR_ID|NSC_FILE|NSC_RDWR, 0, 0, 0);
1054 1050 if (newfd == NULL) {
1055 1051 newfd = nsc_open(newbitmap,
1056 1052 NSC_RDCHR_ID|NSC_CACHE|NSC_DEVICE|NSC_RDWR, 0, 0, 0);
1057 1053 if (newfd == NULL) {
1058 1054 /* Can't open new bitmap */
1059 1055 cmn_err(CE_WARN,
1060 1056 "!rdc_move_bitmap: Cannot open new bitmap %s",
1061 1057 newbitmap);
1062 1058 goto fail;
1063 1059 }
1064 1060 }
1065 1061
1066 1062 sts = nsc_reserve(newfd, 0);
1067 1063 if (!RDC_SUCCESS(sts)) {
1068 1064 cmn_err(CE_WARN, "!rdc_move_bitmap: Reserve failed for %s",
1069 1065 newbitmap);
1070 1066 goto fail;
1071 1067 }
1072 1068 sts = nsc_partsize(newfd, &vol_size);
1073 1069 nsc_release(newfd);
1074 1070
1075 1071 if (!RDC_SUCCESS(sts)) {
1076 1072 cmn_err(CE_WARN,
1077 1073 "!rdc_move_bitmap: nsc_partsize failed for %s", newbitmap);
1078 1074 goto fail;
1079 1075 }
1080 1076
1081 1077 ref_size = rdc_ref_size_possible(krdc->bitmap_size, vol_size);
1082 1078
1083 1079 if (vol_size < req_size) {
1084 1080 cmn_err(CE_WARN,
1085 1081 "!rdc_move_bitmap: bitmap %s too small: %" NSC_SZFMT
1086 1082 " vs %" NSC_SZFMT " blocks", newbitmap, vol_size, req_size);
1087 1083 goto fail;
1088 1084 }
1089 1085
1090 1086 mutex_enter(&krdc->devices->id_rlock);
1091 1087 krdc->bitmapfd = newfd; /* swap under lock */
1092 1088 if (krdc->bmaprsrv > 0) {
1093 1089 sts = nsc_reserve(krdc->bitmapfd, 0);
1094 1090 if (!RDC_SUCCESS(sts)) {
1095 1091 krdc->bitmapfd = oldfd; /* replace under lock */
1096 1092 mutex_exit(&krdc->devices->id_rlock);
1097 1093 cmn_err(CE_WARN,
1098 1094 "!rdc_move_bitmap: Reserve failed for %s",
1099 1095 newbitmap);
1100 1096 goto fail;
1101 1097 }
1102 1098 }
1103 1099 rdc_set_refcnt_ops(krdc, ref_size);
1104 1100 #ifdef DEBUG_REFCNT
1105 1101 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1106 1102 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1107 1103 #endif
1108 1104 mutex_exit(&krdc->devices->id_rlock);
1109 1105
1110 1106 /* Forget newfd now it is krdc->bitmapfd */
1111 1107 newfd = NULL;
1112 1108
1113 1109 /* Put new bitmap name into header and user-visible data structure */
1114 1110 urdc = &rdc_u_info[krdc->index];
1115 1111 if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
1116 1112 (void) strncpy(header.primary.bitmap, newbitmap, NSC_MAXPATH);
1117 1113 (void) strncpy(urdc->primary.bitmap, newbitmap, NSC_MAXPATH);
1118 1114 } else {
1119 1115 (void) strncpy(header.secondary.bitmap, newbitmap, NSC_MAXPATH);
1120 1116 (void) strncpy(urdc->secondary.bitmap, newbitmap, NSC_MAXPATH);
1121 1117 }
1122 1118
1123 1119 if (rdc_write_header(krdc, &header) < 0) {
1124 1120 cmn_err(CE_WARN,
1125 1121 "!rdc_move_bitmap: Write header %s failed", newbitmap);
1126 1122 goto fail;
1127 1123 }
1128 1124
1129 1125 mutex_exit(&krdc->bmapmutex);
1130 1126
1131 1127 if (rdc_write_bitmap(krdc) < 0) {
1132 1128 mutex_enter(&krdc->bmapmutex);
1133 1129 cmn_err(CE_WARN,
1134 1130 "!rdc_move_bitmap: Write bitmap %s failed", newbitmap);
1135 1131 goto fail;
1136 1132 }
1137 1133
1138 1134 /* Unintercept the old bitmap */
1139 1135 if (krdc->b_tok) {
1140 1136 int rc;
1141 1137
1142 1138 rdc_group_exit(krdc);
1143 1139 rc = nsc_unregister_path(krdc->b_tok, 0);
1144 1140 if (rc)
1145 1141 cmn_err(CE_WARN, "!rdc_move_bitmap: "
1146 1142 "unregister bitmap failed %d", rc);
1147 1143 else
1148 1144 krdc->b_tok = nsc_register_path(newbitmap,
1149 1145 NSC_CACHE | NSC_DEVICE, _rdc_io_hc);
1150 1146 rdc_group_enter(krdc);
1151 1147 }
1152 1148
1153 1149 /* clear the old bitmap header */
1154 1150 bzero(&header, sizeof (header));
1155 1151
1156 1152 sts = nsc_held(oldfd) ? 0 : nsc_reserve(oldfd, 0);
1157 1153 if (sts == 0) {
1158 1154
1159 1155 if (krdc->bmp_kstats) {
1160 1156 mutex_enter(krdc->bmp_kstats->ks_lock);
1161 1157 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
1162 1158 mutex_exit(krdc->bmp_kstats->ks_lock);
1163 1159 }
1164 1160
1165 1161 sts = rdc_ns_io(oldfd, rdc_wrflag, 0,
1166 1162 (uchar_t *)&header, sizeof (header));
1167 1163
1168 1164 if (krdc->bmp_kstats) {
1169 1165 mutex_enter(krdc->bmp_kstats->ks_lock);
1170 1166 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
1171 1167 mutex_exit(krdc->bmp_kstats->ks_lock);
1172 1168 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
1173 1169 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten +=
1174 1170 sizeof (header);
1175 1171 }
1176 1172
1177 1173 }
1178 1174 #ifdef DEBUG
1179 1175 if (sts != 0) {
1180 1176 cmn_err(CE_WARN,
1181 1177 "!rdc_move_bitmap: unable to clear bitmap header on %s",
1182 1178 nsc_pathname(oldfd));
1183 1179 }
1184 1180 #endif
1185 1181
1186 1182 /* nsc_close will undo any reservation */
1187 1183 if (nsc_close(oldfd) != 0) {
1188 1184 #ifdef DEBUG
1189 1185 cmn_err(CE_WARN, "!rdc_move_bitmap: close old bitmap failed");
1190 1186 #else
1191 1187 ;
1192 1188 /*EMPTY*/
1193 1189 #endif
1194 1190 }
1195 1191
1196 1192 return (0);
1197 1193
1198 1194 fail:
1199 1195 /* Close newfd if it was unused */
1200 1196 if (newfd && newfd != krdc->bitmapfd) {
1201 1197 (void) nsc_close(newfd);
1202 1198 newfd = NULL;
1203 1199 }
1204 1200
1205 1201 mutex_exit(&krdc->bmapmutex);
1206 1202 return (-1);
1207 1203 }
1208 1204
1209 1205
1210 1206 void
1211 1207 rdc_close_bitmap(rdc_k_info_t *krdc)
1212 1208 {
1213 1209
1214 1210 if (krdc == NULL) {
1215 1211 return;
1216 1212 }
1217 1213
1218 1214 mutex_enter(&krdc->bmapmutex);
1219 1215
1220 1216 if (krdc->bitmapfd) {
1221 1217 if (nsc_close(krdc->bitmapfd) != 0) {
1222 1218 #ifdef DEBUG
1223 1219 cmn_err(CE_WARN, "!nsc_close on bitmap failed");
1224 1220 #else
1225 1221 ;
1226 1222 /*EMPTY*/
1227 1223 #endif
1228 1224 }
1229 1225 krdc->bitmapfd = 0;
1230 1226 }
1231 1227
1232 1228 mutex_exit(&krdc->bmapmutex);
1233 1229 }
1234 1230
1235 1231 void
1236 1232 rdc_free_bitmap(rdc_k_info_t *krdc, int cmd)
1237 1233 {
1238 1234 rdc_header_t header;
1239 1235 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1240 1236
1241 1237 if (krdc == NULL) {
1242 1238 return;
1243 1239 }
1244 1240
1245 1241 mutex_enter(&krdc->bmapmutex);
1246 1242
1247 1243 if (cmd != RDC_CMD_SUSPEND) {
1248 1244
1249 1245 bzero((char *)&header, sizeof (rdc_header_t));
1250 1246
1251 1247 if (krdc->bitmapfd)
1252 1248 (void) rdc_write_header(krdc, &header);
1253 1249 } else {
1254 1250 mutex_exit(&krdc->bmapmutex);
1255 1251 /* gotta drop mutex, in case q needs to fail */
1256 1252 if (RDC_IS_DISKQ(krdc->group) && rdc_suspend_diskq(krdc) < 0) {
1257 1253 cmn_err(CE_WARN,
1258 1254 "!rdc_free_bitmap: diskq suspend failed");
1259 1255 }
1260 1256
1261 1257 mutex_enter(&krdc->bmapmutex);
1262 1258 if (rdc_read_header(krdc, &header) < 0) {
1263 1259 cmn_err(CE_WARN,
1264 1260 "!rdc_free_bitmap: Read header failed");
1265 1261 } else {
1266 1262 rdc_fill_header(urdc, &header);
1267 1263
1268 1264 (void) rdc_write_header(krdc, &header);
1269 1265 }
1270 1266 }
1271 1267
1272 1268 mutex_exit(&krdc->bmapmutex);
1273 1269
1274 1270 if (krdc->dcio_bitmap != NULL) {
1275 1271 if (cmd == RDC_CMD_SUSPEND) {
1276 1272 if (krdc->bitmapfd)
1277 1273 (void) rdc_write_bitmap(krdc);
1278 1274 }
1279 1275
1280 1276 kmem_free(krdc->dcio_bitmap, krdc->bitmap_size);
1281 1277 krdc->dcio_bitmap = NULL;
1282 1278 }
1283 1279 if (krdc->bitmap_ref != NULL) {
1284 1280 kmem_free(krdc->bitmap_ref, (krdc->bitmap_size * BITS_IN_BYTE *
1285 1281 BMAP_REF_PREF_SIZE));
1286 1282 krdc->bitmap_ref = NULL;
1287 1283 }
1288 1284
1289 1285 krdc->bitmap_size = 0;
1290 1286 }
1291 1287
1292 1288 static int
1293 1289 rdc_alloc_bitmap(rdc_k_info_t *krdc)
1294 1290 {
1295 1291 rdc_u_info_t *urdc;
1296 1292 char *bitmapname;
1297 1293 nsc_size_t bitmap_ref_size;
1298 1294
1299 1295 if (krdc == NULL) {
1300 1296 return (-1);
1301 1297 }
1302 1298
1303 1299 urdc = &rdc_u_info[krdc->index];
1304 1300 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1305 1301 bitmapname = &urdc->primary.bitmap[0];
1306 1302 else
1307 1303 bitmapname = &urdc->secondary.bitmap[0];
1308 1304
1309 1305 if (krdc->dcio_bitmap) {
1310 1306 #ifdef DEBUG
1311 1307 cmn_err(CE_WARN,
1312 1308 "!rdc_alloc_bitmap: bitmap %s already allocated",
1313 1309 bitmapname);
1314 1310 #endif
1315 1311 return (0);
1316 1312 }
1317 1313
1318 1314 if (urdc->volume_size == 0)
1319 1315 return (-1);
1320 1316
1321 1317 krdc->bitmap_size = BMAP_LOG_BYTES(urdc->volume_size);
1322 1318 /* Round up */
1323 1319 krdc->bitmap_size = (krdc->bitmap_size + 511) / 512 * 512;
1324 1320
1325 1321 krdc->dcio_bitmap = (uchar_t *)kmem_zalloc(krdc->bitmap_size,
1326 1322 KM_SLEEP);
1327 1323 if (krdc->dcio_bitmap == NULL) {
1328 1324 cmn_err(CE_WARN, "!rdc_alloc_bitmap: alloc %" NSC_SZFMT
1329 1325 " failed for %s", krdc->bitmap_size, bitmapname);
1330 1326 return (-1);
1331 1327 }
1332 1328
1333 1329 /*
1334 1330 * use largest ref count type size as we haven't opened the bitmap
1335 1331 * volume yet to find out what has acutally be used.
1336 1332 */
1337 1333 bitmap_ref_size = krdc->bitmap_size * BITS_IN_BYTE * BMAP_REF_PREF_SIZE;
1338 1334 if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
1339 1335 ((krdc->type_flag & RDC_ASYNCMODE) != 0)) {
1340 1336 krdc->bitmap_ref = (uchar_t *)kmem_zalloc(bitmap_ref_size,
1341 1337 KM_SLEEP);
1342 1338 if (krdc->bitmap_ref == NULL) {
1343 1339 cmn_err(CE_WARN,
1344 1340 "!rdc_alloc_bitmap: ref alloc %" NSC_SZFMT
1345 1341 " failed for %s",
1346 1342 bitmap_ref_size, bitmapname);
1347 1343 return (-1);
1348 1344 }
1349 1345 }
1350 1346
1351 1347 return (0);
1352 1348 }
1353 1349
1354 1350
1355 1351 static int
1356 1352 rdc_open_bitmap(rdc_k_info_t *krdc)
1357 1353 {
1358 1354 rdc_u_info_t *urdc;
1359 1355 int sts;
1360 1356 uint_t hints = 0;
1361 1357 nsc_size_t vol_size;
1362 1358 char *bitmapname;
1363 1359 nsc_size_t req_size;
1364 1360 nsc_size_t bit_size;
1365 1361
1366 1362 urdc = &rdc_u_info[krdc->index];
1367 1363 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1368 1364 bitmapname = &urdc->primary.bitmap[0];
1369 1365 else
1370 1366 bitmapname = &urdc->secondary.bitmap[0];
1371 1367
1372 1368 urdc->bits_set = 0;
1373 1369
1374 1370 bit_size = req_size = RDC_BITMAP_FBA + FBA_LEN(krdc->bitmap_size);
1375 1371 if (RDC_IS_DISKQ(krdc->group)) {
1376 1372 req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1377 1373 sizeof (unsigned char));
1378 1374 }
1379 1375
1380 1376 mutex_enter(&krdc->bmapmutex);
1381 1377
1382 1378 rdc_set_refcnt_ops(krdc, sizeof (unsigned char));
1383 1379 #ifdef DEBUG_REFCNT
1384 1380 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1385 1381 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1386 1382 #endif
1387 1383 if (krdc->bitmapfd == NULL)
1388 1384 krdc->bitmapfd = nsc_open(bitmapname,
1389 1385 NSC_RDCHR_ID|NSC_FILE|NSC_RDWR, 0, 0, 0);
1390 1386 if (krdc->bitmapfd == NULL) {
1391 1387 krdc->bitmapfd = nsc_open(bitmapname,
1392 1388 NSC_RDCHR_ID|NSC_CACHE|NSC_DEVICE|NSC_RDWR, 0, 0, 0);
1393 1389 if (krdc->bitmapfd == NULL) {
1394 1390 cmn_err(CE_WARN, "!rdc_open_bitmap: Unable to open %s",
1395 1391 bitmapname);
1396 1392 goto fail;
1397 1393 }
1398 1394 }
1399 1395
1400 1396 sts = _rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL);
1401 1397 if (!RDC_SUCCESS(sts)) {
1402 1398 cmn_err(CE_WARN, "!rdc_open_bitmap: Reserve failed for %s",
1403 1399 bitmapname);
1404 1400 goto fail;
1405 1401 }
1406 1402 sts = nsc_partsize(krdc->bitmapfd, &vol_size);
1407 1403 _rdc_rlse_devs(krdc, RDC_BMP);
1408 1404
1409 1405 if (!RDC_SUCCESS(sts)) {
1410 1406 cmn_err(CE_WARN,
1411 1407 "!rdc_open_bitmap: nsc_partsize failed for %s", bitmapname);
1412 1408 goto fail;
1413 1409 }
1414 1410
1415 1411 if (vol_size < req_size) {
1416 1412 /* minimum size supports unsigned char reference counts */
1417 1413 cmn_err(CE_WARN,
1418 1414 "!rdc_open_bitmap: bitmap %s too small: %" NSC_SZFMT " vs %"
1419 1415 NSC_SZFMT "blocks",
1420 1416 bitmapname, vol_size, req_size);
1421 1417 goto fail;
1422 1418 }
1423 1419
1424 1420 if (rdc_bitmap_mode == RDC_BMP_NEVER) {
1425 1421 krdc->bitmap_write = 0; /* forced off */
1426 1422 } else if (rdc_bitmap_mode == RDC_BMP_ALWAYS ||
1427 1423 (nsc_node_hints(&hints) == 0 && (hints & NSC_FORCED_WRTHRU) == 0)) {
1428 1424 krdc->bitmap_write = 1; /* forced or autodetect on */
1429 1425 } else {
1430 1426 /* autodetect off */
1431 1427 krdc->bitmap_write = 0;
1432 1428 }
1433 1429
1434 1430 mutex_exit(&krdc->bmapmutex);
1435 1431 if (RDC_IS_DISKQ(krdc->group) && (rdc_refcntsize(krdc) <
1436 1432 BMAP_REF_PREF_SIZE)) {
1437 1433 /* test for larger ref counts */
1438 1434 #ifdef DEBUG_REFCNT
1439 1435 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1440 1436 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1441 1437 #endif
1442 1438 req_size = bit_size;
1443 1439 req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1444 1440 sizeof (unsigned int));
1445 1441 if (vol_size >= req_size)
1446 1442 rdc_set_refcnt_ops(krdc, sizeof (unsigned int));
1447 1443 }
1448 1444 #ifdef DEBUG_REFCNT
1449 1445 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1450 1446 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1451 1447 #endif
1452 1448 return (0);
1453 1449
1454 1450 fail:
1455 1451 mutex_exit(&krdc->bmapmutex);
1456 1452 return (-1);
1457 1453 }
1458 1454
1459 1455 int
1460 1456 rdc_enable_bitmap(rdc_k_info_t *krdc, int set)
1461 1457 {
1462 1458 rdc_header_t header;
1463 1459 rdc_u_info_t *urdc;
1464 1460 char *bitmapname;
1465 1461
1466 1462 urdc = &rdc_u_info[krdc->index];
1467 1463
1468 1464 if (rdc_alloc_bitmap(krdc) < 0)
1469 1465 goto fail;
1470 1466
1471 1467 if (rdc_open_bitmap(krdc) < 0)
1472 1468 goto fail;
1473 1469
1474 1470 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1475 1471 bitmapname = &urdc->primary.bitmap[0];
1476 1472 else
1477 1473 bitmapname = &urdc->secondary.bitmap[0];
1478 1474
1479 1475 mutex_enter(&krdc->bmapmutex);
1480 1476
1481 1477 rdc_clr_flags(urdc, RDC_BMP_FAILED);
1482 1478 if (rdc_read_header(krdc, &header) < 0) {
1483 1479 cmn_err(CE_WARN,
1484 1480 "!rdc_enable_bitmap: Read header %s failed", bitmapname);
1485 1481 mutex_exit(&krdc->bmapmutex);
1486 1482 goto fail;
1487 1483 }
1488 1484
1489 1485 rdc_fill_header(urdc, &header);
1490 1486 rdc_set_refcnt_ops(krdc, (size_t)header.refcntsize);
1491 1487
1492 1488 if (set)
1493 1489 (void) RDC_FILL_BITMAP(krdc, FALSE);
1494 1490
1495 1491 if (rdc_write_header(krdc, &header) < 0) {
1496 1492 cmn_err(CE_WARN,
1497 1493 "!rdc_enable_bitmap: Write header %s failed",
1498 1494 bitmapname);
1499 1495 mutex_exit(&krdc->bmapmutex);
1500 1496 goto fail;
1501 1497 }
1502 1498 mutex_exit(&krdc->bmapmutex);
1503 1499
1504 1500 if (rdc_write_bitmap(krdc) < 0) {
1505 1501 cmn_err(CE_WARN,
1506 1502 "!rdc_enable_bitmap: Write bitmap %s failed",
1507 1503 bitmapname);
1508 1504 goto fail;
1509 1505 }
1510 1506
1511 1507 return (0);
1512 1508
1513 1509 fail:
1514 1510 rdc_free_bitmap(krdc, RDC_CMD_ENABLE);
1515 1511 rdc_close_bitmap(krdc);
1516 1512
1517 1513 mutex_enter(&krdc->bmapmutex);
1518 1514 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "I/O failed");
1519 1515 mutex_exit(&krdc->bmapmutex);
1520 1516 return (-1);
1521 1517 }
1522 1518
1523 1519 static int
1524 1520 _rdc_rdwr_refcnt(rdc_k_info_t *krdc, int rwflg)
1525 1521 {
1526 1522 rdc_u_info_t *urdc;
1527 1523 int rc;
1528 1524 nsc_off_t offset;
1529 1525 nsc_size_t len;
1530 1526
1531 1527 urdc = &rdc_u_info[krdc->index];
1532 1528
1533 1529 #ifdef DEBUG_REFCNT
1534 1530 cmn_err(CE_NOTE, "!rdc_rdwr_refcnt: %s refcount for %s",
1535 1531 (rwflg == NSC_READ) ? "resuming" : "writing",
1536 1532 urdc->primary.bitmap);
1537 1533 #endif
1538 1534 ASSERT(MUTEX_HELD(QLOCK((&krdc->group->diskq))));
1539 1535 mutex_enter(&krdc->bmapmutex);
1540 1536
1541 1537 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
1542 1538 cmn_err(CE_WARN, "!rdc_rdwr_refcnt: reserve failed");
1543 1539 goto fail;
1544 1540 }
1545 1541
1546 1542 if (krdc->bitmap_size == 0) {
1547 1543 cmn_err(CE_WARN, "!rdc_rdwr_refcnt: NULL bitmap!");
1548 1544 goto fail;
1549 1545 }
1550 1546
1551 1547 offset = RDC_BITREF_FBA(krdc);
1552 1548 len = krdc->bitmap_size * BITS_IN_BYTE * rdc_refcntsize(krdc);
1553 1549
1554 1550 rc = rdc_ns_io(krdc->bitmapfd, rwflg, offset,
1555 1551 (uchar_t *)krdc->bitmap_ref, len);
1556 1552
1557 1553 if (!RDC_SUCCESS(rc)) {
1558 1554 cmn_err(CE_WARN, "!unable to %s refcount from bitmap %s",
1559 1555 (rwflg == NSC_READ) ? "retrieve" : "write",
1560 1556 urdc->primary.bitmap);
1561 1557 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "refcount I/O failed");
1562 1558 goto fail;
1563 1559 }
1564 1560
1565 1561 _rdc_rlse_devs(krdc, RDC_BMP);
1566 1562
1567 1563 mutex_exit(&krdc->bmapmutex);
1568 1564
1569 1565 #ifdef DEBUG_REFCNT
1570 1566 cmn_err(CE_NOTE, "!rdc_rdwr_refcnt: %s refcount for %s",
1571 1567 (rwflg == NSC_READ) ? "resumed" : "wrote",
1572 1568 urdc->primary.bitmap);
1573 1569 #endif
1574 1570 return (0);
1575 1571
1576 1572 fail:
1577 1573 _rdc_rlse_devs(krdc, RDC_BMP);
1578 1574
1579 1575 mutex_exit(&krdc->bmapmutex);
1580 1576
1581 1577 return (-1);
1582 1578
1583 1579 }
1584 1580
1585 1581 /*
1586 1582 * rdc_read_refcount
1587 1583 * read the stored refcount from disk
1588 1584 * queue lock is held
1589 1585 */
1590 1586 int
1591 1587 rdc_read_refcount(rdc_k_info_t *krdc)
1592 1588 {
1593 1589 int rc;
1594 1590
1595 1591 rc = _rdc_rdwr_refcnt(krdc, NSC_READ);
1596 1592
1597 1593 return (rc);
1598 1594 }
1599 1595
1600 1596 /*
1601 1597 * rdc_write_refcount
1602 1598 * writes krdc->bitmap_ref to the diskq
1603 1599 * called with qlock held
1604 1600 */
1605 1601 int
1606 1602 rdc_write_refcount(rdc_k_info_t *krdc)
1607 1603 {
1608 1604 int rc;
1609 1605
1610 1606 rc = _rdc_rdwr_refcnt(krdc, NSC_WRBUF);
1611 1607
1612 1608 return (rc);
1613 1609 }
1614 1610
1615 1611 static int
1616 1612 rdc_resume_state(rdc_k_info_t *krdc, const rdc_header_t *header)
1617 1613 {
1618 1614 rdc_u_info_t *urdc;
1619 1615 char *bitmapname;
1620 1616
1621 1617 urdc = &rdc_u_info[krdc->index];
1622 1618 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1623 1619 bitmapname = &urdc->primary.bitmap[0];
1624 1620 else
1625 1621 bitmapname = &urdc->secondary.bitmap[0];
1626 1622
1627 1623 if (header->magic != RDC_HDR_MAGIC) {
1628 1624 cmn_err(CE_WARN, "!rdc_resume_state: Bad magic in %s",
1629 1625 bitmapname);
1630 1626 return (-1);
1631 1627 }
1632 1628
1633 1629 if (strncmp(urdc->primary.file, header->primary.file,
1634 1630 NSC_MAXPATH) != 0) {
1635 1631 #ifdef DEBUG
1636 1632 cmn_err(CE_WARN,
1637 1633 "!rdc_resume_state: Found %s Expected %s",
1638 1634 header->primary.file, urdc->primary.file);
1639 1635 #endif /* DEBUG */
1640 1636 return (-1);
1641 1637 }
1642 1638
1643 1639 if (strncmp(urdc->secondary.file, header->secondary.file,
1644 1640 NSC_MAXPATH) != 0) {
1645 1641 #ifdef DEBUG
1646 1642 cmn_err(CE_WARN,
1647 1643 "!rdc_resume_state: Found %s Expected %s",
1648 1644 header->secondary.file, urdc->secondary.file);
1649 1645 #endif /* DEBUG */
1650 1646 return (-1);
1651 1647 }
1652 1648
1653 1649 if (strncmp(urdc->primary.bitmap, header->primary.bitmap,
1654 1650 NSC_MAXPATH) != 0) {
1655 1651 #ifdef DEBUG
1656 1652 cmn_err(CE_WARN,
1657 1653 "!rdc_resume_state: Found %s Expected %s",
1658 1654 header->primary.bitmap, urdc->primary.bitmap);
1659 1655 #endif /* DEBUG */
1660 1656 return (-1);
1661 1657 }
1662 1658
1663 1659 if (strncmp(urdc->secondary.bitmap, header->secondary.bitmap,
1664 1660 NSC_MAXPATH) != 0) {
1665 1661 #ifdef DEBUG
1666 1662 cmn_err(CE_WARN,
1667 1663 "!rdc_resume_state: Found %s Expected %s",
1668 1664 header->secondary.bitmap, urdc->secondary.bitmap);
1669 1665 #endif /* DEBUG */
1670 1666 return (-1);
1671 1667 }
1672 1668
1673 1669 if (header->maxqfbas)
1674 1670 urdc->maxqfbas = header->maxqfbas;
1675 1671
1676 1672 if (header->maxqitems)
1677 1673 urdc->maxqitems = header->maxqitems;
1678 1674
1679 1675 if (header->autosync >= 0)
1680 1676 urdc->autosync = header->autosync;
1681 1677
1682 1678 if (header->asyncthr)
1683 1679 urdc->asyncthr = header->asyncthr;
1684 1680
1685 1681 rdc_many_enter(krdc);
1686 1682 rdc_set_refcnt_ops(krdc, header->refcntsize);
1687 1683 #ifdef DEBUG_REFCNT
1688 1684 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1689 1685 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1690 1686 #endif
1691 1687 if (header->flags & RDC_VOL_FAILED)
1692 1688 rdc_set_flags(urdc, RDC_VOL_FAILED);
1693 1689 if (header->flags & RDC_QUEUING)
1694 1690 rdc_set_flags(urdc, RDC_QUEUING);
1695 1691
1696 1692 rdc_clr_flags(urdc, RDC_SYNC_NEEDED | RDC_RSYNC_NEEDED);
1697 1693 rdc_set_mflags(urdc, (header->flags & RDC_RSYNC_NEEDED));
1698 1694 rdc_set_flags(urdc, (header->flags & RDC_SYNC_NEEDED));
1699 1695 rdc_many_exit(krdc);
1700 1696
1701 1697 if (urdc->flags & RDC_VOL_FAILED) {
1702 1698
1703 1699 /* Our disk was failed so set all the bits in the bitmap */
1704 1700
1705 1701 if (RDC_FILL_BITMAP(krdc, TRUE) != 0) {
1706 1702 cmn_err(CE_WARN,
1707 1703 "!rdc_resume_state: Fill bitmap %s failed",
1708 1704 bitmapname);
1709 1705 return (-1);
1710 1706 }
1711 1707 rdc_many_enter(krdc);
1712 1708 if (IS_STATE(urdc, RDC_QUEUING))
1713 1709 rdc_clr_flags(urdc, RDC_QUEUING);
1714 1710 rdc_many_exit(krdc);
1715 1711 } else {
1716 1712 /* Header was good, so read in the bitmap */
1717 1713
1718 1714 if (rdc_read_bitmap(krdc, NULL) < 0) {
1719 1715 cmn_err(CE_WARN,
1720 1716 "!rdc_resume_state: Read bitmap %s failed",
1721 1717 bitmapname);
1722 1718 return (-1);
1723 1719 }
1724 1720
1725 1721 urdc->bits_set = RDC_COUNT_BITMAP(krdc);
1726 1722
1727 1723 /*
1728 1724 * Check if another node went down with bits set, but
1729 1725 * without setting logging mode.
1730 1726 */
1731 1727 if (urdc->bits_set != 0 &&
1732 1728 (rdc_get_vflags(urdc) & RDC_ENABLED) &&
1733 1729 !(rdc_get_vflags(urdc) & RDC_LOGGING)) {
1734 1730 rdc_group_log(krdc, RDC_NOFLUSH | RDC_NOREMOTE, NULL);
1735 1731 }
1736 1732 }
1737 1733
1738 1734 /* if we are using a disk queue, read in the reference count bits */
1739 1735 if (RDC_IS_DISKQ(krdc->group)) {
1740 1736 disk_queue *q = &krdc->group->diskq;
1741 1737 mutex_enter(QLOCK(q));
1742 1738 if ((rdc_read_refcount(krdc) < 0)) {
1743 1739 cmn_err(CE_WARN,
1744 1740 "!rdc_resume_state: Resume bitmap %s's refcount"
1745 1741 "failed",
1746 1742 urdc->primary.bitmap);
1747 1743 mutex_exit(QLOCK(q));
1748 1744 rdc_many_enter(krdc);
1749 1745 if (IS_STATE(urdc, RDC_QUEUING))
1750 1746 rdc_clr_flags(urdc, RDC_QUEUING);
1751 1747 rdc_many_exit(krdc);
1752 1748 return (-1);
1753 1749 }
1754 1750 mutex_exit(QLOCK(q));
1755 1751 }
1756 1752
1757 1753 return (0);
1758 1754 }
1759 1755
1760 1756
1761 1757 int
1762 1758 rdc_resume_bitmap(rdc_k_info_t *krdc)
1763 1759 {
1764 1760 rdc_header_t header;
1765 1761 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1766 1762 char *bitmapname;
1767 1763
1768 1764 if (rdc_alloc_bitmap(krdc) < 0)
1769 1765 goto allocfail;
1770 1766
1771 1767 if (rdc_open_bitmap(krdc) < 0)
1772 1768 goto fail;
1773 1769
1774 1770 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1775 1771 bitmapname = &urdc->primary.bitmap[0];
1776 1772 else
1777 1773 bitmapname = &urdc->secondary.bitmap[0];
1778 1774
1779 1775 mutex_enter(&krdc->bmapmutex);
1780 1776
1781 1777 rdc_clr_flags(urdc, RDC_BMP_FAILED);
1782 1778 if (rdc_read_header(krdc, &header) < 0) {
1783 1779 cmn_err(CE_WARN,
1784 1780 "!rdc_resume_bitmap: Read header %s failed", bitmapname);
1785 1781 mutex_exit(&krdc->bmapmutex);
1786 1782 goto fail;
1787 1783 }
1788 1784
1789 1785 mutex_exit(&krdc->bmapmutex);
1790 1786
1791 1787 /* Resuming from the bitmap, so do some checking */
1792 1788
1793 1789 /*CONSTCOND*/
1794 1790 ASSERT(FBA_LEN(sizeof (rdc_header_t)) <= RDC_BITMAP_FBA);
1795 1791 /*CONSTCOND*/
1796 1792 ASSERT(sizeof (rdc_header_t) >= sizeof (rdc_headerv2_t));
1797 1793
1798 1794 if (header.magic == RDC_HDR_V2) {
1799 1795 rdc_headerv2_t *hdr_v2 = (rdc_headerv2_t *)&header;
1800 1796 rdc_header_t new_header;
1801 1797
1802 1798 #ifdef DEBUG
1803 1799 cmn_err(CE_WARN,
1804 1800 "!rdc_resume_bitmap: Converting v2 header for bitmap %s",
1805 1801 bitmapname);
1806 1802 #endif
1807 1803 bzero((char *)&new_header, sizeof (rdc_header_t));
1808 1804
1809 1805 new_header.autosync = -1;
1810 1806 new_header.magic = RDC_HDR_MAGIC;
1811 1807 new_header.syshostid = urdc->syshostid;
1812 1808
1813 1809 if (hdr_v2->volume_failed)
1814 1810 new_header.flags |= RDC_VOL_FAILED;
1815 1811 if (hdr_v2->sync_needed == RDC_SYNC)
1816 1812 new_header.flags |= RDC_SYNC_NEEDED;
1817 1813 if (hdr_v2->sync_needed == RDC_FULL_SYNC)
1818 1814 new_header.flags |= RDC_SYNC_NEEDED;
1819 1815 if (hdr_v2->sync_needed == RDC_REV_SYNC)
1820 1816 new_header.flags |= RDC_RSYNC_NEEDED;
1821 1817 if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
1822 1818 (void) strncpy(new_header.primary.file,
1823 1819 hdr_v2->filename, NSC_MAXPATH);
1824 1820 (void) strncpy(new_header.primary.bitmap,
1825 1821 hdr_v2->bitmapname, NSC_MAXPATH);
1826 1822 (void) strncpy(new_header.secondary.file,
1827 1823 urdc->secondary.file, NSC_MAXPATH);
1828 1824 (void) strncpy(new_header.secondary.bitmap,
1829 1825 urdc->secondary.bitmap, NSC_MAXPATH);
1830 1826 } else {
1831 1827 (void) strncpy(new_header.secondary.file,
1832 1828 hdr_v2->filename, NSC_MAXPATH);
1833 1829 (void) strncpy(new_header.secondary.bitmap,
1834 1830 hdr_v2->bitmapname, NSC_MAXPATH);
1835 1831 (void) strncpy(new_header.primary.file,
1836 1832 urdc->primary.file, NSC_MAXPATH);
1837 1833 (void) strncpy(new_header.primary.bitmap,
1838 1834 urdc->primary.bitmap, NSC_MAXPATH);
1839 1835 }
1840 1836
1841 1837 bcopy(&new_header, &header, sizeof (rdc_header_t));
1842 1838
1843 1839 mutex_enter(&krdc->bmapmutex);
1844 1840 if (rdc_write_header(krdc, &header) < 0) {
1845 1841 mutex_exit(&krdc->bmapmutex);
1846 1842 cmn_err(CE_WARN,
1847 1843 "!rdc_resume_bitmap: Write header %s failed",
1848 1844 bitmapname);
1849 1845 goto fail;
1850 1846 }
1851 1847 mutex_exit(&krdc->bmapmutex);
1852 1848
1853 1849 } else if (header.magic == RDC_HDR_V3) {
1854 1850 /*
1855 1851 * just update asyncthr and magic, and then we're done
1856 1852 */
1857 1853 header.magic = RDC_HDR_MAGIC;
1858 1854 header.asyncthr = RDC_ASYNCTHR;
1859 1855 mutex_enter(&krdc->bmapmutex);
1860 1856 if (rdc_write_header(krdc, &header) < 0) {
1861 1857 mutex_exit(&krdc->bmapmutex);
1862 1858 cmn_err(CE_WARN,
1863 1859 "!rdc_resume_bitmap: Write header %s failed",
1864 1860 bitmapname);
1865 1861 goto fail;
1866 1862 }
1867 1863 mutex_exit(&krdc->bmapmutex);
1868 1864 }
1869 1865
1870 1866 if (rdc_resume_state(krdc, &header) == 0)
1871 1867 return (0);
1872 1868
1873 1869 rdc_close_bitmap(krdc);
1874 1870
1875 1871 fail:
1876 1872 (void) RDC_FILL_BITMAP(krdc, FALSE);
1877 1873 rdc_clr_flags(urdc, RDC_QUEUING);
1878 1874 if (krdc->bitmap_ref)
1879 1875 bzero(krdc->bitmap_ref, krdc->bitmap_size * BITS_IN_BYTE *
1880 1876 rdc_refcntsize(krdc));
1881 1877
1882 1878 allocfail:
1883 1879 mutex_enter(&krdc->bmapmutex);
1884 1880 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "resume bitmap failed");
1885 1881 mutex_exit(&krdc->bmapmutex);
1886 1882
1887 1883 return (-1);
1888 1884 }
1889 1885
1890 1886 void
1891 1887 rdc_std_zero_bitref(rdc_k_info_t *krdc)
1892 1888 {
1893 1889 nsc_size_t vol_size;
1894 1890 int sts;
1895 1891 size_t newrefcntsize;
1896 1892
1897 1893 if (krdc->bitmap_ref) {
1898 1894 mutex_enter(&krdc->bmapmutex);
1899 1895 bzero(krdc->bitmap_ref, krdc->bitmap_size * BITS_IN_BYTE *
1900 1896 BMAP_REF_PREF_SIZE);
1901 1897 if (RDC_IS_DISKQ(krdc->group) && rdc_refcntsize(krdc) !=
1902 1898 BMAP_REF_PREF_SIZE) {
1903 1899 /* see if we can upgrade the size of the ref counters */
1904 1900 sts = _rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL);
1905 1901 if (!RDC_SUCCESS(sts)) {
1906 1902 goto nochange;
1907 1903 }
1908 1904 sts = nsc_partsize(krdc->bitmapfd, &vol_size);
1909 1905
1910 1906 newrefcntsize = rdc_ref_size_possible(krdc->bitmap_size,
1911 1907 vol_size);
1912 1908 if (newrefcntsize > rdc_refcntsize(krdc)) {
1913 1909 rdc_set_refcnt_ops(krdc, newrefcntsize);
1914 1910 #ifdef DEBUG_REFCNT
1915 1911 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1916 1912 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1917 1913 #endif
1918 1914 }
1919 1915 nochange:
1920 1916 _rdc_rlse_devs(krdc, RDC_BMP);
1921 1917 }
1922 1918 mutex_exit(&krdc->bmapmutex);
1923 1919 }
1924 1920 }
1925 1921
1926 1922 int
1927 1923 rdc_reset_bitmap(rdc_k_info_t *krdc)
1928 1924 {
1929 1925 rdc_u_info_t *urdc;
1930 1926 rdc_header_t header;
1931 1927 char *bitmapname;
1932 1928
1933 1929 urdc = &rdc_u_info[krdc->index];
1934 1930 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1935 1931 bitmapname = &urdc->primary.bitmap[0];
1936 1932 else
1937 1933 bitmapname = &urdc->secondary.bitmap[0];
1938 1934
1939 1935 mutex_enter(&krdc->bmapmutex);
1940 1936
1941 1937 rdc_clr_flags(urdc, RDC_BMP_FAILED);
1942 1938 if (rdc_read_header(krdc, &header) < 0) {
1943 1939 cmn_err(CE_WARN,
1944 1940 "!rdc_reset_bitmap: Read header %s failed", bitmapname);
1945 1941 goto fail_with_mutex;
1946 1942 }
1947 1943
1948 1944 rdc_fill_header(urdc, &header);
1949 1945
1950 1946 if (rdc_write_header(krdc, &header) < 0) {
1951 1947 cmn_err(CE_WARN,
1952 1948 "!rdc_reset_bitmap: Write header %s failed",
1953 1949 bitmapname);
1954 1950 goto fail_with_mutex;
1955 1951 }
1956 1952 mutex_exit(&krdc->bmapmutex);
1957 1953
1958 1954 if (krdc->bitmap_write == -1)
1959 1955 krdc->bitmap_write = 0;
1960 1956
1961 1957 if (krdc->bitmap_write == 0) {
1962 1958 if (rdc_write_bitmap_fill(krdc) < 0) {
1963 1959 cmn_err(CE_WARN,
1964 1960 "!rdc_reset_bitmap: Write bitmap %s failed",
1965 1961 bitmapname);
1966 1962 goto fail;
1967 1963 }
1968 1964 krdc->bitmap_write = -1;
1969 1965 } else if (rdc_write_bitmap(krdc) < 0) {
1970 1966 cmn_err(CE_WARN,
1971 1967 "!rdc_reset_bitmap: Write bitmap %s failed",
1972 1968 bitmapname);
1973 1969 goto fail;
1974 1970 }
1975 1971
1976 1972 return (0);
1977 1973
1978 1974 fail:
1979 1975 mutex_enter(&krdc->bmapmutex);
1980 1976 fail_with_mutex:
1981 1977 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reset failed");
1982 1978 mutex_exit(&krdc->bmapmutex);
1983 1979 #ifdef DEBUG
1984 1980 cmn_err(CE_NOTE, "!SNDR: unable to reset bitmap for %s:%s",
1985 1981 urdc->secondary.intf, urdc->secondary.file);
1986 1982 #endif
1987 1983 return (-1);
1988 1984 }
1989 1985
1990 1986
1991 1987 /*
1992 1988 * General bitmap operations
1993 1989 */
1994 1990
1995 1991 /*
1996 1992 * rdc_set_bitmap_many()
1997 1993 *
1998 1994 * Used during reverse syncs to a 1-to-many primary to keep the 'many'
1999 1995 * bitmaps up to date.
2000 1996 */
2001 1997 void
2002 1998 rdc_set_bitmap_many(rdc_k_info_t *krdc, nsc_off_t pos, nsc_size_t len)
2003 1999 {
2004 2000 uint_t dummy;
2005 2001
2006 2002 #ifdef DEBUG
2007 2003 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2008 2004 if (!(rdc_get_vflags(urdc) & RDC_PRIMARY)) {
2009 2005 cmn_err(CE_PANIC, "rdc_set_bitmap_many: not primary, urdc %p",
2010 2006 (void *) urdc);
2011 2007 }
2012 2008 #endif
2013 2009
2014 2010 if (IS_MANY(krdc)) {
2015 2011 rdc_k_info_t *krd;
2016 2012 rdc_u_info_t *urd;
2017 2013
2018 2014 rdc_many_enter(krdc);
2019 2015
2020 2016 for (krd = krdc->many_next; krd != krdc; krd = krd->many_next) {
2021 2017 urd = &rdc_u_info[krd->index];
2022 2018 if (!IS_ENABLED(urd))
2023 2019 continue;
2024 2020 ASSERT(urd->flags & RDC_PRIMARY);
2025 2021 (void) RDC_SET_BITMAP(krd, pos, len, &dummy);
2026 2022 }
2027 2023
2028 2024 rdc_many_exit(krdc);
2029 2025 }
2030 2026 }
2031 2027
2032 2028
2033 2029 static int
2034 2030 _rdc_net_bmap(const struct bmap6 *b6, net_bdata6 *bd6)
2035 2031 {
2036 2032 rdc_k_info_t *krdc = &rdc_k_info[b6->cd];
2037 2033 struct timeval t;
2038 2034 int e, ret;
2039 2035 uint64_t left;
2040 2036 uint64_t bmap_blksize;
2041 2037
2042 2038 bmap_blksize = krdc->rpc_version < RDC_VERSION7 ?
2043 2039 BMAP_BLKSIZE : BMAP_BLKSIZEV7;
2044 2040
2045 2041 t.tv_sec = rdc_rpc_tmout;
2046 2042 t.tv_usec = 0;
2047 2043
2048 2044 if (bd6->data.data_val == NULL) {
2049 2045 return (EINVAL);
2050 2046 }
2051 2047
2052 2048 left = b6->size;
2053 2049 bd6->endoblk = 0;
2054 2050 while (left) {
2055 2051 if (left >= bmap_blksize)
2056 2052 bd6->size = (int)bmap_blksize;
2057 2053 else
2058 2054 bd6->size = (int)left;
2059 2055
2060 2056 bd6->data.data_len = bd6->size;
2061 2057
2062 2058 if ((uint64_t)bd6->size > left) {
2063 2059 left = 0;
2064 2060 } else {
2065 2061 left -= bd6->size;
2066 2062 }
2067 2063 /*
2068 2064 * mark the last block sent.
2069 2065 */
2070 2066 if (left == 0) {
2071 2067 bd6->endoblk = 1;
2072 2068 }
2073 2069 ASSERT(krdc->rpc_version);
2074 2070 if (krdc->rpc_version <= RDC_VERSION5) {
2075 2071 struct net_bdata bd;
2076 2072 bd.cd = bd6->cd;
2077 2073 bd.offset = bd6->offset;
2078 2074 bd.size = bd6->size;
2079 2075 bd.data.data_len = bd6->data.data_len;
2080 2076 bd.data.data_val = bd6->data.data_val;
2081 2077 e = rdc_clnt_call(krdc->lsrv, RDCPROC_BDATA,
2082 2078 krdc->rpc_version, xdr_net_bdata, (char *)&bd,
2083 2079 xdr_int, (char *)&ret, &t);
2084 2080 } else {
2085 2081 e = rdc_clnt_call(krdc->lsrv, RDCPROC_BDATA6,
2086 2082 krdc->rpc_version, xdr_net_bdata6, (char *)bd6,
2087 2083 xdr_int, (char *)&ret, &t);
2088 2084 }
2089 2085 if (e || ret) {
2090 2086 if (e)
2091 2087 ret = e;
2092 2088 return (ret);
2093 2089 }
2094 2090 bd6->offset += bmap_blksize;
2095 2091 bd6->data.data_val += bmap_blksize;
2096 2092 }
2097 2093 return (0);
2098 2094 }
2099 2095
2100 2096
2101 2097 /*
2102 2098 * Standard bitmap operations (combined kmem/disk bitmaps).
2103 2099 */
2104 2100
2105 2101 /*
2106 2102 * rdc_std_set_bitmask(pos, len, &bitmask)
2107 2103 * set a bitmask for this range. used to clear the correct
2108 2104 * bits after flushing
2109 2105 */
2110 2106 static void
2111 2107 rdc_std_set_bitmask(const nsc_off_t fba_pos, const nsc_size_t fba_len,
2112 2108 uint_t *bitmask)
2113 2109 {
2114 2110 int first, st, en;
2115 2111 if (bitmask)
2116 2112 *bitmask = 0;
2117 2113 else
2118 2114 return;
2119 2115
2120 2116 first = st = FBA_TO_LOG_NUM(fba_pos);
2121 2117 en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2122 2118 while (st <= en) {
2123 2119 BMAP_BIT_SET((uchar_t *)bitmask, st - first);
2124 2120 st++;
2125 2121 }
2126 2122
2127 2123 }
2128 2124 /*
2129 2125 * rdc_std_set_bitmap(krdc, fba_pos, fba_len, &bitmask)
2130 2126 *
2131 2127 * Mark modified segments in the dual copy file bitmap
2132 2128 * to provide fast recovery
2133 2129 * Note that bitmask allows for 32 segments, which at 32k per segment equals
2134 2130 * 1 megabyte. If we ever allow more than this to be transferred in one
2135 2131 * operation, or decrease the segment size, then this code will have to be
2136 2132 * changed accordingly.
2137 2133 */
2138 2134
2139 2135 static int
2140 2136 rdc_std_set_bitmap(rdc_k_info_t *krdc, const nsc_off_t fba_pos,
2141 2137 const nsc_size_t fba_len, uint_t *bitmask)
2142 2138 {
2143 2139 int first, st, en;
2144 2140 int fbaset = 0;
2145 2141 nsc_off_t fba = 0;
2146 2142 int printerr = 10;
2147 2143 int tries = RDC_FUTILE_ATTEMPTS;
2148 2144 int queuing = RDC_QUEUING;
2149 2145 rdc_u_info_t *urdc;
2150 2146
2151 2147 if (bitmask)
2152 2148 *bitmask = 0;
2153 2149 else
2154 2150 return (-1);
2155 2151
2156 2152 urdc = &rdc_u_info[krdc->index];
2157 2153 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2158 2154 return (-1);
2159 2155
2160 2156 if (krdc->bitmap_write == 0) {
2161 2157 if (rdc_write_bitmap_fill(krdc) < 0)
2162 2158 return (-1);
2163 2159 krdc->bitmap_write = -1;
2164 2160 }
2165 2161 first = st = FBA_TO_LOG_NUM(fba_pos);
2166 2162 en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2167 2163 ASSERT(st <= en);
2168 2164 while (st <= en) {
2169 2165 int use_ref;
2170 2166 again:
2171 2167 mutex_enter(&krdc->bmapmutex);
2172 2168
2173 2169 if (krdc->dcio_bitmap == NULL) {
2174 2170 #ifdef DEBUG
2175 2171 cmn_err(CE_WARN, "!rdc_std_set_bitmap: "
2176 2172 "recovery bitmaps not allocated");
2177 2173 #endif
2178 2174 mutex_exit(&krdc->bmapmutex);
2179 2175 return (-1);
2180 2176 }
2181 2177
2182 2178 use_ref = IS_PRIMARY(urdc) && IS_ASYNC(urdc) &&
2183 2179 ((rdc_get_vflags(urdc) & RDC_QUEUING) ||
2184 2180 !(rdc_get_vflags(urdc) & RDC_LOGGING));
2185 2181
2186 2182
2187 2183 if (!BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2188 2184 BMAP_BIT_SET(krdc->dcio_bitmap, st);
2189 2185 if (use_ref) {
2190 2186 ASSERT(BMAP_REF_ISSET(krdc, st) ==
2191 2187 0);
2192 2188 BMAP_REF_FORCE(krdc, st, 1);
2193 2189 }
2194 2190 BMAP_BIT_SET((uchar_t *)bitmask, st - first);
2195 2191 urdc->bits_set++;
2196 2192 if ((!fbaset) || fba != BIT_TO_FBA(st)) {
2197 2193 if (fbaset && krdc->bitmap_write > 0) {
2198 2194 mutex_exit(&krdc->bmapmutex);
2199 2195 if (rdc_write_bitmap_fba(krdc, fba) < 0)
2200 2196 return (-1);
2201 2197 mutex_enter(&krdc->bmapmutex);
2202 2198 }
2203 2199 fba = BIT_TO_FBA(st);
2204 2200 fbaset = 1;
2205 2201 }
2206 2202 } else {
2207 2203 /*
2208 2204 * Just bump reference count
2209 2205 * For logging or syncing we do not care what the reference
2210 2206 * is as it will be forced back on the state transition.
2211 2207 */
2212 2208 if (use_ref) {
2213 2209 if (BMAP_REF_ISSET(krdc, st) ==
2214 2210 BMAP_REF_MAXVAL(krdc)) {
2215 2211 /*
2216 2212 * Rollover of reference count.
2217 2213 */
2218 2214
2219 2215 if (!(rdc_get_vflags(urdc) &
2220 2216 RDC_VOL_FAILED)) {
2221 2217 /*
2222 2218 * Impose throttle to help dump
2223 2219 * queue
2224 2220 */
2225 2221 mutex_exit(&krdc->bmapmutex);
2226 2222 delay(4);
2227 2223 rdc_bitmap_delay++;
2228 2224 if (printerr--) {
2229 2225 cmn_err(CE_WARN, "!SNDR: bitmap reference count maxed out for %s:%s",
2230 2226 urdc->secondary.intf, urdc->secondary.file);
2231 2227
2232 2228 }
2233 2229
2234 2230 if ((tries-- <= 0) &&
2235 2231 IS_STATE(urdc, queuing)) {
2236 2232 cmn_err(CE_WARN, "!SNDR: giving up on reference count, logging set"
2237 2233 " %s:%s", urdc->secondary.intf, urdc->secondary.file);
2238 2234 rdc_group_enter(krdc);
2239 2235 rdc_group_log(krdc,
2240 2236 RDC_NOFLUSH |
2241 2237 RDC_NOREMOTE|
2242 2238 RDC_FORCE_GROUP,
2243 2239 "ref count retry limit exceeded");
2244 2240 rdc_group_exit(krdc);
2245 2241 }
2246 2242 goto again;
2247 2243 }
2248 2244 } else {
2249 2245 BMAP_REF_SET(krdc, st);
2250 2246 }
2251 2247 }
2252 2248 }
2253 2249 mutex_exit(&krdc->bmapmutex);
2254 2250 st++;
2255 2251 }
2256 2252 if (fbaset && krdc->bitmap_write > 0) {
2257 2253 if (rdc_write_bitmap_fba(krdc, fba) < 0)
2258 2254 return (-1);
2259 2255 }
2260 2256 return (0);
2261 2257 }
2262 2258
2263 2259 static void
2264 2260 rdc_std_clr_bitmap(rdc_k_info_t *krdc, const nsc_off_t fba_pos,
2265 2261 const nsc_size_t fba_len, const uint_t bitmask, const int force)
2266 2262 {
2267 2263 int first, st, en;
2268 2264 nsc_off_t fba = 0;
2269 2265 int fbaset = 0;
2270 2266 uint_t bm = bitmask;
2271 2267 uchar_t *ptr = (uchar_t *)&bm;
2272 2268 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2273 2269
2274 2270 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2275 2271 return;
2276 2272
2277 2273 first = st = FBA_TO_LOG_NUM(fba_pos);
2278 2274 en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2279 2275 ASSERT(st <= en);
2280 2276 while (st <= en) {
2281 2277 mutex_enter(&krdc->bmapmutex);
2282 2278
2283 2279 if (krdc->dcio_bitmap == NULL) {
2284 2280 #ifdef DEBUG
2285 2281 cmn_err(CE_WARN, "!rdc_std_clr_bitmap: "
2286 2282 "recovery bitmaps not allocated");
2287 2283 #endif
2288 2284 mutex_exit(&krdc->bmapmutex);
2289 2285 return;
2290 2286 }
2291 2287
2292 2288 if (((bitmask == 0xffffffff) ||
2293 2289 (BMAP_BIT_ISSET(ptr, st - first))) &&
2294 2290 BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2295 2291
2296 2292 int use_ref = IS_PRIMARY(urdc) && IS_ASYNC(urdc) &&
2297 2293 ((rdc_get_vflags(urdc) & RDC_QUEUING) ||
2298 2294 !(rdc_get_vflags(urdc) & RDC_LOGGING));
2299 2295
2300 2296 if (force || (use_ref == 0)) {
2301 2297 if (krdc->bitmap_ref)
2302 2298 BMAP_REF_FORCE(krdc, st, 0);
2303 2299 } else if (use_ref) {
2304 2300 if (BMAP_REF_ISSET(krdc, st) != 0)
2305 2301 BMAP_REF_CLR(krdc, st);
2306 2302
2307 2303 }
2308 2304
2309 2305 if ((use_ref == 0) || (use_ref &&
2310 2306 !BMAP_REF_ISSET(krdc, st))) {
2311 2307 BMAP_BIT_CLR(krdc->dcio_bitmap, st);
2312 2308
2313 2309 urdc->bits_set--;
2314 2310 if (!fbaset || fba != BIT_TO_FBA(st)) {
2315 2311 if (fbaset &&
2316 2312 krdc->bitmap_write > 0) {
2317 2313 mutex_exit(&krdc->bmapmutex);
2318 2314 if (rdc_write_bitmap_fba(krdc,
2319 2315 fba) < 0)
2320 2316 return;
2321 2317 mutex_enter(&krdc->bmapmutex);
2322 2318 }
2323 2319 fba = BIT_TO_FBA(st);
2324 2320 fbaset = 1;
2325 2321 }
2326 2322 }
2327 2323 }
2328 2324 mutex_exit(&krdc->bmapmutex);
2329 2325 st++;
2330 2326 }
2331 2327 if (fbaset && krdc->bitmap_write > 0) {
2332 2328 if (rdc_write_bitmap_fba(krdc, fba) < 0)
2333 2329 return;
2334 2330 }
2335 2331 }
2336 2332
2337 2333 /*
2338 2334 * make sure that this bit is set. if it isn't, set it
2339 2335 * used when transitioning from async to sync while going
2340 2336 * from rep to log. an overlapping sync write may unconditionally
2341 2337 * clear the bit that has not been replicated. when the queue
2342 2338 * is being dumped or this is called just to make sure pending stuff
2343 2339 * is in the bitmap
2344 2340 */
2345 2341 void
2346 2342 rdc_std_check_bit(rdc_k_info_t *krdc, nsc_off_t pos, nsc_size_t len)
2347 2343 {
2348 2344 int st;
2349 2345 int en;
2350 2346 nsc_off_t fba;
2351 2347 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2352 2348 st = FBA_TO_LOG_NUM(pos);
2353 2349 en = FBA_TO_LOG_NUM(pos + len - 1);
2354 2350
2355 2351 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2356 2352 return;
2357 2353
2358 2354 while (st <= en) {
2359 2355 mutex_enter(&krdc->bmapmutex);
2360 2356
2361 2357 if (krdc->dcio_bitmap == NULL) {
2362 2358 #ifdef DEBUG
2363 2359 cmn_err(CE_WARN, "!rdc_std_check_bit: "
2364 2360 "recovery bitmaps not allocated");
2365 2361 #endif
2366 2362 mutex_exit(&krdc->bmapmutex);
2367 2363 return;
2368 2364 }
2369 2365
2370 2366 if (!BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2371 2367 BMAP_BIT_SET(krdc->dcio_bitmap, st);
2372 2368 if (krdc->bitmap_write > 0) {
2373 2369 fba = BIT_TO_FBA(st);
2374 2370 mutex_exit(&krdc->bmapmutex);
2375 2371 (void) rdc_write_bitmap_fba(krdc, fba);
2376 2372 mutex_enter(&krdc->bmapmutex);
2377 2373 }
2378 2374 urdc->bits_set++;
2379 2375
2380 2376 }
2381 2377 mutex_exit(&krdc->bmapmutex);
2382 2378 st++;
2383 2379 }
2384 2380
2385 2381 }
2386 2382
2387 2383 /*
2388 2384 * rdc_std_count_dirty(krdc):
2389 2385 *
2390 2386 * Determine the number of segments that need to be flushed, This should
2391 2387 * agree with the number of segments logged, but since we don't lock when
2392 2388 * we increment, we force these values to agree
2393 2389 */
2394 2390 static int
2395 2391 rdc_std_count_dirty(rdc_k_info_t *krdc)
2396 2392 {
2397 2393 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2398 2394 int i, count, size;
2399 2395
2400 2396 if (krdc->dcio_bitmap == NULL) {
2401 2397 #ifdef DEBUG
2402 2398 cmn_err(CE_WARN,
2403 2399 "!rdc_std_count_dirty: no bitmap configured for %s",
2404 2400 urdc->primary.file);
2405 2401 #endif
2406 2402 return (0);
2407 2403 }
2408 2404
2409 2405 count = 0;
2410 2406 ASSERT(urdc->volume_size != 0);
2411 2407 size = FBA_TO_LOG_LEN(urdc->volume_size);
2412 2408 for (i = 0; i < size; i++)
2413 2409 if (BMAP_BIT_ISSET(krdc->dcio_bitmap, i))
2414 2410 count++;
2415 2411
2416 2412 if (count > size)
2417 2413 count = size;
2418 2414
2419 2415 return (count);
2420 2416 }
2421 2417
2422 2418
2423 2419 static int
2424 2420 rdc_std_bit_isset(rdc_k_info_t *krdc, const int bit)
2425 2421 {
2426 2422 return (BMAP_BIT_ISSET(krdc->dcio_bitmap, bit));
2427 2423 }
2428 2424
2429 2425
2430 2426 /*
2431 2427 * rdc_std_fill_bitmap(krdc, write)
2432 2428 *
2433 2429 * Called to force bitmaps to a fully dirty state
2434 2430 */
2435 2431 static int
2436 2432 rdc_std_fill_bitmap(rdc_k_info_t *krdc, const int write)
2437 2433 {
2438 2434 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2439 2435 int i, size;
2440 2436
2441 2437 if (krdc->dcio_bitmap == NULL) {
2442 2438 #ifdef DEBUG
2443 2439 cmn_err(CE_WARN,
2444 2440 "!rdc_std_fill_bitmap: no bitmap configured for %s",
2445 2441 urdc->primary.file);
2446 2442 #endif
2447 2443 return (-1);
2448 2444 }
2449 2445
2450 2446 ASSERT(urdc->volume_size != 0);
2451 2447 size = FBA_TO_LOG_LEN(urdc->volume_size);
2452 2448 for (i = 0; i < size; i++)
2453 2449 BMAP_BIT_SET(krdc->dcio_bitmap, i);
2454 2450
2455 2451 urdc->bits_set = size;
2456 2452
2457 2453 if (write)
2458 2454 return (rdc_write_bitmap(krdc));
2459 2455
2460 2456 return (0);
2461 2457 }
2462 2458
2463 2459
2464 2460 /*
2465 2461 * rdc_std_zero_bitmap(krdc)
2466 2462 *
2467 2463 * Called on the secondary after a sync has completed to force bitmaps
2468 2464 * to a fully clean state
2469 2465 */
2470 2466 static void
2471 2467 rdc_std_zero_bitmap(rdc_k_info_t *krdc)
2472 2468 {
2473 2469 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2474 2470 int i, size;
2475 2471
2476 2472 if (krdc->dcio_bitmap == NULL) {
2477 2473 #ifdef DEBUG
2478 2474 cmn_err(CE_WARN,
2479 2475 "!rdc_std_zero_bitmap: no bitmap configured for %s",
2480 2476 urdc->primary.file);
2481 2477 #endif
2482 2478 return;
2483 2479 }
2484 2480 #ifdef DEBUG
2485 2481 cmn_err(CE_NOTE, "!Clearing bitmap for %s", urdc->secondary.file);
2486 2482 #endif
2487 2483
2488 2484 ASSERT(urdc->volume_size != 0);
2489 2485 size = FBA_TO_LOG_LEN(urdc->volume_size);
2490 2486 for (i = 0; i < size; i++)
2491 2487 BMAP_BIT_CLR(krdc->dcio_bitmap, i);
2492 2488 if (krdc->bitmap_write > 0)
2493 2489 (void) rdc_write_bitmap(krdc);
2494 2490
2495 2491 urdc->bits_set = 0;
2496 2492 }
2497 2493
2498 2494
2499 2495 /*
2500 2496 * rdc_std_net_bmap()
2501 2497 *
2502 2498 * WARNING acts as both client and server
2503 2499 */
2504 2500 static int
2505 2501 rdc_std_net_bmap(const struct bmap6 *b)
2506 2502 {
2507 2503 rdc_k_info_t *krdc = &rdc_k_info[b->cd];
2508 2504 struct net_bdata6 bd;
2509 2505
2510 2506 bd.data.data_val = (char *)krdc->dcio_bitmap;
2511 2507 bd.cd = b->dual;
2512 2508 bd.offset = 0;
2513 2509
2514 2510 return (_rdc_net_bmap(b, &bd));
2515 2511 }
2516 2512
2517 2513
2518 2514 /*
2519 2515 * rdc_std_net_bdata
2520 2516 */
2521 2517 static int
2522 2518 rdc_std_net_bdata(const struct net_bdata6 *bd)
2523 2519 {
2524 2520 rdc_k_info_t *krdc = &rdc_k_info[bd->cd];
2525 2521
2526 2522 rdc_lor((uchar_t *)bd->data.data_val,
2527 2523 (uchar_t *)(((char *)krdc->dcio_bitmap) + bd->offset), bd->size);
2528 2524
2529 2525 return (0);
2530 2526 }
2531 2527
2532 2528
2533 2529 static struct rdc_bitmap_ops rdc_std_bitmap_ops = {
2534 2530 rdc_std_set_bitmap,
2535 2531 rdc_std_clr_bitmap,
2536 2532 rdc_std_count_dirty,
2537 2533 rdc_std_bit_isset,
2538 2534 rdc_std_fill_bitmap,
2539 2535 rdc_std_zero_bitmap,
2540 2536 rdc_std_net_bmap,
2541 2537 rdc_std_net_bdata,
2542 2538 rdc_std_zero_bitref,
2543 2539 rdc_std_set_bitmask,
2544 2540 rdc_std_check_bit
2545 2541 };
2546 2542
2547 2543
2548 2544 void
2549 2545 rdc_bitmap_init()
2550 2546 {
2551 2547 rdc_bitmap_ops = &rdc_std_bitmap_ops;
2552 2548 rdc_wrflag = NSC_WRITE;
2553 2549 }
2554 2550
2555 2551 static void
2556 2552 rdc_bmap_ref_byte_set(rdc_k_info_t *krdc, int ind)
2557 2553 {
2558 2554 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2559 2555
2560 2556 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2561 2557 bmap[ind]++;
2562 2558 }
2563 2559
2564 2560 static void
2565 2561 rdc_bmap_ref_byte_clr(rdc_k_info_t *krdc, int ind)
2566 2562 {
2567 2563 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2568 2564
2569 2565 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2570 2566 bmap[ind]--;
2571 2567 }
2572 2568
2573 2569 static unsigned int
2574 2570 rdc_bmap_ref_byte_isset(rdc_k_info_t *krdc, int ind)
2575 2571 {
2576 2572 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2577 2573
2578 2574 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2579 2575 return ((unsigned int)(bmap[ind]));
2580 2576 }
2581 2577
2582 2578 static void
2583 2579 rdc_bmap_ref_byte_force(rdc_k_info_t *krdc, int ind, unsigned int val)
2584 2580 {
2585 2581 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2586 2582
2587 2583 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2588 2584 bmap[ind] = (unsigned char) val;
2589 2585 }
2590 2586
2591 2587 /* ARGSUSED */
2592 2588 static unsigned int
2593 2589 rdc_bmap_ref_byte_maxval(rdc_k_info_t *krdc)
2594 2590 {
2595 2591 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2596 2592 return ((unsigned int)(UINT8_MAX));
2597 2593 }
2598 2594
2599 2595 struct bm_ref_ops rdc_ref_byte_ops = {
2600 2596 rdc_bmap_ref_byte_set,
2601 2597 rdc_bmap_ref_byte_clr,
2602 2598 rdc_bmap_ref_byte_isset,
2603 2599 rdc_bmap_ref_byte_force,
2604 2600 rdc_bmap_ref_byte_maxval,
2605 2601 sizeof (unsigned char)
2606 2602 };
2607 2603
2608 2604 static void
2609 2605 rdc_bmap_ref_int_set(rdc_k_info_t *krdc, int ind)
2610 2606 {
2611 2607 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2612 2608
2613 2609 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2614 2610 bmap[ind]++;
2615 2611 }
2616 2612
2617 2613 static void
2618 2614 rdc_bmap_ref_int_clr(rdc_k_info_t *krdc, int ind)
2619 2615 {
2620 2616 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2621 2617
2622 2618 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2623 2619 bmap[ind]--;
2624 2620 }
2625 2621
2626 2622 static unsigned int
2627 2623 rdc_bmap_ref_int_isset(rdc_k_info_t *krdc, int ind)
2628 2624 {
2629 2625 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2630 2626
2631 2627 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2632 2628 return ((bmap[ind]));
2633 2629 }
2634 2630
2635 2631 static void
2636 2632 rdc_bmap_ref_int_force(rdc_k_info_t *krdc, int ind, unsigned int val)
2637 2633 {
2638 2634 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2639 2635
2640 2636 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2641 2637 bmap[ind] = val;
2642 2638 }
2643 2639
2644 2640 /* ARGSUSED */
2645 2641 static unsigned int
2646 2642 rdc_bmap_ref_int_maxval(rdc_k_info_t *krdc)
2647 2643 {
2648 2644 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2649 2645 return ((unsigned int)(UINT_MAX));
2650 2646 }
2651 2647
2652 2648 struct bm_ref_ops rdc_ref_int_ops = {
2653 2649 rdc_bmap_ref_int_set,
2654 2650 rdc_bmap_ref_int_clr,
2655 2651 rdc_bmap_ref_int_isset,
2656 2652 rdc_bmap_ref_int_force,
2657 2653 rdc_bmap_ref_int_maxval,
2658 2654 sizeof (unsigned int)
2659 2655 };
↓ open down ↓ |
2013 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX