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 vtoc_man$get_vtoce:
55 proc (Pvid, Pvtx, Vtocx, Parts, Copy_Vtocep, Code);
56
57
58
59 dcl Copy_Vtocep ptr;
60 dcl Code fixed bin (35);
61 dcl Parts bit (3);
62 dcl Pvid bit (36) aligned;
63 dcl Pvtx fixed bin;
64 dcl Vtocx fixed bin;
65
66
67
68 dcl bufx fixed bin;
69 dcl code fixed bin (35);
70 dcl dev_type fixed bin;
71 dcl hot_buffer_tried bit (1);
72 dcl 1 local_vtoce_buffer
73 aligned like vtoce_buffer;
74 dcl old_pseudo_clock fixed bin (35);
75 dcl p99 pic "99";
76 dcl parts bit (3) aligned;
77 dcl parts_to_write bit (3) aligned;
78 dcl pvid bit (36) aligned;
79 dcl pvtx fixed bin;
80 dcl return_vtocx fixed bin;
81 dcl sector_read_required
82 bit (1) aligned;
83 dcl vtocx fixed bin;
84 dcl wait_event bit (36) aligned;
85
86
87
88 dcl ALL_PARTS bit (3) aligned int static options (constant) init ("111"b);
89 dcl CORE_OFFSET (0:7) fixed bin int static options (constant) init (0, 128, 64, 64, 0, 0, 0, 0);
90 dcl MAX_PSEUDO_CLOCK fixed bin (35) int static options (constant) init (1000000);
91 dcl MAX_STEPS fixed bin int static options (constant) init (10000);
92 dcl SECTOR_OFFSET (0:7) fixed bin int static options (constant) init (0, 2, 1, 1, 0, 0, 0, 0);
93 dcl SECTORS_TO_WRITE (0:7) fixed bin int static options (constant) init (0, 1, 1, 2, 1, 0, 2, 3);
94 dcl VALID_WRITE (0:7) bit (1) aligned int static options (constant)
95 init ("0"b, "1"b, "1"b, "1"b, "1"b, "0"b, "1"b, "1"b);
96
97
98
99 dcl 1 Copy_Vtoce aligned like vtoce_buffer based (Copy_Vtocep);
100
101
102
103 dcl error_table_$invalid_pvtx
104 fixed bin (35) external;
105 dcl error_table_$invalid_vtocx
106 fixed bin (35) external;
107 dcl error_table_$pvid_not_found
108 fixed bin (35) external;
109 dcl error_table_$vtoc_io_err
110 fixed bin (35) external;
111 dcl error_table_$vtoce_free
112 fixed bin (35) external;
113 dcl pds$processid bit (36) aligned external;
114 dcl pds$process_group_id
115 char (32) aligned external;
116 dcl pds$vtoc_reads fixed bin (35) external;
117 dcl pds$vtoc_writes fixed bin (35) external;
118 dcl pvt$n_entries fixed bin external;
119
120
121
122 dcl dctl$read_sectors entry (fixed bin, fixed bin (24), bit (18) aligned, fixed bin, fixed bin);
123 dcl dctl$write_sectors entry (fixed bin, fixed bin (24), bit (18) aligned, fixed bin, fixed bin);
124 dcl disk_run entry;
125 dcl lock$lock_fast entry (ptr);
126 dcl lock$unlock_fast entry (ptr);
127 dcl pxss$addevent entry (bit (36) aligned);
128 dcl pxss$delevent entry (bit (36) aligned);
129 dcl pxss$wait entry;
130 dcl syserr entry options (variable);
131 dcl vtoc_search$hash_in entry (ptr);
132 dcl vtoc_search$hash_out
133 entry (ptr);
134 dcl vtoc_search$search entry (fixed bin, fixed bin, ptr);
135 dcl vtoce_stock_man$check_in_use
136 entry (ptr, fixed bin, fixed bin (35));
137 dcl vtoce_stock_man$get_free_vtoce
138 entry (ptr, fixed bin);
139 dcl vtoce_stock_man$return_if_not_free
140 entry (ptr, fixed bin, fixed bin (35));
141 dcl vtoce_stock_man$return_free_vtoce
142 entry (ptr, fixed bin);
143
144
145
146 dcl addr builtin;
147 dcl bin builtin;
148 dcl bit builtin;
149 dcl convert builtin;
150 dcl divide builtin;
151 dcl mod builtin;
152 dcl null builtin;
153 dcl ptr builtin;
154 dcl rel builtin;
155 dcl size builtin;
156 dcl substr builtin;
157 dcl unspec builtin;
158 %page;
159
160
161
162
163
164
165
166
167
168
169 pvid = Pvid;
170 pvtx = Pvtx;
171 vtocx = Vtocx;
172 parts = Parts;
173 Code = 0;
174
175 call SETUP_LOCK (pvtx, code);
176 if code ^= 0
177 then goto GET_VTOCE_RETURNS;
178
179 call VALIDATE_VTOCX (vtocx, code);
180 if code ^= 0
181 then goto GET_VTOCE_RETURNS;
182
183
184 call READ (pvtx, vtocx, parts, vtoc_buf_descp, vtoc_bufp, sector_read_required, code);
185 if code ^= 0
186 then goto GET_VTOCE_RETURNS;
187
188 unspec (local_vtoce_buffer) = unspec (vtoce_buffer);
189
190 GET_VTOCE_RETURNS:
191 call UNLOCK;
192 vtoc_buffer.meters.call_get = vtoc_buffer.meters.call_get + 1;
193
194 if code = 0
195 then call COPY_PARTS (parts, addr (local_vtoce_buffer), Copy_Vtocep);
196
197 Code = code;
198
199 return;
200 %page;
201
202
203
204
205
206
207
208
209
210
211 read_ahead_vtoce:
212 entry (Pvid, Pvtx, Vtocx, Parts, Code);
213
214 pvid = Pvid;
215 pvtx = Pvtx;
216 vtocx = Vtocx;
217 parts = Parts;
218 Code = 0;
219
220 call SETUP_LOCK (pvtx, code);
221 if code ^= 0
222 then goto READ_AHEAD_VTOCE_RETURNS;
223
224 call VALIDATE_VTOCX (vtocx, code);
225 if code ^= 0
226 then goto READ_AHEAD_VTOCE_RETURNS;
227
228 call READ_AHEAD (pvtx, vtocx, parts, vtoc_buf_descp, vtoc_bufp, sector_read_required, code);
229
230 READ_AHEAD_VTOCE_RETURNS:
231 call UNLOCK;
232
233
234 Code = code;
235
236 return;
237
238
239 %page;
240
241
242
243
244
245
246
247
248
249
250 put_vtoce:
251 entry (Pvid, Pvtx, Vtocx, Parts, Copy_Vtocep, Code);
252
253 pvid = Pvid;
254 pvtx = Pvtx;
255 vtocx = Vtocx;
256 parts = Parts;
257 Code = 0;
258 sector_read_required = "0"b;
259 parts_to_write = parts;
260 call COPY_PARTS (parts, Copy_Vtocep, addr (local_vtoce_buffer));
261
262
263 call SETUP_LOCK (pvtx, code);
264 if code ^= 0
265 then goto PUT_VTOCE_RETURNS;
266
267 call VALIDATE_VTOCX (vtocx, code);
268 if code ^= 0
269 then goto PUT_VTOCE_RETURNS;
270
271 vtoc_buffer.unsafe_pvtx = pvtx;
272 if (SECTORS_PER_VTOCE (pvte.device_type) = 1) & (parts ^= ALL_PARTS)
273 then do;
274 call READ (pvtx, vtocx, ALL_PARTS, vtoc_buf_descp, vtoc_bufp, sector_read_required, code);
275 if code ^= 0
276 then goto PUT_VTOCE_RETURNS;
277 parts_to_write = ALL_PARTS;
278 end;
279
280 else call GET_BUFFER (pvtx, vtocx, vtoc_buf_descp, vtoc_bufp, code);
281
282 if code ^= 0
283 then goto PUT_VTOCE_RETURNS;
284 call CLEAR_PAD (addr (local_vtoce_buffer), parts);
285 call COPY_PARTS (parts, addr (local_vtoce_buffer), vtoc_bufp);
286
287
288 call WRITE (parts_to_write, vtoc_buf_descp);
289 if sector_read_required
290 then vtoc_buffer.meters.soft_rar = vtoc_buffer.meters.soft_rar + 1;
291 PUT_VTOCE_RETURNS:
292 vtoc_buffer.unsafe_pvtx = 0;
293 call UNLOCK;
294 vtoc_buffer.meters.call_put = vtoc_buffer.meters.call_put + 1;
295 Code = code;
296 return;
297 %page;
298
299
300
301
302
303
304
305
306
307
308 alloc_and_put_vtoce:
309 entry (Pvid, Pvtx, Copy_Vtocep, Code) returns (fixed bin (17));
310
311 pvid = Pvid;
312 pvtx = Pvtx;
313 Code = 0;
314 return_vtocx = -1;
315
316 unspec (local_vtoce_buffer) = unspec (Copy_Vtoce);
317
318 call SETUP_LOCK (pvtx, code);
319 if code ^= 0
320 then goto ALLOC_PUT_RETURNS;
321
322 RETRY_ALLOC:
323 old_pseudo_clock = vtoc_buffer.scavenger_free_p_clock;
324
325 call vtoce_stock_man$get_free_vtoce (pvtep, vtocx);
326 if vtocx = -1
327 then goto ALLOC_PUT_RETURNS;
328
329 call VALIDATE_VTOCX (vtocx, code);
330 if code ^= 0
331 then do;
332 call SET_VOL_TROUBLE (pvtep, vtocx, "Invalid free");
333 goto RETRY_ALLOC;
334 end;
335
336 call READ (pvtx, vtocx, ALL_PARTS, vtoc_buf_descp, vtoc_bufp, sector_read_required, code);
337 if code ^= 0
338 then goto ALLOC_PUT_RETURNS;
339 vtocep = vtoc_bufp;
340 if vtoce.uid ^= ""b
341 then do;
342 call SET_VOL_TROUBLE (pvtep, vtocx, "UID ^= 0 in free VTOCE");
343 goto RETRY_ALLOC;
344 end;
345
346 if vtoc_buffer.scavenger_free_p_clock ^= old_pseudo_clock
347 then do;
348 vtoc_buffer.meters.scavenger_free_checks = vtoc_buffer.meters.scavenger_free_checks + 1;
349 call vtoce_stock_man$check_in_use (pvtep, vtocx, code);
350 if code ^= 0
351 then do;
352 vtoc_buffer.meters.scavenger_free_losses = vtoc_buffer.meters.scavenger_free_losses + 1;
353 goto RETRY_ALLOC;
354 end;
355 end;
356
357 vtoc_buffer.unsafe_pvtx = pvtx;
358
359 call CLEAR_PAD (addr (local_vtoce_buffer), ALL_PARTS);
360
361 unspec (vtoce_buffer) = unspec (local_vtoce_buffer);
362 call WRITE (ALL_PARTS, vtoc_buf_descp);
363
364 return_vtocx = vtocx;
365
366 ALLOC_PUT_RETURNS:
367 vtoc_buffer.unsafe_pvtx = 0;
368 call UNLOCK;
369 vtoc_buffer.meters.call_alloc = vtoc_buffer.meters.call_alloc + 1;
370
371 Code = code;
372 return (return_vtocx);
373 %page;
374
375
376
377
378
379
380
381 free_vtoce:
382 entry (Pvid, Pvtx, Vtocx, Code);
383
384 pvid = Pvid;
385 pvtx = Pvtx;
386 vtocx = Vtocx;
387 Code = 0;
388
389 call SETUP_LOCK (pvtx, code);
390 if code ^= 0
391 then goto FREE_VTOCE_RETURNS;
392
393 call VALIDATE_VTOCX (vtocx, code);
394 if code ^= 0
395 then goto FREE_VTOCE_RETURNS;
396
397 call GET_BUFFER (pvtx, vtocx, vtoc_buf_descp, vtoc_bufp, code);
398
399 if code ^= 0
400 then goto FREE_VTOCE_RETURNS;
401
402 unspec (vtoce_buffer.parts) = ""b;
403 call WRITE (ALL_PARTS, vtoc_buf_descp);
404
405 call vtoce_stock_man$return_free_vtoce (pvtep, vtocx);
406
407
408 FREE_VTOCE_RETURNS:
409 call UNLOCK;
410 vtoc_buffer.meters.call_free = vtoc_buffer.meters.call_free + 1;
411
412 Code = code;
413 return;
414 %page;
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440 free_vtoce_for_scavenge:
441 entry (Pvid, Pvtx, Vtocx, Code);
442
443
444 pvid = Pvid;
445 pvtx = Pvtx;
446 vtocx = Vtocx;
447 Code = 0;
448
449 call SETUP_LOCK (pvtx, code);
450 if code ^= 0
451 then goto FREE_FOR_SCAVENGE_RETURNS;
452
453 call VALIDATE_VTOCX (vtocx, code);
454 if code ^= 0
455 then goto FREE_FOR_SCAVENGE_RETURNS;
456
457 call READ (pvtx, vtocx, ALL_PARTS, vtoc_buf_descp, vtoc_bufp, sector_read_required, code);
458 if code ^= 0
459 then goto FREE_FOR_SCAVENGE_RETURNS;
460
461 vtocep = vtoc_bufp;
462 if vtoce.uid ^= ""b
463 then do;
464 code = error_table_$vtoce_free;
465 goto FREE_FOR_SCAVENGE_RETURNS;
466 end;
467
468 unspec (vtoce) = ""b;
469 call WRITE (ALL_PARTS, vtoc_buf_descp);
470
471 call vtoce_stock_man$return_if_not_free (pvtep, vtocx, code);
472
473 vtoc_buffer.scavenger_free_p_clock = vtoc_buffer.scavenger_free_p_clock + 1;
474 if vtoc_buffer.scavenger_free_p_clock > MAX_PSEUDO_CLOCK
475 then vtoc_buffer.scavenger_free_p_clock = 0;
476
477 FREE_FOR_SCAVENGE_RETURNS:
478 call UNLOCK;
479
480 Code = code;
481 return;
482
483
484 %page;
485
486
487
488
489
490
491
492
493
494 await_vtoce:
495 entry (Pvid, Pvtx, Vtocx, Code);
496
497 pvid = Pvid;
498 pvtx = Pvtx;
499 vtocx = Vtocx;
500 Code = 0;
501
502 call SETUP_LOCK (pvtx, code);
503 if code ^= 0
504 then goto AWAIT_RETURNS;
505
506 call VALIDATE_VTOCX (vtocx, code);
507 if code ^= 0
508 then goto AWAIT_RETURNS;
509
510 RETRY_AWAIT:
511 call vtoc_search$search (pvtx, vtocx, vtoc_buf_descp);
512
513 if vtoc_buf_descp = null ()
514 then goto AWAIT_RETURNS;
515
516 if vtoc_buf_desc.os
517 then do;
518 call WAIT (vtoc_buf_descp, code);
519 if code ^= 0
520 then goto AWAIT_RETURNS;
521 goto RETRY_AWAIT;
522 end;
523
524 if vtoc_buf_desc.write_sw & vtoc_buf_desc.err
525 then code = error_table_$vtoc_io_err;
526
527 AWAIT_RETURNS:
528 call UNLOCK;
529 vtoc_buffer.meters.call_await = vtoc_buffer.meters.call_await + 1;
530
531 Code = code;
532 return;
533 %page;
534
535
536
537
538
539
540
541 cleanup_pv:
542 entry (Pvtx, Code);
543
544 pvid = ""b;
545 pvtx = Pvtx;
546 vtocx = -1;
547 Code = 0;
548
549 call SETUP_LOCK (pvtx, code);
550
551 do bufx = 1 to vtoc_buffer.n_bufs;
552 vtoc_buf_descp = addr (vtoc_buf_desc_array (bufx));
553 if vtoc_buf_desc.pvtx = pvtx & vtoc_buf_desc.used = "1"b
554 & vtoc_buf_desc.err & vtoc_buf_desc.write_sw & ^vtoc_buf_desc.os
555
556 then call WRITE ((vtoc_buf_desc.parts_used), vtoc_buf_descp);
557 end;
558
559 do bufx = 1 to vtoc_buffer.n_bufs;
560 vtoc_buf_descp = addr (vtoc_buf_desc_array (bufx));
561 do while (vtoc_buf_desc.pvtx = pvtx & vtoc_buf_desc.used
562 & vtoc_buf_desc.os);
563 call WAIT (vtoc_buf_descp, code);
564 end;
565 end;
566
567 code = 0;
568 do bufx = 1 to vtoc_buffer.n_bufs;
569 vtoc_buf_descp = addr (vtoc_buf_desc_array (bufx));
570 if vtoc_buf_desc.pvtx = pvtx & vtoc_buf_desc.used
571
572 then do;
573 if vtoc_buf_desc.os
574 then call syserr (CRASH, "vtoc_man: Buffer out-of-service during cleanup");
575 if vtoc_buf_desc.write_sw & vtoc_buf_desc.err
576
577 then do;
578 call SET_VOL_TROUBLE (pvtep, (vtoc_buf_desc.vtocx),
579 "Hot buffer abandoned during cleanup");
580 code = error_table_$vtoc_io_err;
581 end;
582 call FLUSH_BUFFER (vtoc_buf_descp);
583 end;
584 end;
585
586 call UNLOCK;
587
588 Code = code;
589 return;
590 %page;
591
592
593
594
595
596
597
598
599 stabilize:
600 entry;
601
602 pvid = ""b;
603 pvtx = -1;
604 vtocx = -1;
605
606 vtoc_buffer_segp = addr (vtoc_buffer_seg$);
607 vtoc_buffer.lock.processid = ""b;
608
609 call SETUP_LOCK (pvtx, code);
610
611 call RETHREAD;
612
613 do bufx = 1 to vtoc_buffer.n_bufs;
614 vtoc_buf_descp = addr (vtoc_buf_desc_array (bufx));
615 if vtoc_buf_desc.used & vtoc_buf_desc.os
616 then if vtoc_buf_desc.write_sw
617 then do;
618 vtoc_buf_desc.err = "1"b;
619 vtoc_buf_desc.os = "0"b;
620 end;
621 else call FLUSH_BUFFER (vtoc_buf_descp);
622 end;
623
624 call UNLOCK;
625
626 return;
627 %page;
628
629
630
631
632
633
634
635
636
637
638
639 Note
640
641
642 crawlout:
643 entry;
644
645
646 vtoc_buffer_segp = addr (vtoc_buffer_seg$);
647 vtoc_buf_desc_arrayp = ptr (vtoc_buffer_segp, vtoc_buffer.buf_desc_offset);
648 vtoc_buf_arrayp = ptr (vtoc_buffer_segp, vtoc_buffer.buf_offset);
649 pvt_arrayp = addr (pvt$array);
650
651 if vtoc_buffer.lock.processid ^= pds$processid
652 then return;
653
654 call RETHREAD;
655
656 if vtoc_buffer.unsafe_pvtx ^= 0
657 then do;
658 pvtep = addr (pvt_array (vtoc_buffer.unsafe_pvtx));
659 call SET_VOL_TROUBLE (pvtep, -1, "Update in progress on crawlout by " || pds$process_group_id);
660 end;
661
662 do bufx = 1 to vtoc_buffer.n_bufs;
663 vtoc_buf_descp = addr (vtoc_buf_desc_array (bufx));
664 if vtoc_buf_desc.used & vtoc_buf_desc.os & ^vtoc_buf_desc.ioq
665
666 then do;
667 pvtx = vtoc_buf_desc.pvtx;
668 vtocx = vtoc_buf_desc.vtocx;
669 wait_event = bit (bin (vtoc_buffer.wait_event_constant + vtoc_buf_desc.wait_index, 36), 36);
670 call pxss$addevent (wait_event);
671 call lock$unlock_fast (addr (vtoc_buffer.lock));
672 call pxss$wait;
673 call lock$lock_fast (addr (vtoc_buffer.lock));
674 if vtoc_buf_desc.used & vtoc_buf_desc.os
675 & ^vtoc_buf_desc.ioq
676 & vtoc_buf_desc.pvtx = pvtx & vtoc_buf_desc.vtocx = vtocx
677
678 then do;
679 pvtep = addr (pvt_array (pvtx));
680 if vtoc_buf_desc.write_sw
681 then do;
682 call syserr (LOG,
683 "vtoc_man: write I/O recovered on crawlout by ^a for ^a_^a^a vtocx ^o",
684 pds$process_group_id, pvte.devname,
685 convert (p99, pvte.logical_area_number), pvte.sv_name, vtocx);
686 vtoc_buf_desc.os = "0"b;
687 call WRITE ((vtoc_buf_desc.parts_used), vtoc_buf_descp);
688 end;
689 else do;
690 call syserr (LOG,
691 "vtoc_man: read reset on crawlout by ^a for ^a_^a^a vtocx ^o",
692 pds$process_group_id, pvte.devname,
693 convert (p99, pvte.logical_area_number), pvte.sv_name, vtocx);
694 call FLUSH_BUFFER (vtoc_buf_descp);
695 end;
696 end;
697 end;
698 end;
699
700
701 return;
702 %page;
703
704
705 CLEAR_PAD:
706 proc (Clear_ptr, Parts);
707
708 dcl Clear_ptr ptr;
709 dcl Parts bit (3) aligned;
710
711 dcl 1 Clear_vtoce aligned like vtoce based (Clear_ptr);
712
713 if (Parts & "100"b)
714 then do;
715 Clear_vtoce.pad_free_vtoce_chain = ""b;
716 Clear_vtoce.pad2 = ""b;
717 Clear_vtoce.pad3 = ""b;
718 Clear_vtoce.pad4 = ""b;
719 end;
720 if (Parts & "001"b)
721 then do;
722 unspec (Clear_vtoce.pad6) = ""b;
723 Clear_vtoce.pad7 = ""b;
724 Clear_vtoce.pad8 = ""b;
725 Clear_vtoce.pad9 = ""b;
726 end;
727
728 end CLEAR_PAD;
729 %page;
730
731
732
733
734 COPY_PARTS:
735 proc (Parts, From_ptr, To_ptr);
736
737 dcl Parts bit (3) aligned;
738 dcl From_ptr ptr;
739 dcl To_ptr ptr;
740
741 dcl partsx fixed bin;
742
743 dcl 1 From_Vtoce_Buffer aligned like vtoce_buffer based (From_ptr);
744 dcl 1 To_Vtoce_Buffer aligned like vtoce_buffer based (To_ptr);
745
746 do partsx = 1 to N_PARTS_PER_VTOCE;
747 if substr (Parts, partsx, 1) = "1"b
748 then unspec (To_Vtoce_Buffer.parts (partsx)) = unspec (From_Vtoce_Buffer.parts (partsx));
749 end;
750
751 end COPY_PARTS;
752 %page;
753
754
755
756
757
758
759
760
761
762 CORE:
763 proc (Vtoc_buf_descp) returns (fixed bin (24));
764
765 dcl Vtoc_buf_descp ptr;
766 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
767
768 return (vtoc_buffer.abs_addr + bin (Vtoc_buf_desc.buf_rel));
769
770 end CORE;
771
772
773
774 RECORD:
775 proc (Vtoc_buf_descp) returns (bit (18) aligned);
776
777 dcl Vtoc_buf_descp ptr;
778 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
779
780 return (bit (bin (VTOC_ORIGIN + divide (Vtoc_buf_desc.vtocx, VTOCES_PER_RECORD (dev_type), 17), 18), 18));
781
782 end RECORD;
783
784
785 SECTOR:
786 proc (Vtoc_buf_descp) returns (fixed bin (17));
787
788 dcl Vtoc_buf_descp ptr;
789 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
790
791
792 return (mod (Vtoc_buf_desc.vtocx, VTOCES_PER_RECORD (dev_type)) * SECTORS_PER_VTOCE (dev_type));
793
794 end SECTOR;
795
796
797 %page;
798
799
800
801
802 SET_VOL_TROUBLE:
803 proc (Pvtep, Vtocx, Msg);
804
805 dcl Pvtep ptr;
806 dcl Vtocx fixed bin;
807 dcl Msg char (*);
808
809 dcl 1 Pvte aligned like pvte based (Pvtep);
810
811 Pvte.vol_trouble_count = Pvte.vol_trouble_count + 1;
812
813 call syserr (LOG, "vtoc_man: ^a ^[vtocx ^o ^;^1s^]on ^a_^a^a", Msg, (Vtocx ^= -1), Vtocx, Pvte.devname,
814 convert (p99, Pvte.logical_area_number), Pvte.sv_name);
815
816 end SET_VOL_TROUBLE;
817 %page;
818
819
820
821
822
823 RETHREAD:
824 proc;
825
826 unspec (vtoc_buffer.hash_table) = ""b;
827
828 do bufx = 1 to vtoc_buffer.n_bufs;
829 vtoc_buf_descp = addr (vtoc_buf_desc_array (bufx));
830 if vtoc_buf_desc.used
831 then call vtoc_search$hash_in (vtoc_buf_descp);
832 end;
833
834 end RETHREAD;
835 %page;
836
837
838
839
840 FLUSH_BUFFER:
841 proc (Vtoc_buf_descp);
842
843 dcl Vtoc_buf_descp ptr;
844 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
845
846 call vtoc_search$hash_out (Vtoc_buf_descp);
847
848 vtoc_buffer.search_index =
849 divide (bin (rel (Vtoc_buf_descp)) - bin (rel (vtoc_buf_desc_arrayp)), size (vtoc_buf_desc), 17) + 1;
850
851
852 unspec (Vtoc_buf_desc) = ""b;
853
854
855 end FLUSH_BUFFER;
856 %page;
857
858
859
860
861
862
863
864
865
866 GET_BUFFER:
867 proc (Pvtx, Vtocx, Vtoc_buf_descp, Vtoc_bufp, Code);
868
869 dcl Pvtx fixed bin;
870 dcl Vtocx fixed bin;
871 dcl Vtoc_buf_descp ptr;
872 dcl Vtoc_bufp ptr;
873 dcl Code fixed bin (35);
874
875 dcl first_time bit (1) aligned;
876 dcl skip_waiting bit (1) aligned;
877 dcl steps fixed bin;
878 dcl wait_sw bit (1) aligned;
879 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
880
881
882 wait_sw = "1"b;
883 goto GET_BUFFER_JOIN;
884
885
886 GET_BUFFER_NOWAIT:
887 entry (Pvtx, Vtocx, Vtoc_buf_descp, Vtoc_bufp, Code);
888
889 wait_sw = "0"b;
890
891 GET_BUFFER_JOIN:
892 Code = 0;
893 vtoc_buffer.meters.get_buffer_calls = vtoc_buffer.meters.get_buffer_calls + 1;
894 first_time = "1"b;
895
896
897 GET_BUFFER_RETRY:
898 call vtoc_search$search (Pvtx, Vtocx, Vtoc_buf_descp);
899
900 if Vtoc_buf_descp ^= null () & first_time
901 then vtoc_buffer.meters.get_buffer_hits = vtoc_buffer.meters.get_buffer_hits + 1;
902 first_time = "0"b;
903
904 if Vtoc_buf_descp = null ()
905 then do;
906 steps = 0;
907 skip_waiting = "1"b;
908 bufx = vtoc_buffer.search_index;
909 do while ("1"b);
910 vtoc_buffer.meters.steps = vtoc_buffer.meters.steps + 1;
911 steps = steps + 1;
912 Vtoc_buf_descp = addr (vtoc_buf_desc_array (bufx));
913
914 if ^Vtoc_buf_desc.used
915 then goto FOUND;
916
917 if Vtoc_buf_desc.os
918 then vtoc_buffer.meters.skip_os = vtoc_buffer.meters.skip_os + 1;
919 else if Vtoc_buf_desc.write_sw & Vtoc_buf_desc.err
920 then vtoc_buffer.meters.skip_hot = vtoc_buffer.meters.skip_hot + 1;
921 else if Vtoc_buf_desc.notify_sw & skip_waiting
922 then vtoc_buffer.meters.skip_wait = vtoc_buffer.meters.skip_wait + 1;
923 else goto FOUND;
924
925 if steps > MAX_STEPS
926 then call syserr (CRASH, "vtoc_man: Out of buffers");
927 bufx = bufx + 1;
928 if bufx > vtoc_buffer.n_bufs
929 then bufx = 1;
930 if bufx = vtoc_buffer.search_index
931 then do;
932 skip_waiting = "0"b;
933 call disk_run;
934 end;
935 end;
936
937 FOUND:
938 if bufx >= vtoc_buffer.n_bufs
939 then vtoc_buffer.search_index = 1;
940 else vtoc_buffer.search_index = bufx + 1;
941
942
943 if Vtoc_buf_desc.used
944 then call FLUSH_BUFFER (Vtoc_buf_descp);
945
946 Vtoc_buf_desc.pvtx = Pvtx;
947 Vtoc_buf_desc.vtocx = Vtocx;
948 Vtoc_buf_desc.used = "1"b;
949 Vtoc_buf_desc.wait_index = bufx;
950 Vtoc_buf_desc.buf_rel = rel (addr (vtoce_buffer_array (bufx)));
951
952 call vtoc_search$hash_in (Vtoc_buf_descp);
953
954 end;
955
956 if Vtoc_buf_desc.os & wait_sw
957 then do;
958 call WAIT (Vtoc_buf_descp, Code);
959 if Code ^= 0
960 then do;
961 Vtoc_buf_descp = null ();
962 Vtoc_bufp = null ();
963 return;
964 end;
965 goto GET_BUFFER_RETRY;
966 end;
967
968
969 Vtoc_bufp = ptr (vtoc_buffer_segp, Vtoc_buf_desc.buf_rel);
970
971 end GET_BUFFER;
972
973 %page;
974
975
976
977 Note
978
979
980
981
982
983
984 READ:
985 proc (Pvtx, Vtocx, Parts, Vtoc_buf_descp, Vtoc_bufp, Sector_read_required, Code);
986
987 dcl Pvtx fixed bin;
988 dcl Vtocx fixed bin;
989 dcl Parts bit (3) aligned;
990 dcl Vtoc_buf_descp ptr;
991 dcl Vtoc_bufp ptr;
992 dcl Sector_read_required
993 bit (1) aligned;
994 dcl Code fixed bin (35);
995
996 dcl wait_sw bit (1) aligned;
997
998 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
999
1000
1001 wait_sw = "1"b;
1002 goto READ_JOIN;
1003
1004
1005 READ_AHEAD:
1006 entry (Pvtx, Vtocx, Parts, Vtoc_buf_descp, Vtoc_bufp, Sector_read_required, Code);
1007
1008 wait_sw = "0"b;
1009
1010 READ_JOIN:
1011 Sector_read_required = "0"b;
1012 Code = 0;
1013 hot_buffer_tried = "0"b;
1014 RETRY_READ:
1015 if wait_sw
1016 then call GET_BUFFER (Pvtx, Vtocx, Vtoc_buf_descp, Vtoc_bufp, Code);
1017 else call GET_BUFFER_NOWAIT (Pvtx, Vtocx, Vtoc_buf_descp, Vtoc_bufp, Code);
1018 if Code ^= 0
1019 then return;
1020
1021 if ^wait_sw & Vtoc_buf_desc.os
1022 then return;
1023
1024 if Vtoc_buf_desc.err
1025 then do;
1026 if ^Vtoc_buf_desc.write_sw
1027 then call FLUSH_BUFFER (Vtoc_buf_descp);
1028 else if ^hot_buffer_tried
1029 then do;
1030 hot_buffer_tried = "1"b;
1031 pvt_arrayp = addr (pvt$array);
1032 pvtep = addr (pvt_array (Pvtx));
1033 call syserr (LOG, "vtoc_man: Write I/O being retried by ^a for ^a_^a^a vtocx ^o",
1034 pds$process_group_id, pvte.devname, convert (p99, pvte.logical_area_number),
1035 pvte.sv_name, Vtocx);
1036 Vtoc_buf_desc.os = "0"b;
1037
1038 call WRITE ((Vtoc_buf_desc.parts_used), Vtoc_buf_descp);
1039 goto RETRY_READ;
1040 end;
1041
1042 Code = error_table_$vtoc_io_err;
1043 Vtoc_buf_descp = null ();
1044 Vtoc_bufp = null ();
1045 return;
1046 end;
1047
1048 if (Vtoc_buf_desc.parts_used & Parts) = Parts
1049 then return;
1050
1051 Vtoc_buf_desc.write_sw = "0"b;
1052 Vtoc_buf_desc.err = "0"b;
1053 Vtoc_buf_desc.notify_sw = "0"b;
1054 Vtoc_buf_desc.ioq = "0"b;
1055 Vtoc_buf_desc.os = "1"b;
1056
1057 dev_type = addr (pvt_array (Pvtx)) -> pvte.device_type;
1058
1059 call dctl$read_sectors (Pvtx, CORE (Vtoc_buf_descp), RECORD (Vtoc_buf_descp), SECTOR (Vtoc_buf_descp),
1060 SECTORS_PER_VTOCE (dev_type));
1061 Sector_read_required = "1"b;
1062 Vtoc_buf_desc.ioq = "1"b;
1063 Vtoc_buf_desc.parts_used = ALL_PARTS;
1064
1065 vtoc_buffer.meters.disk_reads = vtoc_buffer.meters.disk_reads + 1;
1066 pds$vtoc_reads = pds$vtoc_reads + 1;
1067
1068 if wait_sw
1069 then goto RETRY_READ;
1070
1071 return;
1072
1073 end READ;
1074 %page;
1075
1076
1077
1078
1079 WRITE:
1080 proc (Parts, Vtoc_buf_descp);
1081
1082 dcl Parts bit (3) aligned;
1083 dcl Vtoc_buf_descp ptr;
1084
1085 dcl partsx fixed bin;
1086
1087 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
1088
1089 dcl n_sectors fixed bin;
1090 if Vtoc_buf_desc.os
1091 then call syserr (CRASH, "vtoc_man: buffer out-of-service on write.");
1092
1093 partsx = bin (Parts, 3);
1094 if ^VALID_WRITE (partsx)
1095 then call syserr (CRASH, "vtoc_man: Invalid write");
1096
1097 Vtoc_buf_desc.err = "0"b;
1098 Vtoc_buf_desc.notify_sw = "0"b;
1099 Vtoc_buf_desc.ioq = "0"b;
1100 Vtoc_buf_desc.write_sw = "1"b;
1101 Vtoc_buf_desc.os = "1"b;
1102
1103 dev_type = addr (pvt_array (Vtoc_buf_desc.pvtx)) -> pvte.device_type;
1104
1105 if SECTORS_PER_VTOCE (dev_type) = 1
1106 then do;
1107 n_sectors = 1;
1108 if Parts ^= ALL_PARTS
1109 then do;
1110 call syserr (CRASH, "vtoc_man: Attempt to write less than entire VTOCE to ^d device.",
1111 MODELN (dev_type));
1112 end;
1113 end;
1114 else n_sectors = SECTORS_TO_WRITE (partsx);
1115 call dctl$write_sectors ((Vtoc_buf_desc.pvtx), CORE (Vtoc_buf_descp) + CORE_OFFSET (partsx),
1116 RECORD (Vtoc_buf_descp), SECTOR (Vtoc_buf_descp) + SECTOR_OFFSET (partsx), n_sectors);
1117
1118 Vtoc_buf_desc.ioq = "1"b;
1119 if VALID_WRITE (bin ((Parts | Vtoc_buf_desc.parts_used), 3))
1120 then Vtoc_buf_desc.parts_used = Vtoc_buf_desc.parts_used | Parts;
1121 else Vtoc_buf_desc.parts_used = Parts;
1122
1123 vtoc_buffer.meters.disk_writes = vtoc_buffer.meters.disk_writes + 1;
1124 pds$vtoc_writes = pds$vtoc_writes + 1;
1125
1126 end WRITE;
1127 %page;
1128
1129
1130
1131
1132 WAIT:
1133 proc (Vtoc_buf_descp, Code);
1134
1135 dcl Vtoc_buf_descp ptr;
1136 dcl Code fixed bin (35);
1137
1138 dcl 1 Vtoc_buf_desc aligned like vtoc_buf_desc based (Vtoc_buf_descp);
1139
1140 Code = 0;
1141 vtoc_buffer.meters.wait_calls = vtoc_buffer.meters.wait_calls + 1;
1142
1143 do while (Vtoc_buf_desc.os);
1144 wait_event = bit (bin (vtoc_buffer.wait_event_constant + Vtoc_buf_desc.wait_index, 36), 36);
1145 call pxss$addevent (wait_event);
1146 Vtoc_buf_desc.notify_sw = "1"b;
1147 if Vtoc_buf_desc.os
1148 then do;
1149 vtoc_buffer.meters.wait_os = vtoc_buffer.meters.wait_os + 1;
1150 call UNLOCK;
1151 call pxss$wait;
1152 call LOCK_CHECK (Code);
1153 if Code ^= 0
1154 then return;
1155 end;
1156 else call pxss$delevent (wait_event);
1157 Vtoc_buf_desc.notify_sw = "0"b;
1158 end;
1159
1160 end WAIT;
1161
1162 %page;
1163
1164
1165
1166
1167 VALIDATE_VTOCX:
1168 proc (Vtocx, Code);
1169
1170 dcl Vtocx fixed bin;
1171 dcl Code fixed bin (35);
1172
1173 if Vtocx < 0 | Vtocx >= pvte.n_vtoce
1174 then Code = error_table_$invalid_vtocx;
1175 else Code = 0;
1176
1177 end VALIDATE_VTOCX;
1178 %page;
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 SETUP_LOCK:
1191 proc (Pvtx, Code);
1192
1193 dcl Pvtx fixed bin;
1194 dcl Code fixed bin (35);
1195
1196
1197 dcl code fixed bin (35);
1198
1199 vtoc_buffer_segp = addr (vtoc_buffer_seg$);
1200 vtoc_buf_desc_arrayp = ptr (vtoc_buffer_segp, vtoc_buffer.buf_desc_offset);
1201 vtoc_buf_arrayp = ptr (vtoc_buffer_segp, vtoc_buffer.buf_offset);
1202 pvt_arrayp = addr (pvt$array);
1203
1204 Code = 0;
1205 pvtep = null ();
1206
1207 if Pvtx < 0 | Pvtx > pvt$n_entries
1208 then Code = error_table_$invalid_pvtx;
1209 else pvtep = addr (pvt_array (Pvtx));
1210
1211 call LOCK_CHECK (code);
1212 if code ^= 0
1213 then Code = code;
1214
1215 end SETUP_LOCK;
1216
1217
1218
1219 LOCK_CHECK:
1220 proc (Code);
1221
1222 dcl Code fixed bin (35);
1223
1224 Code = 0;
1225
1226 if pvtep ^= null ()
1227 then do;
1228 if (pvid ^= ""b & pvid ^= pvte.pvid)
1229 then Code = error_table_$pvid_not_found;
1230 else if pvte.device_inoperative
1231 then Code = error_table_$vtoc_io_err;
1232 else if pvte.being_demounted2
1233 then Code = error_table_$pvid_not_found;
1234 end;
1235
1236 call lock$lock_fast (addr (vtoc_buffer.lock));
1237
1238
1239 end LOCK_CHECK;
1240
1241
1242 UNLOCK:
1243 proc;
1244
1245 call lock$unlock_fast (addr (vtoc_buffer.lock));
1246
1247
1248 end UNLOCK;
1249
1250 %page;
1251 %include disk_pack;
1252 %page;
1253 %include pvte;
1254 %page;
1255 %include syserr_constants;
1256 %page;
1257 %include vtoc_buffer;
1258 %page;
1259 %include vtoce;
1260 %page;
1261 %include fs_dev_types;
1262 %page;
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
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430 end vtoc_man$get_vtoce;