SYSDUMPs AND HP's "TurboSTORE" FACILITY
by Eugene Volokh, VESOFT
Published by INTERACT Magazine, Sep 1988.
At a recent meeting of the GLUG (Greater Los Angeles Users' Group),
one of our users approached me with a technical problem. He had just
bought HP's new TurboSTORE product, which (among other things) lets
you mount several tapes on several tape drives and then specify all
those tape drives on one :STORE command. This way, if your nightly
backup takes 3 reels and you happen to have 3 tape drives, you could
mount tapes on each of the tape drives and say:
:FILE T7;DEV=7
:FILE T8;DEV=8
:FILE T9;DEV=9
:STORE @.@.@;DATE>=xxx;STORESET=(*T7),(*T8),(*T9)
Instead of just specifying the tape file to store to (after the
fileset), you can specify the ;STORESET= keyword; :STORE will write to
the tape on ldev 7, then to the one on ldev 8, and then to the one on
ldev 9. You mount the tapes, do the :STORE, and then go home -- no
need to stay around to mount additional tapes. (This works especially
well if you have HP's new 7980XC compressing tape drives, which could
let you cut your system backup to 2 or 3 tapes rather than 7 or 8 --
the user who prompted this whole paper is getting a 4 to 1 compression
ratio.) It's much more convenient, and can save you $$$ on your
nightly operator costs.
The problem with TurboSTORE is that, although it works perfectly on
the :STORE command, it can't be used with :SYSDUMP -- the one place
you most want to have it (for backup purposes). If you try saying
:FILE T7;DEV=7
:FILE T8;DEV=8
:FILE T9;DEV=9
:SYSDUMP (*T7),(*T8),(*T9)
instead of
:SYSDUMP *T
you'll get a syntax error; if you say
:SYSDUMP *T
...
ENTER DUMP FILE SUBSET (S)
@.@.@;STORESET=(*T7),(*T8),(*T9)
then you'll get an error "'STORESET' NOT ALLOWED WHEN POSITIONAL TAPE
NAME IS SPECIFIED (S/R 6293)".
Thus, you either have to abandon TurboSTORE for system backups (if
you do, why use TurboSTORE at all? -- how many other multi-reel
:STOREs do you do?) or do all your system backups with :STORE. The
latter alternative -- using :STORE for backups -- seems palatable, but
has two substantial problems:
1. Backups made with :STORE do not contain the SYSTEM DIRECTORY. If
you need to restore from a :STORE backup, the best you can do is
put on a ;CREATE, but that still might not create all the users
and groups, and certainly won't preserve capabilities, security
masks, etc.
Your normal coldload tape (which you had to make with :SYSDUMP)
would have this information, but unless you cut a new coldload
tape every night, the directory information on it will be
substantially out of date.
2. While you can :RESTORE equally well from a :STORE backup as from
a :SYSDUMP backup, you can't do a RELOAD COMPACT from a :STORE
tape. If you like to use this option for better disc space
utilization, switching to :STORE backups may be unpleasant.
Well, you say, these might be non-trivial problems, but what can
you do? If that's the way TurboSTORE works, we have to live with it
and wait for a new version that might fix the problem (which may be
some time down the road).
Fortunately, our user was an imaginative type -- he though that
something could be done directly, without having to wait. Even when I
assured him that the problem was probably quite deep and intractable,
he still goaded me to go on; and, as it ultimately turned out, we
managed to come up with a very simple solution.
The :SYSDUMP command does not write the files-to-be-stored to tape
itself; it uses :STORE to do this. After writing all the system
information to the backup tape, it creates STORE.PUB.SYS (the :STORE
program) as a son process and tells it (via the ;INFO= string) which
files are to be stored. Actually, it passes to STORE.PUB.SYS all the
text that you typed in response to "ENTER DUMP FILE SUBSET (S)", so
any :STORE keywords specified there (e.g.
"@.@.@;STORESET=(*T7),(*T8),(*T9)") are seen by STORE.PUB.SYS. In
fact, if you say
:SYSDUMP *T
...
ENTER DUMP FILE SUBSET (S)
@.@.@;STORESET=(*T7),(*T8),(*T9)
then SYSDUMP will essentially do (using the CREATEPROCESS intrinsic)
the equivalent of
:RUN STORE.PUB.SYS;&
INFO="STORE @.@.@;*DUMPTAPE;STORESET=(*T7),(*T8),(*T9)"
The only reason why this fails seems to be that STORE.PUB.SYS doesn't
let you specify both the "storefile" (*DUMPTAPE) parameter and
;STORESET=. It's purely a syntax check on STORE's part; if only
SYSDUMP had done a
:RUN STORE.PUB.SYS; INFO="STORE @.@.@;STORESET=(*T7),(*T8),(*T9)"
-- without specifying *DUMPTAPE -- then everything would work! SYSDUMP
would write all the system stuff to the store file you specified (in
our example, *T, which SYSDUMP later refers to as *DUMPTAPE), and then
use STORE.PUB.SYS to write all the files to the given ;STORESET=. Of
course, *T (the SYSDUMP tape) would have to be on the same device as
*T7 (the first tape in the ;STORESET= parameter).
(Note that SYSDUMP always refers to the tape parameter as
*DUMPTAPE, even though you specified it as *T -- the :SYSDUMP command
automatically sets up a ":FILE DUMPTAPE=*T" file equation.)
So now we know what we wish SYSDUMP would do -- not pass the
*DUMPTAPE parameter to STORE.PUB.SYS when the user specifies a
;STORESET= parameter. Now, the question is: how do we make SYSDUMP do
it? How do we force an HP program (the source of which we don't, of
course, have) to do something it wasn't designed to do?
The solution is surprisingly simple. In fact, it does NOT involve
patching any SYSDUMP code (which would be highly uncertain, which
would constrain the nature of our patch, and which would require us to
re-deduce the patch for every new version of SYSDUMP). What it does
involve is doing the following:
* :HELLO MANAGER.SYS
* :NEWGROUP VESTORE.SYS;CAP=IA,BA,PH,PM,MR,DS
* :FCOPY FROM=SYSDUMP.PUB.SYS;TO=SYSDUMP.VESTORE.SYS;NEW
* Compile the following SPL program:
$CONTROL NOSOURCE, USLINIT, SEGMENT=VESTORE, SUBPROGRAM
BEGIN
PROCEDURE CREATEPROCESS (ERR, PIN, PROGRAM, NUMBERS, ITEMS);
INTEGER ERR;
INTEGER PIN;
BYTE ARRAY PROGRAM;
INTEGER ARRAY NUMBERS;
INTEGER ARRAY ITEMS;
OPTION VARIABLE;
BEGIN
INTRINSIC LOADPROC, UNLOADPROC;
INTEGER VAR'MASK = Q-4;
INTEGER STATUS = Q-1;
BYTE POINTER INFO;
INTEGER INFO'LEN, I, J, PLABEL, IDENT;
BYTE ARRAY PROC'NAME(0:15);
IF VAR'MASK.(14:1)=1 AND VAR'MASK.(15:1)=1 THEN
BEGIN << NUMBERS and ITEMS specified, look at them >>
INFO'LEN:=0;
I:=0;
WHILE NUMBERS(I)<>0 DO
BEGIN << find INFO and INFO LENGTH values >>
IF NUMBERS(I)=11 <<info>> THEN
@INFO:=ITEMS(I)
ELSE IF NUMBERS(I)=12 <<infolen>> THEN
INFO'LEN:=ITEMS(I);
I:=I+1;
END;
IF INFO'LEN<>0 THEN
FOR I:=0 UNTIL INFO'LEN-11 DO
IF INFO(I)=";STORESET=" THEN << store-set specified? >>
FOR J:=0 UNTIL INFO'LEN-12 DO
IF INFO(J)=";*DUMPTAPE;" THEN
MOVE INFO(J):=" ;"; << delete *DUMPTAPE >>
END;
<< Can't call CREATEPROCESS directly (this would just call >>
<< this procedure recursively) -- LOADPROC it and then call. >>
MOVE PROC'NAME:="CREATEPROCESS ";
IDENT:=LOADPROC (PROC'NAME, 0, PLABEL);
TOS:=@ERR;
TOS:=@PIN;
TOS:=@PROGRAM;
TOS:=@NUMBERS;
TOS:=@ITEMS;
TOS:=VAR'MASK;
TOS:=PLABEL;
ASSEMBLE (PCAL 0);
IF > THEN STATUS.(6:2):=0 << set condition code >>
ELSE IF < THEN STATUS.(6:2):=1
ELSE STATUS.(6:2):=2;
UNLOADPROC (IDENT);
END;
END.
* Add it to a group SL by saying
:SEGMENTER
-BUILDSL SL.VESTORE.SYS,20,1
-USL $OLDPASS (or whatever USL you compiled the above
SPL procedure into)
-ADDSL VESTORE
-EXIT
* Now, whenever you want to do a system backup, instead of
saying ":SYSDUMP *T,*LISTFILE", say
:FILE DUMPTAPE=*T
:FILE SYSDLIST=*LISTFILE (or $STDLIST, if you like)
:RUN SYSDUMP.VESTORE.SYS;LIB=G
* When SYSDUMP.VESTORE.SYS prompts you with "ENTER DUMP FILE
SUBSET (S)", say
fileset,fileset,...,fileset;STORESET=(*tape,*tape,...)
In other words, specify everything that you'd normally specify
when asked for the dump file subsets, PLUS the ;STORESET=
parameter that you'd specify on an ordinary :STORE command.
Now, SYSDUMP.VESTORE.SYS -- an exact copy of SYSDUMP.PUB.SYS --
will do your system backup USING TurboSTORE'S ;STORESET= KEYWORD.
How does this work? Well, when SYSDUMP.VESTORE.SYS (which was run
with ;LIB=G) calls the CREATEPROCESS intrinsic to create
STORE.PUB.SYS, it will actually call our own CREATEPROCESS procedure
that we've put into SL.VESTORE.SYS.
This CREATEPROCESS procedure looks exactly like the CREATEPROCESS
intrinsic; however, it also examines the ;INFO= parameter that's being
passed to the program-to-be-created. (We find the ;INFO= string and
its length in the NUMBERS and ITEMS arrays passed to CREATEPROCESS.)
If this ;INFO= string contains the string ";STORESET=", then our
CREATEPROCESS procedure REMOVES the string ";*DUMPTAPE" from the
;INFO= parameter.
After this is done, our own CREATEPROCESS calls the REAL
CREATEPROCESS. Unfortunately, it can't just simply call CREATEPROCESS,
since that would call our own CREATEPROCESS recursively (instead of
calling the real CREATEPROCESS in the system SL). Instead, we use
LOADPROC to load the real CREATEPROCESS explicitly from the system SL
and then call it using PCAL 0.
:SYSDUMP and TurboSTORE can now work together. The customer for
whom we originally did this is using this quite successfully for his
nightly backups. There may be some problems with our approach that we
haven't encountered (use it at your own risk!), but it seems to be
working quite well. If you're a TurboSTORE customer, try it -- it
might help you out of an unpleasant spot!
Go to Adager's index of technical papers