1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * copyright (c) 1990, 1991 UNIX System Laboratories, Inc. 27 * copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T 28 * All rights reserved. 29 */ 30 31 /* 32 * Copyrighted as an unpublished work. 33 * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990 34 * All rights reserved. 35 */ 36 37 #pragma ident "%Z%%M% %I% %E% SMI" 38 39 #include <sys/types.h> 40 #include <ctype.h> 41 #include <fcntl.h> 42 #include <malloc.h> 43 #include <sys/stat.h> 44 #include <sys/swap.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <sys/vtoc.h> 48 #include <sys/param.h> 49 #include <sys/dkio.h> 50 #include <sys/dktp/altsctr.h> 51 #include <sys/dktp/fdisk.h> 52 #include "badsec.h" 53 #include "global.h" 54 #include "ctlr_ata.h" 55 #include "misc.h" 56 57 #define FAILURE 1 58 #define SUCCESS 0 59 60 #define CMD_READ 0 61 #define CMD_WRITE 1 62 63 extern daddr_t altsec_offset; /* Alternate sector offset */ 64 65 struct badsec_lst *badsl_chain = NULL; 66 int badsl_chain_cnt = 0; 67 struct badsec_lst *gbadsl_chain = NULL; 68 int gbadsl_chain_cnt = 0; 69 70 static struct alts_mempart alts_part = { 0, NULL, 0 }; 71 struct alts_mempart *ap = &alts_part; /* pointer to incore */ 72 /* alts tables */ 73 74 /* prototypes */ 75 int updatebadsec(struct partition *, int); 76 int read_altsctr(struct partition *); 77 static int chk_badsec(); 78 static int init_altsctr(); 79 static int get_altsctr(); 80 int wr_altsctr(); 81 static void get_badsec(); 82 static int count_badsec(); 83 static int gen_alts_ent(); 84 static int assign_altsctr(); 85 static void expand_map(); 86 static void compress_map(); 87 static int altsmap_getbit(daddr_t); 88 static int altsmap_alloc(daddr_t, daddr_t, int, int); 89 static void ent_sort(struct alts_ent *, int); 90 static void ent_compress(struct alts_ent *, int); 91 static int ent_merge(struct alts_ent *, struct alts_ent *, int, 92 struct alts_ent *, int); 93 static int ent_bsearch(struct alts_ent *, int, struct alts_ent *); 94 static int chk_bad_altsctr(daddr_t); 95 96 /* 97 * updatebadsec () -- update bad sector/track mapping tables 98 */ 99 int 100 updatebadsec(part, init_flag) 101 int init_flag; 102 struct partition *part; 103 { 104 if (init_flag) 105 ap->ap_flag |= ALTS_ADDPART; 106 get_badsec(); 107 (void) read_altsctr(part); 108 ent_sort(ap->ap_gbadp, ap->ap_gbadcnt); 109 ent_compress(ap->ap_gbadp, ap->ap_gbadcnt); 110 (void) gen_alts_ent(); 111 compress_map(); 112 return (SUCCESS); 113 } 114 115 /* 116 * read_altsctr( ptr to alternate sector partition ) 117 * -- read the alternate sector partition tables 118 */ 119 int 120 read_altsctr(part) 121 struct partition *part; 122 { 123 if (ap->ap_tblp == NULL) { 124 /* allocate buffer for the alts partition table (sector size) */ 125 ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE, NBPSCTR); 126 ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz); 127 if (ap->ap_tblp == NULL) { 128 (void) fprintf(stderr, 129 "Unable to malloc alternate partition table.\n"); 130 return (50); 131 } 132 133 /* allocate buffer for the alts partition map (sector size) */ 134 /* buffers include the disk image bit map */ 135 /* and the incore transformed char map */ 136 137 if ((ap->ap_memmapp = (uchar_t *)malloc(part->p_size)) == NULL) { 138 (void) fprintf(stderr, 139 "Unable to malloc incore alternate partition map.\n"); 140 return (51); 141 } 142 ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8; 143 ap->ap_map_secsiz = byte_to_secsiz(ap->ap_tblp->alts_map_len, 144 NBPSCTR); 145 ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR; 146 if ((ap->ap_mapp = (uchar_t *)malloc(ap->ap_map_secsiz)) == NULL) { 147 (void) fprintf(stderr, 148 "Unable to malloc alternate partition map.\n"); 149 return (52); 150 } 151 /* clear the buffers to zero */ 152 (void) memset(ap->ap_memmapp, 0, part->p_size); 153 (void) memset(ap->ap_mapp, 0, ap->ap_map_secsiz); 154 ap->part = *part; /* struct copy */ 155 156 /* 157 * if add alternate partition flag is set, then install the partition 158 * otherwise read the alts partition info from disk 159 * if failed, then assume the first installation 160 */ 161 if (ap->ap_flag & ALTS_ADDPART) 162 { 163 (void) fprintf(stderr, 164 "WARNING: Manually initializing alternate table.\n"); 165 (void) init_altsctr(); 166 } else { 167 if (get_altsctr() == SUCCESS) 168 (void) chk_badsec(); 169 else 170 (void) init_altsctr(); 171 } 172 } 173 return (SUCCESS); 174 } 175 176 177 /* 178 * checking duplicate bad sectors or bad sectors in ALTSCTR partition 179 */ 180 static int 181 chk_badsec() 182 { 183 daddr_t badsec; 184 daddr_t altsp_srtsec = ap->part.p_start; 185 daddr_t altsp_endsec = ap->part.p_start + ap->part.p_size - 1; 186 int cnt; 187 int status; 188 189 for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) { 190 badsec = (ap->ap_gbadp)[cnt].bad_start; 191 192 /* if bad sector is within the ATLSCTR partition */ 193 if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) { 194 if ((ap->ap_memmapp)[badsec - altsp_srtsec] != ALTS_BAD) { 195 if ((badsec >= altsp_srtsec) && (badsec <= (altsp_srtsec + 196 ap->ap_tbl_secsiz / NBPSCTR - 1))) { 197 (void) fprintf(stderr, 198 "Alternate partition information table is bad.\n"); 199 return (53); 200 } 201 if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) && 202 (badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base + 203 ap->ap_map_sectot - 1))) { 204 (void) fprintf(stderr, 205 "Alternate partition map is bad.\n"); 206 return (54); 207 } 208 if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) && 209 (badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base + 210 ap->ap_ent_secsiz / NBPSCTR - 1))) { 211 (void) fprintf(stderr, 212 "Alternate partition entry table is bad.\n"); 213 return (55); 214 } 215 (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD; 216 (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY; 217 } else { 218 status = chk_bad_altsctr(badsec); 219 (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY; 220 } 221 } else { 222 /* 223 * binary search for bad sector in the alts entry table 224 */ 225 status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used, 226 &((ap->ap_gbadp)[cnt])); 227 /* 228 * if the bad sector had already been remapped(found in alts_entry) 229 * then ignore the bad sector 230 */ 231 if (status != -1) { 232 (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY; 233 } 234 } 235 } 236 return (SUCCESS); 237 } 238 239 /* 240 * initialize the alternate partition tables 241 */ 242 static int 243 init_altsctr() 244 { 245 daddr_t badsec; 246 daddr_t altsp_srtsec = ap->part.p_start; 247 daddr_t altsp_endsec = ap->part.p_start + ap->part.p_size - 1; 248 int cnt; 249 250 ap->ap_entp = NULL; 251 ap->ap_ent_secsiz = 0; 252 ap->ap_tblp->alts_sanity = ALTS_SANITY; 253 ap->ap_tblp->alts_version = ALTS_VERSION1; 254 ap->ap_tblp->alts_map_len = (ap->part.p_size + 8 - 1) / 8; 255 ap->ap_tblp->alts_ent_used = 0; 256 ap->ap_tblp->alts_ent_base = 0; 257 ap->ap_tblp->alts_ent_end = 0; 258 ap->ap_tblp->alts_resv_base = ap->part.p_size - 1; 259 for (cnt = 0; cnt < 5; cnt++) 260 ap->ap_tblp->alts_pad[cnt] = 0; 261 262 for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) { 263 badsec = (ap->ap_gbadp)[cnt].bad_start; 264 if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) { 265 if (badsec == altsp_srtsec) { 266 (void) fprintf(stderr, 267 "First sector of alternate partition is bad.\n"); 268 return (56); 269 } 270 (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD; 271 (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY; 272 } 273 } 274 275 /* allocate the alts_map on disk skipping possible bad sectors */ 276 ap->ap_tblp->alts_map_base = 277 altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR, 278 ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP); 279 if (ap->ap_tblp->alts_map_base == NULL) { 280 perror("Unable to allocate alternate map on disk: "); 281 return (57); 282 } 283 (void) wr_altsctr(); 284 285 return (SUCCESS); 286 } 287 288 289 /* 290 * read the alternate partition tables from disk 291 */ 292 static int 293 get_altsctr() 294 { 295 int mystatus = FAILURE; 296 int status = 0; 297 298 /* get alts partition table info */ 299 300 status = ata_rdwr(DIR_READ, cur_file, altsec_offset, 301 ap->ap_tbl_secsiz / UBSIZE, (char *)ap->ap_tblp, 302 0, NULL); 303 if (status == FAILURE) { 304 perror("Unable to read alternate sector partition: "); 305 return (58); 306 } 307 if (ap->ap_tblp->alts_sanity != ALTS_SANITY) 308 return (mystatus); 309 310 /* get the alts map */ 311 status = ata_rdwr(DIR_READ, cur_file, 312 (ap->ap_tblp->alts_map_base) + altsec_offset, 313 ap->ap_map_secsiz / UBSIZE, (char *)ap->ap_mapp, 0, NULL); 314 if (status == FAILURE) { 315 perror("Unable to read alternate sector partition map: "); 316 return (59); 317 } 318 319 /* transform the disk image bit-map to incore char map */ 320 expand_map(); 321 322 if (ap->ap_tblp->alts_ent_used == 0) { 323 ap->ap_entp = NULL; 324 ap->ap_ent_secsiz = 0; 325 } else { 326 ap->ap_ent_secsiz = byte_to_secsiz( 327 (ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE), NBPSCTR); 328 if ((ap->ap_entp = 329 (struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) { 330 (void) fprintf(stderr, 331 "Unable to malloc alternate sector entry table.\n"); 332 return (60); 333 } 334 335 status = ata_rdwr(DIR_READ, cur_file, 336 (ap->ap_tblp->alts_ent_base) + altsec_offset, 337 ap->ap_ent_secsiz / UBSIZE, (char *)ap->ap_entp, 338 0, NULL); 339 if (status == FAILURE) { 340 perror("Unable to read alternate sector entry table: "); 341 return (61); 342 } 343 } 344 345 return (SUCCESS); 346 } 347 348 349 /* 350 * update the new alternate partition tables on disk 351 */ 352 int 353 wr_altsctr() 354 { 355 int status; 356 357 if (ap->ap_tblp == NULL) 358 return (0); 359 status = ata_rdwr(DIR_WRITE, cur_file, altsec_offset, 360 ap->ap_tbl_secsiz / UBSIZE, (char *)ap->ap_tblp, 0, NULL); 361 if (status) { 362 (void) printf("ata_rdwr status = %d need = %d\n", 363 status, ap->ap_tbl_secsiz / 512); 364 perror("Unable to write with ata_rdwr the alt sector part: "); 365 return (62); 366 } 367 368 if (ata_rdwr(DIR_WRITE, cur_file, (ap->ap_tblp->alts_map_base) + 369 altsec_offset, ap->ap_map_secsiz / UBSIZE, 370 (char *)ap->ap_mapp, 0, NULL) == FAILURE) { 371 perror("Unable to write alternate sector partition map: "); 372 return (63); 373 } 374 375 if (ap->ap_tblp->alts_ent_used != 0) { 376 if (ata_rdwr(DIR_WRITE, cur_file, 377 (ap->ap_tblp->alts_ent_base)+ altsec_offset, 378 ap->ap_ent_secsiz / UBSIZE, 379 (char *)ap->ap_entp, 0, NULL) == FAILURE) { 380 perror("Unable to write alternate sector entry table: "); 381 return (64); 382 } 383 } 384 return (0); 385 } 386 387 388 /* 389 * get a list of bad sector 390 */ 391 static void 392 get_badsec() 393 { 394 int cnt; 395 struct badsec_lst *blc_p; 396 daddr_t curbad; 397 long maxsec = (long)cur_dtype->dtype_nhead * 398 cur_dtype->dtype_ncyl * 399 cur_dtype->dtype_nsect; 400 struct alts_ent *growbadp; 401 int i; 402 403 cnt = count_badsec(); 404 if (!cnt) { 405 ap->ap_gbadp = NULL; 406 ap->ap_gbadcnt = 0; 407 } else { 408 ap->ap_gbadp = malloc(cnt*ALTS_ENT_SIZE); 409 if (ap->ap_gbadp == NULL) { 410 err_print("get_badsec: unable to malloc %d bytes\n", 411 cnt*ALTS_ENT_SIZE); 412 fullabort(); 413 } 414 (void) memset(ap->ap_gbadp, 0, cnt*ALTS_ENT_SIZE); 415 416 for (growbadp = ap->ap_gbadp, cnt = 0, blc_p = badsl_chain; 417 blc_p; blc_p = blc_p->bl_nxt) { 418 for (i = 0; i < blc_p->bl_cnt; i++) { 419 curbad = blc_p->bl_sec[i]; 420 if (curbad < (daddr_t)cur_dtype->dtype_nsect) { 421 (void) fprintf(stderr, 422 "Ignoring bad sector %ld which is in first track of the drive.\n", curbad); 423 continue; 424 } 425 if (curbad >= maxsec) { 426 (void) fprintf(stderr, 427 "Ignoring bad sector %ld which is past the end of the drive.\n", curbad); 428 continue; 429 } 430 growbadp[cnt].bad_start = curbad; 431 growbadp[cnt].bad_end = curbad; 432 cnt++; 433 } 434 } 435 } 436 ap->ap_gbadcnt = cnt; 437 } 438 439 /* 440 * count number of bad sector on list 441 * merging the bad sector list from surface analysis and the 442 * one given through the command line 443 */ 444 static int 445 count_badsec() 446 { 447 448 struct badsec_lst *blc_p; 449 450 if (!badsl_chain) 451 badsl_chain = gbadsl_chain; 452 else { 453 for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p = blc_p->bl_nxt) 454 ; 455 blc_p->bl_nxt = gbadsl_chain; 456 } 457 458 badsl_chain_cnt += gbadsl_chain_cnt; 459 return (badsl_chain_cnt); 460 } 461 462 463 /* 464 * generate alternate entry table by merging the existing and 465 * the new entry list. 466 */ 467 static int 468 gen_alts_ent() { 469 int ent_used; 470 struct alts_ent *entp; 471 472 if (ap->ap_gbadcnt == 0) 473 return (0); 474 475 ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt; 476 ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR); 477 entp = malloc(ap->ap_ent_secsiz); 478 if (entp == NULL) { 479 err_print("get_alts_ent: unable to malloc %d bytes\n", 480 ap->ap_ent_secsiz); 481 fullabort(); 482 } 483 484 ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used, 485 ap->ap_gbadp, ap->ap_gbadcnt); 486 if (ap->ap_entp) 487 free(ap->ap_entp); 488 if (ap->ap_gbadp) 489 free(ap->ap_gbadp); 490 ap->ap_entp = entp; 491 ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR); 492 ap->ap_tblp->alts_ent_used = ent_used; 493 ap->ap_gbadp = NULL; 494 ap->ap_gbadcnt = 0; 495 496 /* assign alternate sectors to the bad sectors */ 497 (void) assign_altsctr(); 498 499 /* allocate the alts_entry on disk skipping possible bad sectors */ 500 ap->ap_tblp->alts_ent_base = 501 altsmap_alloc(ap->ap_tblp->alts_map_base + ap->ap_map_sectot, 502 ap->part.p_size, 503 ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP); 504 if (ap->ap_tblp->alts_ent_base == NULL) { 505 perror("Unable to allocate alternate entry table on disk: "); 506 return (65); 507 } 508 509 ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base + 510 (ap->ap_ent_secsiz / NBPSCTR) - 1; 511 return (0); 512 } 513 514 515 /* 516 * assign alternate sectors for bad sector mapping 517 */ 518 static int 519 assign_altsctr() 520 { 521 int i; 522 int j; 523 daddr_t alts_ind; 524 int cluster; 525 526 for (i = 0; i < ap->ap_tblp->alts_ent_used; i++) { 527 if ((ap->ap_entp)[i].bad_start == ALTS_ENT_EMPTY) 528 continue; 529 if ((ap->ap_entp)[i].good_start != 0) 530 continue; 531 cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1; 532 alts_ind = 533 altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base + 534 ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN); 535 if (alts_ind == NULL) { 536 (void) fprintf(stderr, 537 "Unable to allocate alternates for bad starting sector %ld.\n", 538 (ap->ap_entp)[i].bad_start); 539 return (65); 540 } 541 alts_ind = alts_ind - cluster + 1; 542 (ap->ap_entp)[i].good_start = alts_ind +ap->part.p_start; 543 for (j = 0; j < cluster; j++) { 544 (ap->ap_memmapp)[alts_ind+j] = ALTS_BAD; 545 } 546 547 } 548 return (SUCCESS); 549 } 550 551 /* 552 * transform the disk image alts bit map to incore char map 553 */ 554 static void 555 expand_map() 556 { 557 int i; 558 559 for (i = 0; i < ap->part.p_size; i++) { 560 (ap->ap_memmapp)[i] = altsmap_getbit(i); 561 } 562 } 563 564 /* 565 * transform the incore alts char map to the disk image bit map 566 */ 567 static void 568 compress_map() 569 { 570 571 int i; 572 int bytesz; 573 char mask = 0; 574 int maplen = 0; 575 576 for (i = 0, bytesz = 7; i < ap->part.p_size; i++) { 577 mask |= ((ap->ap_memmapp)[i] << bytesz--); 578 if (bytesz < 0) { 579 (ap->ap_mapp)[maplen++] = mask; 580 bytesz = 7; 581 mask = 0; 582 } 583 } 584 /* 585 * if partition size != multiple number of bytes 586 * then record the last partial byte 587 */ 588 if (bytesz != 7) 589 (ap->ap_mapp)[maplen] = mask; 590 591 } 592 593 /* 594 * given a bad sector number, search in the alts bit map 595 * and identify the sector as good or bad 596 */ 597 static int 598 altsmap_getbit(badsec) 599 daddr_t badsec; 600 { 601 int slot = badsec / 8; 602 int field = badsec % 8; 603 uchar_t mask; 604 605 mask = ALTS_BAD<<7; 606 mask >>= field; 607 if ((ap->ap_mapp)[slot] & mask) 608 return (ALTS_BAD); 609 return (ALTS_GOOD); 610 } 611 612 613 /* 614 * allocate a range of sectors from the alternate partition 615 */ 616 static int 617 altsmap_alloc(srt_ind, end_ind, cnt, dir) 618 daddr_t srt_ind; 619 daddr_t end_ind; 620 int cnt; 621 int dir; 622 { 623 int i; 624 int total; 625 int first_ind; 626 627 for (i = srt_ind, first_ind = srt_ind, total = 0; 628 i != end_ind; i += dir) { 629 if ((ap->ap_memmapp)[i] == ALTS_BAD) { 630 total = 0; 631 first_ind = i + dir; 632 continue; 633 } 634 total++; 635 if (total == cnt) 636 return (first_ind); 637 638 } 639 return (NULL); 640 } 641 642 643 644 /* 645 * bubble sort the entry table into ascending order 646 */ 647 static void 648 ent_sort(buf, cnt) 649 struct alts_ent buf[]; 650 int cnt; 651 { 652 struct alts_ent temp; 653 int flag; 654 int i, j; 655 656 for (i = 0; i < cnt-1; i++) { 657 temp = buf[cnt-1]; 658 flag = 1; 659 660 for (j = cnt-1; j > i; j--) { 661 if (buf[j-1].bad_start < temp.bad_start) { 662 buf[j] = temp; 663 temp = buf[j-1]; 664 } else { 665 buf[j] = buf[j-1]; 666 flag = 0; 667 } 668 } 669 buf[i] = temp; 670 if (flag) break; 671 } 672 673 } 674 675 676 /* 677 * compress all the contiguous bad sectors into a single entry 678 * in the entry table. The entry table must be sorted into ascending 679 * before the compression. 680 */ 681 static void 682 ent_compress(buf, cnt) 683 struct alts_ent buf[]; 684 int cnt; 685 { 686 int keyp; 687 int movp; 688 int i; 689 690 for (i = 0; i < cnt; i++) { 691 if (buf[i].bad_start == ALTS_ENT_EMPTY) 692 continue; 693 for (keyp = i, movp = i+1; movp < cnt; movp++) { 694 if (buf[movp].bad_start == ALTS_ENT_EMPTY) 695 continue; 696 if (buf[keyp].bad_end+1 != buf[movp].bad_start) 697 break; 698 buf[keyp].bad_end++; 699 buf[movp].bad_start = ALTS_ENT_EMPTY; 700 } 701 if (movp == cnt) break; 702 } 703 } 704 705 706 /* 707 * merging two entry tables into a single table. In addition, 708 * all empty slots in the entry table will be removed. 709 */ 710 static int 711 ent_merge(buf, list1, lcnt1, list2, lcnt2) 712 struct alts_ent buf[]; 713 struct alts_ent list1[]; 714 int lcnt1; 715 struct alts_ent list2[]; 716 int lcnt2; 717 { 718 int i; 719 int j1, j2; 720 721 for (i = 0, j1 = 0, j2 = 0; j1 < lcnt1 && j2 < lcnt2; ) { 722 if (list1[j1].bad_start == ALTS_ENT_EMPTY) { 723 j1++; 724 continue; 725 } 726 if (list2[j2].bad_start == ALTS_ENT_EMPTY) { 727 j2++; 728 continue; 729 } 730 if (list1[j1].bad_start < list2[j2].bad_start) 731 buf[i++] = list1[j1++]; 732 else 733 buf[i++] = list2[j2++]; 734 } 735 for (; j1 < lcnt1; j1++) { 736 if (list1[j1].bad_start == ALTS_ENT_EMPTY) 737 continue; 738 buf[i++] = list1[j1]; 739 } 740 for (; j2 < lcnt2; j2++) { 741 if (list2[j2].bad_start == ALTS_ENT_EMPTY) 742 continue; 743 buf[i++] = list2[j2]; 744 } 745 return (i); 746 } 747 748 749 /* 750 * binary search for bad sector in the alternate entry table 751 */ 752 static int 753 ent_bsearch(buf, cnt, key) 754 struct alts_ent buf[]; 755 int cnt; 756 struct alts_ent *key; 757 { 758 int i; 759 int ind; 760 int interval; 761 int mystatus = -1; 762 763 if (!cnt) 764 return (mystatus); 765 766 for (i = 1; i <= cnt; i <<= 1) 767 ind = i; 768 769 for (interval = ind; interval; ) { 770 if ((key->bad_start >= buf[ind-1].bad_start) && 771 (key->bad_start <= buf[ind-1].bad_end)) { 772 return (mystatus = ind-1); 773 } else { 774 interval >>= 1; 775 if (!interval) break; 776 if (key->bad_start < buf[ind-1].bad_start) { 777 ind = ind - interval; 778 } else { 779 /* if key is larger than the last element then break */ 780 if (ind == cnt) break; 781 if ((ind+interval) <= cnt) 782 ind += interval; 783 } 784 } 785 } 786 return (mystatus); 787 } 788 789 /* 790 * check for bad sector in assigned alternate sectors 791 */ 792 static int 793 chk_bad_altsctr(badsec) 794 daddr_t badsec; 795 { 796 int i; 797 daddr_t numsec; 798 int cnt = ap->ap_tblp->alts_ent_used; 799 /* 800 * daddr_t intv[3]; 801 */ 802 803 for (i = 0; i < cnt; i++) { 804 numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start; 805 if ((badsec >= (ap->ap_entp)[i].good_start) && 806 (badsec <= ((ap->ap_entp)[i].good_start + numsec))) { 807 (void) fprintf(stderr, 808 "Bad sector %ld is an assigned alternate sector.\n", badsec); 809 return (66); 810 /* 811 * if (!numsec) { 812 * (ap->ap_entp)[i].good_start = 0; 813 * return (FAILURE); 814 * } 815 * intv[0] = badsec - (ap->ap_entp)[i].good_start; 816 * intv[1] = 1; 817 * intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec; 818 */ 819 } 820 } 821 /* the bad sector has already been identified as bad */ 822 return (SUCCESS); 823 824 } 825