|
|
1.1 ! root 1: /* $Header: /src386/kernel/coh.386/RCS/seg.c,v 1.6 93/06/14 13:35:09 bin Exp Locker: bin $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Coherent. ! 17: * Segment manipulation. ! 18: * ! 19: */ ! 20: #include <sys/coherent.h> ! 21: #include <sys/buf.h> ! 22: #include <errno.h> ! 23: #include <sys/ino.h> ! 24: #include <sys/inode.h> ! 25: #include <sys/proc.h> ! 26: #include <sys/sched.h> ! 27: #include <sys/seg.h> ! 28: #include <a.out.h> ! 29: ! 30: ! 31: #define min(a, b) ((a) < (b) ? (a) : (b)) ! 32: ! 33: /* ! 34: * Initialisation code. ! 35: */ ! 36: seginit() ! 37: { ! 38: /* ! 39: * Create empty circular-list of memory segments. ! 40: */ ! 41: segmq.s_forw = &segmq; ! 42: segmq.s_back = &segmq; ! 43: ! 44: /* ! 45: * Create empty circular-list of disk segments. ! 46: */ ! 47: segdq.s_forw = &segdq; ! 48: segdq.s_back = &segdq; ! 49: } ! 50: ! 51: /* ! 52: * Given an inode, `ip', and flags, `ff', describing a segment associated ! 53: * with the inode, see if the segment already exists and if so, return a ! 54: * copy. If the segment does not exist, allocate the segment having size ! 55: * `ss', and read the segment using the inode at seek offset `dq' with a ! 56: * size of `ds'. ! 57: */ ! 58: SEG * ! 59: ssalloc(ip, ff, ss) ! 60: register INODE *ip; ! 61: { ! 62: register SEG *sp; ! 63: register int f; ! 64: ! 65: lock(seglink); ! 66: f = ff & (SFSHRX|SFTEXT); ! 67: ! 68: /* ! 69: * Look for the segment in the memory queue. ! 70: */ ! 71: for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) { ! 72: if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) { ! 73: unlock(seglink); ! 74: if (sp = segdupl(sp)) ! 75: segfinm(sp); ! 76: return (sp); ! 77: } ! 78: } ! 79: ! 80: /* ! 81: * Look for the segment on the disk queue. ! 82: */ ! 83: for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) { ! 84: if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) { ! 85: unlock(seglink); ! 86: if (sp = segdupl(sp)) ! 87: segfinm(sp); ! 88: return (sp); ! 89: } ! 90: } ! 91: unlock(seglink); ! 92: ! 93: /* ! 94: * Allocate and create the segment. ! 95: */ ! 96: return salloc(roundu(ss, NBPC), ff); ! 97: } ! 98: ! 99: /* ! 100: * Given a pointer to a newly created process, copy all of our segments ! 101: * into the given process. ! 102: * ! 103: * Return nonzero if successful. ! 104: */ ! 105: int ! 106: segadup(cpp) ! 107: register PROC *cpp; ! 108: { ! 109: register SEG *sp; ! 110: register int n; ! 111: register PROC *pp; ! 112: ! 113: pp = SELF; ! 114: cpp->p_flags |= PFSWIO; ! 115: for (n=0; n<NUSEG; n++) { ! 116: if ((sp=pp->p_segp[n]) == NULL) ! 117: continue; ! 118: if ((sp=segdupl(sp)) == NULL) ! 119: break; ! 120: cpp->p_segp[n] = sp; ! 121: if ((sp->s_flags&SFCORE) == 0) ! 122: cpp->p_flags &= ~PFCORE; ! 123: } ! 124: ! 125: /* ! 126: * One of the calls to segdupl() failed. ! 127: * Undo any that succeeded. ! 128: */ ! 129: if (n < NUSEG) { ! 130: while (n > 0) { ! 131: if (sp=cpp->p_segp[--n]) { ! 132: cpp->p_segp[n] = NULL; ! 133: sfree(sp); ! 134: } ! 135: } ! 136: } ! 137: cpp->p_flags &= ~PFSWIO; ! 138: return n; ! 139: } ! 140: ! 141: /* ! 142: * Duplicate a segment. ! 143: */ ! 144: SEG * ! 145: segdupl(sp) ! 146: register SEG *sp; ! 147: { ! 148: register SEG *sp1; ! 149: ! 150: if (sp->s_flags & SFSHRX) { ! 151: sp->s_urefc++; ! 152: sp->s_lrefc++; ! 153: return (sp); ! 154: } ! 155: if ((sp->s_flags&SFCORE) == 0) ! 156: panic("Cannot duplicate non shared swapped segment"); ! 157: if ((sp1=salloc(sp->s_size, sp->s_flags|SFNSWP|SFNCLR)) == NULL) ! 158: sp1 = segdupd(sp); ! 159: else { ! 160: sp1->s_flags = sp->s_flags; ! 161: dmacopy( btoc(sp->s_size), sp->s_vmem, sp1->s_vmem) ; ! 162: } ! 163: return sp1; ! 164: } ! 165: ! 166: /* ! 167: * Allocate a segment `bytes_wanted' bytes long. ! 168: * `flags' contains some pseudo flags. ! 169: */ ! 170: SEG * ! 171: salloc(bytes_wanted, flags) ! 172: int bytes_wanted, flags; ! 173: { ! 174: register SEG *sp; ! 175: register int r; ! 176: ! 177: r = (flags & (SFSYST|SFTEXT|SFSHRX|SFDOWN)) | SFCORE; ! 178: ! 179: /* ! 180: #ifdef _I386 ! 181: bytes_wanted += (sizeof(char *) - 1); ! 182: bytes_wanted &= ~(sizeof(char *) - 1); ! 183: #else ! 184: bytes_wanted += (BSIZE - 1); ! 185: bytes_wanted &= ~(BSIZE - 1); ! 186: #endif ! 187: */ ! 188: ! 189: lock(seglink); ! 190: sp = smalloc(bytes_wanted); ! 191: unlock(seglink); ! 192: ! 193: if (sp) { ! 194: sp->s_flags = r; ! 195: } else { ! 196: #if 0 ! 197: /* no room now - let the swapper try to grow it */ ! 198: if (flags & SFNSWP) ! 199: return 0; ! 200: if ((sp=kalloc(sizeof(SEG))) == NULL) ! 201: return 0; ! 202: sp->s_forw = sp; ! 203: sp->s_back = sp; ! 204: sp->s_flags = r; ! 205: sp->s_urefc = 1; ! 206: sp->s_lrefc = 1; ! 207: if (segsext(sp, bytes_wanted) == NULL) { ! 208: kfree(sp); ! 209: return 0; ! 210: } ! 211: #else ! 212: return 0; ! 213: #endif ! 214: } ! 215: if ((flags&SFNCLR) == 0) ! 216: dmaclear(sp->s_size, MAPIO(sp->s_vmem, 0), 0L); ! 217: return sp; ! 218: } ! 219: ! 220: /* ! 221: * Free the given segment pointer. ! 222: */ ! 223: sfree(sp) ! 224: register SEG *sp; ! 225: { ! 226: register INODE *ip; ! 227: ! 228: if ( sp->s_urefc != 1 ) { ! 229: sp->s_urefc--; ! 230: sp->s_lrefc--; ! 231: return; ! 232: } ! 233: ! 234: lock(seglink); ! 235: ! 236: --sp->s_lrefc; ! 237: ! 238: sp->s_back->s_forw = sp->s_forw; ! 239: sp->s_forw->s_back = sp->s_back; ! 240: ! 241: c_free(sp->s_vmem, btoc(sp->s_size)); ! 242: ! 243: unlock(seglink); ! 244: if (sp->s_lrefc) ! 245: panic("Bad segment count"); ! 246: ! 247: /* ! 248: * Check if inode is ilocked, in order to allow the process ! 249: * to exec itself (file with the same inode as parent). Vlad. ! 250: */ ! 251: if ((ip=sp->s_ip) && !ilocked(ip)) { ! 252: ldetach(ip); ! 253: } ! 254: kfree(sp); ! 255: } ! 256: ! 257: /* ! 258: * Grow or shrink the segment `sp' so that it has size `new_bytes' bytes. ! 259: * ! 260: * downward growing segments not done yet! ! 261: */ ! 262: seggrow(sp, new_bytes) ! 263: register SEG *sp; ! 264: unsigned int new_bytes; ! 265: { ! 266: register SEG *sp1; ! 267: register int dowflag; ! 268: unsigned int old_bytes, common_clicks; ! 269: ! 270: dowflag = sp->s_flags & SFDOWN; ! 271: old_bytes = sp->s_size; ! 272: ! 273: /* ! 274: * If we want a larger segment AND c_grow() succeeds ! 275: * boost segment size to new_bytes ! 276: */ ! 277: if (new_bytes >= old_bytes && c_grow(sp, new_bytes)==0) { ! 278: T_HAL(0x100, printf("c_grow(%d) ", new_bytes)); ! 279: sp->s_size = new_bytes; ! 280: dmaclear(new_bytes - old_bytes, ! 281: MAPIO(sp->s_vmem, old_bytes), 0); ! 282: return 1; ! 283: } ! 284: dont_c_grow: ! 285: ! 286: if (sp1 = salloc(new_bytes, (sp->s_flags|SFNSWP|SFNCLR))) { ! 287: T_HAL(0x100, printf("salloc(%d) ", new_bytes)); ! 288: if (dowflag == 0) { ! 289: common_clicks = btoc(min(new_bytes, old_bytes)); ! 290: dmacopy(common_clicks, sp->s_vmem, sp1->s_vmem); ! 291: if (new_bytes > old_bytes) { ! 292: dmaclear(new_bytes - old_bytes, ! 293: MAPIO(sp1->s_vmem, old_bytes), 0); ! 294: } ! 295: } else ! 296: panic("downflag"); ! 297: lock(seglink); ! 298: c_free(sp->s_vmem, btoc(old_bytes)); ! 299: satcopy(sp, sp1); ! 300: unlock(seglink); ! 301: ! 302: return 1; ! 303: } ! 304: ! 305: #if 1 ! 306: return 0; ! 307: #else ! 308: /* ! 309: * Last chance. Extend the segment by swapping it. ! 310: */ ! 311: if (!segsext(sp, new_bytes)) ! 312: return 0; ! 313: ! 314: if (dowflag == 0) { ! 315: if (new_bytes > old_bytes) ! 316: dmaclear(new_bytes - old_bytes, MAPIO(sp->s_vmem,old_bytes), 0); ! 317: } else ! 318: panic("downflag"); ! 319: ! 320: return (1); ! 321: #endif ! 322: } ! 323: ! 324: /* ! 325: * Given a segment pointer, `sp' and a segment size, grow the given segment ! 326: * to the given size. ! 327: */ ! 328: segsize(sp, s2) ! 329: register SEG *sp; ! 330: caddr_t s2; ! 331: { ! 332: register caddr_t s1; ! 333: ! 334: s1 = (caddr_t) sp->s_size; ! 335: if (s2 == 0 || seggrow(sp, (off_t)s2) == 0) { ! 336: SET_U_ERROR( ENOMEM, "can not grow segment" ); ! 337: return; ! 338: } ! 339: if (sproto(0) == 0) { ! 340: if (seggrow(sp, (off_t)s1)==0 || sproto(0)==0) { ! 341: T_PIGGY( 0x2000000, printf("auto SEGV\n"); ); ! 342: sendsig(SIGSEGV, SELF); ! 343: } ! 344: } ! 345: segload(); ! 346: } ! 347: ! 348: /* ! 349: * Grow the segment `sp1' to the size `s' in bytes by swapping it out ! 350: * and back in. The segment may not be locked. ! 351: */ ! 352: SEG * ! 353: segsext(sp1, s) ! 354: register SEG *sp1; ! 355: register off_t s; ! 356: { ! 357: #if 0 ! 358: register SEG *sp2; ! 359: ! 360: #if MONITOR ! 361: if (swmflag) ! 362: printf("Segsext(%p, %u)\n", SELF, SELF->p_pid); ! 363: #endif ! 364: if (sexflag == 0) { ! 365: SET_U_ERROR( ENOMEM, "can not extend, swapping is off" ); ! 366: return (NULL); ! 367: } ! 368: lock(seglink); ! 369: if ((sp2=sdalloc(s)) == NULL) { ! 370: unlock(seglink); ! 371: return (NULL); ! 372: } ! 373: unlock(seglink); ! 374: sp1->s_lrefc++; ! 375: if (sp1->s_size != 0) ! 376: swapio(1, MAPIO(sp1->s_vmem, 0), sp2->s_daddr, sp1->s_size); ! 377: lock(seglink); ! 378: satcopy(sp1, sp2); ! 379: unlock(seglink); ! 380: sp1->s_flags &= ~SFCORE; ! 381: sp1->s_lrefc--; ! 382: segfinm(sp1); ! 383: return (sp1); ! 384: #else ! 385: return 0; ! 386: #endif ! 387: } ! 388: ! 389: /* ! 390: * Force the given segment to be in memory. One can only force ! 391: * one segment to be in memory at a time. ! 392: */ ! 393: segfinm(sp) ! 394: register SEG *sp; ! 395: { ! 396: register PROC *pp; ! 397: register int s; ! 398: ! 399: if (sp->s_flags&SFCORE) ! 400: return; ! 401: pp = SELF; ! 402: sp->s_urefc++; ! 403: sp->s_lrefc++; ! 404: pp->p_segp[SIAUXIL] = sp; ! 405: pp->p_flags &= ~PFCORE; ! 406: #ifndef QWAKEUP ! 407: s = sphi(); ! 408: #endif ! 409: setrun(pp); ! 410: dispatch(); ! 411: #ifndef QWAKEUP ! 412: spl(s); ! 413: #endif ! 414: pp->p_segp[SIAUXIL] = NULL; ! 415: sfree(sp); ! 416: } ! 417: ! 418: /* ! 419: * Make a copy of the segment `sp1' which is in memory by writing ! 420: * it out to disk. ! 421: */ ! 422: SEG * ! 423: segdupd(sp1) ! 424: register SEG *sp1; ! 425: { ! 426: register SEG *sp2; ! 427: ! 428: if (sexflag == 0) ! 429: return (NULL); ! 430: lock(seglink); ! 431: if ((sp2=sdalloc(sp1->s_size)) == NULL) { ! 432: unlock(seglink); ! 433: return (NULL); ! 434: } ! 435: sp1->s_lrefc++; ! 436: unlock(seglink); ! 437: swapio(1, MAPIO(sp1->s_vmem, 0), sp2->s_daddr, sp1->s_size); ! 438: sp1->s_lrefc--; ! 439: sp2->s_flags = sp1->s_flags & ~SFCORE; ! 440: sp2->s_size = sp1->s_size; ! 441: return (sp2); ! 442: } ! 443: ! 444: /* ! 445: * Given a flag, a physical core address, a disk address and a count in ! 446: * bytes, perform an I/O operation between core and disk. If `flag' is ! 447: * set, the transfer is to the disk otherwise it is to memory. As you may ! 448: * have guessed, this is used by the swapper. ! 449: * ! 450: */ ! 451: swapio(f, p, d, n) ! 452: paddr_t p; ! 453: daddr_t d; ! 454: off_t n; ! 455: { ! 456: register BUF * bp; ! 457: register SEG * sp; ! 458: register int s; ! 459: register int nb; ! 460: ! 461: #if MONITOR ! 462: if (swmflag > 1) ! 463: printf("swapio(%s,%x,%x,%x)\n",f?"out":"in",(int)p,(int)d,n); ! 464: #endif ! 465: if (d < swapbot || d+(n/BSIZE) > swaptop) ! 466: panic("Swapio bad parameter"); ! 467: ! 468: bp = &swapbuf; ! 469: lock(bp->b_gate); ! 470: SELF->p_flags |= PFSWIO; ! 471: bp->b_paddr = p; ! 472: ! 473: while (n) { ! 474: nb = (n > SCHUNK) ? SCHUNK : n; ! 475: /* ! 476: * Prevent I/O transfer from crossing 64 Kbyte boundary. ! 477: */ ! 478: if ( (p & 0xFFFF0000L) != ((p+nb) & 0xFFFF0000L) ) ! 479: nb = 0x10000L - (p & 0x0000FFFFL); ! 480: bp->b_flag = BFNTP; ! 481: bp->b_req = f ? BWRITE : BREAD; ! 482: bp->b_dev = swapdev; ! 483: bp->b_bno = d; ! 484: bp->b_paddr = p; ! 485: bp->b_count = nb; ! 486: s = sphi(); ! 487: dblock(swapdev, bp); ! 488: while ((bp->b_flag&BFNTP) != 0) { ! 489: x_sleep((char *)bp, pridisk, slpriNoSig, "swap"); ! 490: /* Sleeping in the swapper. */ ! 491: } ! 492: spl(s); ! 493: if ((bp->b_flag&BFERR) != 0) ! 494: panic("Swapio error"); ! 495: bp->b_vaddr += nb; ! 496: p += nb; ! 497: d += nb / BSIZE; ! 498: n -= nb; ! 499: } ! 500: unlock(bp->b_gate); ! 501: SELF->p_flags &= ~PFSWIO; ! 502: } ! 503: ! 504: /* ! 505: * Make the segment descriptor pointed to by `sp1' have the attributes ! 506: * of `sp2' including it's position in the segment queue and release ! 507: * `sp2'. `seglink' must be locked when this routine is called. ! 508: */ ! 509: satcopy(sp1, sp2) ! 510: register SEG *sp1; ! 511: register SEG *sp2; ! 512: { ! 513: sp1->s_back->s_forw = sp1->s_forw; ! 514: sp1->s_forw->s_back = sp1->s_back; ! 515: sp2->s_back->s_forw = sp1; ! 516: sp1->s_back = sp2->s_back; ! 517: sp2->s_forw->s_back = sp1; ! 518: sp1->s_forw = sp2->s_forw; ! 519: sp1->s_daddr = sp2->s_daddr; ! 520: sp1->s_size = sp2->s_size; ! 521: sp1->s_vmem = sp2->s_vmem; ! 522: kfree(sp2); ! 523: } ! 524: ! 525: /* ! 526: * Allocate a segment on disk that is `n' bytes long. ! 527: * The `seglink' gate should be locked before this routine is called. ! 528: */ ! 529: SEG * ! 530: sdalloc( s ) ! 531: off_t s; ! 532: { ! 533: register SEG *sp1; ! 534: register SEG *sp2; ! 535: register daddr_t d; ! 536: register daddr_t d1; ! 537: register daddr_t d2; ! 538: ! 539: d = s / BSIZE; ! 540: d1 = swapbot; ! 541: sp1 = &segdq; ! 542: do { ! 543: if (d1 >= swaptop) ! 544: return (NULL); ! 545: if ((sp1=sp1->s_forw) != &segdq) ! 546: d2 = sp1->s_daddr; ! 547: else ! 548: d2 = swaptop; ! 549: if (d2-d1 >= d) { ! 550: if ((sp2=kalloc(sizeof(SEG))) == NULL) ! 551: return (NULL); ! 552: sp1->s_back->s_forw = sp2; ! 553: sp2->s_back = sp1->s_back; ! 554: sp1->s_back = sp2; ! 555: sp2->s_forw = sp1; ! 556: sp2->s_urefc = 1; ! 557: sp2->s_lrefc = 1; ! 558: sp2->s_size = s; ! 559: sp2->s_daddr = d1; ! 560: return (sp2); ! 561: } ! 562: d1 = sp1->s_daddr + (sp1->s_size / BSIZE); ! 563: } while (sp1 != &segdq); ! 564: return (NULL); ! 565: } ! 566: ! 567: /* ! 568: * Allocate a segment in memory that is `bytes_wanted' bytes long. ! 569: * The `seglink' gate should be locked before this routine is called. ! 570: * ! 571: * if successful, return allocated SEG * ! 572: * else, return 0 ! 573: */ ! 574: SEG * ! 575: smalloc(bytes_wanted) ! 576: off_t bytes_wanted; ! 577: { ! 578: register SEG *sp1; ! 579: register SEG *new_seg; ! 580: unsigned clicks_wanted; ! 581: ! 582: clicks_wanted = btoc(bytes_wanted); ! 583: ! 584: /* ! 585: * Estimate space needed for new segment and its overhead. ! 586: * Fail if not enough free RAM available. ! 587: */ ! 588: if (countsize(clicks_wanted) > allocno()) ! 589: return 0; ! 590: /* ! 591: * Allocate a new SEG struct to keep track of the segment, if possible. ! 592: */ ! 593: if ((new_seg = kalloc(sizeof (SEG))) == NULL) ! 594: return 0; ! 595: ! 596: if ((new_seg->s_vmem = c_alloc(clicks_wanted)) == 0) { ! 597: kfree(new_seg); ! 598: return 0; ! 599: } ! 600: ! 601: /* link new_seg in at start of segmq */ ! 602: sp1 = segmq.s_forw; ! 603: sp1->s_back->s_forw = new_seg; ! 604: new_seg->s_back = sp1->s_back; ! 605: sp1->s_back = new_seg; ! 606: new_seg->s_forw = sp1; ! 607: ! 608: new_seg->s_urefc = 1; ! 609: new_seg->s_lrefc = 1; ! 610: new_seg->s_size = bytes_wanted; ! 611: ! 612: return new_seg; ! 613: } ! 614: ! 615: /* ! 616: * Set up `SR' structure in user area from segments descriptors in ! 617: * process structure. Also set up the user segmentation registers. ! 618: */ ! 619: sproto(xhp) ! 620: struct xechdr *xhp; ! 621: { ! 622: register int n; ! 623: register SEG *sp; ! 624: ! 625: for (n=0; n<NUSEG; n++) { ! 626: u.u_segl[n].sr_flag = u.u_segl[n].sr_size = 0; ! 627: u.u_segl[n].sr_segp = 0; ! 628: if ((sp=SELF->p_segp[n]) == NULL) ! 629: continue; ! 630: if (n == SIUSERP) ! 631: u.u_segl[n].sr_base = &u; ! 632: else { ! 633: if (xhp) ! 634: u.u_segl[n].sr_base = xhp->segs[n].mbase; ! 635: u.u_segl[n].sr_flag |= SRFPMAP; ! 636: } ! 637: if (n!=SISTEXT) ! 638: u.u_segl[n].sr_flag |= SRFDUMP; ! 639: if (n!=SIUSERP && n!=SISTEXT) ! 640: u.u_segl[n].sr_flag |= SRFDATA; ! 641: u.u_segl[n].sr_size = sp->s_size; ! 642: u.u_segl[n].sr_segp = sp; ! 643: } ! 644: return (mproto()); ! 645: } ! 646: ! 647: /* ! 648: * Search for a busy text inode. ! 649: */ ! 650: sbusy(ip) ! 651: register INODE *ip; ! 652: { ! 653: register SEG *sp; ! 654: ! 655: lock(seglink); ! 656: /* ! 657: * Look for the segment in the memory queue. ! 658: */ ! 659: for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) { ! 660: if (sp->s_ip==ip ! 661: && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) { ! 662: unlock(seglink); ! 663: return (1); ! 664: } ! 665: } ! 666: ! 667: /* ! 668: * Look for the segment on the disk queue. ! 669: */ ! 670: for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) { ! 671: if (sp->s_ip==ip ! 672: && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) { ! 673: unlock(seglink); ! 674: return (1); ! 675: } ! 676: } ! 677: unlock(seglink); ! 678: return 0; ! 679: } ! 680: ! 681: /* ! 682: * Segment consistency checks for the paranoid. ! 683: segchk() ! 684: { ! 685: register SEG *sp; ! 686: register int nbad; ! 687: off_t s; ! 688: daddr_t d; ! 689: ! 690: nbad = 0; ! 691: sp = &segdq; ! 692: d = swapbot; ! 693: while ((sp=sp->s_forw) != &segdq) { ! 694: if (sp->s_daddr < d) ! 695: nbad += badseg("disk", (int)sp->s_daddr, 0); ! 696: d = sp->s_daddr + (sp->s_size / BSIZE); ! 697: } ! 698: if (swaptop < d) ! 699: nbad += badseg("disk", sp->s_back->s_daddr, sp->s_back->s_size); ! 700: } ! 701: ! 702: badseg(t, b, s) ! 703: char *t; ! 704: daddr_t b; ! 705: off_t s; ! 706: { ! 707: printf( "Bad %s segment at %X of len %X\n", t, b, s ); ! 708: return (1); ! 709: } ! 710: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.