Device Naming Briefing Book JCH 9-Oct-1996 Mods by Glenn C. Everhart, May 1997 1. Documents, module identification, edit history, SCT notes, etc. STAR:: DOCD$:[EVMS.PROJECT_DOCUMENTS]PS-SCSI-NAMING.PS STAR:: DOCD$:[EVMS.PROJECT_DOCUMENTS]IR-SCSI-NAMING.PS STAR:: DOCD$:[EVMS.PROJECT_DOCUMENTS]FS-SCSI-NAMING.PS STAR:: DOCD$:[EVMS.PROJECT_DOCUMENTS]PP-SCSI-NAMING.PS At the end you will find a section listing all modules affected by naming. On the masterpack these are readily identified by edit history comments starting with JCH710. Subsequent edits to the same module carry suffix letters a,b,c, etc., as in JCH710a. The following SCT files list all changes approved for checkin: GRYPHON REDHAWK Alpha EVMS::SCT-GRYPHON EVMS::SCT-REDHAWK VAX STAR::SCT-GRYPHON STAR::SCT-REDHAWK Note SCT-REDHAWK is really a synonym for the standard remedial stream notesfiles, but the ONLY entries *I* have ever made in either SCT-REDHAWK conference are for REDHAWK, never any other remedial stream. (REDHAWK is discussed in its own section below). 2. Facilities with nontrivial changes 2.1 [IOGEN] The main purpose behind the IOGEN changes was to make sure we got the right allocation class in the DDB being created. I way underestimated the details involved. Pre-naming, it was quite easy -- a single allocation class was associated with a node. This assumption found its way into a large number of modules and we may not yet have discovered them all. With new naming this is not the case, and IOGEN was the first place this cropped up. 2.1.1 LOAD_DRIVER 2.1.1.1 A new itemlist entry was added to SYS$LOAD_DRIVER to define a port allocation class: IOGEN$_ALLOCLS. This itemlist entry, useful only for function code IOGEN$_CONNECT, passes the address of a longword which is supposed to contain the port allocation class or -1 to indicate the device does not have a port allocation class ("PAC"). The "-1 option" is there so that itemlists can be built statically and then have the PAC value filled in at runtime. The idea is that whoever calls SYS$LOAD_DRIVER fills in the PAC if there is one. IOGEN-CONNECT will store the PAC and set DDB$V_PAC in the process of initializing the DDB. Currently only IOGEN-SCSI-CONFIG and INIT_IO_DB use IOGEN$_ALLOCLS. Whoever loads the DVDRIVER ought to learn to use it as well. DRDRIVER could also benefit from this. Maybe others, too. >> I modified this to set the 20000000 (hex) bit in the allocation class as a flag for load_driver that the allocation class is from a device controller, not from a PAC. The idea again is to ensure that the DDB gets created with the right allocation class for cases where an HSZ supplies one. In this case the PAC bit is NOT set however, since unlike the case of a port allocation class, a port might have some allocation class for whatever reason and have its allocation class overridden. However I do NOT allow for a device allocation class of zero; the code will not work unless the device allocation class is positive and greater than zero. It is up to the customer to see that it is unique. 2.1.1.2 More recently a hack change was added to get the right allocation class if someone was invoking LOAD_DRIVER via SYSMAN> CONNECT DKAn:, which bypasses the call from IOGEN-SCSI-CONFIG and therefore didn't set the PAC for the device, even if another node in the cluster did. The hack change checked the function code for IOGEN$_CONNECT and if so, checked the device name and if it was 'DK' or 'MK' did a "behind your back" check to see if the device was on a port with a port allocation class. If so, the hack hoked up the necessary magic to make it look like the caller supplied the right PAC. Maybe we should do this for DR/DV as well. In the sysman io connect case, additional processing was added to issue a SCSI INQUIRY to the port and ID being used to load a device controller allocation class if any was present, and to pass this along if appropriate. Here too, the device controller (HSZ) allocation class is intended to override normal allocation classes or PACs. 2.1.2 IOGEN-UTILS 2.1.2.1 Straightforward code in IOGEN$CLASS_MATCH tells you if a given device has a port allocation class. Pass it the device name and address of an output variable. You get the output variable set to -1 or the PAC. 2.1.2.2 Lots of changes in routine IOGEN$SEARCH to look for an allocation class (never needed to, before) and find the SB and DDB that correspond to the device. The DDB may not exist (return DDB=0) or the SB may not exist. When given a PAC for a device, things get more complicated. If PAC>0 you have to fold the controller letter to "A". For any PAC you have to set flag IOC$M_CLASS to indicate it needs to match allocation classes. There is a mountain of comments in the code to explain how the device name is transformed and copied around (figuring *I* would have to maintain the code years later, I was careful to leave plenty of clues). 2.1.2.4 A whole pile of code, more than I ever dreamed would be necessary, to take out a lock on a PAC. A lock is needed to ensure PACs are unique to a given SCSI bus. You don't want two nodes to assign the same nonzero PAC to different SCSI buses that are not connected, so you take out what I call a "class lock". We'll get to how they're used in a minute. The following steps are taken when a PAC is assigned to a device: 1. An EX-mode lock is requested on IOGEN$_, e.g., IOGEN$_300 2. The lock ID is stored in DDB$L_CLASS_LKID. We don't care if we really have the lock or not. If we don't have the lock but instead a pending request, we store a pointer to a pool structure instead of the lock ID in DDB$L_CLASS_LKID. The pool structure serves as a place for the Lock Manager to store status and lock ID. Steps 1,2 are handled in a bunch of routines named IOGEN$CLASS_LOCK* called when the device is configured. SYSINIT will take out the class lock for the system device since it is configured before any locking is available. Finally if nonzero, SYSINIT also takes out a "class lock" on the node's disk and tape allocation classes. You can't have a SCSI bus have the same allocation class as another node, or you could have a naming conflict. The lock in question needs to be a "permanent" lock, not one that goes away when the image (STACONFIG, SYSMAN) exits. It thus has to be a system-owned lock. But step 3 below demands contention for the resource and system-owned locks cannot exist in contention -- they can only be NL. So this set of routines IOGEN$CLASS_LOCK* was written to use the lock manager fork interface, where you can create locks in any mode, granted or waiting, and have them live beyond the life of a process. This is how system context would use the Lock Manager. Trouble is, we're in process context in IOGEN$SHARE\SYS$LOAD_DRIVER so there's a fair amount of shell-game work that goes on to get the calls made correctly. *** And sometimes this doesn't work! See bug list below. *** 3. The list of folks contending for the lock form a clique. Routine [CLUSTER]SCCPUVER\CHECK_SCSI_CPU, called from routine IOGEN$SCSI_CONFIG obtains the CSID of each member of the clique via $GETLKI function LKI$_LOCKS. The CSID is translated into an SCSSYSTEMID with appropriate backoffs at higher levels in case of a cluster transition in the middle of all this. 4. SCCPUVER verifies each member is either (a) us, or (b) another node who is sharing the bus corresponding to the DDB, by having made their SCSSYSTEMID and PAC available to us via SCSI INQUIRY command. If there is a member of the clique who is neither (a) nor (b), SCCPUVER does a bit of waiting on possible clutrans but eventually halts the booting system with a helpful error message. >> No need to hack with locks for HSZ derived allo classes here; everyone who can get to the device should get the same result. 2.1.3 IOGEN-CONNECT If a device has a PAC, IOGEN-CONNECT\CREATE_DDB will store the PAC in the DDB if one has just been created, and set flag bit DDB$L_PAC. Originally I thought I'd be doing a lot of the work here, but actually it's too late. Once you get to CREATE_DDB you've scanned the I/O database for the right SB/device name/Allocls. So you can't change any of those at this point! >> Here added code to allow for an allocls coming from the LDDB that did not have the PAC bit on. 2.1.4 IOGEN-SCSI-CONFIG The control flow is --> sys$load_driver --> --> iogen$scsi_config ... where is usually STACONFIG or SYSMAN and refers to ICBM and other IOGEN code that I've not touched. 2.1.4.1 When configuring a SCSI port, the application gets the port allocation class and passes it to $LOAD_DRIVER, who probes the bus. 2.1.4.2 When a CPU is found on the bus we call SCCPUVER\CPU$CHECK_INQUIRY to see if the remote CPU shares our reality. 2.1.4.3 When logging devices during configuration, have IOGEN$LOG output the new name. >> Arranged to save HSZ alloc classes and transmit them to load_driver if present, plus high bits set to tell load_driver this is NOT a PAC case. 2.2 [SCSI] 2.2.1 DK/TK/GKDRIVER 2.2.1.1 These drivers use the controller letter to determine which bus to "connect" to, basically by subtracting 'A' from the controller letter. If we fold the controller letter to 'A' for nonzero PACs then we need to provide a hook to get the original controller letter back. The original controller letter is stored in DDB$L_PORT_ID when IOGEN-UTILS folds to 'A'. So the change to the class drivers is simple: if DDB$V_PAC then get controller letter from field DDB$L_PORT_ID, else from DDB$T_NAME+2. 2.2.1.2 Copy the device TCQ bit into UCB$Q_DEVDEPEND2 bit 24, where SYSINIT can get at it in order to verify that multihost system disks support TCQ. 2.2.2 PKxDRIVER Some SCSI port drivers support shared SCSI buses, not all do. Those that do need to support the SCSI INQUIRY command, which returns information about the node to a remote initiator. New naming uses a new format SCSI INQUIRY response message to pass the PAC and SCSSYSTEMID for later use in SCCPUVER. Various port drivers (PKE/PKS/PKT/PKQ) were modified to do this. 2.3 [SYS] 2.3.1 PAC_UTILS New module, written in C, to perform various needed functions. A major function is to read the SYS$DEVICES.DAT mapping file into memory, and point cell IOC$GL_PACLIST_F to the mapping. The entire SYS$DEVICES.DAT file is thus in memory permanently once INIT_IO_DB causes it to be read in. Use [IOGEN]IOGEN-UTILS\IOGEN$CLASS_MATCH to access the list. I had to write my own implementation of sscanf() to parse SYS$DEVICES.DAT since the CSPL project decided it wasn't worth their time. It's a private entry point in PAC_UTILS.C. 2.3.2 INIT_IO_DB 2.3.2.1 Calls PAC_UTILS\IOC$GOPAC to read in SYS$DEVICES.DAT and store the parsed list of ports and PACs. Then calls IOGEN$CLASS_MATCH to see if the boot device has a PAC and passes the result to SYS$LOAD_DRIVER to create the boot device I/O database structures. 2.3.2.2 Hack alert! The boot device is named Dxxxx and the port allocation class check in IOGEN$CLASS_MATCH is against the port name, which is of the form Pxxxx. Before calling IOGEN$CLASS_MATCH() the 'D' is changed to a 'P' so the port is checked, not the class. There was some talk about fixing this with an architected interface to FBC but I don't think that happened. You would present the device name to FBC and it would return the corresponding port name. But I think Cathy Fariz left before we got that working, so the boot port name is inferred from the boot device name. 2.3.2.3 If booting via LAN, get the system device allocation class out of the BTADP and store it in the system disk DDB. Also set a variable for use by INIT, below. 2.3.2.4 If booting via LAN or from a DDB with a nonzero PAC, set flag for INIT to use as explained below. 2.3.2.5 I don't know what happens if you boot via LAN, thereby inheriting the allocation class from your server, and then specify a different PAC in SYS$DEVICES.DAT. I've never tried this. 2.3.3 INIT 2.3.3.1 From 2.3.2.4, create the *initial* logical name translations of SYS$DISK and SYS$SYSDEVICE to have $nnn$ddcu: format instead of node$ddcu: format if MOP booting or the boot DDB has the PAC bit set and the boot device allocation class is nonzero. WARNING: It took several tries to get this working right; it's currently possible for customers to boot from a DSSI disk with a different allocation class than the booting CPU. In this case the I/O database is not yet set up correctly and the $dssi$ddcu: format will not work, only the node$ddcu: format. 2.3.3.2 (VAX ONLY) If LAN boot, store the system device allocation class in the system disk DDB. 2.3.4 IOSUBNPAG 2.3.4.1 Output formatting: in the case of a device with a nonzero PAC (local or served) the device name formatting routines substitute the allocation class format for the nodename format. That is, instead of seeing NODE$DKA200: you would see $81$DKA200: if the device had PAC 81. This works for both local node PACs and MSCP served PACs. Section 2.7.1.1 describes how to determine if you have an MSCP served PAC; if it's a local device you just check DDB$V_PAC. $GETDVI inherits this behavior. 2.3.4.2 Device searching: Warning! This section is tricky. IOC$SEARCH used to believe there was only one allocation class per SB and so, e.g., if it saw a different allocation class it knew it could just quit and not scan the SB any further. Not only that, some code (particularly IOGEN) would at times count on getting back pointers even on a failed search, so that when creating new DDBs it would have a DDB after which to link the new DDB. Additionally, people (and .COM files) were used to typing in, e.g., DKA200 and getting a particular unit. With new naming you could have many devices named DKA200 but ideally you would like the user to get the same DKA200 that was returned before going to new naming. So several search control bits were added. These are outlined in gory detail in the edit history for IOSUBNPAG and will not be repeated here. The thing to make note of is that when a device is not found you can't just leave registers with 0 in them, you have to make another pass over the database and return pointers that would have been returned previously. 2.3.4.3 Permit allocation classes to be as large as 32767 by editing routine GETNUMBER. 2.3.5 ERRORLOG Changed to format disk and tape (DT$_DISK, DT$_TAPE) devices as $nn$ddcu: A question I have is -- why format the device name here? Why not call IOC$CVT_DEVNAM like everybody else? 2.4 [SYSBOOT] 2.4.1 SYSGENCMD When built into SYSBOOT, processes SET/CLASS command to interactively define PACs. A list of devices/classes is ultimately stored in pool in a block pointed to by IOC$GL_PACLIST_B. IOGEN$CLASS_MATCH consults this list for a match before consulting the "file-based" list IOC$GL_PACLIST_F. 2.4.2 SYSBOOT Copy the list created by SET/CLASS to its nonpaged pool destination once nonpaged pool exists. 2.5 [SYSINI] 2.5.1 SYSINIT 2.5.1.1 Calls UPDATE_PACFILE to write out a new device mapping file SYS$DEVICES.DAT if anything was defined via a SYSBOOT>SET /CLASS command. Merges existing SYS$DEVICES.DAT with any SYSBOOT-based definitions. In case of conflict, SYSBOOT definition wins. 2.5.1.2 Takes out class lock (see 2.1.2.4) for the system disk once we are in a cluster, and the node's disk and tape allocation classes. See section 2.1.2.4 for details. 2.5.2 UPDATE_PACFILE Code to implement 2.5.1.1. 2.6 [MSCP] 2.6.1 MSCP/TMSCP 2.6.1.1 Pre-naming code would not serve disks with different allocation class from node allocation class. New code will do so if the allocation class is a PAC, by checking DDB$V_PAC. An extra check (see 2.6.1.4) ensures we're offering a device to a remote client who is prepared to deal with the fact that the allocation class is not the same as the server node's. 2.6.1.2 Observation: DDB$V_PAC is only defined on the host system where the drive exists. At the other end of the connection the device will NOT have bit DDB$V_PAC set in its DDB. Thus, the remote system will know not to serve the disk, as the above check will then fail. 2.6.1.3 It is up to the MSCP server to invent a clusterwide unique unit ID for each disk. This ID goes in the MSCP message packets and ultimately will find its way into DU/TUDRIVER UCBs. The unit ID is a quadword, unchanged from years ago, of the form: +-------------------+ | Allocation Class | +---------+---------+ | Ctrlnam | Unit | +---------+---------+ Where you have a standard longword allocation class, word unit number and compressed controller name (e.g. 'DKA') where each byte is compressed into 5 bits by subtracting (ASCII 'A')-1 from each character, leaving an integer in the range 1-26, thus fitting into 5 bits per byte. This uses the low 15 bits of the high word of the unit ID. As far as I know the highest bit is not defined and always 0. 2.6.1.4 When an SCS Connect message comes in, MSCP makes a note if the remote node (i.e., DUDRIVER, TUDRIVER) says it understands new naming. If so, the server marks the HQB with a bit saying "Host Understands New Naming". Each device is similarly marked if it uses new naming, by checking the PAC bit and setting a UQB status bit. When deciding to offer a device to a remote node, the server makes sure the right combination of HQB/UQB bits exists, so that old nodes do not get told about new names. This means you can run whatever versions of VMS you like without confusing your old versions. Of course, a node running an old version can't access a device with a new name, but CAN continue to access devices that don't have new names. 2.6.1.5 A client indicates it understands new naming by setting byte 14 of the SCS Connect data to something other than a blank. 2.6.2 ADDUNIT Permit serving of devices with port allocation classes. 2.7 [DRIVER] The term "MSCP server" refers to a VMS MSCP server, as does the simple term "served disk". I explicitly use the term "controller" when referring to non-VMS-MSCP-served devices, such as those offered by HSC50s, HSJ40s, and all those other hardware products. 2.7.1 DU/TUDRIVER, DUTUSUBS I can't describe the code changes any better than the module comments. The basic idea was to make sure the DDB allocation class gets set correctly from the MSCP message. Routine FIND_DDB creates DDBs if they don't already exist, so it had to be edited to deal with allocation classes from messages. It is important to realize what doesn't work, and how to deal with those tricky situations. 2.7.1.1 A useful thing to know is how to identify the case of a served PAC. Here's how: see if CDDB$B_CTRLMDL is equal to CDDB$K_EMULA (symbols may not be right). If not, it's not a served disk (i.e., is controller served) and the answer is no. If it is a served disk then you can pick up the allocation class from the first longword of UCB$Q_UNIT_ID and compare it to CDDB$L_ALLOCLS. If different, the device is a served PAC, else not. You can't always depend on DDB$L_ALLOCLS because a lot of the code that is executed is either initialization or failover code and the DDB may not be defined at the time, for example if we're re-linking the UCB into a different DDB chain. Of course, whenever you have a calm, normal system the DDB will accurately reflect the allocation class and for served disks will match the UCB allocation class value in UCB$Q_UNIT_ID. 2.7.1.2 There's a word field UCB$W_MSCP_UNIT that has the sign bit set if the device is MSCP served, with the rest of the word being the SLUN. This is another case of \caveat coder/. UCB$W_MSCP_UNIT is only valid under normal operating conditions. During initialization or failover you can't count on it being accurate. The simple reason being that you may have a device failing over from a served to a direct controller path or vice versa, and the UCB has to be rewired to match the new path. And you can have failover in the midst of failover so there's just no way to guarantee the UCB fields are correct when you need to get at them. Once again, the right way to go is to look at the CDDB and see if the controller model is CDDB$K_EMULA. 2.7.1.3 DU/TUDRIVER used to believe the CDDB allocation class matched the DDB allocation class and the two could be used interchangeably. All that had to change, and a lot of those changes were in DUTU$FIND_DDB and code that called it. 2.7.1.4 DU/TUDRIVER were both changed per section 2.6.1.5 to indicate they were able to handle new naming. 2.7.1.5 DU/TUDRIVER failover of served PAC devices has been well tested and I believe it works fine. But because of the way failover happens it is a requirement that failover is constrained to happen between nodes with the same node, I say NODE allocation class. You know, CLU$GB_ALLOCLS a.k.a. SYSGEN parameter ALLOCLS. This is because DUTU failover is driven by CDDB$L_ALLOCLS comparisons and I didn't want to try to shoehorn in something bigger. Of course you need to have the PORT allocation classes match too, but you also have to have NODE allocation classes match in order to do failover. 2.8 [LAA] 2.8.1 NISCS_LAA Used to assume it was sufficient to use NODE$DKA0: to denote a device. Prior to being fixed, the code parsed the controller part of the name (i.e., the "DK" above) by scanning for a "$" and then picking up the alpha characters that follow. It's doing this so it can build an MSCP unit ID quadword as described in 2.6.1.3 and used throughout DUDRIVER. This quadword becomes the value of LAPL$K_MSCP_SLUN and gets stored in the BTADP of the downloaded system. Anyhow, if the device is a PAC device with nonzero allocation class then NISCS_LAA will find itself with a name of the form _$58$DKA0: and when it scans for the "$" it finds the _first_ "$" and gets some mighty strange results for LAPL$K_MSCP_SLUN. Regrettably, no error messages were forthcoming. Instead, the remote booting node found itself very confused and was unable to maintain an SCS connection, forever finding it just didn't know who to talk to. This was loads of fun to debug. The change to NISCS_LAA and LANACP_DLL, below, is to bypasses any initial "_$" or just "$" and THEN starts scanning for "$". Note to Croll: another case of the 1-character controller letter limitation. 2.9 [LAN] 2.9.1 LANACP_DLL Same comments as 2.8.1, NISCS_LAA. 2.10 [BOOTDRIVER] 2.10.1 NISCA_BTDRIVER 2.10.1.1 Changed per section 2.6.1.5 to indicate it was able to handle new naming. 2.11 [SDA] 2.11.1 SDADEVICE for Alpha was changed by Richard Bishop to output allocation classes as longwords. JCH made the VAX changes. 2.12 [CLIUTL] 2.12.1 SETDEVICE was changed to allow serving port allocation classes. 2.13 [CLUSTER] 2.13.1 SCCPUVER Module SCCPUVER was added to do verification work when another CPU was found while scanning a SCSI bus. This used to be done only in STACONFIG but SCCPUVER is called from IOGEN so that *any* time a bus is probed and a new CPU found, we verify it is playing by the naming rules. SCCPUVER routines are called from IOGEN$SCSI_CONFIG(). 2.13.2 STACONFIG Removed SCSI CPU checking, adding it to SCCPUVER. 2.13.3 STACONFIG_TMSCP Permit serving of tapes with port allocation classes 2.14 [MANAGE] 2.14.1 CLUSTER_CONFIG[_LAN].COM Changed to allow interactive mode for defining port allocation classes. This code is the property of the Clusters group and was done there. 2.15 [LEC] (VAX ONLY) 2.15.1 PEBTDRIVER (VAX ONLY) 2.15.1.1 Changed per section 2.6.1.5 to indicate it was able to handle new naming. 3. REDHAWK REDHAWK is a 6.2/7.1 compatibility kit mostly for MOUNT and SHADOWING. Naming ("SCSI96") functionality was backported so that MSCP client nodes could access new-named disks. If you are running mixed 7.1/6.2 clusters, you can install REDHAWK on your 6.2 nodes and it will be able to access new-named devices created on the 7.1 node(s). You cannot create new-named devices under 6.2, just access those that are MSCP served from 7.1 nodes. 3.1 The DU/TUDRIVER code was moved wholesale 3.2 NISCA_BTDRIVER was "ported" 3.3 The changes to IOSUBNPAG were retrofitted to V6.2 3.4 SDADEVICE changes were done by JCH 3.5 ERRORLOG needed no editing (VAX or Alpha), just INSERT GENned from 7.1 3.6 INIT was changed so on a LAN boot the correct allocation class got stored in the system disk DDB (VAX) and set up the correct initial definitions for SYS$DISK and SYS$SYSDEVICE 4. Bug List: Pending Work 4.1 CDDB: In IOSUBNPAG we currently check @UCB$L_CDDB for all devices, even if the device doesn't have a CDDB pointer -- UCB$L_CDDB is defined only for disk and tape devices, but the code is executed for all devices. Basically this is a rotten implementation of 2.6.1.5. This [bug-]check is only made for devices with nonzero non-port allocation classes, and may be benign. 4.2 Boot Delay: With nonzero PACs sometimes a boot delay is observed. Refer to section 2.1.2.4. The call to the Lock Manager is not returning a lock ID, nor lock status, sometimes. The locks appear to be queued so the SCCPUVER\CHECK_SCSI_CPU tests appear to be performed (nobody has actually run a qual test on this, but the locks are enqueued and -sometimes- the DDB$L_CLASS_LKID is set up OK) but (a) there is a peceptible delay added to boot time, mostly in IOGEN$CLUTRAN_WAIT, (b) it is possible this code really isn't working and (c) why the heck isn't the Lock Manager working? I believe this to be due to trying to take out a lock while a cluster is being formed. Originally I thought SYSMAN AUTOCONFIGURE, being part of STARTUP, would be executed wayyy after cluster formation. This much is true, but AUTOCONFIGURE (therefore IOGEN$CLASS_LOCK) is also called by STACONFIG -before- cluster formation. Oops. When writing the class lock code I knew I couldn't take out the system disk class lock from inside IOGEN since the system disk was being configured before EXEC_INIT loaded the Lock Manager. So I had SYSINIT do that since SYSINIT had a convenient hook where we knew we had finished cluster initialization. Perhaps SYSINIT should be drafted to help out more. If I had another week to fix this delay problem/bug I'd probably have the IOGEN locking code take out the class lock for ALL devices configured at that time. Something along the lines of: (a) Take out the I/O database mutex (b) Take out the SCS spinlock (c) See if we've formed a cluster (d) If we're in a cluster, go ahead with locking as is done today (e) If we're not [yet] in a cluster, attempt no locking (f) Drop the SCS spinlock (g) Release the I/O database mutex As done today the locking is via IPL8 calls, not system service requests, so there is no problem doing this while holding the SCS spinlock and the I/O database mutex. Then I'd also modify SYSINIT, where it takes out the system disk class lock, to: (a) Take out the I/O database mutex (b) Scan the DDB chain off the local SB looking for DDBs with DDB$V_PAC set (c) For any such DDB, enqueue the class lock for the DDB (d) At the end of the DDB chain, release the I/O database mutex (e) From exec mode, call CLU$CHECK_SCSI_CPU for each DDB found in step (c). It's OK to call CLU$CHECK_SCSI_CPU multiple times for the same DDB, so no synchronization is required here. This looks like a race-free way to ensure that all PAC DDBs get their allocation class locks taken out, after the cluster has formed, and that the checking code gets called. It's not that difficult to do, either, since you're basically just calling existing routines. The rest of the week would be spent in getting the code reviewed and writing SCT notes :-) 4.3 User-friendly parsing PAC_UTILS permits either of the following in SYS$DEVICES.DAT: [Port GOLEM2$PKA] [Port GOLEM2$PKA0] ... but it does not permit [Port GOLEM2$PKA0:] ... which happened in ZKO testing when somebody manually edited his own SYS$DEVICES.DAT file. Note that PAC_UTILS is required to use its own somewhat limited version of sscanf() so the code to handle this is maybe a bit more than a cakewalk. But it's probably worth doing sometime. 4.4 Free PACs for DR/DV At the end of 2.1.1.2 is a proposal to automagically check DR and DV devices to see if they were assigned port allocation classes in SYS$DEVICES.DAT, and configure them correctly if so. One or two lines of code -- but is it the right thing to do? 5. Module list 5.1 Alpha 5.1.1 GRYPHON [APB]BOOT_MSGS [BOOTDRIVER]NISCA_BTDRIVER [CLIUTL]SETDEVICE [CLUSTER]SCCPUVER [CLUSTER]STACONFIG [CLUSTER]STACONFIG_TMSCP [DRIVER]DUDRIVER [DRIVER]DUTUSUBS [DRIVER]LOGGING_DUDRIVER [DRIVER]LOGGING_DUTUSUBS [DRIVER]LOGGING_TUDRIVER [DRIVER]TUDRIVER [IOGEN]INIT_IOGEN-CONNECT [IOGEN]INIT_IOGEN-UTILS [IOGEN]INIT_LOAD_DRIVER [IOGEN]IOGEN-CONNECT [IOGEN]IOGEN-SCSI-CONFIG [IOGEN]IOGEN-UTILS [IOGEN]LOAD_DRIVER [LAA]NISCS_LAA [LAN]LANACP_DLL [MSCP]ADDUNIT [MSCP]LOGGING_MSCP [MSCP]LOGGING_TMSCP [MSCP]MSCP [MSCP]TMSCP [SCSI]DKDRIVER [SCSI]GKDRIVER [SCSI]MKDRIVER [SCSI]PKEDRIVER [SCSI]PKSDRIVER [SCSI]PKTDRIVER [SDA]SYSDEF [SYS]INIT [SYS]INIT_IO_DB [SYS]IOSUBNPAG [SYS]IOSUBNPAG_MON [SYS]PAC_UTILS [SYS]PARAMETER [SYS]SYSPARAM [SYS]SYSPARAM_MASK [SYS]SYSTEM_DATA_CELLS [SYS]SYSTEM_DATA_CELLS_MASK [SYSBOOT]SYSBOOCMD [SYSBOOT]SYSBOOT [SYSBOOT]SYSGENCMD [SYSINI]LOCKDN [SYSINI]SYSINIT [SYSINI]UPDATE_PACFILE [XSYSGEN]PARAMETER [XSYSGEN]SYSPARAM [ZSYSGEN]PARAMETER [ZSYSGEN]SYSPARAM 5.1.2 REDHAWK [SDA]DEVICE.MAR [SYS]ERRORLOG.MAR [SYS]INIT.MAR [SYS]INIT_IO_DB.MAR [SYS]IOSUBNPAG.MAR [LAA]NISCS_LAA.B32 [LAN]LANACP_DLL.CXX [BOOTDRIVER]NISCA_BTDRIVER.MAR 5.2 VAX 5.2.1 GRYPHON [DRIVER]DUDRIVER [DRIVER]DUTUSUBS [DRIVER]LOGGING_DUDRIVER [DRIVER]LOGGING_DUTUSUBS [DRIVER]LOGGING_TUDRIVER [DRIVER]TUDRIVER [LEC]PEBTDRIVR [SDA]DEVICE [SYS]ERRORLOG [SYS]INIT [SYS]IOSUBNPAG 5.2.2 REDHAWK [SDA]DEVICE.MAR [SYS]ERRORLOG.MAR [SYS]INIT.MAR [SYS]SYSASM.DAT [SYS]IOSUBNPAG.MAR [LEC]PEBTDRIVR.MAR