1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) BULL HN Information Systems Inc., 1992   *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Bull Inc., 1987                *
  6         *                                                         *
  7         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  8         *                                                         *
  9         * Copyright (c) 1972 by Massachusetts Institute of        *
 10         * Technology and Honeywell Information Systems, Inc.      *
 11         *                                                         *
 12         *********************************************************** */
 13 
 14 
 15 
 16 
 17 /****^  HISTORY COMMENTS:
 18   1) change(88-03-28,Parisek), approve(88-05-27,MCR7907),
 19      audit(88-06-02,Fawcett), install(88-09-27,MR12.2-1122):
 20      Free the pvtx and pvid binding (done by get_pvtx$hold_pvtx to keep other
 21      processes from allocating the potential target pv during VTOCE move) when
 22      that target pv is found to be full, thus making it unusable for the VTOCE
 23      move. (phx20920).
 24   2) change(92-09-11,Zimmerman), approve(92-09-11,MCR8259), audit(92-09-22,Vu),
 25      install(92-10-23,MR12.5-1040):
 26      Change to include names of sub_volumes in error messages.
 27                                                    END HISTORY COMMENTS */
 28 
 29 
 30 /* format: style2,indcomtxt */
 31 segment_mover:
 32      proc (a_refaddr, a_astep, a_ep, a_segno, a_code);
 33 
 34 /**** This procedure is invoked from the segment fault handler when the latter finds
 35       a flag (aste.pack_ovfl) on in an ASTE to which a process is trying to connect.
 36       This flag is turned on when the page fault handler finds that no page of the
 37       segment's Physical Volume of residence is availble for allocation.
 38 
 39       Segment_mover tries to allocate a vtoce for the segment on some
 40       other physical volume of the logical volume. The PVT is scanned once,
 41       via a coroutine with create_vtoce$createv_for_segmove. The target
 42       physical volume must have at least as many free records as the current requirement
 43       of the segment, plus the one extra sought. If no allocation can be made, segment_mover
 44       returns the logical volume full error code.
 45 
 46       In the case of a demand segment move (hphcs_ call to move a segment),
 47       optimization of physical volume selection is allowed for create_vtoce.
 48       This optimization will place segments on devices with the most space,
 49       over a sufficiently large number of segment creations.
 50 
 51       segment_mover relies upon page_control detected out-of-physical-volume
 52       conditions on the target physical volume. If the segment fault handler
 53       notices a fault on the illegal low segment number, an error is signalled, which
 54       is caught by a condition handler in this program, and interpreted appropriately.
 55 
 56       The basic strategy is to move all pages into memory, wired,
 57       and then change the record addresses. For synchronized segments,
 58       it is neccessary to guarantee that no held pages exist, since
 59       the disk records for held pages would have to be preserved and
 60       their contents moved. Thus, for synchronized segments,
 61       pc force writes the journal pages, and then can use the usual
 62       strategy.
 63 
 64       Designed and coded by Bernard Greenberg, 9-10/75
 65 
 66       Last modified:
 67 
 68       02/19/76 by Richard Bratt to change coroutine coordination with create_vtoce
 69       05/76    by BSG for demounter, hphcs_ seg mover
 70       06/76         by D. Vinograd to copy volume dump info to new aste and to set volume dump bit map for old vtoce.
 71       12/1/78 by BSG for +-1 bugs in pc calls and special-case of 1 PV LV
 72       10/03/79 by J. A. Bush to copy terminal quota attributes out of old vtoce, into new one
 73       03/10/80 by Mike Grady to code around a compiler bug
 74       04/08/80 by Mike Grady to fix a bug in releasing of held pvtx's.
 75       03/20/81, W. Olin Sibert, to change for ADP PTW formats
 76       03/22/81, WOS, to only complain about illegal deactivations in segment fault case (not hphcs_)
 77       04/19/81, W. Olin Sibert, to stop maintaining aste.ic
 78       02/28/82, J. Bongiovanni, to eliminate obsolete vtoce.infqcnt, rework pvte refs,
 79       add demand_segmove entry and optimization of PV allocation
 80       08/18/82, J. Bongiovanni, for new pc$list_deposited_add and
 81       pc$deposit_list calling sequences
 82       10/26/82, J. Bongiovanni, for fm_damaged and synchronized segments
 83       831211, E. N. Kittlitz, for EHS moves, demand moves within a PV.
 84       84-01-03 BIM to finish the above.
 85       84-07-01 BIM to unthread one aste from get_aste before getting
 86       the other. Otherwise, you can get the same aste twice.
 87       1984-10-15 BIM to release pvtx's on failure.
 88       1984-12-18 BIM: to zero special SDW for synch segment (it has no trailer,
 89       so cannot be left around), and to sum$dirmod.
 90       1985-04-01, BIM: only rethread the ASTE once on failure.
 91 */
 92 
 93           dcl     a_astep                ptr;               /* for efficiency */
 94           dcl     a_code                 fixed bin (35);    /* return error code */
 95           dcl     a_ep                   ptr;
 96           dcl     a_refaddr              fixed bin (18);    /* referenced address, <0 if hphcs_ */
 97           dcl     a_segno                fixed bin;         /* arg segno of reference */
 98 
 99           dcl     aste_uid               bit (36) aligned;
100           dcl     aste_tqsw              (0:1) bit (1) aligned;
101           dcl     cleanup_must_zero_sdw  bit (1) aligned;
102           dcl     code                   fixed bin (35);    /* temp var for that */
103           dcl     corout_pvtx            fixed bin;         /* control point for create_vtoce$createv_for_segmove */
104 
105           dcl     demand_segmove         bit (1);
106           dcl     depolist               (0:255) bit (36) aligned;
107                                                             /* deposit array */
108           dcl     dlp                    ptr;
109           dcl     move_astep             ptr;               /* Target ASTE if ehs segmove */
110           dcl     held_pvtx              bit (1);           /* flag, on if we held new pvtx */
111           dcl     ignore                 fixed bin (35);    /* what it says */
112           dcl     mod_status             bit (1);           /* old seg fms status */
113           dcl     n_nulled_pages         fixed bin;
114           dcl     new_pts                fixed bin;
115           dcl     new_ptsi               fixed bin;
116           dcl     new_pvid               bit (36) aligned;
117           dcl     new_pvtx               fixed bin;
118           dcl     new_vtocx              fixed bin;
119           dcl     old_nqsw               bit (1);           /* setting of no quota sw */
120           dcl     old_pts                fixed bin;         /* old seg page table size */
121           dcl     old_ptsi               fixed bin;         /* old seg page table size index */
122           dcl     old_pvid               bit (36) aligned;
123           dcl     old_pvtx               fixed bin;
124           dcl     old_vtocx              fixed bin;
125           dcl     optimizing             bit (1) aligned;
126           dcl     pageno_list            (256) fixed bin;   /* Page number list */
127           dcl     pvid                   bit (36);          /* New pvid, to go in branch when ready */
128           dcl     pw1                    fixed bin;
129           dcl     pw2                    fixed bin;
130           dcl     qtype                  fixed bin;         /* seg/dir quota index */
131           dcl     recs_needed            fixed bin;         /* Target vol must have this many */
132           dcl     ref_addr               fixed bin (18);    /* address of fault */
133           dcl     refpage                fixed bin;         /* page of fault */
134           dcl     same_pvtx              bit (1);           /* flag, on new PVTX is same as old */
135           dcl     segno                  fixed bin;         /* temp for segno of reference */
136           dcl     size_needed            fixed bin;         /* Size of new aste */
137           dcl     skip_pvtx              fixed bin;         /* pvtx for cv to skip */
138           dcl     temp_ename             char (32);
139           dcl     time1                  fixed bin (71);
140           dcl     time2                  fixed bin (71);
141           dcl     tsdw                   fixed bin (71) aligned;
142                                                             /* Temp SDW stash */
143 
144           dcl     1 aq_cell              like quota_cell aligned;
145                                                             /* auto copy of quota cell */
146           dcl     1 atq_info             like tq_info aligned;
147                                                             /* auto copy of tq_info */
148 
149           dcl     MAGIC_NPAGES           fixed bin static init (10);
150                                                             /* if more than this many pages are nulled (found zero by PC), we will deposit them and retry the fault. */
151 
152           dcl     create_vtoce$createv_for_segmove
153                                          entry (ptr, bit (36), fixed bin, fixed bin (35), fixed bin, fixed bin, fixed bin,
154                                          ptr, bit (1) aligned);
155           dcl     dbm_man$set_incr       entry (fixed bin, fixed bin, fixed bin (35));
156           dcl     get_aste               entry (fixed bin) returns (ptr);
157           dcl     get_ptrs_$given_astep  entry (ptr) returns (fixed bin (71) aligned);
158           dcl     get_pvtx$hold_pvtx     entry (bit (36) aligned, fixed bin, fixed bin (35));
159           dcl     get_pvtx$release_pvtx  entry (bit (36) aligned, fixed bin);
160           dcl     lock$lock_ast          ext entry;
161           dcl     lock$unlock_ast        ext entry;
162           dcl     logical_volume_manager$lvtep
163                                          entry (bit (36) aligned, ptr, fixed bin (35));
164           dcl     pc$deposit_list        entry (fixed bin, fixed bin, ptr, fixed bin, ptr);
165           dcl     pc$list_deposited_add  entry (ptr, fixed bin, fixed bin, fixed bin, ptr, ptr);
166           dcl     pc$segmove             entry (ptr, ptr, ptr, fixed bin, fixed bin, fixed bin, ptr, ptr, fixed bin (35));
167           dcl     pds$process_group_id   ext char (32) aligned;
168           dcl     pmut$swap_sdw          entry (ptr, ptr);
169           dcl     put_aste               entry (ptr);
170           dcl     setfaults              entry (ptr, bit (1) aligned);
171           dcl     sum$dirmod             entry (pointer);
172 
173           dcl     syserr                 entry options (variable);
174           dcl     syserr$error_code      entry options (variable);
175           dcl     (
176                   search_ast$hash_in,
177                   search_ast$hash_out
178                   )                      entry (pointer);
179           dcl     thread$cin             entry (ptr, bit (18));
180           dcl     thread$out             entry (ptr, bit (18));
181           dcl     usage_values           entry (fixed bin (17), fixed bin (71));
182           dcl     vtoc_attributes$get_quota
183                                          entry (bit (36) aligned, bit (36) aligned, fixed bin, ptr, fixed bin,
184                                          fixed bin (35));
185           dcl     vtoc_man$await_vtoce   entry (bit (36) aligned, fixed bin, fixed bin, fixed bin (35));
186           dcl     vtoc_man$free_vtoce    entry (bit (36) aligned, fixed bin, fixed bin, fixed bin (35));
187 
188           dcl     sys_info$page_size     fixed bin external static;
189           dcl     error_table_$log_vol_full
190                                          fixed bin (35) ext static;
191           dcl     error_table_$illegal_deactivation
192                                          fixed bin (35) external;
193                                                             /* Sent if illegal seg for move */
194 
195           dcl     (addr, baseptr, divide, fixed, null, setwordno, unspec, wordno)
196                                          builtin;
197 
198 %page;
199 
200 /**** Entry conditions:
201 
202       DIRECTORY WRITE LOCKED
203       AST LOCKED
204 
205 */
206 
207           demand_segmove = "0"b;                            /* Called from seg_fault */
208           ref_addr = a_refaddr;
209           goto COMMON;
210 
211 demand_segmove:
212      entry (a_astep, a_ep, a_segno, a_code);
213 
214           demand_segmove = "1"b;                            /* Called via hphcs_ */
215           ref_addr = -1;
216 
217 COMMON:
218           call usage_values (pw1, time1);                   /* Meter */
219           code = 0;
220           segno = a_segno;
221           ep = a_ep;
222           astep = null ();                                  /* temporary use only */
223           move_astep = a_astep;                             /* Current astep */
224 
225           dlp = addr (depolist);                            /* in general, use automatic table for deposits */
226           pvt_arrayp = addr (pvt$array);                    /* for disk names and pvids */
227           sstp = addr (sst_seg$);
228 
229           if move_astep -> aste.hc_sdw | move_astep -> aste.hc | move_astep -> aste.par_astep = "0"b
230           then do;
231                     a_code = error_table_$illegal_deactivation;
232                                                             /* Only complain for seg-fault invocation, not hphcs_ */
233                     if ^demand_segmove
234                     then /* theory is that these will go away next bootload, anyway */
235                          call syserr (LOG, "segment_mover: critical segment out of disk on ^a, segno/astep = ^o ^o",
236                               diskname ((move_astep -> aste.pvtx)), segno, wordno (move_astep));
237                     call lock$unlock_ast;
238                     return;                                 /* leave pack_ovfl bit on */
239                end;
240 
241 /**** Don't attempt non-demand segmoves on single PV case.
242       In the demand case, someone may have changed the sons_lvid to force a cross-LV move.
243       If we happen to take an oopv after this sons_lvid has changed but before a demand
244       move on the segment, we will move it within the old LV first. Oh well. */
245 
246           call logical_volume_manager$lvtep ((pvt_array (move_astep -> aste.pvtx).lvid), lvtep, code);
247           if code = 0 & ^demand_segmove
248           then if move_astep -> aste.pvtx = lvte.pvtex & pvt_array (move_astep -> aste.pvtx).brother_pvtx = 0
249                then do;
250                          call lock$unlock_ast;
251                          a_code = error_table_$log_vol_full;
252                          return;
253                     end;
254 
255           /*** For synchronized segs, we must prevent any new held pages.
256                to do this, we must prevent any other process from modifying
257                a page of this segment. To do that, we cut its trailer with setfaults.
258                Once the trailer is cut, the segment is inaccessable until we release
259                the directory lock. */
260 
261 
262           if move_astep -> aste.synchronized
263           then do;
264                     call setfaults (move_astep, "0"b);      /* revoke all sdws */
265                     tsdw = get_ptrs_$given_astep (move_astep);
266                                                             /* but regenerate ours */
267                     call pmut$swap_sdw (baseptr (segno), addr (tsdw));
268                                                             /* back to normal */
269                     cleanup_must_zero_sdw = "1"b;           /* an SDW without a trailer is not permissible */
270                end;
271           else cleanup_must_zero_sdw = "0"b;
272 
273           /*** Now we thread the segment out. Strictly speaking, only ^ehs
274                segments need this. However, we can race with other processes
275                on the ehs bit. It is simpler to always thread out.
276 
277                The segment is threaded out to prevent deactivation. Deactivation,
278                while unlikely, would break the strategy. */
279 
280           call thread$out (move_astep, sst.ausedp (fixed (move_astep -> aste.ptsi, 2)));
281           call search_ast$hash_out (move_astep);            /* we have to rethread on new vtocx */
282 
283 /* Get modified/not modified status of old segment, and needed pages. */
284 
285           old_ptsi = fixed (move_astep -> aste.ptsi, 9);
286           old_pts = sst.pts (old_ptsi);
287           old_vtocx = move_astep -> aste.vtocx;
288           old_pvtx = move_astep -> aste.pvtx;
289           old_pvid = pvt_array (old_pvtx).pvid;
290 
291           call get_pvtx$hold_pvtx (old_pvid, old_pvtx, code);
292           if code ^= 0
293           then call syserr (CRASH, "segment_mover: get_pvtx(^o) fails under ast lock", old_pvtx);
294           held_pvtx = "0"b;                                 /* Didn't grab second pvtx yet */
295 
296           mod_status = move_astep -> aste.fms;
297 
298           n_nulled_pages = 0;
299           if ^move_astep -> aste.ddnp & ^(move_astep -> aste.fm_damaged & (sst.checksum_filemap ^= 0))
300           then do;
301                     call pc$list_deposited_add (move_astep, 0, old_pts - 1, n_nulled_pages, dlp, addr (pageno_list));
302                                                             /* He means those nulled's */
303                     if n_nulled_pages > 0 & ^demand_segmove
304                     then do;
305                               call vtoc_man$await_vtoce (old_pvid, old_pvtx, old_vtocx, code);
306                                                             /* Wait out before deposit */
307                               if code ^= 0
308                               then go to retake_fault;
309                               call pc$deposit_list (fixed (move_astep -> aste.pvtx, 17), n_nulled_pages, dlp, old_vtocx,
310                                    addr (pageno_list));     /* Free the addresses */
311                               if n_nulled_pages > MAGIC_NPAGES & ^demand_segmove
312                               then do;                      /* Avoid this hack for sweep_pv */
313 retake_fault:
314                                         call thread$cin (move_astep, sst.ausedp (fixed (move_astep -> aste.ptsi, 2)));
315                                         call search_ast$hash_in (move_astep);
316                                         call cleanup_dseg_and_meter;
317                                         if move_astep -> aste.uid = aste_uid
318                                         then move_astep -> aste.pack_ovfl = "0"b;
319                                         call release_pvtxs; /* wallow in his own soup */
320                                         call lock$unlock_ast;
321                                         a_code = code;      /* success or failure, depending ... */
322                                         return;
323                                    end;
324                          end;
325                end;
326 
327           recs_needed = n_nulled_pages + fixed (move_astep -> aste.records, 9);
328                                                             /* Assume he will regen those pages */
329           refpage = divide (ref_addr, sys_info$page_size, 18, 0);
330           size_needed = old_pts;                            /* Cannot be oob, seg_fault would have caught it */
331           aste_uid = move_astep -> aste.uid;                /* copy before AST unlock */
332           aste_tqsw (*) = move_astep -> aste.tqsw (*);      /* ... */
333           old_nqsw = move_astep -> aste.nqsw;               /* Get old nqsw */
334 
335 
336           move_astep -> aste.nqsw = "1"b;                   /* no quota checking whilst we play */
337 
338           new_ptsi, new_pts = -1;
339 
340 
341           call lock$unlock_ast;                             /* *** AST UNLOCKED *** */
342 
343           if aste_tqsw (0) | aste_tqsw (1)
344           then do;                                          /* any terminal quota? */
345                     unspec (atq_info) = "0"b;               /* initialize structure */
346                     tq_infop = addr (atq_info);             /* and set ptr */
347                     qcp = addr (aq_cell);                   /* set ptr for vtoc_attributes */
348                     do qtype = 0 to 1;                      /* check for both seg and dir quota */
349                          if aste_tqsw (qtype)
350                          then do;                           /* if terminal quota of this type.. */
351                                    call vtoc_attributes$get_quota (aste_uid, old_pvid, old_vtocx, qcp, qtype, code);
352                                    if code ^= 0
353                                    then /* we lose, log the error */
354                                         call syserr$error_code (LOG, code,
355                                              "segment_mover: Moving ^[segment^;directory^] quota account from pvtx ^o, vtocx ^o^/",
356                                              qtype + 1, old_pvtx, old_vtocx);
357                                    else do;
358                                              tq_info.trp (qtype) = quota_cell.trp;
359                                                             /* copy pertinent info */
360                                              tq_info.tup (qtype) = quota_cell.tup;
361                                              tq_info.received (qtype) = quota_cell.received;
362                                         end;
363                               end;
364                     end;
365                end;
366           else tq_infop = null;                             /* no terminal quota */
367 
368           temp_ename = addr (ep -> entry.primary_name) -> names.name;
369           corout_pvtx = 0;                                  /* Prime corutine */
370           optimizing = demand_segmove;                      /* If hphcs_ call, attempt optimization */
371           if demand_segmove
372           then skip_pvtx = 0;                               /* allow use of same pv if cv pleases */
373           else skip_pvtx = old_pvtx;                        /* if oopv then skip this pv */
374 
375 next_pv:                                                    /* RESTART POINT */
376 /**** ASSERT:  aste is thread$out'ed
377       aste is search_ast$hash_out'ed
378 */
379           same_pvtx, held_pvtx = "0"b;
380           call create_vtoce$createv_for_segmove (ep, pvid, new_vtocx, code, corout_pvtx, skip_pvtx, recs_needed, tq_infop,
381                optimizing);
382 
383 /**** + Debug
384       call syserr$error_code (ANNOUNCE, code, "sgm: pvid: ^w new_vtocx ^o corout_pvtx ^d skip_pvtx ^d recs_needed ^d ^[optimizing^].",
385       pvid, new_vtocx, corout_pvtx, skip_pvtx, recs_needed, optimizing);
386 */
387 
388           if code ^= 0
389           then go to move_fails;
390           new_pvtx = corout_pvtx;                           /* This is selected place */
391           if optimizing
392           then do;                                          /* in case this PV fails, punt further optimization */
393                     optimizing = "0"b;                      /* no more of this stuff */
394                     corout_pvtx = 0;                        /* start from the beginning again */
395                end;
396           new_pvid = pvid;                                  /* alignment */
397           if new_pvtx = old_pvtx
398           then same_pvtx = "1"b;
399           else do;
400                     call get_pvtx$hold_pvtx (new_pvid, new_pvtx, code);
401                     if code = 0
402                     then held_pvtx = "1"b;
403                     else go to next_pv;
404                end;
405 
406 
407           call MOVE_THE_SEGMENT;
408 
409           sstp -> sst.good_sgms = sstp -> sst.good_sgms + 1;
410           if ^demand_segmove
411           then /* Only for seg_fault calls */
412                call syserr (LOG, "segment_mover: Moved ^w(^a) from ^a to ^a for ^a", move_astep -> aste.uid, temp_ename,
413                     diskname (old_pvtx), diskname (new_pvtx), pds$process_group_id);
414           move_astep = null ();
415           call release_pvtxs;
416           call cleanup_dseg_and_meter;
417           a_code = 0;                                       /* That was easy, wasn't it !? */
418           return;
419 
420 move_fails:                                                 /* Code is set appropriately */
421           sstp -> sst.bad_sgms = sstp -> sst.bad_sgms + 1;  /* meter */
422           if ^demand_segmove
423           then call syserr$error_code (LOG, code, "segment_mover: Failed to seg move ^w(^a) from ^a for ^a",
424                     move_astep -> aste.uid, temp_ename, diskname (old_pvtx), pds$process_group_id);
425           call lock$lock_ast;                               /* AST LOCKED */
426           call thread$cin (move_astep, sst.ausedp (fixed (move_astep -> aste.ptsi, 2)));
427                                                             /* put ASTE back the way we found it. */
428           move_astep -> aste.pack_ovfl = "0"b;
429           move_astep -> aste.nqsw = old_nqsw;
430           call search_ast$hash_in (move_astep);
431           call release_pvtxs;
432           call lock$unlock_ast;                             /* AST UNLOCKED */
433           call cleanup_dseg_and_meter;
434           a_code = code;
435 %page;
436 
437 
438 MOVE_THE_SEGMENT:
439      procedure;
440           dcl     astes                  (2) pointer;
441           dcl     px                     fixed bin;
442 
443           code = 0;
444           call lock$lock_ast;                               /* *** AST LOCKED *** */
445 
446           do px = 1, 2;                                     /* old and new */
447                astep, astes (px) = get_aste (size_needed);
448                if astes (px) = null ()
449                then do;
450                          code = error_table_$log_vol_full;  /* lie */
451                          go to retake_fault;
452                     end;
453 
454                call thread$out (astep, sst.ausedp (fixed (astep -> aste.ptsi, 2)));
455                                                             /* Thread out on 1 BEFORE getting 2. */
456           end;
457           astep = null ();
458 
459           call lock$unlock_ast;                             /* seg is now protected from deactivation */
460 
461           astes (1) -> aste.nqsw, astes (1) -> aste.gtms, astes (1) -> aste.gtus = "1"b;
462           astes (2) -> aste.nqsw, astes (2) -> aste.gtms, astes (2) -> aste.gtus = "1"b;
463           astes (2) -> aste.pvtx = new_pvtx;                /* for pc_check_tables_ */
464 
465 /**** depolist, n_nulled_pages, pageno_list describe the addresses from
466       the old vtoce. */
467 
468           n_nulled_pages = 0;
469           depolist = ""b;
470           pageno_list = 0;
471           code = 0;
472 
473           call pc$segmove (move_astep, astes (1), astes (2), new_pvtx, new_vtocx, n_nulled_pages, dlp, addr (pageno_list),
474                code);
475 
476 /**** + Debug
477       call syserr$error_code (ANNOUNCE, code, "sgm: new_pvtx ^d new_vtocx ^o n_to_deposit ^d.", new_pvtx, new_vtocx, n_nulled_pages);
478 */
479 
480           call lock$lock_ast;                               /* pc returns unlocked. */
481           if code ^= 0
482           then do;
483                     call put_aste (astes (1));
484                     astes (1) = null;
485                     call put_aste (astes (2));
486                     astes (2) = null ();
487                     call lock$unlock_ast;
488                     if code = error_table_$log_vol_full     /* try another pv */
489                     then do;
490                               call release_pvtxs;           /* free ptvx/pvid binding */
491                               go to next_pv;
492                          end;
493                     else go to move_fails;                  /* fatal error */
494                end;
495 
496           call thread$cin (move_astep, sst.ausedp (fixed (move_astep -> aste.ptsi, 2)));
497                                                             /* Okay, it goes back into replacement. Since move_fails and next_pv both expect it out, we delay this call to here. */
498 
499           move_astep -> aste.pack_ovfl = "0"b;              /* as good as it will ever be */
500           move_astep -> aste.nqsw = old_nqsw;
501           call search_ast$hash_in (move_astep);
502 
503           do astep = astes (1), astes (2);
504                call put_aste (astep);
505           end;
506 
507           astep, astes (1), astes (2) = null;
508 
509           call lock$unlock_ast;                             /* *** AST UNLOCKED *** */
510           ep -> entry.pvid = pvid;                          /* Make directory point right */
511           ep -> entry.vtocx = new_vtocx;                    /* Both these must complete */
512           if ep -> entry.dirsw
513           then do;
514                     dp = baseptr (segno);
515                     dp -> dir.vtocx = new_vtocx;
516                     dp -> dir.pvid = pvid;
517                     call sum$dirmod (dp);
518                end;
519           else call sum$dirmod (setwordno (ep, 0));         /* Since this walks up, the above call includes this call */
520           call release_old_vtoce;
521 
522      end MOVE_THE_SEGMENT;
523 %page;
524 
525 cleanup_dseg_and_meter:
526      procedure;
527 
528           if cleanup_must_zero_sdw
529           then do;
530                     tsdw = 0;
531                     call pmut$swap_sdw (baseptr (segno), addr (tsdw));
532                                                             /* remove our SDW for this */
533                end;
534           call usage_values (pw2, time2);                   /* meter */
535           sstp -> sst.sgm_time = sstp -> sst.sgm_time + time2 - time1;
536           sstp -> sst.sgm_pf = sstp -> sst.sgm_pf + pw2 - pw1;
537 
538      end cleanup_dseg_and_meter;
539 
540 
541 diskname:
542      proc (pvtx1) returns (char (9));
543           dcl     pic99                  pic "99";
544           dcl     pvtx1                  fixed bin;
545 
546           pvtep = addr (pvt_array (pvtx1));
547           pic99 = pvte.logical_area_number;
548           if ^pvte.is_sv
549           then return (pvte.devname || "_" || pic99);
550           else return (pvte.devname || "_" || pic99 || pvte.sv_name);
551 
552      end diskname;
553 
554 
555 release_old_vtoce:
556      procedure;
557           call dbm_man$set_incr (old_pvtx, old_vtocx, ignore);
558           call vtoc_man$free_vtoce (old_pvid, old_pvtx, old_vtocx, code);
559           if code = 0
560           then call truncator (old_pvid, old_pvtx, old_vtocx);
561           else do;
562                     call syserr$error_code (0, code, "segment_mover: freeing vtocx ^o on old pvtx ^o", old_vtocx,
563                          old_pvtx);
564                     pvt_array (old_pvtx).vol_trouble_count = pvt_array (old_pvtx).vol_trouble_count + 1;
565                end;
566 
567      end release_old_vtoce;
568 
569 
570 release_pvtxs:
571      proc;
572           call get_pvtx$release_pvtx (old_pvid, old_pvtx);
573           if held_pvtx
574           then call get_pvtx$release_pvtx (new_pvid, new_pvtx);
575 
576      end release_pvtxs;
577 
578 
579 /**** Procedure to release the records from the old vtoce. */
580 
581 truncator:
582      procedure (a_pvid, a_pvtx, a_vtocx);
583 
584           dcl     (a_pvtx, a_vtocx)      fixed bin;
585           dcl     a_pvid                 bit (36) aligned;
586 
587           call vtoc_man$await_vtoce (a_pvid, a_pvtx, a_vtocx, code);
588                                                             /* make sure the free "took". */
589           if code = 0
590           then call pc$deposit_list (a_pvtx, n_nulled_pages, dlp, a_vtocx, addr (pageno_list));
591           else do;
592                     call syserr$error_code (0, code, "segment_mover: finishing truncation of pvtx ^o vtocx ^o.", a_pvtx,
593                          a_vtocx);
594                     pvt_array (a_pvtx).vol_trouble_count = pvt_array (a_pvtx).vol_trouble_count + 1;
595                end;
596 
597      end truncator;
598 
599 
600 
601 /* format: off */
602 %page; %include aste;
603 %page; %include add_type;
604 %page; %include dir_entry;
605 %include dir_header;
606 
607 %include dir_name;
608 %page; %include pvte;
609 %page; %include lvt;
610 %page; %include sst;
611 %page; %include tq_info;
612 %page; %include quota_cell;
613 %page; %include syserr_constants;
614 %page;
615 
616 /* BEGIN MESSAGE DOCUMENTATION
617 
618    Message:
619    segment_mover: critical segment out of disk on DRIVENAME, segno/astep = sss/aaa
620 
621    S: $info
622 
623    T: $run
624 
625    M: There are no more free pages on the physical volume where a critical
626    segment resides, and an extra page can not be found for that segment.
627    Such a critical segment may be a physical buffer segment for a
628    peripheral device attached via IOI.
629    The user process receives a seg_fault_error signal.
630 
631    A: The logical volume containing the pack residing on DRIVENAME
632    may be too full, or may need rebalancing with the sweep_pv tool.
633    $notify_sa
634 
635    Message:
636    segment_mover: get_pvtx (PPP) fails under ast lock
637 
638    S: $crash
639 
640    T: $run
641 
642    M: The segment mover found that a physical volume appears to have been
643    demounted during the time that the segment mover has had the active segment
644    table locked. $err
645 
646    A: $recover
647 
648    Message:
649    segment_mover: unexpected segfault
650 
651    S: $crash
652 
653    T: $run
654 
655    M: A segment fault occured during the cross-pack moving of a segment, but
656    this segment fault was not on the segment on which the segment mover was
657    expecting one. $err
658 
659    A: $recover
660    There may be inconsistencies in the physical volumes involved. These can
661    be corrected by a physical volume salvage.
662 
663    Message:
664    segment_mover: freeing vtocx VVV on new pvtx PPP. ERRORMESSAGE
665 
666    S: $info
667 
668    T: $run
669 
670    M: The segment mover encountered an unexpected error in freeing
671    the VTOC entry of a segment being moved on a volume to which an abortive
672    attempt to move the segment was made.
673    This may be a physical device error.
674 
675    A: $inform
676 
677    Message:
678    segment_mover: threading error
679 
680    S: $crash
681 
682    T: $run
683 
684    M: The segment mover encountered bad threads while rethreading the old or new AST entries
685    of  a segment involved in a cross-pack segment move.
686    $err
687 
688    A: $recover
689 
690    Message:
691    segment_mover: freeing vtocx VVV on old pvtx PPP ERRORMESSAGE
692 
693    S: $info
694 
695    T: $run
696 
697    M: During a cross-pack segment move, the system encountered an unexpected
698    error in freeing the VTOC entry of the segment on the old pack
699    This may be a physical device error, or
700    may be indicative of a logic problem in the supervisor, or main memory or
701    CPU problems.
702 
703    A: $inform
704 
705    Message:
706    segment_mover: Moved UUUU(ENTRYNAME) from DRIVENAME1 to DRIVENAME2 for USERNAME
707 
708    S: $log
709 
710    T: $run
711 
712    M: The system has successfully moved a segment from the pack
713    on DRIVENAME1 to the pack on DRIVENAME2, on a request for a new page on
714    behalf of the user whose process group ID is USERNAME. UUUU is the
715    unique ID of the segment, and ENTRYNAME its primary name.
716 
717    A: If a large number of these messages occur, the logical volume containing
718    the packs specified by the drive names may be nearly full or
719    poorly balanced. If these messages persist, contact the system
720    administrator.
721 
722    Message:
723    segment_mover: Failed to seg move UUU(ENTRYNAME) from DRIVENAME1 to DRIVENAME2 for USERNAME
724 
725    S: $log
726 
727    T: $run
728 
729    M: The system could not perform a cross-pack segment move because no pack
730    in the logical volume had enough space to hold the segment. UUUU is the
731    unique ID of the segment, and ENTRYNAME its primary name.
732 
733    A: If this message persists, the logical volume containing the packs
734    on the drives noted is near full. In this case, contact the system
735    administrator.
736 
737    Message:
738    segment_mover: finishing truncation of pvtx PPP vtocx VVV
739 
740    S: $info
741 
742    T: $run
743 
744    M: The segment mover encountered an unexpected error in truncating
745    either the old copy of a segment being moved cross-packs or in
746    a new copy which was aborted for lack of space. This may be a physical
747    device error, or may be indicative of a logic problem in the
748    supervisor, or may be symptomatic of main memory or CPU problems.
749 
750    A: $inform
751 
752    Message:
753    segment_mover: Moving QUOTA-TYPE quota account from pvtx PPP, vtocx VVV
754    ERRORMESSAGE
755 
756    S: $log
757 
758    T: $run
759 
760    M: An error code was returned from the entry vtoc_attributes$get_quota when attempting to
761    get terminal quota information from the old vtoce before new vtoce is created. In this case
762    the terminal quota attributes for this QUOTA-TYPE  (either segment or directory) quota account
763    is lost.
764 
765    A: If this occurs, the quota account for the segment that has been moved must be corrected
766    manually by the System Administrator or other qualified site personell.
767 
768 
769    END MESSAGE DOCUMENTATION */
770 
771 
772      end segment_mover;