#define MAXDEVICE 200 #define MAXDEVNAMLEN 64 #define MAXDEVLOCKNAM 13 #define MAXFILNAMLEN 80 #define MAXPID 16 /* ** BLOCKING.C, Hein van den Heuvel, Digital, July 1995 ** ** List all locks not granted (converting, waiting) for a specified PID. ** For each, print blocking lock information, resource name and parent. ** Have fun, ** Hein van den Heuvel, July 1995. */ #include #include #include #include #include #include #include #include #include #define terminator 0,0,0,0 #define EFN 1 static char devnam[MAXDEVICE][MAXDEVNAMLEN]; /* counted string */ static char devlocknames[MAXDEVICE][MAXDEVLOCKNAM+1]; static int device_count = 0; typedef struct { short len, cod; void *address; short *retlen; } item; typedef struct { unsigned int len; void *address; } desc; int sys$getlkiw(), sys$getjpi(), sys$setprv(), sys$cmexec(); void dump_data () ; int make_device_name_list(), print_filename_and_record() ; char *find_device_name(); char *mode[]={"NL", "CR", "CW", "PR", "PW", "EX", "??"}; main(int argc, char *argv[]) { int stat, s, i, l, parent, grand_parent, lock_id, lock_pid; int wildcard=0, retlen=0, parent_retlen=0, pid=0, locks=0; char *x; struct lkidef lkibuf[100], *lki; struct { unsigned all : 16, one : 15, too_small : 1 ;} lkilen; int privs[] = { PRV$M_WORLD | PRV$M_CMEXEC , 0}; int *search_devnam=0; desc search_devnam_desc; #pragma nostandard /* Using address of variable where constant is standard */ struct { char rqmode, grmode, queue, fill;} lki_state; struct { int rms; unsigned short fid_num, fid_seq, fid_rvn; char devlocknam[22] ;} parent_resnam; struct { unsigned int id, vbn, fill[6];} resnam; item getlki_items[] = { 4, LKI$_LOCKID, &lock_id, 0, 4, LKI$_PID, &lock_pid, 0, 3, LKI$_STATE, &lki_state, 0, terminator}; item block_items[] = { 31, LKI$_RESNAM, &resnam, &retlen, 4, LKI$_PARENT, &parent, 0, sizeof lkibuf, LKI$_BLOCKING,&lkibuf, &lkilen, terminator}; item parent_items[] = {31, LKI$_RESNAM, &parent_resnam, &parent_retlen, 4, LKI$_PARENT, &grand_parent, 0, terminator}; int getlki_args[] = {7, EFN, (int) &wildcard, (int) &getlki_items,0,0,0,0}, parent_args[] = {7, EFN, (int) &parent, (int) &parent_items,0,0,0,0}, block_args[] = {7, EFN, (int) &lock_id, (int) &block_items,0,0,0,0}; #pragma standard /* ** First get some temporary privs for the GETLKI in EXEC mode later on. */ stat = sys$setprv ( 1, privs, 0, 0); if (stat != SS$_NORMAL) return (stat & -2); if (argc > 1) { /* ** First argument, if present, specifies PID to look for. 0 = All. */ sscanf (argv[1], "%x", &pid); if (pid > MAXPID) { printf (" Looking for non-granted locks for PID %8X\n\n", pid); } else { x = ""; if (pid > 0) x = "RMS "; printf (" Looking for non-granted %slocks for all PIDs\n\n", x); }; }; if (argc > 2) { /* ** Second argument, if present, specifies wildcarded device name ** to look for. For lock on matching devices, the RMS files name ** and locked record is attempted to be displayed. */ search_devnam_desc.len = strlen(argv[2]); search_devnam_desc.address = (int) argv[2]; search_devnam = &search_devnam_desc; str$upcase (&search_devnam_desc, &search_devnam_desc); } (void) make_device_name_list(search_devnam); /* ** Main loop. Get a lock, any lock. ** Find out wether it is held by specified process, and waiting. */ stat = sys$cmexec (&sys$getlkiw, &getlki_args); while (stat & 1) { locks++; if ( (lki_state.queue != LKI$C_GRANTED) && ((pid < MAXPID) || (lock_pid == pid)) ) { int rms = 0; parent = 0; /* ** Have blocked lock for specified PID, request details. */ stat = sys$cmexec (&sys$getlkiw, &block_args); if (!(stat & 1)) break; /* ** Let's see if we stumbled into an rms record or bucket lock... */ if (parent!=0) { s = sys$cmexec (&sys$getlkiw, &parent_args); if ((s & 1) && (grand_parent==0) && (parent_resnam.rms == 'RMS$')) rms = 1; } /* ** Print out all locks, or just RMS ? */ if ((pid == 0) || (pid > MAXPID) || rms) { l = lkilen.all / lkilen.one; printf ("Pid %08X Lock %08X, Rq=%s, Parent %08X, blocked by %d.\n", lock_pid, lock_id, mode[lki_state.rqmode], parent, l); dump_data (&resnam, retlen, "Resource Name "); lki = &lkibuf; for ( i = 0; i < l; i++) { printf (" PID=%8X, Gr=%s, Rq=%s, LockId=%08X, System=%08\n", lki->lki$l_pid, mode[lki->lki$b_grmode], mode[lki->lki$b_rqmode], lki->lki$l_lkid, lki->lki$l_csid); lki++; } if (parent!=0) dump_data (&parent_resnam, parent_retlen, "Parent Resource Name"); printf ("\n"); } if (rms) { printf (" RMS lock! VBN/ID %X/%X, File (%d,%d,%d) on %s\n", resnam.vbn, resnam.id, parent_resnam.fid_num, parent_resnam.fid_seq, parent_resnam.fid_rvn, &parent_resnam.devlocknam[1]); print_filename_and_record ( &parent_resnam.devlocknam[0], &parent_resnam.fid_num, resnam.vbn, resnam.id); } } /* PID ? */ if (stat &1) stat = sys$cmexec (&sys$getlkiw, &getlki_args); } /* stat ? */ if (stat == SS$_NOMORELOCK) stat = SS$_NORMAL; printf (" Done. Scanned %d locks.\n", locks); return stat; } void dump_data (void *p, short len, char *t) { int i, j, k, l; unsigned char (*x)[72]; char out[80], *in, c; x = in = p; l = len; if (l > 72) l = 72; /* sizeof out */ for (i=0; i\n", t, len, &out[0]); j = 0; for (i=0; i #include /* #include does not exist, hand coded defines follow */ #define DVS$_DEVCLASS 1 #define DVS$_DEVTYPE 2 #define SS$_NOMOREDEV 2648 int i, stat, context[] = {0,0}, devclass = DC$_DISK; short int retlen; desc devnam_desc; item getdvi_items[] = { MAXDEVLOCKNAM, DVI$_DEVLOCKNAM,0, 0, terminator}; item device_items[] = { 4, DVS$_DEVCLASS, &devclass, 0, terminator}; /* ** Build two arrays with DISK device names and their lock names. */ for (i=0; i