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