From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 19-NOV-1989 00:51
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Re: Cancelling Mount Verify Timeout

Received: From UCBVAX.BERKELEY.EDU by GIZMO.SRI.COM with TCP; Sat, 18 NOV 89 20:19:16 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.39)
	id AA17891; Sat, 18 Nov 89 20:13:23 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 19 Nov 89 04:08:56 GMT
From: drycas!synful@pt.cs.cmu.edu  (Marc Shannon)
Organization: Computer Club, Carnegie-Mellon University
Subject: Re: Cancelling Mount Verify Timeout
Message-Id: <99.2565e108@drycas.club.cc.cmu.edu>
References: <891117103139.20c020ea@NSSDCA.GSFC.NASA.GOV>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

In article <891117103139.20c020ea@NSSDCA.GSFC.NASA.GOV>, TENCATI@NSSDCA.GSFC.NASA.GOV (SPAN SECURITY MGR. (301)286-5223) writes:
> Does anyone know the low-level magic one types on the console to cause
> mount-verify timeout to be cleared for a particular disk drive?

We had had a problem a few months ago where we were getting flaky power to
our disk drives causing no end to drives with the ever-famed MntVerifyTimeout
status.

Since I'm the kernel-hacker in the group, I decided to see what I could do
for this.  In examining UCBs and poking random values in different places,
I finally came up with a combination which allowed me to dismount the drive
and remount it again, much to the pleasure of our Administrative Systems
users.

Unfortunately, once word got around our department that I could do that, I
ended up doing it several times in a week.  Not that I don't like hacking
in kernel-mode, mind you, but I have this small fear of crashing the system
while my NEWS session was still active. :-)

So, anyway, I wrote a program to do the same steps.  Following this message
is a VMS_SHARE (I think) file with the source for REMOUNT.PAS and SETVALID.MAR.
It has been tested on both VMS V4.7 and V5.1 and will probably work on
others.  As you can guess, though, no guarantee is made as to its validity
on your system.  (Oh, yeah, it doesn't work with volume-sets, although that
is fairly easy to add.)

--Marc
-- 
+-----------------------------------------------------------------------------+
| Marc Shannon                                 Internet Address (Bitnet name) |
| VAX Systems Programmer               SYNFUL@DRYCAS.CLUB.CC.CMU.EDU (DRYCAS) |
| Carnegie-Mellon University                  R602MS5U@VB.CC.CMU.EDU (CMCCVB) |
| (412) 268-6290              "I mean, really, what could possibly go wrong?" |
+-----------------------------------------------------------------------------+

$! ................... Cut between dotted lines and save. ...................
$!...........................................................................
$! VAX/VMS archive file created by VMS_SHARE V06.10 7-FEB-1989.
$!
$! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from
$! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au).
$!
$! To unpack, simply save, concatinate all parts into one file and
$! execute (@) that file.
$!
$! This archive was created by user R602MS5U
$! on 27-JUL-1989 10:16:48.37.
$!
$! It contains the following 2 files:
$!        REMOUNT.PAS
$!        SETVALID.MAR
$!
$!============================================================================
$ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL )
$ VERSION = F$GETSYI( "VERSION" )
$ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK
$ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", -
    "VMS_SHARE V06.10 7-FEB-1989 requires VMS V4.4 or higher."
$ EXIT 44 ! SS$_ABORT
$VERSION_OK:
$ GOTO START
$!
$UNPACK_FILE:
$ WRITE SYS$OUTPUT "Creating ''FILE_IS'"
$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION -
    VMS_SHARE_DUMMY.DUMMY
b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) )
; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE
, b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors 
:= 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN 
& "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION
( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail 
& LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP
; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK
( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 )
; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip 
<> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF
; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT )
; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip 
:= MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip 
<> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET )
; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) 
); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF
; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE
; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1
; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line 
<> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF
; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors 
:= i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT
( "The following line could not be unpacked properly:" ); SPLIT_LINE
; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL
( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH
( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 
); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP
; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION
( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO
( "The following !UL errors were detected while unpacking !AS", i_errors
, s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" )
; ENDIF; EXIT; 
$ DELETE VMS_SHARE_DUMMY.DUMMY;*
$ CHECKSUM 'FILE_IS
$ WRITE SYS$OUTPUT " CHECKSUM ", -
  F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." )
$ RETURN
$!
$START: 
$ FILE_IS = "REMOUNT.PAS"
$ CHECKSUM_IS = 527760262
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X[Ident('V1.0'),
X Inherit('Sys$Library:Starlet',
X         'Sys$Library:Pascal$Lib_Routines')]
XProgram Remount;
X
X(****************************************************************************
X *                                                                          *
X *   REMOUNT V1.0                                                           *
X *                                                                          *
X *   by Marc A. Shannon (R602MS5U@VB.CC.CMU.EDU)                            *
X *      Computing Services                                                  *
X *      Carnegie-Mellon University                                          *
X *                                                                          *
V ****************************************************************************
X)
X
XConst UCB$M_VALID = 2048;
X
XType Byte = [Byte] 0..255;
X     Word = [Word] 0..65535;
X     String = Varying [64] of Char;
X     ItemListBlock = Record
X                        BufLen : Word;
X                        ItmCod : Word;
X                        BufAdr : Unsigned;
X                        RetLenAdr : Unsigned
X                     End;
X     StatusBlock = [Quad] Record
X                             Err_Stat : Word;
X                             ByteCount : Integer
X                          End;
X
XVar DevName, RealDevName, LogicalName, VolumeLabel : String;
X    DevChar, DevClass, Status, MountFlags : Integer;
X    ItemList : Array [1..7] of ItemListBlock;
X    IOSB : StatusBlock;
X
XProcedure Check(Error_Status : [Unsafe] Integer);
X
XBegin
X   If Not Odd(Error_Status) Then $Exit(Error_Status)
XEnd;
X
XFunction SetValidBit(DevName : Varying [A] of Char) : Integer; Extern;
X
XBegin
X   If Not Odd(LIB$GET_FOREIGN(DevName.Body, '_Device: ', DevName.Length))
X      Then $Exit;
X
X   ItemList := Zero;
X
X   With ItemList[1] Do
X      Begin
X         BufLen := Size(RealDevName.Body);
X         ItmCod := DVI$_ALLDEVNAM;
X         BufAdr := IAddress(RealDevName.Body);
X         RetLenAdr := IAddress(RealDevName.Length)
X      End;
X   With ItemList[2] Do
X      Begin
X         BufLen := Size(DevChar);
X         ItmCod := DVI$_DEVCHAR;
X         BufAdr := IAddress(DevChar)
X      End;
X   With ItemList[3] Do
X      Begin
X         BufLen := Size(DevClass);
X         ItmCod := DVI$_DEVCLASS;
X         BufAdr := IAddress(DevClass)
X      End;
X   With ItemList[4] Do
X      Begin
X         BufLen := Size(LogicalName.Body);
X         ItmCod := DVI$_LOGVOLNAM;
X         BufAdr := IAddress(LogicalName.Body);
X         RetLenAdr := IAddress(LogicalName.Length)
X      End;
X   With ItemList[5] Do
X      Begin
X         BufLen := Size(Status);
X         ItmCod := DVI$_STS;
X         BufAdr := IAddress(Status)
X      End;
X   With ItemList[6] Do
X      Begin
X         BufLen := Size(VolumeLabel.Body);
X         ItmCod := DVI$_VOLNAM;
X         BufAdr := IAddress(VolumeLabel.Body);
X         RetLenAdr := IAddress(VolumeLabel.Length)
X   End;
X
X   Check($GETDVIW(, , DevName, ItemList, IOSB));
X   Check(IOSB.Err_Stat);
X
X   If UAnd(DevChar, DEV$M_MNT) = 0 Then $Exit(SS$_DEVNOTMOUNT);
X   If UAnd(Status, UCB$M_VALID) <> 0 Then $Exit(SS$_DEVMOUNT);
X   If DevClass <> DC$_DISK Then $Exit(SS$_NOTFILEDEV);
X
X   Check(SetValidBit(RealDevName));
X
X   (* Now that the bit is on again, dismount with appropriate flags... *)
X   Check($DISMOU(RealDevName, DMT$M_NoUnload+DMT$M_Abort));
X
X   (* and remount it... *)
X   ItemList := Zero;
X
X   MountFlags := MNT$M_MESSAGE+MNT$M_SYSTEM+MNT$M_NOASSIST;
X
X   With ItemList[1] Do
X      Begin
X         BufLen := Length(RealDevName);
X         ItmCod := MNT$_DEVNAM;
X         BufAdr := IAddress(RealDevName.Body)
X      End;
X   With ItemList[2] Do
X      Begin
X         BufLen := Length(VolumeLabel);
X         ItmCod := MNT$_VOLNAM;
X         BufAdr := IAddress(VolumeLabel.Body)
X      End;
X   With ItemList[3] Do
X      Begin
X         BufLen := Length(LogicalName);
X         ItmCod := MNT$_LOGNAM;
X         BufAdr := IAddress(LogicalName.Body)
X      End;
X   With ItemList[4] Do
X      Begin
X         BufLen := Size(MountFlags);
X         ItmCod := MNT$_FLAGS;
X         BufAdr := IAddress(MountFlags)
X      End;
X
X   $Exit($MOUNT(ItemList))
XEnd.
$ GOSUB UNPACK_FILE

$ FILE_IS = "SETVALID.MAR"
$ CHECKSUM_IS = 1332097707
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X;
X;  This is used to set the UCB$M_VALID bit in UCB$L_STS for
X;  the device whose descriptor is passed in 4(AP).
X;
X`009.Title`009SetValid
X`009.Ident`009/V1.0/
X
X`009.Library /Sys$Library:Lib/
X`009.Link`009/Sys$System:Sys.Stb/
X
X`009$DSCDEF
X`009$UCBDEF
X
XDevName: .Long`0092
X
X`009.Entry`009SetValidBit,`094M<R2>
X
X;  This is just an entry place to pass in the arguments...
X
X;  AP points to the argument list, which is supposed to be a 1, followed
X;  by the address of a descriptor which points to the varying string.
X
X`009Movl`0094(AP),R2
X`009Movl`0094(R2),R2`009`009; R2 now points to the string
X
X`009Movzwl`009(R2),R1
X`009Bisl3`009#<<DSC$K_CLASS_D@24>!<DSC$K_DTYPE_T@16>>,R1,DevName
X
X`009Movab`0092(R2),DevName+4
X
X`009Pushal`009DevName
X`009Pushl`009#1
X`009Pushal`009(SP)
X`009Pushab`009Kernel_Routine
X`009Calls`009#2,G`094SYS$CMKRNL
X`009Movl`0094(SP),SP
X`009Ret
X
X`009.Entry`009Kernel_Routine,`094M<>
X
X`009Movl`0094(AP),R1
X`009Jsb`009G`094IOC$SearchDev
X`009Blbc`009R0,99$
X
X; R1 now contains the address of the UCB.  Turn on the valid bit now.
X`009Bisl`009#UCB$M_VALID,UCB$L_STS(R1)
X
X99$:`009Ret
X`009.End
$ GOSUB UNPACK_FILE
$ EXIT

