1 /****^  ***********************************************************
   2         *                                                         *
   3         * Copyright, (C) Honeywell Bull Inc., 1987                *
   4         *                                                         *
   5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
   6         *                                                         *
   7         *********************************************************** */
   8 
   9 /* format: style3,idind30,indcomtxt */
  10 scavenge_volume:
  11      proc (Pvtep, Scavenger_blockp, Scavenger_Optionsp, Sc_metersp, Code);
  12 
  13 /*  The Volume Scavenger
  14 
  15    Written July 1982 by J. Bongiovanni
  16    Modified October 1982 by J. Bongiovanni for Filemap Checksum, fm_damaged
  17    Modified May 1983 by E. N. Kittlitz for free_map/in-use conflict.
  18    Modified August 1983 by E. N. Kittlitz for search_ast$check.
  19    Modified 83-12-13 BIM for fault for debugging locking.
  20 */
  21 
  22 
  23 /****^  HISTORY COMMENTS:
  24   1) change(86-10-23,Fawcett), approve(86-10-23,MCR7517),
  25      audit(86-10-30,Beattie), install(86-11-03,MR12.0-1206):
  26      Change Error Documentation to remove the word BOS.
  27                                                    END HISTORY COMMENTS */
  28 
  29 
  30 /*  Parameter  */
  31 
  32 dcl       Pvtep                         ptr;                /* -> PVTE for volume */
  33 dcl       Scavenger_blockp              ptr;                /* -> scavenger block allocated for scavenge */
  34 dcl       Scavenger_Optionsp            ptr;                /* -> options for this scavenge */
  35 dcl       Sc_metersp                    ptr;                /* -> metering cells */
  36 dcl       Code                          fixed bin (35);     /* Error code */
  37 
  38 /*  Automatic  */
  39 
  40 dcl       base_vtocx                    fixed bin;
  41 dcl       conflicts_unclaimed           fixed bin;
  42 dcl       1 copy_options                aligned like scavenger_options;
  43 dcl       damaged_vtoces                bit (MAX_VTOCE_PER_PACK) aligned;
  44 dcl       device_name                   char (8);
  45 dcl       freed_vtoces                  bit (MAX_VTOCE_PER_PACK) aligned;
  46 dcl       get_vtoce_errors              fixed bin;
  47 dcl       old_mask                      fixed bin (71);
  48 dcl       p99                           pic "99";
  49 dcl       ptp                           ptr;
  50 dcl       ptwp                          ptr;
  51 dcl       pvtx                          fixed bin;
  52 dcl       restart_sw                    bit (1) aligned;
  53 dcl       tsdw                          fixed bin (71);
  54 dcl       vastep                        ptr;
  55 dcl       vtoce_bitsp                   ptr;
  56 dcl       vtoces_damaged                fixed bin;
  57 dcl       vtoces_damaged_by_me          fixed bin;
  58 
  59 /*  Static  */
  60 
  61 dcl       ALL_PARTS                     bit (3) int static options (constant) init ("111"b);
  62 dcl       GET_VTOCE_ERROR_THRESHOLD     fixed bin int static options (constant) init (30);
  63 dcl       RLV_INITIALIZED               fixed bin int static options (constant) init (2);
  64 
  65 /*  Based  */
  66 
  67 dcl       1 file_map                    aligned based,
  68             2 fm                        (0:255) fixed bin (18) uns unal;
  69 dcl       1 Scavenger_Options           aligned like scavenger_options based (Scavenger_Optionsp);
  70 dcl       1 vtoce_bits                  aligned based (vtoce_bitsp),
  71             2 pad                       bit (base_vtocx) unaligned,
  72             2 remaining                 bit (MAX_VTOCE_PER_PACK - base_vtocx) unaligned;
  73 
  74 /*  External  */
  75 
  76 dcl       active_hardcore_data$pdd_uid  bit (36) aligned external;
  77 dcl       active_hardcore_data$sl1_uid  bit (36) aligned external;
  78 dcl       error_table_$scavenge_aborted fixed bin (35) external;
  79 dcl       error_table_$vtoce_free       fixed bin (35) external;
  80 dcl       pds$process_group_id          char (32) ext static;
  81 dcl       pvt$root_lvid                 bit (36) aligned external;
  82 dcl       sst$astap                     ptr external;
  83 dcl       sst$checksum_filemap          fixed bin (35) external;
  84 dcl       sst$cmp                       ptr external;
  85 dcl       sst$damaged_ct                fixed bin (35) external;
  86 dcl       1 sst$level                   (0:3) aligned external,
  87             2 ausedp                    bit (18) unaligned,
  88             2 no_aste                   bit (18) unaligned;
  89 dcl       sst$pts                       (0:3) fixed bin external;
  90 dcl       sys_info$initialization_state fixed bin external;
  91 dcl       volmap_abs_seg$               external;
  92 
  93 /*  Entry  */
  94 
  95 dcl       filemap_checksum_             entry (ptr, fixed bin, bit (36) aligned);
  96 dcl       fsout_vol                     entry (fixed bin, fixed bin);
  97 dcl       lock$lock_ast                 entry;
  98 dcl       lock$unlock_ast               entry;
  99 dcl       page$free_address_for_scavenge
 100                                         entry (fixed bin, fixed bin (18));
 101 dcl       page$lock_volmap              entry (ptr);
 102 dcl       page$unlock_volmap            entry (ptr);
 103 dcl       pc$deposit_list               entry (fixed bin, fixed bin, ptr, fixed bin, ptr);
 104 dcl       pc$cleanup                    entry (ptr);
 105 dcl       pmut$lock_ptl                 entry (fixed bin (71), ptr);
 106 dcl       pmut$swap_sdw                 entry (ptr, ptr);
 107 dcl       pmut$unlock_ptl               entry (fixed bin (71), ptr);
 108 dcl       priv_delete_vtoce             entry (bit (36) aligned, bit (36) aligned, fixed bin, fixed bin (35));
 109 dcl       pxss$relinquish_priority      entry;
 110 dcl       search_ast$check              entry (bit (36) aligned, bit (36) aligned, fixed bin, fixed bin (35))
 111                                         returns (ptr);
 112 dcl       setfaults                     entry (ptr, bit (1) aligned);
 113 dcl       syserr                        entry options (variable);
 114 dcl       syserr$binary                 entry options (variable);
 115 dcl       syserr$error_code             entry options (variable);
 116 dcl       tc_util$check_abort           entry (fixed bin (35));
 117 dcl       update_vtoce                  entry (ptr);
 118 dcl       vtoc_man$free_vtoce_for_scavenge
 119                                         entry (bit (36) aligned, fixed bin, fixed bin, fixed bin (35));
 120 dcl       vtoc_man$get_vtoce            entry (bit (36) aligned, fixed bin, fixed bin, bit (3), ptr, fixed bin (35));
 121 dcl       vtoc_man$put_vtoce            entry (bit (36) aligned, fixed bin, fixed bin, bit (3), ptr, fixed bin (35));
 122 dcl       vtoc_man$read_ahead_vtoce     entry (bit (36) aligned, fixed bin, fixed bin, bit (3), fixed bin (35));
 123 
 124 declare   (addr, addrel, bin, bit, clock, convert, divide, fixed, hbound, index, null, ptr, rel, rtrim, size, stacq, substr,
 125           unspec, mod)                  builtin;
 126 ^L
 127 
 128 
 129           pvtep = Pvtep;
 130           scavenger_blockp = Scavenger_blockp;
 131           sc_metersp = Sc_metersp;
 132           copy_options = Scavenger_Options;
 133           Code = 0;
 134 
 135 
 136           scavenger_datap = addr (scavenger_data$);
 137           pvt_arrayp = addr (pvt$array);
 138           pvtx = divide (bin (rel (pvtep)) - bin (rel (pvt_arrayp)), size (pvte), 17) + 1;
 139           device_name = pvte.devname || "_" || convert (p99, pvte.logical_area_number) || rtrim (pvte.sv_name);
 140 
 141 
 142           call pmut$swap_sdw (addr (volmap_abs_seg$), addr (pvte.volmap_seg_sdw));
 143           vol_mapp = ptr (addr (volmap_abs_seg$), pvte.volmap_offset);
 144           vtoc_mapp = ptr (vol_mapp, pvte.vtoc_map_offset);
 145 
 146 RESTART:
 147           restart_sw = "0"b;
 148 
 149           vtoces_damaged, vtoces_damaged_by_me = 0;
 150           get_vtoce_errors = 0;
 151           conflicts_unclaimed = 0;
 152 
 153           unspec (freed_vtoces) = ""b;
 154           unspec (damaged_vtoces) = ""b;
 155 
 156           call lock$lock_ast;
 157 
 158           if copy_options.fault_under_ast
 159           then call FAULT ("AST Lock");
 160 
 161           call page$lock_volmap (pvtep);
 162           if copy_options.fault_under_volmap
 163           then call FAULT ("VOLMAP Lock");
 164 
 165           call COPY_VOLMAP;
 166 
 167           pvte.deposit_to_volmap = "1"b;
 168           call pmut$lock_ptl (old_mask, ptwp);
 169           if copy_options.fault_under_pt
 170           then call FAULT ("Global PTL");
 171 
 172           pvte.scav_check_address = "1"b;
 173           call COPY_STOCK;
 174           call WALK_SST;
 175           call pmut$unlock_ptl (old_mask, ptwp);
 176           pvte.deposit_to_volmap = "0"b;
 177 
 178           call page$unlock_volmap (pvtep);
 179           call lock$unlock_ast;
 180 
 181           call WALK_VOLUME;
 182 
 183 RECOVER_OVERFLOW:
 184           call RESOLVE_CONFLICTS;
 185 
 186           if get_vtoce_errors = 0
 187           then call FREE_RECORDS;
 188           pvte.scav_check_address = "0"b;
 189 
 190           if restart_sw
 191           then do;
 192                     unspec (scavenger_block.records) = ""b;
 193                     unspec (scavenger_block.overflow) = ""b;
 194                     scavenger_block.ovfl_free_ix = 1;
 195                     goto RESTART;
 196                end;
 197 
 198           call CHECK_VTOCE_DAMAGE;
 199           call FREE_VTOCES;
 200 
 201           if get_vtoce_errors = 0
 202           then do;
 203                     pvte.vol_trouble_count = 0;
 204                     call fsout_vol (pvtx, 0);
 205                end;
 206 
 207 
 208           if get_vtoce_errors > 0
 209           then call syserr (ANNOUNCE, "scavenge_volume: ^d errors reading VTOCEs on ^a", get_vtoce_errors, device_name);
 210 
 211           if vtoces_damaged > 0
 212           then call syserr (ANNOUNCE,
 213                     "scavenge_volume: ^d VTOCEs on ^a damaged.^[ ^d damaged during this scavenge.^;^1s^]", vtoces_damaged,
 214                     device_name, (vtoces_damaged_by_me > 0), vtoces_damaged_by_me);
 215 
 216 ABORT_JOIN:
 217           pvte.scav_check_address = "0"b;
 218 
 219           tsdw = 0;
 220           call pmut$swap_sdw (addr (volmap_abs_seg$), addr (tsdw));
 221 
 222           if copy_options.trap
 223           then call syserr (CRASH, "scavenge_volume: Debug Trap on scavenge of ^a", device_name);
 224 
 225 
 226           return;
 227 %page;
 228 /*  Internal Procedure to find all free records in the volume map
 229    and mark them as free in the scavenger block. It is assumed that there
 230    will be no conflicts. This must be called with the volume map locked.
 231    This prevents record addresses from migrating between the volume map
 232    and the record stock.
 233 */
 234 
 235 COPY_VOLMAP:
 236      proc;
 237 
 238 dcl       bit_mapx                      fixed bin;
 239 dcl       bx                            fixed bin;
 240 dcl       rec_add                       fixed bin (18);
 241 dcl       word_baseadd                  fixed bin (18);
 242 
 243 
 244           do bit_mapx = 1 to vol_map.bit_map_n_words;
 245                bit_map_wordp = addr (vol_map.bit_map (bit_mapx));
 246                if bit_map_word.bits ^= ""b                  /* Some free this word */
 247                then do;
 248                          word_baseadd = (bit_mapx - 1) * 32;
 249                          do bx = 1 to 32;
 250                               if substr (bit_map_word.bits, bx, 1) = "1"b
 251                               then do;
 252                                         rec_add = word_baseadd + bx;
 253                                         scavenger_block.records (rec_add).state = STATE_FREE;
 254                                    end;
 255                          end;
 256                     end;
 257           end;
 258 
 259      end COPY_VOLMAP;
 260 %page;
 261 /*  Internal Procedure to find all free addresses in the record stock and
 262    mark them as free in the scavenger block. Any conflicts are marked as
 263    such (this can only happen if an address in the stock was found in the
 264    volume map, which can only happen if an address deposited recently is
 265    marked as free in the volume map). Both the volume map and the Page
 266    Table Lock must be held to ensure the stability of free addresses during
 267    this scan. The Page Table Lock prevents withdrawal from the stock.
 268    pvte.deposit_to_volmap ON disables lockless stock deposits,
 269    and so deposits are done under the volume map lock.
 270 */
 271 
 272 COPY_STOCK:
 273      proc;
 274 
 275 dcl       rec_add                       fixed bin (18);
 276 dcl       sx                            fixed bin;
 277 
 278 
 279           record_stockp = pvte.volmap_stock_ptr;
 280           do sx = 1 to record_stock.n_in_stock;
 281                if record_stock.stock (sx) ^= ""b            /* Record address this slot */
 282                then if substr (record_stock.stock (sx), 1, 1) = "1"b
 283                                                             /* Out-of-service */
 284                     then call syserr (CRASH, "scavenge_volume: Out-of-service address in stock for ^a", device_name);
 285                     else do;
 286                               rec_add = bin (record_stock.stock (sx), 18) - pvte.baseadd + 1;
 287                               if scavenger_block.records (rec_add).state ^= STATE_UNSEEN
 288                               then scavenger_block.records (rec_add).state = STATE_CONFLICT;
 289 
 290                               else scavenger_block.records (rec_add).state = STATE_FREE;
 291                          end;
 292           end;
 293 
 294      end COPY_STOCK;
 295 %page;
 296 /*  Internal Procedure to walk the SST. For each non-special ASTE on this
 297    physical volume, we construct its file map from the page table and
 298    core map entries. We then check the file map, as is done for each
 299    VTOCE at another time.  The AST Lock and the Page Table Lock must be held.
 300 */
 301 WALK_SST:
 302      proc;
 303 
 304 
 305 dcl       astx                          fixed bin;
 306 dcl       1 aste_file_map               aligned like file_map;
 307 dcl       n_pages                       fixed bin;
 308 dcl       px                            fixed bin;
 309 
 310 
 311           astep = sst$astap;
 312 
 313           do px = 0 to hbound (sst$level, 1);
 314                n_pages = sst$pts (px);
 315                do astx = 1 to bin (sst$level.no_aste (px));
 316                     if aste.usedf & (aste.pvtx = pvtx)
 317                     then if (aste.vtocx ^= -1) & ^aste.hc_part & ^aste.volmap_seg
 318                          then do;
 319                                    call BUILD_FILEMAP_FROM_ASTE (astep, addr (aste_file_map), n_pages);
 320                                    call CHECK_FILE_MAP ((aste.vtocx), addr (aste_file_map), n_pages, (aste.fm_damaged));
 321                                    if aste.fm_damaged
 322                                    then substr (damaged_vtoces, aste.vtocx + 1, 1) = "1"b;
 323                               end;
 324                     astep = addrel (astep, size (aste) + n_pages);
 325                end;
 326           end;
 327 
 328      end WALK_SST;
 329 %page;
 330 /*  Internal Procedure to examine all VTOCEs on a volume. Each VTOCE is
 331    validated syntactically, and the file map is checked for conflicts.
 332    A list of VTOCEs to be freed and of damaged VTOCEs is maintained. However,
 333    none are freed or damaged in this pass. The goal is to minimize the
 334    time through this pass, due to the overhead in Page Control deposit/
 335    withdraw while this is going on.
 336 
 337    Any free VTOCE is checked against the VTOC map. If it is not there,
 338    it is marked to-be-freed. This is an optimization. Any VTOCE in the
 339    VTOC map is not lost. It doesn't matter if we mark a VTOCE which is
 340    not lost to-be-freed, since we'll detect this later.
 341 
 342 */
 343 
 344 WALK_VOLUME:
 345      proc;
 346 
 347 dcl       bitx                          fixed bin;
 348 dcl       code                          fixed bin (35);
 349 dcl       free_it                       bit (1) aligned;
 350 dcl       1 local_vtoce                 aligned like vtoce;
 351 dcl       1 vtoce_file_map              aligned like file_map;
 352 dcl       vtocx                         fixed bin;
 353 dcl       wordx                         fixed bin;
 354 
 355 
 356           do vtocx = 0 to pvte.n_vtoce - 1;
 357 
 358                if copy_options.debug
 359                then if mod (vtocx, 1024) = 0
 360                     then call syserr (ANNOUNCE, "scavenge_volume: Processing vtocx ^o on ^a.", vtocx, device_name);
 361 
 362                sc_meters.n_vtoces = sc_meters.n_vtoces + 1;
 363                call vtoc_man$get_vtoce (""b, pvtx, vtocx, ALL_PARTS, addr (local_vtoce), code);
 364                if code ^= 0
 365                then do;
 366                          call syserr$error_code (SEVERITY (LOG), code, "scavenge_volume: Error reading vtocx ^o on ^a",
 367                               vtocx, device_name);
 368                          get_vtoce_errors = get_vtoce_errors + 1;
 369                          goto NEXT_VTOCE;
 370                     end;
 371 
 372                if copy_options.no_optimize
 373                then call pxss$relinquish_priority;          /* Give up the CPU */
 374                else if vtocx < pvte.n_vtoce - 1
 375                then call vtoc_man$read_ahead_vtoce (""b, pvtx, vtocx + 1, ALL_PARTS, code);
 376 
 377                if local_vtoce.uid = ""b
 378                then do;
 379                          wordx = divide (vtocx, 32, 17);
 380                          bit_map_wordp = addr (vtoc_map.bit_map (wordx));
 381                          bitx = mod (vtocx, 32);
 382                          if substr (bit_map_word.bits, bitx + 1, 1) ^= "1"b
 383                          then substr (freed_vtoces, vtocx + 1, 1) = "1"b;
 384                          goto NEXT_VTOCE;
 385                     end;
 386 
 387                call CHECK_VTOCE_FOR_FREE (addr (local_vtoce), "0"b, (""), free_it);
 388                if free_it
 389                then substr (freed_vtoces, vtocx + 1, 1) = "1"b;
 390 
 391                call CHECK_VTOCE (vtocx, addr (local_vtoce), "0"b, ("0"b));
 392                if local_vtoce.damaged | local_vtoce.fm_damaged
 393                then substr (damaged_vtoces, vtocx + 1, 1) = "1"b;
 394 
 395                call BUILD_FILEMAP_FROM_VTOCE (addr (local_vtoce), addr (vtoce_file_map));
 396                call CHECK_FILE_MAP (vtocx, addr (vtoce_file_map), bin (local_vtoce.csl), (local_vtoce.fm_damaged));
 397 
 398 NEXT_VTOCE:
 399                if get_vtoce_errors > GET_VTOCE_ERROR_THRESHOLD
 400                then do;
 401                          pvte.scav_check_address = "0"b;
 402                          Code = error_table_$scavenge_aborted;
 403                          goto ABORT_JOIN;
 404                     end;
 405                call CHECK_ABORT;
 406           end;
 407 
 408 
 409 
 410      end WALK_VOLUME;
 411 
 412 %page;
 413 /*  Internal Procedure to construct a file map from an ASTE. The AST and Page
 414    Table Locks must be held.
 415 */
 416 
 417 BUILD_FILEMAP_FROM_ASTE:
 418      proc (Astep, File_Mapp, PT_Size);
 419 
 420 dcl       Astep                         ptr;
 421 dcl       File_Mapp                     ptr;
 422 dcl       PT_Size                       fixed bin;
 423 
 424 dcl       page_tablep                   ptr;
 425 dcl       px                            fixed bin;
 426 
 427 dcl       1 Aste                        aligned like aste based (Astep);
 428 dcl       1 File_Map                    aligned like file_map based (File_Mapp);
 429 
 430           page_tablep = addrel (Astep, size (Aste));
 431           unspec (File_Map) = ""b;
 432 
 433           do px = 0 to PT_Size - 1;
 434                ptp = addrel (page_tablep, px);
 435                if l68_ptw.flags.add_type = ""b
 436                then File_Map.fm (px) = 0;
 437                else if l68_ptw.flags.add_type = add_type.core
 438                then do;
 439                          cmep = addr (sst$cmp -> cma (l68_core_ptw.frame));
 440                          if mcme.add_type = add_type.disk
 441                          then File_Map.fm (px) = bin (substr (mcme.record_no, 2, 17));
 442                          else File_Map.fm (px) = 0;
 443                     end;
 444                else if l68_ptw.flags.add_type = add_type.disk
 445                then File_Map.fm (px) = bin (substr (l68_ptw.add, 2, 17));
 446                else File_Map.fm (px) = 0;
 447           end;
 448 
 449      end BUILD_FILEMAP_FROM_ASTE;
 450 %page;
 451 /*  Internal Procedure to construct a file map from a VTOCE */
 452 
 453 BUILD_FILEMAP_FROM_VTOCE:
 454      proc (Vtocep, File_Mapp);
 455 
 456 dcl       Vtocep                        ptr;
 457 dcl       File_Mapp                     ptr;
 458 
 459 dcl       px                            fixed bin;
 460 
 461 dcl       1 File_Map                    aligned like file_map based (File_Mapp);
 462 dcl       1 Vtoce                       aligned like vtoce based (Vtocep);
 463 
 464 
 465           do px = 0 to hbound (Vtoce.fm, 1);
 466                if substr (Vtoce.fm (px), 1, 1) = "1"b
 467                then File_Map.fm (px) = 0;
 468                else File_Map.fm (px) = bin (Vtoce.fm (px), 18);
 469           end;
 470 
 471      end BUILD_FILEMAP_FROM_VTOCE;
 472 
 473 
 474 %page;
 475 /*  Internal Procedure to examine the list of VTOCEs marked as damaged
 476    during the first pass. Each is checked again for damage under the
 477    AST lock (if the segment is active it is skipped, since activate
 478    checks most of the fields we check). If damage is found, the
 479    segment is damaged for real, and messages dumped into the syserr
 480    log.
 481 */
 482 CHECK_VTOCE_DAMAGE:
 483      proc;
 484 
 485 dcl       code                          fixed bin (35);
 486 dcl       1 copy_vtoce                  aligned like vtoce;
 487 dcl       damaged_sw                    bit (1) aligned;
 488 dcl       done_damage                   bit (1) aligned;
 489 dcl       1 local_vtoce                 aligned like vtoce;
 490 dcl       prev_damaged                  bit (1) aligned;
 491 dcl       prev_fm_damaged               bit (1) aligned;
 492 dcl       vtocx                         fixed bin;
 493 
 494 
 495           vtoce_bitsp = addr (damaged_vtoces);
 496 
 497           base_vtocx = 0;
 498           done_damage = "0"b;
 499 
 500           do while (^done_damage);
 501 
 502                vtocx = index (vtoce_bits.remaining, "1"b);
 503                if vtocx = 0
 504                then do;                                     /* None left */
 505                          done_damage = "1"b;
 506                          goto NEXT;
 507                     end;
 508 
 509                vtocx = vtocx + base_vtocx - 1;
 510                base_vtocx = vtocx + 1;
 511                call vtoc_man$get_vtoce (""b, pvtx, vtocx, ALL_PARTS, addr (local_vtoce), code);
 512                if code ^= 0
 513                then do;
 514                          call syserr$error_code (SEVERITY (LOG), "scavenge_volume: Error reading vtocx ^o on ^a", vtocx,
 515                               device_name);
 516                          goto NEXT;
 517                     end;
 518 
 519                if copy_options.dump
 520                then unspec (copy_vtoce) = unspec (local_vtoce);
 521 
 522                call LOCK_AST_CHECK_UID ((local_vtoce.uid), vtocx, astep);
 523                if astep = null ()
 524                then do;                                     /* Only non-active segments. lock prevent activation */
 525 
 526                          prev_damaged = local_vtoce.damaged;
 527                          call CHECK_VTOCE (vtocx, addr (local_vtoce), "1"b, damaged_sw);
 528 
 529                          if local_vtoce.damaged
 530                          then vtoces_damaged = vtoces_damaged + 1;
 531                          if (local_vtoce.damaged & ^prev_damaged)
 532                          then vtoces_damaged_by_me = vtoces_damaged_by_me + 1;
 533 
 534                          if damaged_sw | prev_damaged
 535                          then call SEGDAMAGE (vtocx, addr (local_vtoce), addr (copy_vtoce), prev_damaged);
 536 
 537                          if local_vtoce.fm_damaged
 538                          then do;
 539                                    prev_fm_damaged = "1"b;
 540                                    local_vtoce.fm_damaged = "0"b;
 541                                    if sst$checksum_filemap ^= 0
 542                                    then do;
 543                                              call filemap_checksum_ (addr (local_vtoce.fm), fixed (local_vtoce.csl),
 544                                                   local_vtoce.fm_checksum);
 545                                              local_vtoce.fm_checksum_valid = "1"b;
 546                                         end;
 547                                    else do;
 548                                              local_vtoce.fm_checksum_valid = "0"b;
 549                                              local_vtoce.fm_checksum = ""b;
 550                                         end;
 551                                    sc_meters.n_vtoces_fmd = sc_meters.n_vtoces_fmd + 1;
 552                               end;
 553 
 554                          if damaged_sw | prev_fm_damaged
 555                          then do;
 556                                    call vtoc_man$put_vtoce (""b, pvtx, vtocx, ALL_PARTS, addr (local_vtoce), code);
 557                                    if code ^= 0
 558                                    then call syserr$error_code (SEVERITY (LOG), code,
 559                                              "scavenge_volume: Error writing vtocx ^a on ^a.", vtocx, device_name);
 560                               end;
 561 
 562                     end;
 563                else do;                                     /* active */
 564                          if aste.fm_damaged
 565                          then do;
 566                                    sc_meters.n_vtoces_fmd = sc_meters.n_vtoces_fmd + 1;
 567                                    aste.fm_damaged = "0"b;
 568                               end;
 569                     end;
 570 
 571                call lock$unlock_ast;
 572 
 573 NEXT:
 574           end;
 575 
 576 
 577 
 578 
 579      end CHECK_VTOCE_DAMAGE;
 580 %page;
 581 /*  Internal Procedure to free any records which are unseen. Any unseen
 582    records are known not to be claimed by any VTOCE and not to be in
 583    the Volume Map. It is safe to free these without further examination
 584    or adieu.
 585 */
 586 
 587 FREE_RECORDS:
 588      proc;
 589 
 590 dcl       1 deposit_list                (256) aligned,
 591             2 record                    fixed bin (18) uns unal,
 592             2 pad                       bit (18) unal;
 593 dcl       dx                            fixed bin;
 594 dcl       records_freed                 fixed bin;
 595 dcl       rx                            fixed bin;
 596 
 597           unspec (deposit_list) = ""b;
 598           records_freed = 0;
 599           dx = 0;
 600 
 601           do rx = 1 to scavenger_block.n_records;
 602 
 603                record_blockp = addr (scavenger_block.records (rx));
 604                if record_block.state = STATE_UNSEEN
 605                then do;
 606                          dx = dx + 1;
 607                          records_freed = records_freed + 1;
 608                          deposit_list (dx).record = rx + pvte.baseadd - 1;
 609                          if dx >= hbound (deposit_list, 1)
 610                          then do;
 611                                    call pc$deposit_list (pvtx, dx, addr (deposit_list), -1, null ());
 612                                    dx = 0;
 613                                    call CHECK_ABORT;
 614                               end;
 615                     end;
 616 
 617           end;
 618 
 619           if dx > 0
 620           then call pc$deposit_list (pvtx, dx, addr (deposit_list), -1, null ());
 621 
 622           records_freed = records_freed - conflicts_unclaimed;
 623                                                             /* Adjust for those really lost */
 624           sc_meters.n_lost_records = records_freed;
 625           if records_freed > 0
 626           then call syserr (SEVERITY (LOG), "scavenge_volume: Freed ^d records on ^a", records_freed, device_name);
 627 
 628      end FREE_RECORDS;
 629 %page;
 630 /*  Internal Procedure to look for record addresses which have potential
 631    conflicts. A routine to resolve the conflict is called for each such.
 632    This driver routine is split out for logic clarity.
 633 */
 634 
 635 RESOLVE_CONFLICTS:
 636      proc;
 637 
 638 dcl       rx                            fixed bin;
 639 
 640 
 641           do rx = 1 to scavenger_block.n_records;
 642                record_blockp = addr (scavenger_block.records (rx));
 643                if record_block.state = STATE_CONFLICT
 644                then do;
 645                          call RESOLVE_THIS_CONFLICT ((rx - 1 + pvte.baseadd), record_blockp);
 646                          call CHECK_ABORT;
 647                     end;
 648           end;
 649 
 650      end RESOLVE_CONFLICTS;
 651 %page;
 652 /*  Internal Procedure to resolve conflicts for a given record address.
 653    This routine is the real hair of the scavenger, the complexity due
 654    to the many races, both here and in the first pass (which flagged
 655    the potential conflicts).
 656 
 657    The logic is as follows:
 658 
 659    1. Make sure that the address is not marked as free in the
 660    stock or Volume Map (using a special page control entry for us).
 661 
 662    2. Walk the thread of potential conflicts. For each entry, note
 663    whether the conflict in fact exists. Of those segments still
 664    claiming the address, select at most one to get it, according
 665    to the following rules:
 666 
 667    If only one segment claims the address, it gets it.
 668 
 669    If only one directory claims the address, it gets it. The
 670    directory salvager is presumed capable of straightening
 671    any mess out.
 672 
 673    If only one segment which has no record of file map damage
 674    claims the address, it gets it.
 675 
 676    Otherwise nobody gets it. Note that our covenant with page control
 677    deposit/withdraw prevents any segment from getting this address other
 678    than the ones we know about.
 679 
 680    3. Walk the thread of potential conflicts again. For each entry which
 681    doesn't get the address, attempt to bust the address loose.
 682    A setfaults is used to disconnect the segment from active processes.
 683    If the segment is entry-held, we log a message and give up. The
 684    address is nulled, and the segment is damaged.
 685    This is all done under the AST lock.
 686 
 687    4. Under the AST lock, check whether the lucky segment which gets
 688    the address still has it. If not, deposit it after setting the
 689    state "unseen" (so that the deposit takes).
 690 
 691    It is assumed that conflicts are relatively rare, and that efficiency
 692    can be sacrificed for a modicum of simplicity.
 693 */
 694 
 695 RESOLVE_THIS_CONFLICT:
 696      proc (Record_Address, Record_Blockp);
 697 
 698 dcl       Record_Address                fixed bin (18);
 699 dcl       Record_Blockp                 ptr;
 700 
 701 dcl       checksum                      bit (36) aligned;
 702 dcl       claim_count                   fixed bin;
 703 dcl       claims_address                bit (1) aligned;
 704 dcl       code                          fixed bin (35);
 705 dcl       conflict_blockp               ptr;
 706 dcl       1 copy_vtoce                  aligned like vtoce;
 707 dcl       csl                           fixed bin;
 708 dcl       dir_count                     fixed bin;
 709 dcl       done_thread                   bit (1) aligned;
 710 dcl       1 local_file_map              aligned like file_map;
 711 dcl       1 local_vtoce                 aligned like vtoce;
 712 dcl       not_fmd_count                 fixed bin;
 713 dcl       owner_pageno                  fixed bin;
 714 dcl       owner_vtocx                   fixed bin;
 715 dcl       pageno                        fixed bin;
 716 dcl       prev_damaged                  bit (1) aligned;
 717 dcl       real_conflict                 bit (1) aligned;
 718 dcl       records                       fixed bin;
 719 dcl       vtocx                         fixed bin;
 720 
 721 dcl       1 conflict_block              aligned like record_block based (conflict_blockp);
 722 dcl       1 Record_Block                aligned like record_block based (Record_Blockp);
 723 
 724 
 725 /* Free the address. Check whether each conflict is real, and select an
 726    owner for the address. */
 727 
 728           sc_meters.n_conflicts = sc_meters.n_conflicts + 1;
 729           real_conflict = "0"b;
 730 
 731           conflict_blockp = Record_Blockp;
 732 
 733           call page$free_address_for_scavenge (pvtx, Record_Address);
 734 
 735           dir_count, claim_count, not_fmd_count = 0;
 736           owner_vtocx = -1;
 737           done_thread = "0"b;
 738           do while (^done_thread);
 739 
 740                vtocx = conflict_block.vtocx;
 741                pageno = conflict_block.pageno;
 742 
 743                call GET_VTOCE_CHECK_ADDRESS (vtocx, addr (local_vtoce), pageno, Record_Address, astep, claims_address,
 744                     code);
 745                if code ^= 0
 746                then do;
 747 ERROR_PUNT:
 748                          call syserr$error_code (SEVERITY (LOG), code,
 749                               "scavenge_volume: Unable to resolve conflict for address ^o on ^a. Error at vtocx ^o.",
 750                               Record_Address, device_name, vtocx);
 751                          get_vtoce_errors = get_vtoce_errors + 1;
 752                          return;
 753                     end;
 754                if claims_address
 755                then do;
 756                          call lock$unlock_ast;
 757                          claim_count = claim_count + 1;
 758                          if local_vtoce.dirsw
 759                          then dir_count = dir_count + 1;
 760                          if ^local_vtoce.fm_damaged & local_vtoce.fm_checksum_valid
 761                          then do;
 762                                    call filemap_checksum_ (addr (local_vtoce.fm), fixed (local_vtoce.csl, 9), checksum);
 763                                    if local_vtoce.fm_checksum ^= checksum
 764                                    then local_vtoce.fm_damaged = "1"b;
 765                               end;
 766                          if ^local_vtoce.fm_damaged
 767                          then not_fmd_count = not_fmd_count + 1;
 768                          if (claim_count = 1) | (local_vtoce.dirsw & (dir_count = 1))
 769                               | (^local_vtoce.fm_damaged & (not_fmd_count = 1) & (dir_count = 0))
 770                          then do;
 771                                    owner_vtocx = vtocx;
 772                                    owner_pageno = pageno;
 773                               end;
 774                     end;
 775                if conflict_block.ovflx = 0
 776                then done_thread = "1"b;
 777                else conflict_blockp = addr (scavenger_block.overflow (conflict_block.ovflx));
 778 
 779           end;
 780 
 781 
 782 /*  If there are no claimants, mark the address as unseen. This will
 783    cause it to be freed later.
 784 */
 785 
 786           if claim_count = 0
 787           then do;
 788 FREE_RETURN:
 789                     call LOCK_RECORD (record_blockp);
 790                     Record_Block.state = STATE_UNSEEN;
 791                     record_block.lock = "0"b;
 792                     conflicts_unclaimed = conflicts_unclaimed + 1;
 793                     return;
 794                end;
 795 
 796 %page;
 797 /*  Walk the list of conflicts, and attempt to bust the address loose
 798    from all except the owner. Note that there may be no owner.  */
 799 
 800           done_thread = "0"b;
 801           conflict_blockp = Record_Blockp;
 802 
 803           if (claim_count > 1) & (dir_count ^= 1) & (not_fmd_count ^= 1)
 804           then owner_vtocx = -1;
 805 
 806           do while (^done_thread);
 807 
 808                vtocx = conflict_block.vtocx;
 809                pageno = conflict_block.pageno;
 810                if ((vtocx ^= owner_vtocx) | (pageno ^= owner_pageno))
 811                then do;
 812 
 813                          call GET_VTOCE_CHECK_ADDRESS (vtocx, addr (local_vtoce), pageno, Record_Address, astep,
 814                               claims_address, code);
 815                          if code ^= 0
 816                          then goto ERROR_PUNT;
 817                          if ^claims_address
 818                          then goto NEXT;
 819                          real_conflict = "1"b;
 820 
 821                          if copy_options.dump
 822                          then unspec (copy_vtoce) = unspec (local_vtoce);
 823 
 824                          if astep ^= null ()
 825                          then do;
 826                                    if aste.ehs | aste.hc_sdw | aste.hc | aste.hc_part
 827                                    then do;
 828 PUNT_ASTE:
 829                                              call lock$unlock_ast;
 830                                              call syserr (SEVERITY (LOG),
 831                                                   "scavenge_volume: Unable to resolve conflict for address ^o on ^a. astep=^p"
 832                                                   , Record_Address, device_name, astep);
 833                                              return;
 834                                         end;
 835                                    call setfaults (astep, "0"b);
 836                                    call pc$cleanup (astep);
 837                                    ptp = addrel (astep, size (aste) + pageno);
 838                                    if l68_ptw.add_type ^= add_type.disk
 839                                    then goto PUNT_ASTE;
 840                                    l68_ptw.add_type = ""b;
 841                                    l68_ptw.add = pv_scav_null_addr;
 842                                    prev_damaged = aste.damaged;
 843                                    aste.damaged = "1"b;
 844                                    aste.fmchanged = "1"b;
 845 
 846                                    call BUILD_FILEMAP_FROM_ASTE (astep, addr (local_file_map), sst$pts (bin (aste.ptsi)));
 847                                    call COMPUTE_RECORDS_CSL (addr (local_file_map), records, csl);
 848                                    aste.records = bit (bin (records, 9), 9);
 849                                    aste.csl = bit (bin (csl, 9), 9);
 850 
 851                                    call update_vtoce (astep);
 852                                                             /* Reflect into VTOCE */
 853 
 854                               end;
 855                          else do;
 856                                    call vtoc_man$get_vtoce (""b, pvtx, vtocx, ALL_PARTS, addr (local_vtoce), code);
 857                                    if code ^= 0
 858                                    then do;
 859                                              call lock$unlock_ast;
 860                                              goto ERROR_PUNT;
 861                                         end;
 862                                    prev_damaged = local_vtoce.damaged;
 863                                    local_vtoce.fm (pageno) = pv_scav_null_addr;
 864                                    call BUILD_FILEMAP_FROM_VTOCE (addr (local_vtoce), addr (local_file_map));
 865                                    call COMPUTE_RECORDS_CSL (addr (local_file_map), records, csl);
 866                                    local_vtoce.csl = bit (bin (csl, 9), 9);
 867                                    local_vtoce.records = bit (bin (records, 9), 9);
 868                                    if sst$checksum_filemap = 0
 869                                    then do;
 870                                              local_vtoce.fm_checksum_valid = "0"b;
 871                                              local_vtoce.fm_checksum = ""b;
 872                                         end;
 873                                    else do;
 874                                              local_vtoce.fm_checksum_valid = "1"b;
 875                                              call filemap_checksum_ (addr (local_vtoce.fm), csl, local_vtoce.fm_checksum);
 876                                         end;
 877 
 878                                    local_vtoce.damaged = "1"b;
 879                                    call vtoc_man$put_vtoce (""b, pvtx, vtocx, ALL_PARTS, addr (local_vtoce), code);
 880                                    if code ^= 0
 881                                    then do;
 882                                              call lock$unlock_ast;
 883                                              goto ERROR_PUNT;
 884                                         end;
 885                               end;
 886                          call lock$unlock_ast;
 887                          call syserr (SEVERITY (LOG),
 888                               "scavenge_volume: vtoce ^a at ^o (^a). ref to pageno ^o at addr ^o deleted",
 889                               local_vtoce.primary_name, vtocx, device_name, pageno, Record_Address);
 890                          if ^prev_damaged
 891                          then do;
 892                                    call SEGDAMAGE (vtocx, addr (local_vtoce), addr (copy_vtoce), prev_damaged);
 893                                    vtoces_damaged = vtoces_damaged + 1;
 894                                    vtoces_damaged_by_me = vtoces_damaged_by_me + 1;
 895                               end;
 896                     end;
 897 
 898 NEXT:
 899                if conflict_block.ovflx = 0
 900                then done_thread = "1"b;
 901                else conflict_blockp = addr (scavenger_block.overflow (conflict_block.ovflx));
 902           end;
 903 
 904           if real_conflict
 905           then sc_meters.n_real_conflicts = sc_meters.n_real_conflicts + 1;
 906 %page;
 907 /*  Now check whether the owner (if any) still claims the address. If not,
 908    free it.  */
 909 
 910           if owner_vtocx = -1
 911           then do;
 912                     call LOCK_RECORD (record_blockp);
 913                     record_block.state = STATE_UNSEEN;
 914                     record_block.lock = "0"b;
 915                     return;
 916                end;
 917 
 918           call GET_VTOCE_CHECK_ADDRESS (owner_vtocx, addr (local_vtoce), owner_pageno, Record_Address, astep,
 919                claims_address, code);
 920           if code ^= 0
 921           then return;
 922 
 923 
 924           if ^claims_address
 925           then goto FREE_RETURN;
 926 
 927           call lock$unlock_ast;
 928 
 929      end RESOLVE_THIS_CONFLICT;
 930 
 931 %page;
 932 /*  Internal Procedure to recompute the number of records and current
 933    segment length from a file map.
 934 */
 935 
 936 COMPUTE_RECORDS_CSL:
 937      proc (File_Mapp, Records, Csl);
 938 
 939 dcl       File_Mapp                     ptr;
 940 dcl       Records                       fixed bin;
 941 dcl       Csl                           fixed bin;
 942 
 943 dcl       px                            fixed bin;
 944 
 945 dcl       1 File_Map                    aligned like file_map based (File_Mapp);
 946 
 947           Records, Csl = 0;
 948           do px = 0 to hbound (File_Map.fm, 1);
 949                if File_Map.fm (px) ^= 0
 950                then do;
 951                          Csl = px + 1;
 952                          Records = Records + 1;
 953                     end;
 954           end;
 955 
 956      end COMPUTE_RECORDS_CSL;
 957 %page;
 958 /*  Internal Procedure to read a VTOCE, check whether the segment is active,
 959    and whether the segment claims a specified address for a certain page.
 960    The AST is locked, and left locked if the address is claimed.
 961 */
 962 GET_VTOCE_CHECK_ADDRESS:
 963      proc (Vtocx, Vtocep, Pageno, Record_Address, Astep, Claims, Code);
 964 
 965 dcl       Vtocx                         fixed bin;
 966 dcl       Vtocep                        ptr;
 967 dcl       Pageno                        fixed bin;
 968 dcl       Record_Address                fixed bin (18);
 969 dcl       Astep                         ptr;
 970 dcl       Claims                        bit (1) aligned;
 971 dcl       Code                          fixed bin (35);
 972 
 973 dcl       old_mask                      fixed bin (71);
 974 dcl       ptwp                          ptr;
 975 
 976 dcl       1 Vtoce                       aligned like vtoce based (Vtocep);
 977 
 978 
 979           Code = 0;
 980           Astep = null ();
 981           Claims = "0"b;
 982 
 983           call vtoc_man$get_vtoce (""b, pvtx, Vtocx, ALL_PARTS, Vtocep, Code);
 984           if Code ^= 0
 985           then return;
 986 
 987           call LOCK_AST_CHECK_UID ((Vtoce.uid), Vtocx, Astep);
 988           if Astep = null ()
 989           then do;
 990                     if substr (Vtoce.fm (Pageno), 1, 1) = "0"b
 991                     then if bin (Vtoce.fm (Pageno), 18) = Record_Address
 992                          then Claims = "1"b;
 993                end;
 994           else do;
 995                     if Pageno < sst$pts (fixed (Astep -> aste.ptsi, 3))
 996                                                             /* silly scoping */
 997                     then do;
 998                               ptp = addrel (Astep, size (aste) + Pageno);
 999                               call pmut$lock_ptl (old_mask, ptwp);
1000                               if l68_ptw.flags.add_type = add_type.core
1001                               then do;
1002                                         cmep = addr (sst$cmp -> cma (l68_core_ptw.frame));
1003                                         if mcme.add_type = add_type.disk
1004                                         then if bin (substr (mcme.record_no, 2, 17)) = Record_Address
1005                                              then Claims = "1"b;
1006                                    end;
1007                               else if l68_ptw.flags.add_type = add_type.disk
1008                               then if bin (substr (l68_ptw.add, 2, 17)) = Record_Address
1009                                    then Claims = "1"b;
1010                               call pmut$unlock_ptl (old_mask, ptwp);
1011                          end;
1012                end;
1013 
1014           if ^Claims
1015           then call lock$unlock_ast;
1016 
1017 
1018      end GET_VTOCE_CHECK_ADDRESS;
1019 
1020 
1021 %page;
1022 /*  Internal Procedure to examine the list of VTOCEs to be freed which
1023    were found in the first pass. Each is examined again.
1024    If not active and still to-be-freed, it is freed. Potentially lost
1025    VTOCEs are freed using a special entry to vtoc_man to avoid the
1026    race with an in-progress allocation. Other VTOCEs are freed by
1027    priv_delete_vtoce, which  protects against races and active segments.
1028 */
1029 FREE_VTOCES:
1030      proc;
1031 
1032 dcl       code                          fixed bin (35);
1033 dcl       done_free                     bit (1) aligned;
1034 dcl       free_it                       bit (1) aligned;
1035 dcl       1 local_vtoce                 aligned like vtoce;
1036 dcl       message                       char (32);
1037 dcl       vtoces_freed                  fixed bin;
1038 dcl       vtocx                         fixed bin;
1039 
1040 
1041           vtoces_freed = 0;
1042           vtoce_bitsp = addr (freed_vtoces);
1043 
1044           base_vtocx = 0;
1045           done_free = "0"b;
1046 
1047           do while (^done_free);
1048 
1049                vtocx = index (vtoce_bits.remaining, "1"b);
1050                if vtocx = 0
1051                then do;                                     /* None left */
1052                          done_free = "1"b;
1053                          goto NEXT;
1054                     end;
1055 
1056                vtocx = vtocx + base_vtocx - 1;
1057                base_vtocx = vtocx + 1;
1058                call vtoc_man$get_vtoce (""b, pvtx, vtocx, ALL_PARTS, addr (local_vtoce), code);
1059                if code ^= 0
1060                then do;
1061                          call syserr$error_code (SEVERITY (LOG), code, "scavenge_volume: Error reading vtocx ^a on ^a.",
1062                               vtocx, device_name);
1063                          get_vtoce_errors = get_vtoce_errors + 1;
1064                          goto NEXT;
1065                     end;
1066 
1067 
1068                call CHECK_VTOCE_FOR_FREE (addr (local_vtoce), "1"b, message, free_it);
1069                if free_it
1070                then do;
1071 
1072                          if local_vtoce.uid = ""b
1073                          then call vtoc_man$free_vtoce_for_scavenge (""b, pvtx, vtocx, code);
1074 
1075                          else call priv_delete_vtoce ((local_vtoce.uid), pvte.pvid, vtocx, code);
1076 
1077                          if code = 0
1078                          then do;
1079                                    vtoces_freed = vtoces_freed + 1;
1080                                    if copy_options.debug
1081                                    then call syserr (SEVERITY (JUST_LOG),
1082                                              "scavenge_volume: Freeing ^a VTOCE ^[^a ^;^1s^]at ^o (^a)", message,
1083                                              (local_vtoce.uid ^= ""b), local_vtoce.primary_name, vtocx, device_name);
1084                               end;
1085                          else if code ^= error_table_$vtoce_free
1086                          then call syserr$error_code (SEVERITY (LOG), code,
1087                                    "scavenge_volume: Error freeing ^a vtocx ^o on ^a", message, vtocx, device_name);
1088 
1089 
1090                     end;
1091 
1092 NEXT:
1093                call CHECK_ABORT;
1094           end;
1095 
1096           sc_meters.n_vtoces_freed = vtoces_freed;
1097           if vtoces_freed > 0
1098           then call syserr (SEVERITY (LOG), "scavenge_volume: Freed ^d VTOCEs on ^a", vtoces_freed, device_name);
1099 
1100      end FREE_VTOCES;
1101 
1102 %page;
1103 /*  Internal Procedure to lock the AST Lock and find the ASTE (if any)
1104    corresponding to a supplied UID.
1105 */
1106 LOCK_AST_CHECK_UID:
1107      proc (Uid, Vtocx, Astep);
1108 
1109 dcl       Uid                           bit (36) aligned;
1110 dcl       Vtocx                         fixed bin;
1111 dcl       Astep                         ptr;
1112 
1113 
1114           call lock$lock_ast;
1115           if Uid = ""b
1116           then Astep = null ();
1117           else Astep = search_ast$check (Uid, pvte.pvid, Vtocx, (0));
1118                                                             /* use global pvid (!), ignore double-uid error */
1119 
1120      end LOCK_AST_CHECK_UID;
1121 
1122 
1123 
1124 %page;
1125 /*  Internal Procedure to validate a VTOCE. Invalid fields are corrected,
1126    to the extent possible. If the corrections are "for real" (second
1127    pass), they are reported into the syserr log.
1128 */
1129 
1130 CHECK_VTOCE:
1131      proc (Vtocx, Vtocep, Loud, Damaged);
1132 
1133 dcl       Vtocx                         fixed bin;
1134 dcl       Vtocep                        ptr;
1135 dcl       Loud                          bit (1) aligned;
1136 dcl       Damaged                       bit (1) aligned;
1137 
1138 dcl       checksum                      bit (36) aligned;
1139 dcl       csl                           fixed bin;
1140 dcl       cur_fstime                    bit (36) aligned;
1141 dcl       low_add                       fixed bin (18);
1142 dcl       high_add                      fixed bin (18);
1143 dcl       px                            fixed bin;
1144 dcl       rec_add                       fixed bin (18);
1145 dcl       records                       fixed bin;
1146 dcl       trp_bad                       bit (1) aligned;
1147 dcl       tx                            fixed bin;
1148 
1149 dcl       1 Vtoce                       aligned like vtoce based (Vtocep);
1150 
1151 
1152           Damaged = "0"b;
1153 
1154           low_add = pvte.baseadd;
1155           high_add = pvte.baseadd + pvte.totrec - 1;
1156           csl, records = 0;
1157 
1158           cur_fstime = substr (bit (bin (clock (), 71), 71), 20, 36);
1159 
1160           do px = 0 to hbound (Vtoce.fm, 1);
1161                if substr (Vtoce.fm (px), 1, 1) = "0"b
1162                then do;
1163                          rec_add = bin (Vtoce.fm (px), 18);
1164                          if rec_add < low_add | rec_add > high_add
1165                          then do;
1166                                    Damaged = "1"b;
1167                                    Vtoce.damaged = "1"b;
1168                                    Vtoce.fm (px) = pv_scav_null_addr;
1169                                    if Loud & copy_options.debug
1170                                    then call syserr (SEVERITY (JUST_LOG),
1171                                              "scavenge_volume: vtoce ^a at ^o (^a) disk addr ^o bad", Vtoce.primary_name,
1172                                              Vtocx, pvte.devname, device_name, rec_add);
1173                               end;
1174                          else do;
1175                                    csl = px + 1;
1176                                    records = records + 1;
1177                               end;
1178                     end;
1179           end;
1180 
1181           if bin (Vtoce.records) ^= records
1182           then do;
1183                     if Loud
1184                     then call syserr (SEVERITY (JUST_LOG),
1185                               "scavnege_volume: vtoce ^a at ^o (^a). rec used changed from ^o to ^o", Vtoce.primary_name,
1186                               Vtocx, device_name, bin (Vtoce.records), records);
1187                     Damaged = "1"b;
1188                     Vtoce.damaged = "1"b;
1189                     Vtoce.records = bit (bin (records, 9), 9);
1190                end;
1191 
1192           if bin (Vtoce.csl) ^= csl
1193           then do;
1194                     if Loud
1195                     then call syserr (SEVERITY (JUST_LOG),
1196                               "scavenge_volume: vtoce ^a at ^o (^a). cur len changed from ^o to ^o", Vtoce.primary_name,
1197                               Vtocx, device_name, bin (Vtoce.csl), csl);
1198                     Damaged = "1"b;
1199                     Vtoce.damaged = "1"b;
1200                     Vtoce.csl = bit (bin (csl, 9), 9);
1201                end;
1202 
1203           if (bin (Vtoce.msl) > 256) | (bin (Vtoce.msl) < 0) | (bin (Vtoce.msl) < csl)
1204           then do;
1205                     if Loud
1206                     then call syserr (SEVERITY (JUST_LOG),
1207                               "scavenge_volume: vtoce ^a at ^o (^a). max len changed from ^o to 400", Vtoce.primary_name,
1208                               Vtocx, device_name, bin (Vtoce.msl));
1209                     Damaged = "1"b;
1210                     Vtoce.damaged = "1"b;
1211                     Vtoce.msl = bit (bin (256, 9), 9);
1212                end;
1213 
1214           trp_bad = "0"b;
1215           do tx = 0 to 1;
1216                if Vtoce.trp (tx) < 0 | bin (Vtoce.trp (tx), 36) > bin (cur_fstime, 36)
1217                then trp_bad = "1"b;
1218           end;
1219           if trp_bad
1220           then do;
1221                     do tx = 0 to 1;
1222                          Vtoce.trp (tx) = 0;
1223                          Vtoce.trp_time (tx) = cur_fstime;
1224                     end;
1225                     if Loud
1226                     then call syserr (SEVERITY (JUST_LOG),
1227                               "scavenge_volume: vtoce ^a at ^o (^a). time-record-product reset to zero",
1228                               Vtoce.primary_name, Vtocx, device_name);
1229                end;
1230 
1231           if Vtoce.dirsw & pvte.lvid ^= pvt$root_lvid
1232           then do;
1233                     if Loud
1234                     then call syserr (SEVERITY (JUST_LOG), "scavenge_volume: dirsw turned off for ^a at ^o (^a)",
1235                               Vtoce.primary_name, Vtocx, device_name);
1236                     Damaged = "1"b;
1237                     Vtoce.damaged = "1"b;
1238                     Vtoce.dirsw = "0"b;
1239                end;
1240 
1241           if Vtoce.fm_checksum_valid
1242           then do;
1243                     call filemap_checksum_ (addr (Vtoce.fm), fixed (Vtoce.csl, 9), checksum);
1244                     if Vtoce.fm_checksum ^= checksum
1245                     then do;
1246                               Vtoce.fm_damaged = "1"b;
1247                               if Loud & copy_options.debug
1248                               then call syserr (SEVERITY (JUST_LOG),
1249                                         "scavenge_volume: Invalid File Map Checksum for ^a at ^o (^a)",
1250                                         Vtoce.primary_name, Vtocx, device_name);
1251                          end;
1252                end;
1253 
1254      end CHECK_VTOCE;
1255 
1256 
1257 
1258 %page;
1259 /*  Internal Procedure which is the brains of the scavenger. It examines
1260    a file map and updates the scavenger data base for this volume. It
1261    is operating asynchronously on this data base along with page
1262    control deposit/withdraw.
1263 */
1264 
1265 CHECK_FILE_MAP:
1266      proc (Vtocx, File_Mapp, N_Pages, Fm_Damaged);
1267 
1268 dcl       Vtocx                         fixed bin;
1269 dcl       File_Mapp                     ptr;
1270 dcl       N_Pages                       fixed bin;
1271 dcl       Fm_Damaged                    bit (1) aligned;
1272 
1273 dcl       high_add                      fixed bin (18);
1274 dcl       low_add                       fixed bin (18);
1275 dcl       px                            fixed bin;
1276 dcl       rec_add                       fixed bin (18);
1277 
1278 dcl       1 File_Map                    aligned like file_map based (File_Mapp);
1279 
1280           low_add = pvte.baseadd;
1281           high_add = pvte.baseadd + pvte.totrec - 1;
1282           do px = 0 to N_Pages - 1;
1283                if File_Map.fm (px) ^= 0
1284                then if (File_Map.fm (px) >= low_add) & (File_Map.fm (px) <= high_add)
1285                     then do;
1286                               rec_add = File_Map.fm (px) - pvte.baseadd + 1;
1287                               sc_meters.n_records = sc_meters.n_records + 1;
1288                               record_blockp = addr (scavenger_block.records (rec_add));
1289 
1290 /*  Lock the record block */
1291 
1292                               call LOCK_RECORD (record_blockp);
1293 
1294 
1295 /*  Update scavenger data for this record. If the File Map is potentially
1296    damaged (invalid checksum at some point), all record addresses must
1297    be marked as conflicts, since they are not deposited. This way, truncations
1298    happening at the same time as the scavenge will not result in lost
1299    addresses.  */
1300 
1301                               if Fm_Damaged
1302                               then do;
1303                                         call THREAD_IN_CONFLICT (record_blockp, Vtocx, px);
1304                                         sc_meters.n_fmd_conflicts = sc_meters.n_fmd_conflicts + 1;
1305                                    end;
1306                               else if record_block.state = STATE_UNSEEN
1307                               then do;
1308                                         record_block.state = STATE_IN_USE;
1309                                         record_block.vtocx = Vtocx;
1310                                         record_block.pageno = px;
1311                                    end;
1312                               else if record_block.state = STATE_IN_USE
1313                               then do;
1314                                         if record_block.vtocx ^= Vtocx | record_block.pageno ^= px
1315                                         then call THREAD_IN_CONFLICT (record_blockp, Vtocx, px);
1316                                    end;
1317                               else if record_block.state = STATE_FREE | record_block.state = STATE_CONFLICT
1318                               then call THREAD_IN_CONFLICT (record_blockp, Vtocx, px);
1319 
1320 
1321                               record_block.lock = "0"b;
1322                          end;
1323           end;
1324      end CHECK_FILE_MAP;
1325 %page;
1326 /*  Internal Procedure to check whether a VTOCE should be freed, or perhaps
1327    already is free.
1328 */
1329 
1330 CHECK_VTOCE_FOR_FREE:
1331      proc (Vtocep, Meter_It, Reason, Free_It);
1332 
1333 dcl       Vtocep                        ptr;
1334 dcl       Reason                        char (*);
1335 dcl       Meter_It                      bit (1) aligned;
1336 dcl       Free_It                       bit (1) aligned;
1337 
1338 dcl       1 Vtoce                       aligned like vtoce based (Vtocep);
1339 
1340 
1341           Free_It = "0"b;
1342 
1343           if Vtoce.uid = ""b
1344           then do;
1345                     Free_It = "1"b;
1346                     Reason = "lost";
1347                end;
1348           else if ^Vtoce.dirsw
1349           then do;
1350                     if Vtoce.per_process & (Vtoce.uid_path (1) ^= active_hardcore_data$pdd_uid)
1351                     then do;
1352                               Free_It = "1"b;
1353                               Reason = "per-process";
1354                               if Meter_It
1355                               then sc_meters.n_vtoces_per_proc = sc_meters.n_vtoces_per_proc + 1;
1356                          end;
1357                     else if Vtoce.deciduous & (Vtoce.uid_path (1) ^= active_hardcore_data$sl1_uid)
1358                     then do;
1359                               Free_It = "1"b;
1360                               Reason = "deciduous";
1361                               if Meter_It
1362                               then sc_meters.n_vtoces_per_boot = sc_meters.n_vtoces_per_boot + 1;
1363                          end;
1364                     else if Vtoce.perm_flags.per_bootload & (Vtoce.uid_path (1) ^= active_hardcore_data$sl1_uid)
1365                     then do;
1366                               Free_It = "1"b;
1367                               Reason = "per-bootload";
1368                               if Meter_It
1369                               then sc_meters.n_vtoces_per_boot = sc_meters.n_vtoces_per_boot + 1;
1370                          end;
1371                end;
1372 
1373      end CHECK_VTOCE_FOR_FREE;
1374 %page;
1375 /*  Internal Procedure to report segment damage to the syserr log  */
1376 
1377 SEGDAMAGE:
1378      proc (Vtocx, Vtocep, Dump_Vtocep, Prev_Damaged);
1379 
1380 dcl       Vtocx                         fixed bin;
1381 dcl       Vtocep                        ptr;
1382 dcl       Dump_Vtocep                   ptr;
1383 dcl       Prev_Damaged                  bit (1) aligned;
1384 
1385 dcl       1 Vtoce                       aligned like vtoce based (Vtocep);
1386 
1387 
1388           segdamage.pvid = pvte.pvid;
1389           segdamage.lvid = pvte.lvid;
1390           segdamage.uid = Vtoce.uid;
1391           segdamage.vtocx = Vtocx;
1392           segdamage.pno = -1;
1393           segdamage.uid_path = Vtoce.uid_path;
1394           call syserr$binary (SEVERITY (LOG), addr (segdamage), SB_vtoc_salv_dam, SBL_vtoc_salv_dam,
1395                "scavenge_volume: ^[damaged switch found on for^;setting damaged switch on^] ^a at ^o (^a).", Prev_Damaged,
1396                Vtoce.primary_name, Vtocx, device_name);
1397 
1398           if ^Prev_Damaged
1399           then do;
1400                     sst$damaged_ct = sst$damaged_ct + 1;
1401                     sc_meters.n_vtoces_damaged = sc_meters.n_vtoces_damaged + 1;
1402                     if copy_options.dump
1403                     then call syserr$binary (SEVERITY (JUST_LOG), Dump_Vtocep, SB_vtoce, SBL_vtoce,
1404                               "scavenge_volume: Damaged vtoce ^o (^a).", Vtocx, device_name);
1405                end;
1406 
1407 
1408 %include segdamage_msg;
1409 
1410      end SEGDAMAGE;
1411 %page;
1412 /*  Internal procedure to lock a record address  */
1413 
1414 LOCK_RECORD:
1415      proc (Record_Blockp);
1416 
1417 dcl       Record_Blockp                 ptr;
1418 
1419 dcl       1 A_record_block              aligned like record_block;
1420 dcl       Ap                            ptr;
1421 dcl       locked                        bit (1) aligned;
1422 dcl       1 Q_record_block              aligned like record_block;
1423 dcl       Qp                            ptr;
1424 dcl       Wp                            ptr;
1425 
1426 dcl       A                             bit (36) aligned based (Ap);
1427 dcl       Q                             bit (36) aligned based (Qp);
1428 dcl       1 Record_Block                aligned like record_block based (Record_Blockp);
1429 dcl       W                             bit (36) aligned based (Wp);
1430 
1431 
1432           locked = "0"b;
1433           Ap = addr (A_record_block);
1434           Qp = addr (Q_record_block);
1435           Wp = Record_Blockp;
1436           do while (^locked);
1437                unspec (Q_record_block) = unspec (Record_Block);
1438                unspec (A_record_block) = unspec (Q_record_block);
1439                if ^A_record_block.lock
1440                then do;
1441                          A_record_block.lock = "1"b;
1442                          locked = stacq (W, A, Q);
1443                     end;
1444           end;
1445 
1446      end LOCK_RECORD;
1447 %page;
1448 /*  Internal Procedure to check whether the invoker requested an abort. */
1449 
1450 CHECK_ABORT:
1451      proc;
1452 
1453           call tc_util$check_abort (Code);
1454           if Code ^= 0
1455           then goto ABORT_JOIN;
1456 
1457      end CHECK_ABORT;
1458 %page;
1459 /*  Internal Procedure to translate syserr severity codes, based on
1460    attendant circumstances. Only severity codes of 4 or higher are
1461    affected, as follows:
1462 
1463    debug option in effect - all messages are printed
1464 
1465    scavenge during initialization - 4 becomes 0, 5 becomes 4
1466 
1467    otherwise 5 becomes 4.
1468 */
1469 
1470 SEVERITY:
1471      proc (Severity) returns (fixed bin);
1472 
1473 dcl       Severity                      fixed bin;
1474 
1475           if Severity <= BEEP
1476           then return (Severity);
1477 
1478           if copy_options.debug
1479           then return (ANNOUNCE);
1480 
1481           if sys_info$initialization_state < RLV_INITIALIZED
1482           then do;
1483                     if Severity = LOG
1484                     then return (ANNOUNCE);
1485                     else return (LOG);
1486                end;
1487 
1488           return (LOG);
1489 
1490 
1491      end SEVERITY;
1492 
1493 
1494 %page;
1495 /*  Internal Procedure to add an entry to the thread of conflicts for this
1496    record address.
1497 */
1498 
1499 THREAD_IN_CONFLICT:
1500      proc (Record_Blockp, Vtocx, Page_No);
1501 
1502 dcl       Record_Blockp                 ptr;
1503 dcl       Vtocx                         fixed bin;
1504 dcl       Page_No                       fixed bin;
1505 
1506 dcl       A                             bit (36) aligned;
1507 dcl       free_ix                       fixed bin;
1508 dcl       got_free                      bit (1) aligned;
1509 dcl       next_free                     fixed bin;
1510 dcl       ovfl_blockp                   ptr;
1511 dcl       Q                             bit (36) aligned;
1512 dcl       Wp                            ptr;
1513 
1514 dcl       1 ovfl_block                  aligned like record_block based (ovfl_blockp);
1515 dcl       1 Record_Block                aligned like record_block based (Record_Blockp);
1516 dcl       W                             bit (36) aligned based (Wp);
1517 
1518           if (Record_Block.state = STATE_UNSEEN) | (Record_Block.state = STATE_FREE)
1519           then do;
1520                     Record_Block.vtocx = Vtocx;
1521                     Record_Block.pageno = Page_No;
1522                end;
1523           else if (Record_Block.vtocx ^= Vtocx) | (Record_Block.pageno ^= Page_No)
1524           then do;
1525 
1526                     got_free = "0"b;
1527                     do while (^got_free);
1528                          free_ix = scavenger_block.ovfl_free_ix;
1529                          if free_ix <= 0 | free_ix > scavenger_block.n_ovfl
1530                          then do;                           /* Fix damage so far and restart */
1531                                    call syserr (ANNOUNCE, "scavenge_volume: Overflow on scavenge of ^a. Restarting.",
1532                                         device_name);
1533                                    restart_sw = "1"b;
1534                                    Record_Block.lock = "0"b;
1535                                    goto RECOVER_OVERFLOW;
1536                               end;
1537                          next_free = free_ix + 1;
1538                          Q = bit (bin (free_ix, 36), 36);
1539                          A = bit (bin (next_free, 36), 36);
1540                          Wp = addr (scavenger_block.ovfl_free_ix);
1541                          got_free = stacq (W, A, Q);
1542                     end;
1543 
1544                     ovfl_blockp = addr (scavenger_block.overflow (free_ix));
1545 
1546                     ovfl_block.vtocx = Vtocx;
1547                     ovfl_block.pageno = Page_No;
1548                     ovfl_block.state = STATE_CONFLICT;
1549                     ovfl_block.ovflx = Record_Block.ovflx;
1550                     Record_Block.ovflx = free_ix;
1551                end;
1552 
1553           Record_Block.state = STATE_CONFLICT;
1554 
1555 
1556      end THREAD_IN_CONFLICT;
1557 
1558 FAULT:
1559      procedure (Lock_name);
1560 
1561 declare   Lock_name                     char (*);
1562 
1563 declare   faulting_ptr                  pointer;
1564 declare   1 faulting_ptr_under_construction
1565                                         aligned like its_unsigned;
1566 declare   foo                           bit (36) aligned;   /* any old thing */
1567 declare   based_foo                     bit (36) aligned based;
1568 
1569           unspec (faulting_ptr_under_construction) = ""b;
1570           faulting_ptr_under_construction.its_mod = "47"b3; /* DF 2 */
1571           unspec (faulting_ptr) = unspec (faulting_ptr_under_construction);
1572 
1573           call syserr (BEEP, "scavenge_volume: Faulting under the ^a for debugging for ^a.", Lock_name,
1574                pds$process_group_id);
1575 
1576           foo = faulting_ptr -> based_foo;
1577           return;
1578      end FAULT;
1579 
1580 /* format: off */
1581 %page;  %include add_type;
1582 %page;  %include aste;
1583 %page;  %include cmp;
1584 %page;  %include disk_pack;
1585 %page;  %include its;
1586 %page;  %include null_addresses;
1587 %page;  %include "ptw.l68";
1588 %page;  %include pvte;
1589 %page;  %include scavenger_data;
1590 %page;  %include stock_seg;
1591 %page;  %include syserr_binary_def;
1592 %page;  %include syserr_constants;
1593 %page;  %include vol_map;
1594 %page;  %include vtoc_map;
1595 %page;  %include vtoce;
1596 %page;
1597 /* BEGIN MESSAGE DOCUMENTATION
1598 
1599    Message:
1600    scavenge_volume: NNN errors reading VTOCEs on dskX_NN{S}
1601 
1602    S:     $info
1603 
1604    T:     During a physical volume scavenge of dskX_NN{S}
1605 
1606    M:     Errors were encountered reading VTOCEs. A message describing
1607    each error was recorded into the syserr log. The VTOCEs with errors
1608    are skipped, and lost records are not recovered.
1609 
1610    A:     When the volume has been repaired, rerun the scavenger to
1611    recover the lost records.
1612 
1613    Message:
1614    scavenge_volume: NNN VTOCEs on dskX_NN{S} damaged. MMM damaged during this scavenge.
1615 
1616    S:     $info
1617 
1618    T:     At the completion of a volume scavenge of dskX_NN{S}
1619 
1620    M:     The scavenger found a total of NNN damaged segments on the volume.
1621    Of these, MMM were damaged by the scavenger due to inconsistencies in the
1622    VTOCEs for these segments. A message for each was recorded into the
1623    syserr log.
1624 
1625    A:     Examine the syserr log to find the damaged segments and recover them.
1626 
1627    Message:
1628    scavenge_volume: Debug Trap on scavenge of dskX_NN{S}
1629 
1630    S:     $crash
1631 
1632    T:     At the completion of a volume scavenge of dskX_NN{S}
1633 
1634    M:     This is a debugging trap which results when scavenge_vol
1635    is used with the -trap control argument.
1636 
1637    A:     Type GO to resume Multics operation.
1638 
1639    Message:
1640    scavenge_volume: Out-of-service address in stock for dskX_NN{S}
1641 
1642    S:     $crash
1643 
1644    T:     During a scavenge of dskX_NN{S}
1645 
1646    M:     While examining the record stock, and out-of-service address was
1647    encountered.  Due to the volume map locking protocols used, this should
1648    never happen. It indicates hardware or software malfunction.
1649 
1650    A:     $recover
1651 
1652    Message:
1653    scavenge_volume: Processing vtocx NNNNN on dskX_NN{S}
1654 
1655    S:     $info
1656 
1657    T:     During a volume scavenge of dskX_NN{S}
1658 
1659    M:     This message is printed every 2000 (octal) VTOCEs during the
1660    scan of the VTOC by the scavenger if scavenge_vol was invoked with
1661    the -debug option.
1662 
1663    A:     $ignore
1664 
1665    Message:
1666    scavenge_volume: Error reading vtocx NNNN on dskX_NN{S}. ERRORMESSAGE
1667 
1668    S:     $log
1669 
1670    T:     During a physical volume scavenge of dskX_NN{S}
1671 
1672    M:     An error was encountered attempting to read the VTOCE indicated.
1673    The VTOCE is skipped, and lost records are not recovered. The count
1674    of volume inconsistencies is not reset to zero.
1675 
1676    A:     After the problems with the volume have been repaired, run
1677    the scavenger again to recover lost records.
1678 
1679    Message:
1680    scavenge_volume: Error writing vtocx NNNNN on dskX_NN{S}. ERRORMESSAGE
1681 
1682    S:     $log
1683 
1684    T:     During a physical volume scavenge of dskX_NN{S}
1685 
1686    M:     The error indicated was encountered writing a VTOCE.
1687 
1688    A:     $ignore
1689 
1690    Message:
1691    scavenge_volume: Freed NNNN records on dskX_NN{S}
1692 
1693    S:     $log
1694 
1695    T:     During a physical volume scavenge of dskX_NN{S}
1696 
1697    M:     NNNN records were not claimed by any VTOCE and were not listed as
1698    free in the volume map. These records have been freed.
1699 
1700    A:     $ignore
1701 
1702    Message:
1703    scavenge_volume: Unable to resolve conflict for address RRR on dskX_NN{S}. Error at vtocx NNNN. ERRORMESSAGE.
1704 
1705    S:     $log
1706 
1707    T:     During a physical volume scavenge of dskX_NN{S}
1708 
1709    M:     During the VTOC walk, the scavenger found several VTOCEs claiming the
1710    save address RRR. It was unable to resolve the conflict due to a VTOCE read
1711    error.
1712 
1713    A:     After the volume has been repaired, rerun the scavenger.
1714 
1715    Message:
1716    scavenge_volume: Unable to resolve conflict for address RRR on dskX_NN{S}. astep=PTR
1717 
1718    S:     $log
1719 
1720    T:     During a physical volume scavenge of dskX_NN{S}
1721 
1722    M:     During the scan of the VTOC, the scavenger found several VTOCEs which
1723    claimed the same record address RRR. It could not resolve the conflict,
1724    since the segment with the ASTE indicated was active and could not be
1725    deactivated.
1726 
1727    A:     Rerun the scavenger at a later time. It may be necessary to
1728    wait until the next bootload.
1729 
1730    Message:
1731    scavenge_volume: vtoce NAME at VTOCX (dskX_NN{S}). ref to pageno PPP at addr RRR deleted
1732 
1733    S:     $log
1734 
1735    T:     During a physical volume scavenge of dskX_NN{S}
1736 
1737    M:     Address RRR was claimed by more than one VTOCE. The page indicated
1738    has been changed to a null page, and the segment has been damaged.
1739 
1740    A:     Recover the segment.
1741 
1742    Message:
1743    scavenge_volume: freeing TYPE VTOCE NAME at VTOCX (dskX_NN{S})
1744 
1745    S:     $log
1746 
1747    T:     During a physical volume scavenge of dskX_NN{S}
1748 
1749    M:     The message appears for each VTOCE freed if scavenge_vol was
1750    invoked with the -debug control argument.
1751 
1752    A:     $ignore
1753 
1754    Message:
1755    scavenge_volume: Error freeing TYPE vtocx VTOCX on dskX_NN{S}. ERRORMESSAGE
1756 
1757    S:     $log
1758 
1759    T:     During a physical volume scavenge of dskX_NN{S}.
1760 
1761    M:     The VTOCE indicated could not be freed due to the error
1762    indicated.
1763 
1764    A:     $ignore
1765 
1766    Message:
1767    scavenge_volume: Freed NNN VTOCEs on dskX_NN{S}
1768 
1769    S:     $log
1770 
1771    T:     During a physical volume scavenge of dskX_NN{S}
1772 
1773    M:     NNN VTOCEs were added to the free pool. These VTOCEs are VTOCEs
1774    found free but not marked as free in the VTOC map, per-process VTOCEs from
1775    a prior bootload, and per-bootload VTOCEs from a prior bootload.
1776 
1777    Message:
1778    scavenge_volume: vtoce NAME at VTOCX (dskX_NN{S}) disk addr RRR bad
1779 
1780    S:     $log
1781 
1782    T:     During a physical volume scavenge of dskX_NN{S}
1783 
1784    M:     Record address RRR in the VTOCE indicated is outside of the paging
1785    region for the volume. The segment has been damaged.
1786 
1787    A:     Recover the segment.
1788 
1789    Message:
1790    scavenge_volume: vtoce NAME at VTOCX (dskX_NN{S}). rec used changed from X to Y
1791 
1792    S:     $log
1793 
1794    T:     During a physical volume scavenge of dskX_NN{S}
1795 
1796    M:     The records used field in the VTOCE has been corrected.  The segment
1797    has been damaged.
1798 
1799    A:     Recover the segment.
1800 
1801    Message:
1802    scavenge_volume: vtoce NAME at VTOCX (dskX_NN{S}). cur len changed from X to Y
1803 
1804    S:     $log
1805 
1806    T:     During a physical volume scavenge of dskX_NN{S}
1807 
1808    M:     The current segment length field in the VTOCE has been corrected.
1809    The segment has been damaged.
1810 
1811    A:     Recover the segment.
1812 
1813    Message:
1814    scavenge_volume: vtoce NAME at VTOCX (dskX_NN{S}). max len changed from X to Y
1815 
1816    S:     $log
1817 
1818    T:     During a physical volume scavenge of dskX_NN{S}
1819 
1820    M:     The max length field in the VTOCE has been corrected. The segment has
1821    been damaged.
1822 
1823    A:     Recover the segment.
1824 
1825    Message:
1826    scavenge_volume: vtoce NAME at VTOCX (dskX_NN{S}). time-record-product reset to zero
1827 
1828    S:     $log
1829 
1830    T:     During a physical volume scavenge of dskX_NN{S}
1831 
1832    M:     An invalid value was found in the time-record-product field of
1833    the VTOCE indicated. This field has been reset to zero.
1834 
1835    A:     $ignore
1836 
1837    Message:
1838    scavenge_volume: dirsw turned off for NAME at VTOCX (dskX_NN{S})
1839 
1840    S:     $log
1841 
1842    T:     During a physical volume scavenge of dskX_NN{S}
1843 
1844    M:     The directory switch in the VTOCE was found on for a non-directory
1845    segment. It has been turned off. The segment has been damaged.
1846 
1847    A:     Recover the segment.
1848 
1849    Message:
1850    scavenge_volume: Invalid File Map Checksum for NAME at VTOCX (dskX_NN{S}).
1851 
1852    S:        $log
1853 
1854    T:     During a physical volume scavenge of dskX_NN{S}.
1855 
1856    M:     The filemap checksum was incorrect, indicating damage to the
1857    VTOCE. The checksum is corrected. Other damage, if found, is reported.
1858 
1859    A:        $ignore
1860 
1861    Message:
1862    scavenge_volume: damaged switch found on for NAME at VTOCX (dskX_NN{S})
1863 
1864    S:     $log
1865 
1866    T:     During a physical volume scavenge of dskX_NN{S}
1867 
1868    M:     The damaged switch in the VTOCEwas set prior to the scavenge.
1869 
1870    A:     Recover the segment.
1871 
1872    Message:
1873    scavenge_volume: setting damaged switch on NAME at VTOCX (dskX_NN{S}).
1874 
1875    S:     $log
1876 
1877    T:     During a physical volume scavenge of dskX_NN{S}
1878 
1879    M:     An inconsistency has been detected in the VTOCE and the damaged
1880    switch has been set. A message describing the inconsistency has been
1881    recorded in the syserr log. The binary information associated with this
1882    message includes the segment UID-path.
1883 
1884    A:     Recover the segment.
1885 
1886    Message:
1887    scavenge_volume: Damaged vtoce VTOCX (dskX_NN{S}).
1888 
1889    S:     $log
1890 
1891    T:     During a physical volume scavenge of dskX_NN{S}
1892 
1893    M:     The VTOCE image before correction is recorded into
1894    the syserr log if scavenge_vol was invoked with the -dump control
1895    argument.
1896 
1897    A:     $ignore
1898 
1899    Message:
1900    scavenge_volume: Overflow on scavenge of dskX_NN{S}. Restarting.
1901 
1902    S:     $info
1903 
1904    T:     During a physical volume scavenge of dskX_NN{S}.
1905 
1906    M:     An internal table which tracks reused record addresses overflowed.
1907    All conflicts detected so far are resolved, and the scavenge is restarted
1908    from the beginning.
1909 
1910    A:     $ignore
1911 
1912    Message:
1913    scavenge_volume: Faulting under the LOCK for debugging for USER
1914 
1915    S:     $beep
1916 
1917    T:     During a physical volume salvage.
1918 
1919    M:     A fault tag three fault is taken to exercise fault recovery.
1920 
1921    A:     $ignore
1922 
1923 END MESSAGE DOCUMENTATION */
1924 
1925      end scavenge_volume;