This Multics source file was rescued from the messed-up source archive at MIT.
This is the piece of segment control that makes an AST entry for a segment and brings its page table into core.
This hardcore module ends with a special comment that starts with "BEGIN MESSAGE DOCUMENTATION." A program was run over the hardcore source to extract and process these comments into a manual that explained each message the system could produce on the operator's console. This manual was regenerated for each release.
Back to Multics Source index.
activate.pl1 11/19/82 1530.9r w 11/19/82 1528.6 13113 /* *********************************************************** * * * Copyright, (C) Honeywell Information Systems Inc., 1982 * * * * Copyright (c) 1972 by Massachusetts Institute of * * Technology and Honeywell Information Systems, Inc. * * * *********************************************************** */ /* astep = activate (branchp, code) FUNCTION - This procedure activates the segment whose branch is pointed to by the input argument "branchp", and it returns the aste pointer for that segment. In order to activate the segment this procedure activates any superior directory that happens to be inactive. If the operation is successful, the return occurs with the following state: astep ^= null, code = 0 and AST is locked. It is the responsability of the caller to unlock the AST whenever it is appropriate. If the operation fails, the return occurs with the following state: astep = null, code ^= 0 and AST is unlocked. MODIFICATIONS - 10/26/82 by J. Bongiovanni for synchronized segments, filemap checksum 7/10/82 by J. Bongiovanni to read entire VTOCE 3/7/82 by J. Bongiovanni for new PVTE 12/25/81 by Benson I. Margulies to not depend on the directory read lock as protection against activations. 5/31/81 by J. Bongiovanni to validate fields in VTOCE 03/21/81, W. Olin Sibert, for ADP PTWs and SDWs, and get_ptrs_$given_sdw 02/81 by E. N. Kittlitz for activate_long entry 04/77 by THVV for damaged sw and messages 8/76 by D. Vinograd to add entry for activating without parent being active. This entry, backup_activate, is used only by the volume dumper. 09/13/76 by Greenberg to meter activations and fixe demount window error reporting 03/25/76 by R. Bratt to fix gtpd bug and add explicit user deactive capability 04/08/75 by Andre Bensoussan. This procedure has been completely rewritten for the new storage system. */ %page; activate: proc (branchp, code) returns (ptr); dcl branchp ptr, /* Input - branch pointer */ a_vtocep ptr, a_pvtx fixed bin, a_vtocx fixed bin, a_activated_sw bit (1) aligned, code fixed bin (35); /* Output - error code */ dcl (par_astep, par_sdwp) ptr; dcl (i, pts, ptsi, pvtx, vtocx, esw) fixed bin (17); dcl (uid, pvid, temp) bit (36) aligned; dcl old_par_ehs bit (1); dcl already_active_by_backup bit (1); dcl dirsw bit (1); dcl parts bit (3); dcl long_sw bit (1) aligned; dcl 1 local_vtoce like vtoce aligned; dcl 1 par_aste like aste aligned based (par_astep); dcl checksum bit (36) aligned; dcl p99 pic "99"; dcl normal fixed bin internal static init (1); dcl backup fixed bin internal static init (2); dcl dseg$ (0 : 1023) fixed bin (71) external static; dcl error_table_$synch_seg_limit fixed bin (35) ext; dcl error_table_$vtoce_connection_fail fixed bin (35) ext; dcl error_table_$pvid_not_found ext fixed bin (35); dcl error_table_$illegal_activation fixed bin (35) ext; dcl error_table_$invalid_vtoce fixed bin (35) ext; dcl error_table_$dm_not_enabled fixed bin (35) ext; dcl pc$fill_page_table entry (ptr, ptr, fixed bin); dcl get_aste entry (fixed bin) returns (ptr); dcl get_aste$synchronized entry (fixed bin) returns (ptr); dcl lock$lock_ast entry; dcl lock$unlock_ast entry; dcl search_ast entry (bit (36) aligned) returns (ptr); dcl search_ast$hash_in entry (ptr); dcl get_pvtx entry (bit (36) aligned, fixed bin (35)) returns (fixed bin); dcl vtoc_man$get_vtoce entry (bit (36) aligned, fixed bin, fixed bin, bit (3), ptr, fixed bin (35)); dcl get_ptrs_$given_sdw entry (pointer) returns (pointer); dcl filemap_checksum_ entry (ptr, fixed bin, bit (36) aligned); dcl sdw_util_$get_valid entry (pointer) returns (bit (1) aligned); dcl trace entry options (variable); dcl syserr entry options (variable); dcl syserr$binary entry options (variable); dcl (addr, baseno, bin, convert, dim, divide, fixed, null, ptr, rel, reverse, substr, verify) builtin; /* */ long_sw = "0"b; goto START; /* activate_long is the same as activate, except that extra information is returned to the caller. */ activate_long: entry (branchp, a_activated_sw, code) returns (ptr); long_sw = "1"b; a_activated_sw = "0"b; START: ep = branchp; dp = ptr (ep, 0); uid = entry.uid; pvid = entry.pvid; vtocx = entry.vtocx; dirsw = entry.dirsw; temp_entry_name = addr (ep -> entry.primary_name) -> names.name; pvtx = get_pvtx (pvid, code); if code ^= 0 then return (null); esw = normal; COMMON: code = 0; already_active_by_backup = "0"b; sstp = addr (sst_seg$); pvt_arrayp = addr (pvt$array); pvtep = addr (pvt_array (pvtx)); call lock$lock_ast; /**** before multi-read directory locks, the directory lock was sufficient to protect against another processor making an activation. Thus the code below could unlock the AST, do VTOC I/O, and lock the AST, secure in the knowledge that nobody else was going to do the same thing while it was waiting for the I/O. This had the additional side effect of locking out any directory accesses for the duration. Now, the AST hash table is searched a second time after the AST is relocked after the VTOC I/O. If the uid is found, the code go-to's to ACTIVATED_BY_SOMEONE_ELSE to rejoin the same sequence that it would have taken had the segment been active to begin with. Under the new locking strategy, a program that wishes to protect against activations in a directory MUST HOLD A WRITE LOCK ON THAT DIRECTORY, or some higher lock. ****/ astep = search_ast (uid); if astep ^= null then ACTIVATED_BY_SOMEONE_ELSE: do; if (aste.pvtx ^= pvtx) | (aste.vtocx ^= vtocx) then do; call syserr (LOG, "activate: double uid ^w. vtocx ^o on ^a. vtocx ^o on ^a", uid, vtocx, pvte.devname || "_" || convert (p99, pvte.logical_area_number), aste.vtocx, pvt_array (aste.pvtx).devname || "_" || convert (p99, pvt_array (aste.pvtx).logical_area_number)); code = error_table_$vtoce_connection_fail; ret_ulast: call lock$unlock_ast; return (null); end; if aste.par_astep ^= "0"b | aste.uid = (36)"1"b then return (astep); /* the normal case */ already_active_by_backup = "1"b; /* set switch */ end; if esw = normal then do; if ^already_active_by_backup then do; call lock$unlock_ast; vtocep = addr (local_vtoce); call vtoc_man$get_vtoce (pvid, pvtx, vtocx, "111"b, vtocep, code); if code ^= 0 then return (null); if vtoce.uid ^= uid then code = error_table_$vtoce_connection_fail; else if vtoce.dirsw ^= dirsw | vtoce.deciduous then do; code = error_table_$vtoce_connection_fail; call syserr (LOG, "activate: error on ^[deciduous ^]^[dir ^]^a", vtoce.deciduous, vtoce.dirsw, temp_entry_name); end; else code = 0; if code ^= 0 then return (null); call lock$lock_ast; /* now check to make sure it hasn't been activated while we were VTOCE reading */ astep = search_ast (uid); if astep ^= null then go to ACTIVATED_BY_SOMEONE_ELSE; end; par_sdwp = addr (dseg$ (fixed (baseno (dp), 18))); /* ptr to parent sdw */ do while (sdw_util_$get_valid (par_sdwp) = "0"b); /* If parent active */ call lock$unlock_ast; /* Unlock the global lock */ temp = dp -> dir.uid; /* Cause a segfault on parent dir */ call lock$lock_ast; /* relock */ end; if (pvte.pvid ^= pvid) | pvte.being_demounted then do; code = error_table_$pvid_not_found; /* Check demount with AST locked */ go to ret_ulast; end; par_astep = get_ptrs_$given_sdw (par_sdwp); old_par_ehs = par_aste.ehs; /* Save old ehs on parent */ par_aste.ehs = "1"b; /* Do not let son deactivate his father */ if already_active_by_backup then do; aste.par_astep = rel (par_astep); /* set parent astep */ aste.infl = par_aste.infp; par_aste.infp = rel (astep); aste.per_process = par_aste.per_process; par_aste.ehs = old_par_ehs; return (astep); /* not that hard */ end; end; /* validate some fields in the VTOCE which could really kill us if they're bogus */ if fixed (vtoce.records) > fixed (vtoce.csl) | fixed (vtoce.csl) > fixed (vtoce.msl) | fixed (vtoce.msl) > dim (vtoce.fm, 1) then do; code = error_table_$invalid_vtoce; goto ret_ulast; end; /* checksum the file map */ if vtoce.fm_checksum_valid & (sst.checksum_filemap ^= 0) & ^vtoce.fm_damaged then do; call filemap_checksum_ (addr (vtoce.fm), fixed (vtoce.csl, 9), checksum); if vtoce.fm_checksum ^= checksum then do; segdamage.pvid = pvte.pvid; segdamage.lvid = pvte.lvid; segdamage.uid = vtoce.uid; segdamage.vtocx = vtocx; segdamage.pno = -1; segdamage.uid_path = vtoce.uid_path; call syserr$binary (LOG, addr (segdamage), SB_vtoc_salv_dam, SBL_vtoc_salv_dam, "activate: Setting damaged switch on ^a at ^o (^a). Filemap damaged.", vtoce.primary_name, vtocx, pvte.devname || "_" || convert (p99, pvte.logical_area_number)); vtoce.damaged = "1"b; vtoce.fm_damaged = "1"b; sst.damaged_ct = sst.damaged_ct + 1; pvte.vol_trouble_count = pvte.vol_trouble_count + 1; end; end; if ^vtoce.synchronized then do; /* Normal case */ astep = get_aste (fixed (vtoce.csl)); if astep = null() then do; code = error_table_$illegal_activation; goto ret_ulast; end; end; else do; /* Synchronized segment */ if ^sst.dm_enabled then do; /* No journal */ code = error_table_$dm_not_enabled; goto ret_ulast; end; astep = get_aste$synchronized (fixed (vtoce.csl)); if astep = null () then do; code = error_table_$synch_seg_limit; goto ret_ulast; end; end; if esw = normal then do; if astep = par_astep then call syserr (CRASH, "activate: activating into father ^p", astep); par_aste.ehs = old_par_ehs; /* aste.fp, aste.bp = have been set by get_aste or deactivate */ aste.infl = par_aste.infp; par_aste.infp = rel (astep); aste.par_astep = rel (par_astep); aste.per_process = par_aste.per_process; /* Inherit this one */ end; /* aste.uid = uid; */ /* dont fill in now -protect against shutdown */ aste.msl = vtoce.msl; aste.pvtx = pvtx; aste.vtocx = vtocx; aste.usedf = "1"b; aste.gtus = "1"b; aste.gtms = "1"b; aste.explicit_deact_ok = "1"b; aste.dnzp = vtoce.dnzp; aste.damaged = vtoce.damaged; aste.fm_damaged = vtoce.fm_damaged; aste.synchronized = vtoce.synchronized; aste.nqsw = vtoce.nqsw; aste.dirsw = vtoce.dirsw; aste.dtu = vtoce.dtu; aste.dtm = vtoce.dtm; aste.csl = vtoce.csl; aste.nid = vtoce.nid; aste.records = vtoce.records; sst.activations = sst.activations + 1; if esw = backup then sst.backup_activations = sst.backup_activations + 1; if long_sw then a_activated_sw = "1"b; /* indicate activation occured */ if dirsw then do; aste.master_dir = vtoce.master_dir; aste.quota = vtoce.quota; aste.used = vtoce.used; aste.tqsw (0) = vtoce.received (0) ^= 0 | vtoce.master_dir; aste.tqsw (1) = vtoce.received (1) ^= 0; sst.dir_activations = sst.dir_activations + 1; end; else seg_aste.usage = seg_vtoce.usage; /* Segments have no quota. keep pf count */ call pc$fill_page_table (astep, addr (vtoce.fm), fixed (vtoce.csl)); /* fill in page table */ aste.uid = uid; /* aste is stable now */ call search_ast$hash_in (astep); nm_astep = astep; %include make_sstnt_entry; return (astep); /* return a pointer to the new AST entry */ /* */ backup_activate: entry (a_vtocep, a_vtocx, a_pvtx, code) returns (ptr); esw = backup; long_sw = "0"b; vtocep = a_vtocep; pvtx = a_pvtx; vtocx = a_vtocx; uid = vtoce.uid; /* set local variables */ dirsw = vtoce.dirsw; temp_entry_name = vtoce.primary_name; goto COMMON; /* with multiple entries you have to have one label */ %page; %include aste; %page; %include dir_entry; %page; %include dir_header; %page; %include dir_name; %page; %include pvte; %page; %include segdamage_msg; %page; %include sst; %page; %include sstnt; %page; %include syserr_binary_def; %page; %include syserr_constants; %page; %include vtoce; %page; /* BEGIN MESSAGE DOCUMENTATION Message: activate: double uid UUUU. vtocx N on dskX_MM. vtocx P on dskY_QQ. S: $log T: $run M: A mismatch has been detected between the branch and the ASTE for a segment. The two segments indicated by VTOCE index and physical volume name claim to have the same file system unique identifier. A connection failure is returned to the user process. This message is logged for the use of system programmers. This error can occur if damage to a directory branch has caused its unique ID to become incorrect, and if the incorrect unique ID happens to be identical to the unique ID of a segment already active. A: $inform Message: activate: error on (deciduous) (dir) NAME S: $log T: $run M: An attempt has been made to activate a deciduous segment, or to activate a segment when the VTOCE's directory switch did not match the branch. A connection failure is returned to the user process. This information is logged for the use of system programmers. A: $ignore Message: activate: activating into father PPPP S: $crash T: $run M: The AST entry pointer returned by get_aste is identical to the AST entry pointer for the parent of the segment being activated. $err $crashes A: $recover Message: activate: Setting damaged switch on NAME at VTOCX (dskX_NN). Filemap damaged. S: $log T: $run M: The segment's File Map in the VTOCE had an invalid checksum, which indicates likely damage to the File Map. The segment is marked as damaged. It is possible that there is other damage on the physical volume due to invalid or reused disk addresses. The count of volume inconsistencies is incremented by 1. A: Examine the VTOCE for damage using dump_vtoce. If other damage is evident, delete it using hp_delete_vtoce -clear and recover the segment. Run the physical volume scavenger as soon as possible to detect and correct other damage on the physical volume. END MESSAGE DOCUMENTATION */ end activate;
"This material is presented to ensure dissemination of scholarly and technical work. Copyright and all rights therein are retained by authors or by other copyright holders. All persons copying this information are expected to adhere to the terms and constraints invoked by each author's copyright. In most cases, these works may not be reposted without the explicit permission of the copyright holder."