420 likes | 578 Vues
Disk partitioning on VMS with LDdriver Session A311/A312. Jur van der Burg HP OpenVMS Engineering. LDdriver: What can it do?. Use a file on any disk as a disk Use a range of logical blocks on a disk as a new disk Investigate I/O behavior Test application error handling
E N D
Disk partitioning on VMS with LDdriverSession A311/A312 Jur van der Burg HP OpenVMS Engineering
LDdriver: What can it do? • Use a file on any disk as a disk • Use a range of logical blocks on a disk as a new disk • Investigate I/O behavior • Test application error handling • Play around with disks without doing damage • Emulate a magtape (future) • Create havoc (with privileges)
Where can I find it? • On the OpenVMS freeware website http://www.hp.com/go/openvms/freeware • On the main lddriver site http://www.digiater.nl/lddriver (under construction) • Integrated in VMS since V7.3-1(sort of....) • Fully integrated in VMS V8.2
Preparation • Ready for use after @SYS$STARTUP:LD$STARTUP • Any command that needs the driver will give an error if not started properly: $ LD CONNECT FILE.DSK LDA1 %LD-F-INVOKESTARTUP, LD has not been setup correctly, invoke @SYS$STARTUP:LD$STARTUP.COM • Exceptions are LD HELP and LD CREATE • Version can be obtained like this: $ LD VERSION %LD-I-VERSION, LD version V9.0, module X-9 built on May 17 2006 09:01:31 -LD-I-DRIVERVERSION, Driver version: 17-MAY-2006 09:02:10.86 (MON version) -LD-I-SYSINFO, Node: THEBAT, Hardware: hp AlphaServer DS20L 833 MHz, VMS version: XB9P-BL2
Basics – File mode • Use a file as a disk • Create a file on a physical disk: LD CREATE DKA100:[LD]DISK/SIZE=10000 • Connect the file to a device: LD CONNECT DKA100:[LD]DISK LDA1 • Use it: INIT LDA1: LDDISK MOUNT LDA1: LDDISK ..... DISMOUNT LDA1: • Disconnect the file: LD DISCONNECT LDA1
Basics – LBN mode • Use a range of logical blocks as a disk • Physical disk may not be used by anything else • Connect a range of logical blocks to a disk: LD CONNECT DKA100:/LBN=(START=0,END=9999) LDA1 LD CONNECT DKA100:/LBN=(START=10000,END=19999) LDA2 LD CONNECT DKA100:/LBN=(START=20000,END=29999) LDA3 • Connect using a size: LD CONNECT DKA100:/LBN=(START=0,SIZE=10000) LDA1 LD CONNECT DKA100:/LBN=(START=10000,SIZE=10000) LDA2 LD CONNECT DKA100:/LBN=(START=20000,SIZE=10000) LDA3
Basics – Replace mode • Access another disk via an LD device • Not a real form of partitioning • Useful for I/O tracing and watchpoints • Physical disk may not be used by anything else • Connect and replace: LD CONNECT DKA100:/REPLACE LDA1
Advanced use • Sharing of LD devices in a cluster is possible • LD devices itself are not MSCP-served • For shared use the physical devices where the container file resides must be MSCP served • Shadowing host-based raid disks • LD devices may be nested, i.e. you can create an LD disk on an LD disk on an LD disk etc.
Sharing LD devices • LD devices must be connected the same way on multiple nodes to allow sharing of container files • This means the same device name, allocation class, geometry, filename, etc. • Any mismatch will be detected by the driver • The utility attempts to give the reason for the failure $ ld connect $1$dga1: lda3:/lbn=(start=600,end=2000)/log/share %LD-F-DEVICEINUSE, Device incompatible connected to other LD disk in cluster -LD-F-RANGEINUSE, LBN range already in use
I/O tracing • Very powerful feature to see what’s happening on a low level • Can be viewed real-time (continuously) • Can be logged to disk (unattended) • Flexible selectable output • different time formats • different I/O status block formats • different I/O function code formats
I/O Tracing example $ ld trace lda1: ..... $ ld show/trace lda1 I/O trace for device $7$LDA1: 26-APR-2006 22:18:36.28 on node LDDRVR:: Start Time Elaps Pid Lbn Bytes Iosb Function -------------------------------------------------------------- 22:18:32.65 00.00 09C00227 0 0 NORMAL PACKACK|INHERLOG 22:18:32.65 00.01 09C00227 1 512 NORMAL READPBLK 22:18:32.66 00.00 09C00227 1034 512 NORMAL READPBLK 22:18:32.67 00.00 09C00227 5002 512 NORMAL READPBLK 22:18:32.68 00.00 09C00227 5002 512 NORMAL WRITEPBLK 22:18:32.69 00.00 09C00227 5003 1536 NORMAL READPBLK 22:18:32.69 00.00 09C00227 5006 512 NORMAL READPBLK 22:18:32.69 00.00 09C00227 5000 512 NORMAL READPBLK|EXFUNC 22:18:32.69 00.00 09C00227 0 0 NORMAL PACKACK|BYPASS_VALID_CHK 22:18:32.70 00.00 09C00227 5016 512 NORMAL READPBLK|EXFUNC 22:18:32.70 00.00 09C00227 5023 1024 NORMAL READPBLK 22:18:32.70 00.00 09C00227 5016 512 NORMAL WRITEPBLK|EXFUNC|DATACHECK
Watchpoints • A watchpoint is a special action performed when a targeted logical block is hit by a request • These actions are possible: • Return a specific error • Suspend the I/O request • Generate an Opcom message • Crash the system (needs CMKRNL privilege) • The user controls which LBN is watched, on which function code is acted, and which error is returned • The ‘Opcom’ action may be combined with other actions
Watchpoint example $ ld watch lda1 1/action=error=2928 $ ld watch lda1 1/action=opcom $ ld show/watch lda1 Index LBN Action Function Error return code -------------------------------------------------------------------- 1 1 Opcom READPBLK 2 1 Error READPBLK 0B70 (FISH) $ dump lda1:/block=(count=1,start=1) %%%%%%%%%%% OPCOM 5-APR-2006 14:21:46.70 %%%%%%%%%%% Message from user VDBURG on LDDRVR ***** LDdriver detected LBN watchpoint access ***** PID: 26000224 Image: DUMP Device: $7$LDA1: (LDDRVR) Function: 000C LBN: 1 %DUMP-E-READERR, error reading LDA1: -SYSTEM-W-FISH, my hovercraft is full of eels
Callable interface • LDdriver is controlled by a user mode program issuing normal QIO requests • The required function codes and definitions are available in the kit, and in VMS since V8.2-1 ($LDDEF or lddef.h) • The driver is doing very strong validity checks of all requests (You can’t shoot yourself in the foot (if you can, I apologize, please let me know how you did it))
Limits • Create as many devices as your diskspace allows • Creation of any device takes BYTLM quota from the creating process • The tracebuffer as well as watchpoints come out of non-paged pool and are charged against BYTLM as well • If 9999 LD devices are not enough then you can create LD devices on other controllers, like LDB1:, LDC1:, etc. • Configure the driver with @SYS$STARTUP:LD$STARTUP x where x is the controller to use.
New developments • LD V8.1: • LD CREATE/EXTEND Allows extension of existing container file Expand volume with SET VOLUME/SIZE • LD CONNECT/NOFORCED_ERROR Prevent handling of forced errors with shadowing • Bug fixes: • Fix possible system crash in I/O completion • Fix I/O hang with host-based raid • Fix mount verification issues
New developments • LD V8.2: • LD V8.2 has no new features when compared to V8.1 • It is only a bug fix release. • Properly expel shadowset members on error • Reconnecting an LD device could fail the first time after reboot if the container file was used on another node • Allow container file on an NFS mounted ODS5 volume • Prevent system crash on reconnecting a container file in a cluster
New developments - cont • LD V9.0: • LD CREATE/ERASE Erase container file on creation • More accurate timing in trace records (starting with VMS V8.3) $ ld show/trace lda1 I/O trace for device $9$LDA1: 17-MAY-2006 09:21:15.16 on node THEBAT End Time Elaps Pid Lbn Bytes Iosb Function --------------------------------------------------------------------- 09:21:12.232269 00.000000 2060042F 0 0 NORMAL PACKACK|INHERLOG 09:21:12.240950 00.008581 2060042F 1 512 NORMAL READPBLK 09:21:12.247513 00.006426 2060042F 1034 512 NORMAL READPBLK 09:21:12.248595 00.000959 2060042F 50033 512 NORMAL READPBLK 09:21:12.249557 00.000838 2060042F 50034 512 NORMAL READPBLK 09:21:12.255176 00.005504 2060042F 50016 512 NORMAL READPBLK 09:21:12.263548 00.008258 2060042F 50016 512 NORMAL WRITEPBLK
New developments – Tape emulation • Emulate tape device (not yet finished) • Device is called ‘LM’ (Logical Magtape) • Uses the same driver as LD $ lm create tape1/siz=10000 $ lm connect tape1 lma1/log %LD-I-CONNECTED, Connected $9$LMA1: to $9$DKA100:[LD]TAPE1.DSK;1 $ show dev/fu lma1 Magtape $9$LMA1: (THEBAT), device type (Generic SCSI tape), is online, file- oriented device. Error count 0 Operations completed 2 Owner process "" Owner UIC [JUR] Owner process ID 00000000 Dev Prot S:RWPL,O:RWPL,G:R,W Reference count 0 Default buffer size 2048 Density 6666 Format Normal-11 Allocation class 12 Volume status: no-unload on dismount, odd parity.
New developments – Tape emulation $ lm trace lma1 $ mount/for lma1: %MOUNT-I-MOUNTED, mounted on _$9$LMA1: (THEBAT) $ dismount lma1: $ lm show/trace lma1 I/O trace for device $9$LMA1: 17-MAY-2006 09:25:49.65 on node THEBAT End Time Elaps Pid Lbn Bytes Iosb Function --------------------------------------------------------------------- 09:24:12.914151 00.000000 000000A9 0 0 NORMAL PACKACK 09:24:12.914153 00.000000 000000A9 0 0 NORMAL REWIND 09:24:12.914157 00.000000 000000A9 0 0 NORMAL PACKACK 09:24:12.914159 00.000000 000000A9 0 0 NORMAL REWIND 09:24:12.914161 00.000000 000000A9 0 80 ILLBLKNUM READPBLK 09:24:12.914163 00.000000 000000A9 0 0 NORMAL REWIND 09:24:12.980426 00.000000 000000A9 0 0 NORMAL UNLOAD|CLSEREXCP 09:24:12.980427 00.000000 000000A9 0 0 NORMAL AVAILABLE
Internals – connecting a container file • The most tricky part is connecting an LD device to a container file • Container file physical device must be a mounted disk • It must contain a known file system • File must be mapped with cathedral windows • Caching must be disabled for this file • Check for usage on other cluster members • File ID • Allocation class • Device name / controller letter / unit number • Geometry • Maximum block size • Sharing • Mode of connection
Internals – connecting a disk by LBN • Connecting part of a disk by LBN range needs other checks • Physical device may not be mounted • It may not be accessed on any other node • The logical block range must fit and may not be in use anywhere in the cluster • The exception is that parts that match exactly may be shared • After connecting the physical device is guarded against access with a lock which prevents mounting
Internals – checking LBN range (1) • When connecting a part of a physical disk we need to check availability of the logical blocks, clusterwide • We can’s take out a lock based on a resource name with the encoded range as we don’t know what’s used on other nodes • We don’t want to invoke a helper process – driver check only! • We can’t store all ranges in a valueblock • So we use the lockmanager in a smart way
Internals – checking LBN range (2) • At connection time the block range we want is entered in a lock value block • By taking out a lock a blocking AST routine is fired on other nodes with interest in the same device • The blocking routine scans all local LD devices for a matching device • If found the LBN range is checked • In case of an error a bit is set in the lock value block • After lock conversion the initiator examines the error bit and rejects the request if set
Internals – Finding an I/O • LDdriver sends most I/O requests it receives directly to the physical disk driver • This may happen for multiple file segments in parallel • This can make it harder to find an active I/O • IRP’s forwarded to the physical disk can be found in the LDIOB structure • LDdriver’s structure definitions can be found in SYS$LDDRIVER.STB (only after installing the LD kit)
SDA> read/exec SDA> show device lda2 ... SDA> format/typ=ldiob @(ucb+ucb$l_ld_aiofl) FFFFFFFF.81DDE140 LDIOB$L_QFL 81DD9800 UCB+00200 FFFFFFFF.81DDE144 LDIOB$L_QBL 81DD9800 UCB+00200 FFFFFFFF.81DDE148 LDIOB$W_SIZE 0080 FFFFFFFF.81DDE14A LDIOB$B_TYPE 13 FFFFFFFF.81DDE14B LDIOB$B_SPARE 53 FFFFFFFF.81DDE14C LDIOB$L_IRP 81DB1780 FFFFFFFF.81DDE150 LDIOB$L_PID 0001002B LNM$C_DEL_OVERLAY+00027 FFFFFFFF.81DDE154 LDIOB$L_MEDIA 00000000 FFFFFFFF.81DDE158 LDIOB$L_BCNT 00000200 FFFFFFFF.81DDE15C LDIOB$W_FUNC 000C FFFFFFFF.81DDE15E LDIOB$W_IOST 0001 FFFFFFFF.81DDE160 LDIOB$Q_STAT 00000000.00000000 FFFFFFFF.81DDE168 LDIOB$Q_ST_TIME 00000000.00000000 FFFFFFFF.81DDE170 LDIOB$Q_EN_TIME 000000A8.00010025 FFFFFFFF.81DDE178 LDIOB$Q_ST_SCC 00000000.1C10E15D FFFFFFFF.81DDE180 LDIOB$Q_EN_SCC 44070017.34465003 FFFFFFFF.81DDE188 LDIOB$L_ST_CPU 00000000 FFFFFFFF.81DDE18C LDIOB$L_EN_CPU 00000000 FFFFFFFF.81DDE190 LDIOB$L_ELAPSED 00000000 LDIOB$Q_ELAPSED FFFFFFFF.81DDE194 00000000 FFFFFFFF.81DDE198 LDIOB$Q_ST_USEC 613D6500.746C7561 FFFFFFFF.81DDE1A0 LDIOB$Q_EN_USEC 2F657461.642F6C6C FFFFFFFF.81DDE1A8 LDIOB$L_ABCNT 00000000 Number of bytes transferred so far FFFFFFFF.81DDE1AC LDIOB$L_KPB 81C5C9C0 FFFFFFFF.81DDE1B0 LDIOB$L_FWDQFL 81DC0878 Queue of forwared IRP's FFFFFFFF.81DDE1B4 LDIOB$L_FWDQBL 81DC0878 FFFFFFFF.81DDE1B8 LDIOB$W_IRPCNT 0001 Number of active forwarded IRP's FFFFFFFF.81DDE1BA LDIOB$W_FLAGS 0000 SDA> format @(@(ucb+ucb$l_ld_aiofl)+ldiob$l_fwdqfl)-irp$l_ld_fwdqfl FFFFFFFF.81DC0640 IRP$L_IOQFL 81DC5BA0 FFFFFFFF.81DC0644 IRP$L_IOQBL 81DC5BA0 FFFFFFFF.81DC0648 IRP$W_SIZE 0240 FFFFFFFF.81DC064A IRP$B_TYPE 0A FFFFFFFF.81DC064B IRP$B_RMOD 00 FFFFFFFF.81DC064C IRP$L_PID 81B278F0 SYS$LDDRIVER+118F0 ...
Which VMS versions? • Runs on VAX/VMS since V5.5-2 • Alpha V6.1 and higher • IA64 V8.2 and higher • The current kit is HP-VMS-LD-V0802--1.PCSI • Installs on: • VAX V7.3 • Alpha V7.2-2 V7.3 V7.3-1 V7.3-2 V8.2 • Ia64 V8.2 V8.2-1
Other versions • Other versions may work too, but the driver and utility needs to be built from source (included in the kit) • Build procedure is included • C compiler required • Driver may need an edit for specific versions (enable / disable a conditional) • LD V9.0 will NOT run on VAX! • LD V8.2 is integrated in the VMS V8.3 release
Known issues • V8.2: • If the XFC cache is turned off (VCC_FLAGS != 2) then connecting a file will return this error: • %LD-F-BLKOUTOFRANGE, Blocks out of range • This problem is corrected in VMS V8.3 and the future LD V9.0 kit
Internal usage • Heavily used for testing • Used in the VMS build • Used by the host-based Infoserver • Used by CDRECORD
Futures • Bug fixes (if any....) • You name it.... suggestions are welcome (buy me a beer )
More information • LDDRIVER article in the HP technical journal http://www.hp.com/go/openvms/journal • After installation: $ LD HELP • Questions / Bugs / Ideas? Email: lddriver@digiater.nl
LD_FILE.COM $ ld create disk1.dsk /size=5000 $ ld connect disk1.dsk lda1: $ ld show lda1: $ ld trace lda1: $ init lda1: test $ mount lda1: test $ dir lda1:[000000] $ ld show/trace lda1: $ ld trace/reset lda1: $ dismount lda1: $ ld show/trace lda1: $ ld disconnect lda1: $ delete disk1.dsk;
LD_FILE_SHARE.COM $ if f$search("disk1.dsk") .eqs. "" $ then $ ld create disk1.dsk /size=5000 $ ld connect disk1.dsk lda1:/share/alloclass=4/log $ init lda1: test $ else $ ld connect disk1.dsk lda1:/share/alloclass=4/log $ endif $ mount/system lda1: test $ show dev lda1 $ inquire dummy "return to continue" $ dismount lda1: $ ld disconnect/log lda1: $ if f$search("disk1.dsk") .nes. "" then delete disk1.dsk;
LD_FILE_SHARE_LOCK.COM $ if f$search("disk1.dsk") .eqs. "" $ then $ ld create disk1.dsk /size=5000 $ ld connect disk1.dsk lda1:/share/alloclass=4/log/lock $ init lda1: test $ else $ ld connect disk1.dsk lda1:/share/alloclass=4/log/lock $ endif $ mount/system lda1: test $ show dev lda1 $ inquire dummy "return to continue" $ dismount lda1: $ ld disconnect/log lda1: $ if f$search("disk1.dsk") .nes. "" then delete disk1.dsk;
LD_FILE_TRACE.COM $ on control_y then goto exit $ ld create disk1.dsk /size=5000 $ ld connect disk1.dsk lda1:/log $ init lda1: test $ mount lda1: test $ ld trace lda1: $loop: $ dir lda1:[000000] $ wait 0:0:5 $ analyze/disk lda1: $ wait 0:0:5 $ goto loop $ dismount lda1: $exit: $ set noon $ dismount lda1: $ ld trace/stop lda1: $ ld disconnect lda1: $ delete disk1.dsk;
LD_FILE_SHADOW.COM $ ld create disk1.dsk /size=5000 $ ld create disk2.dsk /size=5000 $ ld connect disk1.dsk lda1:/log/alloclass=4 $ ld connect disk2.dsk lda2:/log/alloclass=4 $ ld trace lda1: $ ld trace lda2: $ init lda1: test $ mount dsa0:/shadow=($4$lda1:,$4$lda2:) test $ ld show/trace lda1: $ ld show/trace lda2: $ ld trace/reset lda1: $ ld trace/reset lda2: $ show shadow/copy $ inquire dummy "return to continue" $ dismount dsa0: $ ld show/trace lda1: $ ld show/trace lda2: $ ld disconnect lda1: $ ld disconnect lda2: $ delete disk1.dsk; $ delete disk2.dsk;
LD_LBN.COM $ phdev := $9$dka400: $ show dev 'phdev' $ ld connect 'phdev' lda1:/log/lbn=(start=0,count=10000) $ ld connect 'phdev' lda2:/log/lbn=(start=10000,count=10000) $ ld connect 'phdev' lda3:/log/lbn=(start=20000,count=10000) $ ld connect 'phdev' lda4:/log/lbn=(start=30000,count=10000) $ init lda1: test1 $ init lda2: test2 $ init lda3: test3 $ init lda4: test4 $ mount lda1: test1 $ mount lda2: test2 $ mount lda3: test3 $ mount lda4: test4 $ show dev lda1 $ show dev lda2 $ show dev lda3 $ show dev lda4 $ show dev 'phdev' $ inquire dummy "return to continue" $ dismount lda1: $ dismount lda2: $ dismount lda3: $ dismount lda4: $ ld disconnect/log/all $ show dev 'phdev'
LD_LBN_SHARE.COM $ phdev := $9$dka400: $ show dev 'phdev' $ ld connect 'phdev' lda1:/log/lbn=(start=0,count=10000)/share/alloclass=4 $ ld connect 'phdev' lda2:/log/lbn=(start=10000,count=10000)/share/alloclass=4 $ ld connect 'phdev' lda3:/log/lbn=(start=20000,count=10000)/share/alloclass=4 $ ld connect 'phdev' lda4:/log/lbn=(start=30000,count=10000)/share/alloclass=4 $ mount/system lda1: test1 $ mount/system lda2: test2 $ mount/system lda3: test3 $ mount/system lda4: test4 $ show dev lda1 $ show dev lda2 $ show dev lda3 $ show dev lda4 $ show dev 'phdev' $ inquire dummy "return to continue" $ dismount lda1: $ dismount lda2: $ dismount lda3: $ dismount lda4: $ ld disconnect/log/all $ show dev 'phdev'
LD_REPLACE.COM $ phdev := $9$dka400: $ show dev 'phdev' $ ld connect 'phdev' lda1:/log/replace $ ld trace lda1: $ init lda1: test1 $ mount lda1: test1 $ show dev/full lda1 $ show dev/full 'phdev' $ ld show/trace lda1: $ inquire dummy "return to continue" $ dismount lda1: $ ld disconnect/log lda1: $ show dev 'phdev'
LD_MOUNTVER.COM $ ld create disk1.dsk $ ld connect/log/symbol disk1.dsk $ init/nohigh/system lda'ld_unit': test $ mount lda'ld_unit': test $ ld trace lda'ld_unit': $ ld watch lda'ld_unit': 1/action=error=%x84/function=code=%x0808 $ ld watch lda'ld_unit': 10/action=error=%x84/function=read $ ld watch lda'ld_unit': 10/action=opcom/function=read $ ld show/watch lda'ld_unit': $ reply/enable/temp $ spawn/nowait/input=nl: dump lda'ld_unit':/block=(start=10,count=1) $ inquire dummy "return to continue" $ ld nowatch lda'ld_unit': $ ld show/trace lda'ld_unit': $ reply/disable $ wait 0:0:1 $ dism lda'ld_unit': $ set noon $ ld trace/stop lda'ld_unit': $ ld disc lda'ld_unit': $ delete/nolog/noconf disk1.dsk;