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