MVS TOOLS AND TRICKS OF THE TRADE July 1989 Sam Golob MVS Systems Programmer THE AMAZING EXCP-COUNT ZAP This monthly column is for sharing practical advice and techniques which can be employed in your shop. We hope to provide stimulating discussion and help to as large a group of MVS systems programmers as possible. As many of you already know, this column depends largely on you, the reading public, for contributions and ideas. We greatly appreciate calls and messages from interested readers who will ask me to write about some favorite trick or method of theirs. Just send an email to me at sbgolob@cbttape.org. Please include your phone number. A word about software tools. This column is task oriented. In other words, the idea is to learn how to get a job done. Whatever software tool will work, is fine. We have tried, however, to make all of the techniques as accessible to as many people as possible, REGARDLESS OF BUDGET. For that reason, we refer to the many quality public-domain offerings available on the Connecticut Bank and Trust MVS Tape (known as the CBT Tape) and the NaSPA V.I.P. MVS tapes. To obtain the CBT tape materials (which contains HUNDREDS of software packages), go online to www.cbttape.org. Our topic this month concerns an amazing addition to the MVS operating system. Read on, and find out about some wonderful records that are kept by the system. We need only encourage MVS to give these figures out and show them to us onlookers. * * * * * * * * * * * * * * * * * * * * Nearly every computer user who runs a job wants to know what his job DID. If it read files and produced reports, and everything looks good, it probably did what it was supposed to. But you can't say much more than that. Very often you don't KNOW more than that. Trust the machine? We all have to, but it would be better if the machine would tell us more. There is one way to get the machine to tell you quite a bit more. We'll show how to make it tell you about its file I/O activity. For FREE. File I/O in IBM/370 architecture is done by "executing channel programs" (EXCP for short). This means that the "channels", which can be viewed as connectors between the CPU and peripheral devices, are instructed (or programmed) how to transmit data between the computer itself and the connected device. With each execution of a channel program, a burst of data is read from or written to a file. EXCP is the "rock bottom" of File I/O, in the same sense as MACHINE INSTRUCTIONS are the "rock bottom" of program execution in a CPU. You can write a program in a higher-level language, such as COBOL or PL/1, but before it can be run, it must be converted (or "compiled") into machine instructions. It is the machine instructions which actually RUN. Same with File I/O. You can tell the machine using ACCESS METHODS such as QSAM, BSAM, or VSAM, what you want it to do with files, such as reading or writing data in a certain format. But the "access method source" instructions cannot do any transfer of the data itself, just as COBOL SOURCE statements cannot tell a CPU what to do. The "access methods" must first convert your I/O orders into EXCP before any data transfers can be done. The data transfer machinery only understands EXCP; it does not understand "access method source" instructions directly. Counting the NUMBER OF TIMES a channel program was executed to a particular file gives some indication of how much file I/O activity there was. This measure of file activity is called EXCP COUNTS. EXCP counts may not express exact quantification of data transfer, because the data may be transferred in many little bursts, resulting in a high count, or in a few large bursts, resulting in a low count. Very good indications can be supplied to the programmer who knows how his program works. The counts can give him, and others, a very good feel for what is happening during the execution of the program. Sometimes it is sufficient to know if there was any I/O activity at all. A number of vendor products are available to supply this kind of information for your jobs. I personally haven't done a survey of them because I have a FREE means of providing the data, which is probably better than all of these products. We can actually CAUSE THE MVS OPERATING SYSTEM ITSELF to supply us with EXCP counts for EACH ALLOCATED DD NAME, right in the JCL allocation messages themselves! How can we accomplish this wonderful thing? First let me tell you what you'll get. If you're running MVS, you've all seen JCL allocation messages for files on your job printouts. They look like: IEF285I SYS1.LINKLIB KEPT IEF285I VOL SER NOS= MVSRES. After you've done our magic, you get: IEF285I SYS1.LINKLIB KEPT *----1,294 IEF285I VOL SER NOS= MVSRES. You get this for all allocated ddnames. On my system, I've even seen the counts on the SYSLOG from the very beginning of system initialization. MVS itself is made to provide them. You don't have to rely on SMF records, as many of the vendor packages do. I'll tell you how it's done. The system module which produces the IEF285I messages is called IEFAB4B0. On MVS/370, the module has not changed since base version 3.8. On MVS/XA, it has also not changed since the base level. This is how the counts are obtained. IEFAB4B0 is expanded to add a patch area at the end. Code is inserted into the patch area which obtains the counts and puts them into the IEF285I message. The code works as follows: It goes back into the module which CALLS IEFAB4B0 (its name is IEFAB4A2) by accessing the saved registers from the calling program. It is this calling program, IEFAB4A2, which has access to the DSAB control block that contains the EXCP-count information. The patched code in IEFAB4B0 uses ITS CALLER's REGISTERS and acts for a while as if it were really executing in the caller, IEFAB4A2. After the information is obtained, it is formatted and inserted into the IEF285I message. Cool! This is the concept. Now how can you install it? The code is on the Connecticut Bank and Trust MVS Mods Tape, (the CBT tape) FILE 369, and it was donated by Dick Sziede and his staff of the Planning Research Corporation at Dulles Airport in Virginia. Dick is running MVS/XA 2.2 in his shop. His old MVS/370 version is maintained by me, and that code is in file 369 also. (There are two XA versions. On recent CBT tapes is the one called LM01603, which works for XA through 2.2. The older XA version, called LM01602, was good through XA 2.1.7.) The zap is applied to module IEFAB4B0 (from load module IEFW21SD) in the form of an SMP USERMOD, but the USERMOD is generated in a very novel manner. Howard Gilbert of Yale University Computer Center, one of the geniuses of user-written MVS software, has a PL/1 program called ASMTOZAP, whose SOURCE is on file 369 of the CBT tape. (The LOAD MODULE is on FILE 035 of more recent versions of the CBT tape.) ASMTOZAP allows you to code SYSTEM ZAPS as if they were ASSEMBLER PROGRAMS. This is how ASMTOZAP works. Certain control statements are coded as comments in your assembler source code telling ASMTOZAP where to start the VER statements and where to start the REP statements. (You don't have to do this in the EXCP-count mod, because it is already done.) You assemble the source code (NO LINKEDIT please) and create a LISTING on a disk file. You then run the PL/1 program ASMTOZAP against the LISTING. In our case, it produces an already-coded SMP USERMOD, which has the zap in it. Now. After editing the generated USERMOD to your installation's taste, and APPLYing it, the LMOD, which is called IEFW21SD, is changed in LPALIB, and an IPL with CLPA will allow you to test the mod. ONE WARNING is in order. The calling mod IEFAB4A2 is sensitive to IBM maintenance. Whenever IEFAB4A2 is changed, you must look into the FICHE of the new PTF level for the field called DSABPTR. In my current version on MVS/370, this is at displacement +138 hex, into IEFAB4A2. This displacement must be hard-coded into your USERMOD. Notes in the assembler source will tell you where to code it. The displacement of the DSABPTR has been known to change with fairly recent modifications of IEFAB4A2, and you must check it with every change to that module. I safeguard myself by doing a UCLIN of my USERMOD NUMBER as a UMID to IEFAB4A2, even though IEFAB4A2 is not itself affected by applying the USERMOD. This gives me an ID check in SMP whenever maintenance hits this module. The other module IEFAB4B0 which has the zap in it, never has gotten maintenance to it. There are 3 versions of the mod, one for MVS/370, an early version for XA, and a later modification that covers all XA levels through XA 2.2. As for the XA versions, the one called LM01603 is the preferred one, and is necessary for 2.2. LM01603 can be found on file 369 of very recent versions of the CBT tape. LM01602 will work for those versions of XA previous to 2.2. The latest version for XA has been worked over at Planning Research Corp. to handle I/O counts to multi-volume disk datasets, whereas the MVS/370 one has not been so reworked. It is on my wish list to rework it. (The 370 version shows the I/O's to the last volume only.) The mod is still great, however. Just a final note. The USERMOD as supplied by file 369 has a linkedit EXPAND statement in it, which creates the patch area at the end of module IEFAB4B0. This EXPAND only has to be done once. In my shop, I separated the EXPAND into a separate USERMOD that PREs the actual zap. That way, if I have to repeat the APPLYing of the USERMOD, it won't keep expanding the size of the IEFAB4B0 module. You are referred to the figures which will show what this modification looks like, both in original assembler source and in generated zap form as it exists at my shop (for MVS/370. The MVS/XA level of the zap can be found on file 369 of the CBT tape.) Also included here is ASMTOZAP execution JCL. Good luck. Everyone in your shop will enjoy this mod! * * * * * * * * * * * * * * * * * * * * * FIGURE ONE: EXCP-COUNT SOURCE IN "ASMTOZAP" FORMAT. *------- TITLE LM02301...I/O COUNT IN MSG IEF285I *------- *------- AUTHOR LARRY KRAUSE...LITTON COMPUTER SERVICES 1978 *------- DICK SZIEDE....GENERAL ELECTRIC 1983 *------- *------- BACKGROUND AS FAR AS I KNOW,LARRY IS THE ONLY ONE TO *------- WRITE A MVS VERSION OF THIS MOD, ALTHOUGH IT *------- COMMON IN MVT (RICK DUVALL...CSC) AND SVS (AUTHOR *------- UNKNOWN). THIS VERSION HAS BEEN RECODED IN ASMTOZAP *------- FORMAT FOR MVS SP1.3, WITH SOME COSMETIC CHANGES. *------- ...DICK SZIEDE...CSC 1982. *------- MAKE WORK UNDER VS ASSEMBLER INSTEAD OF ASMH, AND *------- MORE COSMETIC CHANGES...DICK SZIEDE, GE 1983. *------- *ZAP CARD ++ USERMOD(LM02301) /* I.O COUNTS IN IEF285I */. *ZAP CARD ++ VER(Z038) FMID(EBB1102) PRE(JBB1326). *ZAP CARD ++ ZAP (IEFAB4B0). *ZAP CARD NAME IEFAB4B0 *ZAP CARD EXPAND IEFAB4B0(128) LM02301A CSECT IEFAB4B0 DS 0H PRINT ON,GEN,DATA ORG @PSTART USING *,@12 USING @DATD,@11 *ZAP START VER ORG CLRKEY STC @02,@OLDKEY ORG CLRTXT MVC MSGBUFFR+1(73),MSGBUFFR BLANK ENTIRE BUFFER ORG STEAL MVI MSGDISP+1,C' ' DISPLACED INSTRUCTION ORG @EL00001 IC @02,@OLDKEY ORG @SIZDATD DC AL1(230),AL3(@ENDATD-@DATD) ORG PATCH DC 4F'0' *ZAP START REP ORG CLRKEY STC @02,@NEWKEY ORG CLRTXT MVC MSGBUFFR+1(78),MSGBUFFR BLANK ENTIRE BUFFER ORG STEAL B PATCH MAINLINE EQU * ORG @EL00001 IC @02,@NEWKEY ORG @SIZDATD DC AL1(230),AL3(@NEWDATD-@DATD) ORG PATCH PATCHOUT MVI MSGLNGTH+3,79 SET MSGLNGTH TO 79 L @10,@PC00001 ADDR OF MSGID TM 0(@10),X'01' MSGID=1 ? BNO PATEXIT NO ==> WE EXIT. L @10,4(,@13) ADDR OF IEFAB4A2'S SAVE AREA L @10,X'3C'(,@10) IEFAB4A2'S R10 * ICM @10,15,X'13C'(@10) ADDR OF DSAB (IEFAB4A2 DSABPTR * LEVEL JBB1326) ICM @10,15,X'138'(@10) ADDR OF DSAB (IEFAB4A2 DSABPTR * LEVELS UZ75725 AND UZ84610) BZ PATEXIT EXIT IF NO DSAB L @10,DSABTIOT(,@10) ADDR OF TIOT ENTRY SLR @06,@06 CLEAR WORK REG CH @06,TIOPSTTB(,@10) IS THERE A UCB ENTRY IN TIOT? BZ PATEXIT NO ==> WE QUIT. L @01,@PC00001+16 ADDR OF JSCB PTR L @01,0(,@01) ADDR OF JSCB L @04,JSCBTCBP(,@01) ADDR OF INIT'S TCB L @01,JSCTMCOR(,@01) ADDR OF TIOT MGMT AREA S @10,X'18'(,@01) CALC TIOT ENTRY OFFSET ICM @04,15,TCBTCT(@04) ADDR OF TIMING CONTROL TABLE BZ PATEXIT EXIT IF NONE L @04,TCTIOTBL(,@04) ADDR OF TCT I/O TABLE LA @05,TCTDCBTD(,@04) ADDR OF 1ST DD LOOKUP TABLE ENTRY PATDDLOP CH @06,0(,@05) LAST ENTRY IS ZERO BZ PATEXIT EXIT IF ZERO. CH @10,0(,@05) DO THE TIOT DISPLACEMENTS MATCH? BE PATPRINT YES ==> PRINT I/O COUNT. LA @05,4(,@05) BUMP TO NEXT DD TABLE ENTRY B PATDDLOP SPACE PATPRINT AH @04,TCTIOTSD(,@05) OFFSET TO THE DEVICE ENTRY * (TCTDDENT OR TCBUCBP) L @06,TCTDCTR(,@04) GET THE I/O COUNT CVD @06,MSGDISP+1 INTO PACKED FORMAT MVC MSGCOUNT(L'EDMSK1),EDMSK1 PREPARE TO EDIT ED MSGCOUNT(L'EDMSK1),MSGDISP+5 STICK IN SOME COMMAS MVI MSGCOUNT,C'*' MARK WITH A SPLAT PATEXIT MVI MSGDISP+1,C' ' DISPLACED INSTRUCTION B MAINLINE * EDMSK1 DC X'60206B2020206B202120' *ZAP END @DATD DSECT ORG @DATD+X'48' @PC00001 DS 5F ORG @DATD+X'B4' MSGLNGTH DS F DS 2F MSGBUFFR DS C ORG @DATD+X'F7' MSGDISP DS X ORG @DATD+X'105' MSGCOUNT DS CL6 @OLDKEY DS AL1 @ENDATD EQU * ORG @DATD+X'120' @NEWKEY DS AL1 DS D ALIGN TO DUBBLEWORD FOR GETMAIN @NEWDATD EQU * SPACE LM02301A CSECT * ***** EQUATES FOR DSECTS I'M TOO LAZY TO DO THE DROPS * ***** 'N USINGS FOR. DSABTIOT EQU X'10' TIOPSTTB EQU X'12' JSCBTCBP EQU X'D0' ' JSCTMCOR EQU X'14C' ' TCBTCT EQU X'A4' TCTIOTBL EQU X'C' TCTDCBTD EQU X'8' TCTIOTSD EQU X'2' TCTDCTR EQU X'4' * * ***** EQUATES FOR LOCATIONS WITHIN IEFAB4B0 @PSTART EQU IEFAB4B0+X'1C' CLRKEY EQU IEFAB4B0+X'52' CLRTXT EQU IEFAB4B0+X'76' STEAL EQU IEFAB4B0+X'156' @EL00001 EQU IEFAB4B0+X'2EE' @SIZDATD EQU IEFAB4B0+X'3E8' PATCH EQU IEFAB4B0+X'45C' * ***** AND OF COURSE, THE REGISTERS @01 EQU 01 @02 EQU 02 @04 EQU 04 @05 EQU 05 @06 EQU 06 @10 EQU 10 @11 EQU 11 @12 EQU 12 @13 EQU 13 END * * * * * * * * * * * * * * * * * * * * * FIGURE TWO: "ASMTOZAP" PROGRAM - EXECUTION JCL. //TSTBDP2S JOB ,'TECH.SUPP-SAM.GOLOB',CLASS=M,NOTIFY=TSTBSSG, // MSGLEVEL=(1,1),MSGCLASS=T TYPRUN=HOLD //******************************************************************// //* ASMTOZAP EXECUTION - FILE 317 OF CBT254 TAPE *// //* FILE 044 OF CBT299 TAPE *// //* FILE 035 - LOAD MODULE *// //******************************************************************// //* //ASMTOZAP EXEC PGM=ASMTOZAP //SYSPRINT DD SYSOUT=* //PL1DUMP DD SYSOUT=* //IN DD DISP=SHR,DSN=TSTBSSG.NZPIO.ASM <=== ASSEMBLY LISTING //OUT DD DISP=SHR,DSN=TSTBSSG.NZPIO.ZAP, <=== ZAP FMT OUTPUT // DCB=(RECFM=FB,LRECL=80,BLKSIZE=800) //* * * * * * * * * * * * * * * * * * * * * * FIGURE THREE: EXCP-COUNT ZAP AS FOUND AT NEWSWEEK, INC. ++ USERMOD(NZPIO06) /* I.O COUNTS IN IEF285I */ . ++ VER(Z038) FMID(EBB1102) PRE(JBB1329 UZ84610 NZPIO05) SUP(NZPIO01 NZPIO02 NZPIO03 NZPIO04) /* DOCUMENTATION: S. GOLOB - NEWSWEEK INCORPORATED - 01/21/87 THIS USERMOD WAS INSTALLED FROM FILE 369 OF THE CBT254 MODS TAPE FOR MVS. IT WAS NOT CORRECT AS FOUND THERE BECAUSE OF AN INCORRECT DSAB POINTER (DSABPTR) IN MODULE IEFAB4A2, WHICH BELONGS TO FMID JBB1329 (MVS SP 1.3.3) AND IS ON OUR SYSTEM AT RMID UZ75725 (PUT TAPE 8409). THE OLD POINTER OF 013C NOW POINTS TO A DIFFERENT CONTROL BLOCK AND THE MOD WILL NOT WORK IF YOU HAVE THE WRONG OFFSET. NOTE: YOU MUST DO THE FOLLOWING UCLIN TO DISABLE IBM MAINTENANCE ON MODULE IEFAB4A2. THIS WILL FORCE AN ID CHECK. UCLIN CDS. REP MOD(IEFAB4A2) RMID(NZPIO06). ENDUCL. */ . ++ ZAP (IEFAB4B0). NAME IEFAB4B0 * ORG CLRKEY VER 0052 4220,B10B STC @02,@OLDKEY * ORG CLRTXT VER 0076 D248,B0C1,B0C0 MVC MSGBUFFR+1(73),MSGBUFFR BLANK ENTIRE BUFFER * ORG STEAL VER 0156 9240,B0F8 MVI MSGDISP+1,C' ' DISPLACED INSTRUCTION * ORG @EL00001 VER 02EE 4320,B10B IC @02,@OLDKEY * ORG @SIZDATD VER 03E8 E600,010C DC AL1(230),AL3(@ENDATD-@DATD) * ORG PATCH VER 045C 0000,0000,0000,0000 DC 4F'0' VER 0464 0000,0000,0000,0000 * ORG CLRKEY REP 0052 4220,B120 STC @02,@NEWKEY * ORG CLRTXT REP 0076 D24D,B0C1,B0C0 MVC MSGBUFFR+1(78),MSGBUFFR BLANK ENTIRE BUFFER * ORG STEAL REP 0156 47F0,C440 B PATCH * MAINLINE EQU * * ORG @EL00001 REP 02EE 4320,B120 IC @02,@NEWKEY * ORG @SIZDATD REP 03E8 E600,0130 DC AL1(230),AL3(@NEWDATD-@DATD) * ORG PATCH * PATCHOUT EQU * REP 045C 924F,B0B7 MVI MSGLNGTH+3,79 SET MSGLNGTH TO 79 REP 0460 58A0,B048 L @10,@PC00001 ADDR OF MSGID REP 0464 9101,A000 TM 0(@10),X'01' MSGID=1 ? REP 0468 47E0,C4C6 BNO PATEXIT NO ==> WE EXIT. REP 046C 58A0,D004 L @10,4(,@13) ADDR OF IEFAB4A2'S SAVE A REP 0470 58A0,A03C L @10,X'3C'(,@10) IEFAB4A2'S R10 REP 0474 BFAF,A138 ICM @10,15,X'138'(@10) ADDR OF DSAB (IEFAB4A2 DS * LEVEL JBB1329 RMID UZ75725) REP 0478 4780,C4C6 BZ PATEXIT EXIT IF NO DSAB REP 047C 58A0,A010 L @10,DSABTIOT(,@10) ADDR OF TIOT ENTRY REP 0480 1F66 SLR @06,@06 CLEAR WORK REG REP 0482 4960,A012 CH @06,TIOPSTTB(,@10) IS THERE A UCB ENTRY IN T REP 0486 4780,C4C6 BZ PATEXIT NO ==> WE QUIT. REP 048A 5810,B058 L @01,@PC00001+16 ADDR OF JSCB PTR REP 048E 5810,1000 L @01,0(,@01) ADDR OF JSCB REP 0492 5840,10D0 L @04,JSCBTCBP(,@01) ADDR OF INIT'S TCB REP 0496 5810,114C L @01,JSCTMCOR(,@01) ADDR OF TIOT MGMT AREA REP 049A 5BA0,1018 S @10,X'18'(,@01) CALC TIOT ENTRY OFFSET REP 049E BF4F,40A4 ICM @04,15,TCBTCT(@04) ADDR OF TIMING CONTROL TA REP 04A2 4780,C4C6 BZ PATEXIT EXIT IF NONE REP 04A6 5840,400C L @04,TCTIOTBL(,@04) ADDR OF TCT I/O TABLE REP 04AA 4150,4008 LA @05,TCTDCBTD(,@04) ADDR OF 1ST DD LOOKUP TAB * PATDDLOP EQU * REP 04AE 4960,5000 CH @06,0(,@05) LAST ENTRY IS ZERO * REP 04B2 4780,C4C6 BZ PATEXIT EXIT IF ZERO. REP 04B6 49A0,5000 CH @10,0(,@05) DO THE TIOT DISPLACEMENTS REP 04BA 4780,C4AA BE PATPRINT YES ==> PRINT I/O CO REP 04BE 4150,5004 LA @05,4(,@05) BUMP TO NEXT DD TABLE ENT REP 04C2 47F0,C492 B PATDDLOP * PATPRINT EQU * REP 04C6 4A40,5002 AH @04,TCTIOTSD(,@05) OFFSET TO THE DEVICE ENTR * (TCTDDENT OR TCBUCBP) REP 04CA 5860,4004 L @06,TCTDCTR(,@04) GET THE I/O COUNT REP 04CE 4E60,B0F8 CVD @06,MSGDISP+1 INTO PACKED FORMAT REP 04D2 D209,B105,C4CE MVC MSGCOUNT(L'EDMSK1),EDMSK1 PREPARE TO EDIT REP 04D8 DE09,B105,B0FC ED MSGCOUNT(L'EDMSK1),MSGDISP+5 STICK IN SOME CO REP 04DE 925C,B105 MVI MSGCOUNT,C'*' MARK WITH A SPLAT * PATEXIT EQU * REP 04E2 9240,B0F8 MVI MSGDISP+1,C' ' DISPLACED INSTRUCTION REP 04E6 47F0,C13E B MAINLINE * * EDMSK1 EQU * REP 04EA 6020,6B20,2020,6B20 DC X'60206B2020206B202120' REP 04F2 2120 * DECK PRODUCED BY THE ASMTOZAP UTILITY 85/12/16 165820