MVS TOOLS AND TRICKS OF THE TRADE December 1995 Sam Golob MVS Systems Programmer sbgolob@cbttape.org Sam Golob is a Senior Systems Programmer KEEPING UP WITH THE UNIT CONTROL BLOCK - PART 1 What do most of us work on? Often the answer is: "what needs fixing". I once opened a service call to IBM Level 2. We were having trouble with a certain module. The problem was a known problem, and the technician gave me a clear answer to it. Then I mentioned the name of another module to her. She had never heard of that one, even though it was closely related to the one which needed fixing. I think the reason why she had never heard of it, was because it hadn't been changed in ten years. I had heard of it, because I had fitted an enhancement zap to it. There was no way an IBM technician could have known about that zap. The moral of the story is: System components that don't have problems, usually don't get people's attention. This is why we have conversion notebooks. When a new version of the operating system comes out, people want to know what has changed. What still works, is often of no concern to them. I really don't blame anyone for that attitude. The operating system is so big, that most of us don't have time to care about what is working properly. Our job is to keep the computer center running. The problems and changes alone will normally keep us busy enough. This month, I'd like to focus on an operating system area which has recently changed quite a bit, and therefore we have to adjust to the consequences. This is the topic of the UCB, or Unit Control Block. The Unit Control Block describes a physical peripheral device, and contains all the necessary information for the device to be used in performing I/O requests. On old systems, the UCB's used to be statically generated during system generation, and the collection of UCB's, representing all peripheral devices known to the MVS system, was a fixed block of storage in the Nucleus area. With the recent introduction of Dynamic I/O reconfigurations, Dynamic UCB's and four-digit unit addresses (instead of three digits), some user programs and tools which used to work, have stopped doing their job. Therefore they have to be fixed. The question is, by whom? We, who have maintained user-written code for years, have an answer. If a program was not written by IBM or by some other vendor, there is no one "official" to call. If the original source was on a public tape, such as the CBT MVS Utilities Tape, or the NaSPA VIP tape, one can try and call the original author, or the proprietor of the tape. If possible, a user who considers this program important, should fix it. Then, that person can send the updated program to the proprietor of the public tape where the source is kept. After the tape gets updated with the new source, everyone else will benefit from having a version of the program which now works. In such a way, the job of fixing all the affected programs gets divided among a number of people. Today, I'd like to talk about what's involved in handling the Dynamic UCB situation. There are quite a few new topics, and it will take two installments. Also, several different types of code changes will have to be discussed. By the end, I hope you'll have a good feel for what needs to be done, and we'll all have a better handle on getting some of our old tools to work in this "era of Dynamic UCBs". FUNDAMENTALS. IBM, in response to many customer suggestions, is trying to make more system resources dynamically modifiable. In our day and age, when numerous computer operations have to be up 24 hours a day, 7 days a week, system "down" time for IPL's is very scarce. For as many system parameters as possible, we'd like to employ an operator command to change them "on the fly", instead of requiring an IPL. Internally, coding-wise, what is involved in such a change? To explain matters, I want to use a relatively simple example I happen to know about. The JES2 Remote Destination Table (or RDT) is a list of remote connections in JES2, and it also includes destination addresses which can be referred to by the DEST JCL parameter or a DEST keyword in a TSO command. The RDT used to be modifiable only by a JES2 WARM start, which meant an IPL. In JES2 version 4.1, the ability to add and delete connection and destination addresses (with $ADD and $DELETE commands) was introduced. This involved the complete restructuring of the physical layout of RDT table entries. Formerly, the destination table entries were created in one big block of storage at JES2 startup time. The table was searched by starting at the beginning of its storage, and bumping through it sequentially, entry by entry. This can't work in a dynamic situation where you could add or delete new entries at will. Where would there be space to put an "unlimited" quantity of new table entries? Now that the RDT was made dynamic, this is how it has been restructured. When a new RDT is built, a 4K block of storage is GETMAINed and marked with a header saying that this will be storage for RDT table entries. Header fields are created to show how full the block of storage is. Then the new table entries are built in this block of storage and are all logically chained to each other, beginning from the first entry. To locate the beginning of the table, the address of the first entry is put into a known JES2 control block when the table was initially created, usually at startup time. Every time we run out of storage for RDT entries, a new 4K block of storage is GETMAINed, headed, and filled with new entries chained from the previous ones. Since the $DELETE command is also supported, we sometimes have a need to "zero out" some entries, re-chain the remaining ones to each other, and reuse the newly freed space. In a large JES2 network, it may come out that RDT table entries in a chain might jump from one 4K block to another 4K block and back again, many times. Clearly, a sequential search will not do the job any more, and old programs or JES2 exits which search the RDT that way, will no longer work. The search algorithm must be rewritten to start at the first record, and then follow the chain of record addresses until you find the entry that you want. I've used the RDT illustration to make things easier to see. The UCB situation is more complicated and hidden, but most of its principles are similar. JES2, which owns the RDT, has much of its source code accessible to us. The base operating system code and IOS, which deal with the UCB, have mostly OCO (Object Code Only) modules, and we can't easily observe what those components are actually doing. To deal with UCB issues, IBM has provided us with Macro access to most of the services. Since these services have been changing between MVS releases recently, the MVS Conversion Notebook manuals are an excellent source for finding out what to do. UCB STRUCTURE CONSIDERATIONS. There are two issues with which we have to deal here. One is the actual structure of the UCB, and how it is changing. The other is how to search for and obtain information from the particular UCB's which represent physical devices that we are interested in. The mapping macro for a UCB is called IEFUCBOB, which is found in SYS1.MACLIB. This macro will describe the structure of every type of UCB in detail. Optionally, IEFUCBOB can limit itself to describing only UCBs of a certain device type. The allowable device types are: DASD (disk) devices, magnetic tape devices, unit record devices, communications equipment, CTC's, and graphics devices. Serious UCB restructuring began at the MVS/ESA 4.1.0 level. A previous drastic change also occurred at the time MVS/XA was first introduced. Therefore, it is worth discussing how an assembler program can determine the system level it is operating under. The CVT (Communications Vector Table) which is the backbone of MVS control blocks, contains an old field, CVTDCB, which is used to determine the level of OS that is running. In addition, at the ESA levels and (in future) above, there is another field called CVTOSLVL, which reserves no less than 16 bytes of bit flags, so that IBM will "never in the future" have any trouble telling you which level of the operating system is currently operating. For an MVS/XA system, the CVTDCB field is set to X'93'. For an MVS/ESA system, CVTDCB is set to X'9B'. The extra bit X'08' indicates that the CVTOSLVL area is present and may be referenced. See the CVT mapping macro in SYS1.MACLIB at your system's level for further details. If you are on an MVS/ESA system, the X'08' bit called CVTUCBSV in flag CVTOSLV0, indicating system level HBB4410 or above, will show that the new UCB macro services are now available and ready for use. The actual structure of the UCB storage area(s) is determined by whether MVSCP is used to create the I/O configuration of the system, or HCD and IODF are. MVSCP is the old way. HCD, the Hardware Configuration Dialog, which is used to build an I/O Definition File or IODF, is the new way. At the MVS/ESA Version 5 level, you don't have a choice any more. MVSCP no longer works, and you have to use HCD. If MVSCP is used to define the I/O configuration, then the UCB's reside in member IOSUCBxx of SYS1.NUCLEUS, where xx is the identifier of the designated I/O configuration. The UCB's are created and initialized by the MVSCP and are loaded into the Nucleus region (below the 16 Meg line) during IPL. If HCD is used to build an IODF to represent the I/O configuration, then the UCB's are built in SQA during the IPL. In this latter case, they do not have to be contiguous, and everything we said before about dynamically modifiable control block chains, can now apply. The UCB itself consists of a prefix, a Common Segment, and various device-dependent segments. There are also various extensions nowadays. In the older systems, the UCB segments were physically contiguous, but IBM no longer guarantees that. It is for such reasons, that the only recommended way of searching and scanning UCB's is through the IBM-supplied macro services. UCB SEARCHING AND SCANNING. We'll conclude this installment with an overview of some new UCB searching and scanning services. This will deal with the issue of how to find the UCB's you want, even in this new environment, when some or all of the UCB's may be dynamic. Next time, we hope to show more of the details of how to convert existing programs to use the new scanning and searching methods. Two principal macros which concern us are UCBLOOK and UCBSCAN, both of which may be found in SYS1.MACLIB. UCBLOOK is used to obtain the UCB common segment address of a given device number or a given volume serial. UCBSCAN is used to scan UCB's. The following types of scans are supported: All UCB's, or all UCB's within a particular device class. Remember that we spoke about device classes before. They may be, for example, DASD devices, tape devices, unit record devices, and the like. In a given UCB scan, we may restrict the scan further. Permissible restrictions are: Only report static (non-dynamic) UCB's, only report 3-digit device addresses (excluding the new 4-digit addresses), specify the device number from which the scan should begin. In the dynamic UCB environment, there are several more concepts which need mentioning. If we're looking at a UCB, what can we do to prevent it from disappearing during an I/O configuration change? Secondly, if we are in the middle of conducting a UCB scan operation, how can we detect that an I/O configuration change has been started, potentially upsetting and invalidating much of what we're looking at? In answer to the first question, the concept of fixing or "pinning" the UCB was invented. The UCBLOOK macro has the capability of optionally pinning the UCB, or preventing its deletion if we're looking at it during a configuration change. There is another macro which is specific to this purpose, called UCBPIN. The UCBPIN macro, also in SYS1.MACLIB, can be used either to pin or "unpin" a UCB when it needs to be fixed or freed. Any system component can pin a UCB. In order for a pinned UCB to be freed, it must be specifically unpinned, using the UCBPIN macro. In answer to the second question, the concept of an IOC Token was invented. This token seems to be essentially a "configuration change identification number". The current I/O configuration's token may be discovered through the IOCINFO service, which is invoked by the IOCINFO macro. Both the UCBLOOK and UCBSCAN macros may be invoked using the IOCTOKEN keyword. This allows the UCB lookup or scan to verify that a configuration change has not occurred recently. We first obtain the current I/O configuration's token using the IOCINFO macro, which returns the token value into a 48-byte storage field, obtained for our program's use. Then, the UCBLOOK or UCBSCAN IOCTOKEN keyword is pointed to this token field. If UCBSCAN gets a return code of 12 in Register 15, this is an indicator that a configuration change has occurred. So far, we have discussed many of the new concepts involved in the recent UCB changes. The picture is by no means complete as yet, but this much is probably enough for one sitting. Next time, I hope to continue this topic with more practical application. Good luck. We'll see you then.