1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 disk_rebuild: proc (a_pvtx1, a_pvtx2, label_pagep, opt_bits, addr_delta, a_code);
70
71
72 dcl (a_pvtx1, a_pvtx2, pvtx) fixed bin;
73 dcl (pvtx1, pvtx2) fixed bin,
74 (i, j, k, l, r, first_free, last_free) fixed bin;
75 dcl (vtoce_incr, n_vtoce, addr_delta) fixed bin;
76 dcl (baseadd1, baseadd2, old_vtoc_size, lost_pages) fixed bin,
77 (addr_index, map_size) fixed bin,
78 (lp, label_pagep) ptr,
79 opt_bits bit (36) aligned,
80 save_vtocx fixed bin init (-1),
81 damaged_count fixed bin init (0),
82 delta fixed bin;
83 dcl vtoc_buf bit (36 * 192) aligned,
84 vtoc_bufp ptr;
85 dcl page_buf bit (36 * 1024) aligned,
86 bufp ptr;
87 dcl (a_code, code) fixed bin (35);
88
89 dcl no_free_aste_err fixed bin (35) internal static init (1);
90
91 dcl table1p ptr;
92 dcl table3p ptr;
93
94 dcl s_ptr ptr;
95
96 dcl ptp pointer;
97 dcl vtocx fixed bin;
98 dcl pvid bit (36) aligned;
99 dcl n_used_rec fixed bin;
100 dcl n_free_vtoce fixed bin;
101 dcl max_n_vtoc_seg fixed bin internal static init (16);
102 dcl free_count fixed bin;
103 dcl p99 pic "99";
104 dcl (dname1, dname2) char (9) varying;
105
106
107 dcl 1 table1 based (table1p) aligned,
108 2 bit_table (0:label.vol_size - 1) bit (1) unaligned;
109
110
111 dcl pds$processid ext bit (36) aligned;
112
113 dcl sst$astl bit (36) aligned external;
114 dcl sst$astsize fixed bin external;
115 dcl sst$checksum_filemap fixed bin external;
116 dcl 1 sst$level (0:3) aligned external,
117 2 ausedp bit (18) unaligned,
118 2 no_aste bit (18) unaligned;
119 dcl sst$pts (0:3) fixed bin external;
120 dcl sst$root_pvtx fixed bin external;
121
122 dcl pv_salv_seg$ fixed bin external static;
123 dcl volmap_abs_seg$ external static;
124 dcl dseg$ (0:1023) fixed bin (71) aligned external static;
125
126 dcl filemap_checksum_ entry (ptr, fixed bin, bit (36) aligned);
127 dcl get_aste entry (fixed bin) returns (ptr);
128 dcl get_ptrs_$given_segno entry (fixed bin) returns (ptr);
129 dcl get_ptrs_$given_astep entry (ptr) returns (fixed bin (71) aligned);
130 dcl get_pvtx$hold_pvtx entry (bit (36) aligned, fixed bin, fixed bin (35));
131 dcl get_pvtx$release_pvtx entry (bit (36) aligned, fixed bin (35));
132 dcl lock$lock_ast entry;
133 dcl lock$unlock_ast entry;
134 dcl page$cam entry;
135 dcl pc$cleanup ext entry (ptr);
136 dcl pc$truncate_deposit_all entry (ptr);
137 dcl pc_wired$write entry (ptr, fixed bin, fixed bin);
138 dcl pc_wired$write_wait entry (ptr, fixed bin, fixed bin);
139 dcl pmut$swap_sdw entry (ptr, ptr);
140 dcl ptw_util_$make_null entry (pointer, bit (22) aligned);
141 dcl put_aste entry (ptr);
142 dcl read_disk entry (fixed bin, fixed bin, ptr, fixed bin (35));
143 dcl read_disk$read_disk_no_test entry (fixed bin, fixed bin, ptr, fixed bin (35));
144 dcl salvager$set_options ext entry (bit (36) aligned);
145 dcl salv_err_msg entry options (variable);
146 dcl salv_err_msg$code entry options (variable);
147 dcl search_ast$check ext entry (bit (36) aligned, bit (36) aligned, fixed bin, fixed bin (35)) returns (ptr);
148 dcl syserr entry options (variable);
149 dcl thread$out entry (ptr, bit (18));
150 dcl update_vtoce ext entry (ptr);
151 dcl vm_vio$clean_up entry (fixed bin);
152 dcl vm_vio$get_vtocep entry (fixed bin, fixed bin) returns (ptr);
153 dcl vm_vio$init entry (fixed bin, fixed bin (35)) returns (ptr);
154 dcl vtoc_man$get_vtoce ext entry (bit (36) aligned, fixed bin, fixed bin, bit (3) aligned, ptr, fixed bin (35));
155 dcl vtoce_stock_man$drain_stock_range entry (ptr, fixed bin, fixed bin);
156 dcl write_disk entry (fixed bin, fixed bin, ptr, fixed bin (35));
157 dcl write_disk$write_disk_no_test entry (fixed bin, fixed bin, ptr, fixed bin (35));
158
159 dcl (cleanup, page_fault_error) condition;
160
161 dcl (min, null, addr, addrel, baseno, bit, ceil, divide, fixed, mod, ptr, rel, rtrim, substr, unspec) builtin;
162
163 %page;
164
165
166
167 vtoc_bufp = addr (vtoc_buf);
168 bufp = addr (page_buf);
169
170 begin;
171
172 dcl last_used (addr_delta) fixed bin;
173
174 delta = addr_delta;
175 lp = label_pagep;
176 pvtx1 = a_pvtx1;
177 pvtx2, pvtx = a_pvtx2;
178 code = 0;
179 free_count = 0;
180 pvt_arrayp = addr (pvt$array);
181
182 call salvager$set_options (opt_bits);
183 p99 = pvt_array (pvtx1).logical_area_number;
184 dname1 = rtrim (pvt_array (pvtx1).devname || "_" || p99 || pvt_array (pvtx1).sv_name);
185 p99 = pvt_array (pvtx2).logical_area_number;
186 dname2 = rtrim (pvt_array (pvtx2).devname || "_" || p99 || pvt_array (pvtx2).sv_name);
187
188 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: Begin disk rebuild of ^a onto ^a.", dname1, dname2);
189 if pvtx1 = pvtx2 then do;
190 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: same drive specified for source and copy, aborting.");
191 goto err_ret;
192 end;
193
194 if ^pvt_array (pvtx1).used then do;
195 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: ^a must be mounted for rebuild.", dname1);
196 goto err_ret;
197 end;
198
199 if pvt_array (pvtx2).used then do;
200 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: ^a must not be mounted for rebuild.", dname2);
201 goto err_ret;
202 end;
203
204 call CHECK_VTOC_SIZES;
205
206 pvtep = addr (pvt_array (pvtx2));
207 pvid = addr (pvt_array (pvtx1)) -> pvte.pvid;
208
209
210 do i = 0 to VTOC_ORIGIN - 0;
211 if i = 0 then call copy_page (0, 0, "1"b);
212 else call copy_page (i, i, "0"b);
213 end;
214
215 on cleanup begin;
216 if salv_data$debug then call syserr (CRASH, "disk_rebuild: salv cleanup debugging stop, dump and type go.");
217 call CLEAN_UP;
218 end;
219
220
221 s_ptr = vm_vio$init (pvtx, code); if code ^= 0 then goto err_ret;
222
223 labelp = ptr (s_ptr, LABEL_ADDR * 1024);
224 vol_mapp = ptr (s_ptr, VOLMAP_ADDR * 1024);
225 vtoc_headerp = ptr (s_ptr, DUMPER_BIT_MAP_ADDR * 1024);
226 vtoc_mapp = ptr (s_ptr, VTOC_MAP_ADDR * 1024);
227
228 call salv_err_msg (SALV_DEBUG, "^/disk_rebuild: Summary of original disk contents follows:^/");
229 call REPORT_SUMMARY;
230
231
232
233 vtoc_header.n_vtoce = n_vtoce;
234 vtoc_header.n_free_vtoce = 0;
235 vtoc_header.first_free_vtocx = -1;
236 vtoc_header.vtoc_last_recno = label.vtoc_size - 1;
237
238
239
240 vtoc_map.n_vtoce = n_vtoce;
241 vtoc_map.vtoc_last_recno = label.vtoc_size - 1;
242 vtoc_map.bit_map_n_words = divide (n_vtoce + 31, 32, 17);
243 unspec (vtoc_map.bit_map) = ""b;
244
245 pvt_array (pvtx2).n_vtoce = n_vtoce;
246 vtoce_incr = n_vtoce - old_vtoc_size;
247 vtoc_header.vtoc_last_recno = label.vtoc_size - 1;
248
249 first_free = label.vtoc_size;
250 update_frec: do i = 1 to lp -> label.nparts;
251 if lp -> label.parts (i).frec = first_free then do;
252 first_free = first_free + lp -> label.parts (i).nrec;
253 goto update_frec;
254 end;
255 end;
256
257 last_free = lp -> label.vol_size;
258 do j = 1 to lp -> label.nparts;
259 if lp -> label.parts (j).frec > first_free then if lp -> label.parts (j).frec < last_free then
260 last_free = lp -> label.parts (j).frec;
261 end;
262
263 last_free = last_free - 1;
264 lost_pages = vol_map.n_rec - (last_free - first_free);
265 if lost_pages > vol_map.n_free_rec then do;
266 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: not enough free records (only ^d.) for increase (need ^d.)",
267 vol_map.n_free_rec, lost_pages);
268 goto err_out;
269 end;
270
271 baseadd1 = vol_map.base_add;
272 baseadd2 = first_free;
273
274 if baseadd1 ^= baseadd2 then
275 call salv_err_msg (SALV_DEBUG, "disk_rebuild: base of paging region changed from ^d. to ^d.", baseadd1, baseadd2);
276
277 vol_map.base_add = baseadd2;
278 map_size, vol_map.n_rec = vol_map.n_rec - lost_pages;
279 vol_map.bit_map_n_words = ceil (map_size / 32);
280
281 do i = 1 to lp -> label.nparts;
282 do j = 1 to label.nparts;
283 if lp -> label.parts (i).part = label.parts (j).part then do;
284 r = min (lp -> label.parts (i).nrec, label.parts (j).nrec);
285 if lp -> label.parts (i).part = "bos"
286 | lp -> label.parts (i).part = "alt" then r = 0;
287 call salv_err_msg (SALV_DEBUG, "disk_rebuild: copying ^d. rec of part ^a", r, label.parts (j).part);
288 k = label.parts (j).frec;
289 do l = lp -> label.parts (i).frec to lp -> label.parts (i).frec + (r - 1);
290 call copy_page (k, l, "0"b);
291 k = k + 1;
292 end;
293 end;
294 end;
295 end;
296
297 call write_disk (pvtx2, 0, lp, code);
298 if code ^= 0 then do;
299 call salv_err_msg$code (SALV_ANNOUNCE, "", code, "disk_rebuild: Error writing label:");
300 goto err_out;
301 end;
302 labelp = lp;
303 %page;
304
305 call INIT_TABLES (table1p, table3p, code);
306
307 n_free_vtoce = 0;
308 n_used_rec = 0;
309 save_vtocx = -1;
310
311 do i = 1 to delta;
312 last_used (i) = baseadd2 - i;
313 end;
314
315 call copy_vtoc;
316
317 call UPDATE_VOL_MAP;
318
319 call UPDATE_VTOC_MAP;
320
321 call FORCE_VTOC_ON_DISK;
322
323 call FORCE_LABEL_ON_DISK;
324
325 call salv_err_msg (SALV_DEBUG, "disk_rebuild: End of rebuilding. New summary report follows:^/");
326
327 call REPORT_SUMMARY;
328
329
330 err_out:
331 if free_count > 0 then call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: ^d. vtoces added to list of free vtoces", free_count);
332 if code = 0 then call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: Disk rebuild finished.");
333 else call salv_err_msg$code (SALV_ANNOUNCE, "", code, "disk_rebuild: disk rebuild finished with error:");
334
335
336 call CLEAN_UP;
337
338 err_ret: a_code = code;
339 if ^pvt_array (pvtx2).used
340 then pvt_array (pvtx2).n_vtoce = 0;
341
342 return;
343 %page;
344
345 copy_vtoc: proc;
346
347 dcl r fixed bin;
348
349 dcl whole_vtoce bit (192 * 36) based aligned;
350
351 do vtocx = 0 to min (old_vtoc_size, n_vtoce) - 1;
352 if mod (vtocx, 1000) = 0 then if vtocx > 0 then
353 call syserr (ANNOUNCE, "disk_rebuild: processing VTOCE #^d.", vtocx);
354 call vtoc_man$get_vtoce (pvid, pvtx1, vtocx, "111"b, vtoc_bufp, code);
355 if code ^= 0 then do;
356 call salv_err_msg$code (SALV_ANNOUNCE, "", code, "disk_rebuild: reading vtocx ^oo:", vtocx);
357 goto err_out;
358 end;
359
360
361 vtocep = vm_vio$get_vtocep (pvtx2, vtocx);
362 if vtoc_bufp -> vtoce.uid = "0"b then do;
363 call FREE_VTOCE;
364 goto next_vtocx;
365 end;
366 if ^vtoc_bufp -> vtoce.dirsw then do;
367 if vtoc_bufp -> vtoce.per_process then do;
368 if salv_data$debug then call salv_err_msg (SALV_DEBUG, "disk_rebuild: freeing per process vtocx ^oo: ^a",
369 vtocx, vtoc_bufp -> vtoce.primary_name);
370 call FREE_VTOCE;
371 goto next_vtocx;
372 end;
373 if vtoc_bufp -> vtoce.deciduous then do;
374 if salv_data$debug then call salv_err_msg (SALV_DEBUG, "disk_rebuild: freeing deciduous vtocx ^oo: ^a",
375 vtocx, vtoc_bufp -> vtoce.primary_name);
376 call FREE_VTOCE;
377 goto next_vtocx;
378 end;
379 end;
380
381 call lock$lock_ast;
382 astep = search_ast$check ((vtoc_bufp -> vtoce.uid), pvid, vtocx, (0));
383 if astep ^= null then do;
384 if ^aste.ehs then
385 call pc$cleanup (astep);
386 else if ^aste.hc_part then
387 call pc_wired$write (astep, 0, -1);
388 call update_vtoce (astep);
389 call lock$unlock_ast;
390 call vtoc_man$get_vtoce (pvid, pvtx1, vtocx, "111"b, vtoc_bufp, code);
391 if code ^= 0 then do;
392 call salv_err_msg$code (SALV_ANNOUNCE, "", code, "disk_rebuild: reading vtocx ^oo:", vtocx);
393 goto err_out;
394 end;
395 end;
396 else call lock$unlock_ast;
397
398 if vtoc_bufp -> vtoce.damaged then damaged_count = damaged_count + 1;
399
400 vtocep -> whole_vtoce = vtoc_bufp -> whole_vtoce;
401 do i = 0 to 255;
402 if substr (vtoce.fm (i), 1, 1) ^= "1"b then do;
403 call get_new_addr (vtocx, r);
404 call copy_page (fixed (substr (vtoce.fm (i), 2, 17), 17), r, "0"b);
405 vtoce.fm (i) = bit (fixed (r, 18), 18);
406 n_used_rec = n_used_rec + 1;
407 end;
408 end;
409 if sst$checksum_filemap = 0 then do;
410 vtocep -> vtoce.fm_checksum_valid = "0"b;
411 vtocep -> vtoce.fm_checksum = ""b;
412 end;
413 else do;
414 vtocep -> vtoce.fm_checksum_valid = "1"b;
415 call filemap_checksum_ (addr (vtocep -> vtoce.fm),
416 fixed (vtocep -> vtoce.csl), vtocep -> vtoce.fm_checksum);
417 end;
418 vtocep -> vtoce.fm_damaged = "0"b;
419
420 next_vtocx:
421 end;
422
423 if old_vtoc_size ^= n_vtoce then
424 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: no. vtoces changed from ^d. to ^d.", old_vtoc_size, n_vtoce);
425 if n_vtoce > old_vtoc_size then do vtocx = old_vtoc_size to n_vtoce - 1;
426 vtocep = vm_vio$get_vtocep (pvtx2, vtocx);
427 call FREE_VTOCE;
428 end;
429
430 end copy_vtoc;
431 %page;
432
433 copy_page: proc (from, to, sp_bit);
434
435 dcl (from, to) fixed bin;
436 dcl sp_bit bit (1) aligned;
437
438 if sp_bit then
439 call read_disk (pvtx1, from, bufp, code);
440 else call read_disk$read_disk_no_test (pvtx1, from, bufp, code);
441 if code ^= 0 then do;
442 call salv_err_msg$code (SALV_ANNOUNCE, "", code, "disk_rebuild: Error from read_disk, aborting:");
443 goto err_out;
444 end;
445
446 if sp_bit then do;
447 bufp -> label.vtoc_size = lp -> label.vtoc_size;
448 call write_disk (pvtx2, to, bufp, code);
449 end;
450 else call write_disk$write_disk_no_test (pvtx2, to, bufp, code);
451 if code ^= 0 then do;
452 call salv_err_msg$code (SALV_ANNOUNCE, "", code, "disk_rebuild: Error from write_disk, aborting:");
453 goto err_out;
454 end;
455
456 end copy_page;
457
458 get_new_addr: proc (a_vtocx, a_addr);
459
460 dcl a_vtocx fixed bin,
461 a_addr fixed bin;
462
463 if a_vtocx ^= save_vtocx then do;
464 addr_index = 1;
465 do j = 1 to delta;
466 if last_used (j) < last_used (addr_index) then addr_index = j;
467 end;
468 save_vtocx = a_vtocx;
469 end;
470
471 a_addr, last_used (addr_index) = last_used (addr_index) + delta;
472 bit_table (last_used (addr_index)) = "1"b;
473
474 if last_used (addr_index) + delta > map_size + baseadd2 then do;
475 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: out of room on vtocx ^oo , page ^oo", vtocx, i);
476 goto err_out;
477 end;
478 end get_new_addr;
479 %page;
480
481 FREE_VTOCE: proc;
482
483 dcl bitx fixed bin;
484 dcl wordx fixed bin;
485
486
487 if vtoce.uid ^= "0"b then free_count = free_count + 1;
488
489 unspec (vtoce) = "0"b;
490
491 wordx = divide (vtocx, 32, 17);
492 bitx = mod (vtocx, 32) + 1;
493 bit_map_wordp = addr (vtoc_map.bit_map (wordx));
494 substr (bit_map_word.bits, bitx, 1) = "1"b;
495
496 n_free_vtoce = n_free_vtoce + 1;
497
498 return;
499
500 end FREE_VTOCE;
501
502
503
504 UPDATE_VOL_MAP: proc;
505
506 dcl 1 old_map (vol_map.bit_map_n_words) based (addr (vol_map.bit_map)) aligned,
507 2 pad1 bit (1) unaligned,
508 2 bits bit (32) unaligned,
509 2 pad2 bit (3) unaligned;
510
511 dcl 1 new_map (vol_map.bit_map_n_words) based (table3p) aligned like old_map;
512
513 dcl bit_table_map (1000) bit (32) based (addr (bit_table (vol_map.base_add))) unaligned;
514
515 dcl w fixed bin;
516 dcl j fixed bin;
517 dcl n_free_rec fixed bin;
518
519
520
521 unspec (new_map) = "0"b;
522
523 do w = 1 to vol_map.bit_map_n_words;
524 new_map (w).bits = ^bit_table_map (w);
525 end;
526
527 j = mod (vol_map.n_rec, 32);
528 if j ^= 0 then substr (new_map (w - 1).bits, j + 1) = "0"b;
529
530 if unspec (old_map) = unspec (new_map) then ;
531 else do;
532 call report_bit_map_changed;
533 unspec (old_map) = unspec (new_map);
534 end;
535
536 n_free_rec = vol_map.n_rec - n_used_rec;
537
538 if vol_map.n_free_rec ^= n_free_rec then
539 do;
540 call report_n_free_rec_changed;
541 vol_map.n_free_rec = n_free_rec;
542 end;
543 return;
544
545 %page;
546
547 report_bit_map_changed: proc;
548 call salv_err_msg (SALV_DEBUG, "disk_rebuild: Map of assigned addresses changed");
549 return;
550 end;
551
552 report_n_free_rec_changed: proc;
553 call salv_err_msg (SALV_DEBUG, "disk_rebuild: no. of free recs changed from ^d. to ^d.",
554 vol_map.n_free_rec, n_free_rec);
555 return;
556 end;
557
558 end UPDATE_VOL_MAP;
559
560
561 UPDATE_VTOC_MAP: proc;
562
563 if vtoc_map.n_free_vtoce ^= n_free_vtoce then do;
564 call report_n_free_vtoce;
565 vtoc_map.n_free_vtoce = n_free_vtoce;
566 end;
567
568
569 return;
570
571
572 report_n_free_vtoce: proc;
573 call salv_err_msg (SALV_DEBUG, "disk_rebuild: no. of free vtoces changed from ^d. to ^d.",
574 vtoc_header.n_free_vtoce, n_free_vtoce);
575 return;
576 end;
577
578 end UPDATE_VTOC_MAP;
579
580
581
582
583
584
585
586 FORCE_VTOC_ON_DISK: proc;
587
588 dcl i fixed bin;
589
590
591 do i = 1 to max_n_vtoc_seg - 1;
592 astep = get_ptrs_$given_segno (fixed (baseno (s_ptr)) + i);
593 if astep ^= null then call pc_wired$write_wait (astep, 0, -1);
594 end;
595
596 return;
597
598 end FORCE_VTOC_ON_DISK;
599 %page;
600 FORCE_LABEL_ON_DISK: proc;
601
602 astep = get_ptrs_$given_segno (fixed (baseno (s_ptr)));
603
604 if astep ^= null then call pc_wired$write_wait (astep, LABEL_ADDR, 1);
605
606 return;
607
608 end FORCE_LABEL_ON_DISK;
609 %page;
610 REPORT_SUMMARY: procedure;
611
612 dcl i fixed bin, ptot fixed bin (24);
613
614 call salv_err_msg (SALV_DEBUG, "^/disk_rebuild: Summary Report^/^5xVolume ^a of logical volume ^a.^/",
615 label.pv_name, label.lv_name);
616
617 call salv_err_msg (SALV_DEBUG, "Paging region begins at record ^d. (^oo), for ^d. (^oo) records.",
618 vol_map.base_add, vol_map.base_add, vol_map.n_rec, vol_map.n_rec);
619 call salv_err_msg (SALV_DEBUG, "^d. (^oo) free records therein.", vol_map.n_free_rec, vol_map.n_free_rec);
620
621 call salv_err_msg (SALV_DEBUG, "Label/VTOC size is ^d. records, ^d. VTOCEs.", label.vtoc_size, vtoc_header.n_vtoce);
622 call salv_err_msg (SALV_DEBUG, "VTOC version ^d., ^d. free VTOCEs.^/", vtoc_header.version, vtoc_header.n_free_vtoce);
623
624 if label.nparts = 0 then call salv_err_msg (SALV_DEBUG, "No partitions defined.");
625 else do;
626 ptot = 0;
627 call salv_err_msg (SALV_DEBUG, "^/^10xPartition Map^/Name^16xStart^15xLength^/");
628 do i = 1 to label.nparts;
629 call salv_err_msg (SALV_DEBUG, "^4a^6x^9d.^x(^6oo)^x^9d.^x(^6oo)",
630 label.parts.part (i), label.parts (i).frec, label.parts (i).frec, label.parts (i).nrec,
631 label.parts (i).nrec);
632 ptot = ptot + label.parts (i).nrec;
633 end;
634 call salv_err_msg (SALV_DEBUG, "^35x______^2x_______^/^31x^9d.^x(^6oo)^/", ptot, ptot);
635 end;
636 call salv_err_msg (SALV_DEBUG, "Volume size is ^d. (^oo) records total.^/", label.vol_size, label.vol_size);
637
638 if damaged_count > 0 then call salv_err_msg (SALV_DEBUG, "^/^10x^d. damaged segments.", damaged_count);
639
640
641 end REPORT_SUMMARY;
642 %page;
643 CHECK_VTOC_SIZES:
644 proc;
645
646
647
648
649
650 dcl all_free bit (1);
651 dcl bit_map_words fixed bin;
652 dcl first_free_word fixed bin;
653 dcl res fixed bin;
654 dcl tsdw fixed bin (71);
655 dcl wordx fixed bin;
656
657 dcl ALL_FREE bit (36) aligned internal static options (constant)
658 init ("377777777770"b3);
659
660
661 old_vtoc_size = pvt_array (pvtx1).n_vtoce;
662 n_vtoce = (lp -> label.vtoc_size - VTOC_ORIGIN) * VTOCES_PER_RECORD (pvt_array (pvtx2).device_type);
663
664 if n_vtoce >= old_vtoc_size then return;
665
666
667
668 call vtoce_stock_man$drain_stock_range (addr (pvt_array (pvtx1)), n_vtoce, old_vtoc_size - 1);
669
670 call pmut$swap_sdw (addr (volmap_abs_seg$), addr (pvt_array (pvtx1).volmap_seg_sdw));
671 vtoc_mapp = ptr (addr (volmap_abs_seg$), pvt_array (pvtx1).vtoc_map_offset);
672
673 on page_fault_error begin;
674 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: Read error accessing VTOC Map of ^a",
675 dname1);
676 tsdw = 0;
677 call pmut$swap_sdw (addr (volmap_abs_seg$), addr (tsdw));
678 goto err_ret;
679 end;
680
681 all_free = "1"b;
682 first_free_word = divide (n_vtoce + 32, 32, 17);
683 bit_map_words = divide (old_vtoc_size + 31, 32, 17);
684 if (bit_map_words - 2) >= first_free_word
685 then do wordx = first_free_word to bit_map_words - 2
686 while (all_free);
687 if (vtoc_map.bit_map (wordx) & ALL_FREE) ^= ALL_FREE
688 then all_free = "0"b;
689 end;
690
691 res = mod (n_vtoce, 32);
692 if res ^= 0
693 then do;
694 bit_map_wordp = addr (vtoc_map.bit_map (first_free_word - 1));
695 if substr (bit_map_word.bits, res + 1, 32 - res) ^= substr (ALL_FREE, 2, 32 - res)
696 then all_free = "0"b;
697 end;
698
699 res = mod (old_vtoc_size, 32);
700 if res = 0 then res = 32;
701 bit_map_wordp = addr (vtoc_map.bit_map (bit_map_words - 1));
702 if substr (bit_map_word.bits, 1, res) ^= substr (ALL_FREE, 2, res)
703 then all_free = "0"b;
704
705 tsdw = 0;
706 call pmut$swap_sdw (addr (volmap_abs_seg$), addr (tsdw));
707 vtoc_mapp = null ();
708
709 if ^all_free then do;
710 call salv_err_msg (SALV_ANNOUNCE, "disk_rebuild: Cannot compress VTOC on ^a because active VTOCEs in the truncated region.",
711 dname1);
712 goto err_ret;
713 end;
714
715 return;
716
717 end;
718
719 %page;
720 CLEAN_UP: proc;
721
722
723 dcl segno fixed bin;
724
725
726 segno = fixed (baseno (addr (pv_salv_seg$)), 18);
727
728 astep = get_ptrs_$given_segno (segno);
729
730 if astep ^= null then
731 do;
732
733 dseg$ (segno) = 0;
734 call page$cam;
735
736 call pc$truncate_deposit_all (astep);
737 if aste.usedf then call get_pvtx$release_pvtx ((pvt_array.pvid (aste.pvtx)), (aste.pvtx));
738
739 if sst$astl ^= pds$processid then call lock$lock_ast;
740 call put_aste (astep);
741 call lock$unlock_ast;
742
743 end;
744
745 call vm_vio$clean_up (pvtx);
746
747 end CLEAN_UP;
748 %page;
749 INIT_TABLES: proc (table1p, table3p, code);
750
751 dcl table1p ptr;
752 dcl table3p ptr;
753 dcl code fixed bin (35);
754
755 dcl pv_salv_seg$ ext;
756
757 dcl 1 pv_salv_seg based (addr (pv_salv_seg$)) aligned,
758
759 2 table1,
760 3 bit_table (0:label.vol_size - 1) bit (1) unaligned,
761
762 2 table3,
763 3 new_map (1:vol_map.bit_map_n_words) bit (36) aligned,
764
765 2 end bit (36) aligned;
766
767 dcl segno fixed bin,
768 pvtx fixed bin,
769 msl fixed bin;
770
771 dcl (i, pts, ptsi) fixed bin;
772
773 dcl tsdw fixed bin (71);
774
775 code = 0;
776
777 segno = fixed (baseno (addr (pv_salv_seg$)), 18);
778 pvtx = sst$root_pvtx;
779 msl = divide (fixed (rel (addr (pv_salv_seg.end)), 18), 1024, 17, 0) + 1;
780
781
782
783
784 call lock$lock_ast;
785
786 astep = get_aste (msl);
787
788 if astep = null then
789 do;
790 call lock$unlock_ast;
791 code = no_free_aste_err;
792 call syserr (ANNOUNCE, "disk_rebuild: INIT_TABLES: aste pool ^oo too small", msl);
793 return;
794 end;
795
796 ptsi = fixed (aste.ptsi);
797 pts = sst$pts (ptsi);
798
799
800
801
802 astep -> aste_part.two = "0"b;
803
804
805
806
807 ptp = addrel (astep, sst$astsize);
808
809 do i = 0 to pts - 1;
810 call ptw_util_$make_null (addrel (ptp, i), fill_page_table_null_addr);
811 end;
812
813
814
815
816 astep -> aste.vtocx = -1;
817 astep -> aste.dnzp = "1"b;
818 astep -> aste.nqsw = "1"b;
819 astep -> aste.strp = bit (fixed (segno, 18), 18);
820 astep -> aste.msl = bit (fixed (msl, 9), 9);
821 astep -> aste.pvtx = pvtx;
822
823
824
825
826 tsdw = get_ptrs_$given_astep (astep);
827 dseg$ (segno) = tsdw;
828 call page$cam;
829 call get_pvtx$hold_pvtx ((pvt_array (pvtx).pvid), pvtx, (0));
830
831 astep -> aste.usedf = "1"b;
832
833 call thread$out (astep, sst$level (ptsi).ausedp);
834
835 call lock$unlock_ast;
836
837
838
839
840 table1p = addr (pv_salv_seg.table1);
841 table3p = addr (pv_salv_seg.table3);
842
843 return;
844
845 end INIT_TABLES;
846
847 end;
848
849
850
851 %page; %include aste;
852 %page; %include disk_pack;
853 %page; %include fs_vol_label;
854 %page; %include null_addresses;
855 %page; %include pvte;
856 %page; %include salv_data;
857 %page; %include salvager_severities;
858 %page; %include syserr_constants;
859 %page; %include vol_map;
860 %page; %include vtoc_header;
861 %page; %include vtoc_map;
862 %page; %include vtoce;
863
864
865 %page;
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887 debug
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914 XXX
915
916
917
918
919
920
921
922
923
924
925
926
927 XXX
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958 XXX
959
960
961
962
963
964
965
966
967
968
969
970
971 XXX
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 debug
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307 end disk_rebuild;