Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

admpdisk(1M)

admvdisk(1M)

dg_sysctl(2)

ioctl(2)

dsk(7)

rdsk(7)

vdmaggr(7)

vdmcache(7)

vdmdummy(7)

vdmmirr(7)

vdmmpio(7)

vdmpart(7)

vdmphys(7)

vdmremap(7)

vdmtest(7)



vdm(7)                         DG/UX R4.11MU05                        vdm(7)


NAME
       vdm - Virtual Disk Manager

DESCRIPTION
       The VDM (Virtual Disk Manager) allows you to create and manage
       "virtual disks".  Virtual disks function the same way as physical
       disks, but provide an abstraction to your data, as well as many high-
       availability features.

       The VDM enables you to subdivide the space on a physical disk into
       discrete units called partitions.  These partitions can be used
       separately as virtual disks or combined to form more complex virtual
       disks.  For example, several partitions can be combined into an
       aggregation to form a virtual disk larger than any single physical
       disk on the system.  Mirrors can be set up between partitions to
       replicate the data.  Higher availability can be achieved by
       establishing multiple redundant paths to a disk or by setting up
       software bad-block remapping.

       Furthermore, you can create virtual disks in whatever arrangements
       you need.   For example, you can create mirrors whose images are
       aggregations.  You can also create aggregations whose pieces are
       mirrors.

       The VDM provides data independence for your applications, so that
       they will function correctly, independently of where the data is
       actually stored.  This allows you to move virtual disks around on the
       system as you need to without having to make any modifications to
       your applications.

       If some of the physical disks in the system experience hardware
       problems, the VDM will maintain access to the remaining healthy
       disks.  This fault isolation limits how much of a system is affected
       when there are hardware problems.

       The VDM also provides high-availability to your data via on-line disk
       management operations.  The operations provide uninterrupted access
       to the data for users and applications.  This includes the ability to
       expand file systems on-line, move virtual disks on-line, create and
       remove software mirrors on-line, and many other operations.  Your
       applications do not need to be shut down to do disk management tasks,
       nor will you have to plan them for times when there are few users on
       the system.  The VDM allows you to perform your disk management tasks
       at your convenience.

       Pictorially, a set of virtual disks on two physical disks looks like
       this:

                                           +-------------------+
                                           | aggregation "X11" |
                                           | is 120000 blocks  |
                                           +-------------------+
                                                 |       |
                                         +-------+       +-------+
                                         |                       |
       +-------------------+   +-------------------+   +-------------------+
       |                   |   | piece 0           |   | piece 1           |
       | partition "root"  |   | partition         |   | partition         |
       | starts at 1000    |   | starts at 50000   |   | starts at 1000    |
       | is 40000 blocks   |   | is 40000 blocks   |   | is 80000 blocks   |
       +-------------------+   +-------------------+   +-------------------+
                 |                       |                       |
                 +-------+       +-------+                       |
                         |       |                               |
                   +-------------------+               +-------------------+
                   | physical          |               | physical          |
                   | sd(ncsc(0,7),0,0) |               | sd(ncsc(0,7),1,0) |
                   +-------------------+               +-------------------+
                             |                                   |
                             |                                   |
                         ----------                          ----------
                        (          )                        (          )
                        (          )                        (          )
                        (   disk   )                        (   disk   )
                        (   drive  )                        (   drive  )
                        (     1    )                        (     2    )
                        (          )                        (          )
                         ----------                          ----------

       The VDM refers to the various virtual disks (or instances) as parents
       and children.  In this example, the aggregation instance, X11, has
       two children, piece zero on sd(ncsc(0,7),0,0) and piece one on
       sd(ncsc(0,7),1,0).  The physical instance for sd(ncsc(0,7),0,0) has
       two parents, the partition "root" and the partition that is piece
       zero for the aggregation.

       The VDM creates and manages "virtual disks".  Each partition on a
       disk, or aggregation, or mirror, etc., is a virtual disk.  Each
       virtual disk behaves exactly as if it were a true physical disk of
       its own.  The interfaces for I/O to virtual disks are the same as
       those for physical disks.  This means that applications can access
       virtual disks as they normally would physical disks.  No changes to
       the applications are required to use virtual disks.  All of the
       management work that the VDM does is transparent to the applications
       using the data.

       In order to use the VDM, you must configure vdm() into your kernel.
       It appears in all new system files by default, so it is usually
       already configured.  Further, you will need to configure the various
       subdrivers you intend to use, such as vdmpart(), vdmaggr(),
       vdmmirr(), etc.

       The VDM is divided into two general parts:  the framework and the
       subdrivers.

   THE VDM FRAMEWORK
       The VDM framework provides all of the administrative management for
       the subdrivers.  Some of these functions are:

         ·    Creating, deleting, listing, and updating instances and their
              children.

         ·    Registering and deregistering physical disks.

         ·    Storing, retrieving, deleting, and updating attributes on disk
              (called persistence).

         ·    Providing common interfaces for the subdrivers, and support
              routines that are common to all of them.

   THE VDM SUBDRIVERS
       The subdrivers do all the actual I/O work for virtual disks.  There
       are nine subdriver types:

       Aggr   Provides aggregations of virtual disks to make larger virtual
              disks.

       Cache  Provides fast NVRAM or disk caches for slower back-end
              devices.

       Dummy  Used for insert and extract operations that allow the VDM to
              manipulate virtual disks on-line.

       Mirr   Provides identical copies of virtual disks for greater
              reliability.

       Mpio   Provides multiple controller paths to the same physical disk
              for greater availability.

       Part   Subdivides the space on a physical disk into discrete units
              called partitions and allows these partitions to be accessed
              as if they were separate physical disks.

       Phys   Provides access to physical disks by translating internal VDM
              interfaces to physical disk interfaces.

       Remap  Provides software bad-block remapping for greater reliability.

       Test   Provides fault injection for debugging.

       Each subdriver does only one thing.  For example, the mirror
       subdriver knows only how to keep multiple identical images, each the
       same size, consistent with each other.  Mirrors know nothing about
       what the images are (they could be partitions, aggregations, or other
       mirrors, etc.).  Likewise, mirrors know nothing about what virtual
       disks they may belong to.

       Each subdriver is also a pseudo-device driver.  Each is separately
       configurable, and they are optional.  They can be left out of kernels
       that don't need them (like diskless clients).  By default, all of
       them (except test) are automatically configured in each kernel so
       they are always available and ready to be used.

       Each subdriver does its work on child virtual disks.  Each one calls
       its children by the roles they play:

         ·    Aggregations manage pieces.

         ·    Caches manage fast front-end devices and slow back-end
              devices.

         ·    Dummy never has any children.

         ·    Mirrors manage images.

         ·    Multi-path disk I/O instances manage paths to the physical
              disk.

         ·    Partitions manage a partitioned child and a remap child.

         ·    Physical manages a physical disk.

         ·    Remap manages a primary remap table, a duplicate secondary
              remap table, and a remap area.

         ·    Test manages a single child.

       For more information about the subdrivers, see their individual man
       pages, which are: vdmaggr(7), vdmcache(7), vdmdummy(7), vdmmirr(7),
       vdmmpio(7), vdmpart(7), vdmphys(7), vdmremap(7), and vdmtest(7).

   INSTANCES
       An instance is a running copy of a subdriver doing useful work in the
       system.  The terms "instance" and "virtual disk" are synonymous.
       Instances are composed of two major parts.

       The first part is the generic characteristics for the instance, like
       its name, its instance ID, its device number, whether it is usable,
       whether it is persistent, whether it is open, whether it is quiesced
       for I/O, and some registration information about it.  The generic
       characteristics are managed by the framework.

       The second part is the type-specific attributes, which include the
       type of subdriver that is managing the instance, the pointers to the
       subdriver's I/O routines, and the instance attributes.  All this
       information, called the instance functionality, is managed by the
       subdriver itself.

       Instances have a four-part name that makes them unique:

           vdm(root,2C9730ED,0C052BED,0)

               root      is the user-defined name of the instance
               2C9730ED  is the generation number of the instance
               0C052BED  is the system ID of the instance
               0         is the duplicate number of the instance

       The user-defined name of the instance is called the short name of the
       instance. If the instance is exported ("made a volume", in sysadm(1M)
       parlance), then there will be a device node by that name in /dev/dsk
       and /dev/rdsk.  These nodes can be opened by applications so they can
       do I/O to the virtual disks.

       Regardless of whether the short name is present or unique, all
       exported instances also have a device node for their long name.  This
       allows you to access duplicate named instances and instances that
       have no short name.

       Here are some typical device nodes for an instance called "root" in
       /dev/dsk:

           brw-r----- 1 root root 24, 11 root
           brw-r----- 1 root root 24, 11 vdm(root,2C9730ED,0C052BED,0)

       The generation number is a timestamp of when the instance was created
       on the system. It is unique on a given system, even if the time is
       changed.

       The system ID is unique to each system manufactured. You can find out
       the system ID for a system with the systemid(1M) command. The VDM
       does not validate that an instance is being used on the system it was
       created on, so you are free to move disks from system to system, as
       needed.

       The combination of the generation number and system ID is unique
       across all time and machines, so it can be used to uniquely identify
       an instance.  Once assigned, an instance's ID is never changed.

       The duplicate number is used only if you have completely duplicated a
       physical disk, so the other three fields would be identical between
       two instances. The first instance would get duplicate number zero,
       the next number one, etc. Presently, DG/UX does not permit
       registration of two duplicated disks at the same time.

       Instance short names can be up to DG_VDM_MAX_INSTANCE_NAME_LENGTH
       characters long, including the required terminating null.  The name
       may be entirely null.  The name can be composed of any characters in
       the ISO-8859-1 character set (including 8-bit characters), except for
       the following:

           \001 through \037           ASCII Control Characters
                                       Space
           "                           Double Quote
           '                           Single Quote
           (                           Left Parenthesis
           )                           Right Parenthesis
           ,                           Comma
           /                           Slash
           :                           Colon
           @                           Commercial At
           \177                        ASCII DEL
           \200 through \237           Undefined Characters

       These characters are prohibited because they would interfere with
       printing instance names or with listing their names as arguments to
       commands in the various shells and system files.

   SPECIFYING INSTANCES IN COMMANDS
       All VDM commands list instances by their device number (the major and
       minor device numbers).  These device numbers are small and unique on
       a given system and are, therefore, an easy way to list instances.
       The device numbers will change from boot to boot, so they can be used
       only while the system is up.  The commands specify the device number
       in a field of type dev_t.  Using device numbers avoids having to
       transmit long character strings back and forth in the commands.

       There are two methods to translate the device number for an instance
       into the instance name.

       The first is by using the dg_sysctl(2) commands
       DG_SYSCTL_NAME_TO_DEVICE and DG_SYSCTL_DEVICE_TO_NAME.  They will
       translate an instance name to its corresponding device number so you
       can specify it in VDM commands, or translate a device number from a
       VDM command into an instance name so you can print it.

       The DG_SYSCTL_NAME_TO_DEVICE command will accept fully qualified
       instance names. It will also accept abbreviated instance names, as
       long as they are unique.  If there was only one "root" virtual disk
       on a system, all of these names will refer to it:

           vdm(root,2C9730ED,0C052BED,0)
           vdm(root,2C9730ED,0C052BED)
           vdm(root,2C9730ED)
           vdm(root)
           vdm(,2C9730ED)
           vdm(,2C9730ED,0C052BED)
           vdm(,2C9730ED,0C052BED,0)

       Since the instance number is what must be unique about an instance,
       the short name does not need to be included to translate the name to
       the device number.  If there were multiple "root" instances, then you
       would have to specify enough additional pieces of the name to make it
       unique so it could be translated (usually adding the generation
       number is enough to make it unique).  This will ensure that you are
       referring to the specific instance that you want.

       The DG_SYSCTL_DEVICE_TO_NAME command will always return the fully
       qualified name for the instance (all four components).

       The second method to translate a device number to an instance name is
       to use the DG_VDM_GET_INSTANCE_UNIQUE_NAME VDM command.  This command
       is similar to the DG_SYSCTL_DEVICE_TO_NAME command, but will always
       return the minimally unique name for an instance.  In the above
       example with a unique "root" virtual disk, the minimally unique name
       would be "vdm(root)".

       Using DG_VDM_GET_INSTANCE_UNIQUE_NAME can make printing instance
       names easier, since your application doesn't have to worry about how
       to abbreviate the name to make it unique.  The returned name will
       already be abbreviated and unique.

       The "vdm()" wrapper around the instance name identifies it as a
       device belonging to the VDM.  The wrapper is required when
       translating names.

   ATTRIBUTES
       The attributes for an instance record information about the children
       the instance is managing. They also record information about the
       state of the instance from the subdriver's perspective.  The generic
       characteristics of an instance and the type-specific information for
       it, combined, make up the attributes for the instance.

       For example, for a mirror, the attributes would include the
       instance's name, its ID, how many images it manages, whether each
       image is in sync or corrupt, the instance IDs of the images
       themselves, and whether an automatic synchronization is to be
       performed upon system reboots.

       In general, the attributes for an instance are all the things you
       specify when you create the instance. So, when you create a mirror,
       you specify whether to auto sync and what the images are. Those items
       form the attributes for the mirror instance.

       Only the subdriver that owns a given set of attributes knows how to
       interpret them. Other subdrivers of different types cannot look at
       them, and neither can the framework.  This information-hiding forms
       the basis of the on-line operations that the VDM offers.

   DOING I/O TO VIRTUAL DISKS
       I/O is done to virtual disks the same way it is done to physical
       disks.  The standard system call interfaces are open(2), lseek(2),
       read(2), write(2), and close(2).  There are other interfaces as well
       (such as dg_block_seek(3C)), but they all have the same basic
       functionality.

       All virtual disks are divided up into 512-byte segments, called disk
       blocks.  Virtual disks are addressed by block numbers, which start at
       zero, and go to N-1, where N is the number of blocks in the virtual
       disk.  The application opening a virtual disk should consider the
       virtual disk to be one large contiguous region.  The application does
       not need to know that it might be a mirror, or an aggregation, and it
       does not need to know which physical disk on which any given block is
       stored.

       Virtual disks follow the normal file-access semantics, with some
       additions:

       1.     I/O requests to the buffered device node for a virtual disk
              (the node in /dev/dsk) may begin on any byte boundary and may
              be any number of bytes long.  The minimum request is one byte.

              Read I/O requests may not actually read from the disk if the
              data is already buffered in memory buffers.

              When a write I/O request returns, the data is not guaranteed
              to be on disk.  It may still be held in memory buffers to be
              flushed later, and therefore may be lost due to unexpected
              system outages.  The application can use the O_SYNC flag to
              the open(2) system call to force write flushing on each I/O if
              desired.  If flushing is requested, the I/O request will not
              return until the data is on disk.

       2.     I/O requests to the raw (unbuffered) device node for a virtual
              disk (the node in /dev/rdsk) must begin on a 512-byte disk
              block boundary, and must be a multiple of disk blocks long.
              The minimum request is one block.

              Read I/O requests will always read from disk.

              When a write I/O request returns, the data is guaranteed to be
              on disk, and will not be lost due to unexpected system
              outages.

       3.     I/O requests that start within a virtual disk but run off the
              end of it will succeed, and the VDM will truncate them to the
              end of the virtual disk.  The normally returned status
              information will indicate that the returned data is less than
              the requested size.

       4.     I/O requests that start off the end of the virtual disk will
              fail and will return an error.

       5.     If two threads are both issuing I/O requests to the same
              virtual disk, the I/O requests may be overlapped and
              interleaved in execution order.  The VDM does not lock virtual
              disks when I/O is done to them, so multiple threads may issue
              I/Os to the same disk blocks at the same time.  The order in
              which the I/Os are executed is not defined.  If the ordering
              between threads is important, then the applications must
              cooperate via some application-defined locking mechanism to
              avoid trampling on each other's I/O.

       6.     Reads to disk blocks that have not previously been written to
              will return whatever data was last written there when it was a
              part of some previous virtual disk.  The VDM does not scrub
              disk blocks before first-time reads.

       See the dsk(7) and rdsk(7) man pages for further details.

   VIRTUAL DISK INFORMATION TABLES
       All of the information about instances and their attributes are
       stored by the VDM in the Virtual Disk Information Table (VDIT) on
       each physical disk.  The VDM handles reading, writing, modifying, and
       deleting entries from these tables as the instances are manipulated.

       A VDIT for a disk will contain all instances and attributes for any
       virtual disk that has any piece of it living on the physical disk.
       The rule is that an instance's attributes are stored on all disks
       that any of its children are stored on.  So, for example, if you had
       an aggregation that spanned two physical disks, the aggregation
       instance would be stored on both disks.  Each of the pieces would be
       stored only on the disk that it resides on.

       This redundancy ensures the best chance of properly recreating all
       the virtual disks for a system, even if one disk is missing.  In such
       a case, you would still see the aggregation that partially lives on
       the missing disk, but it would not be able to be used since some of
       its pieces were missing.

       The VDM maintains two copies of the VDIT on each disk, called the
       primary and secondary copies.  They contain exact copies of all of
       the information for redundancy and are kept in sync by the VDM.  If
       one VDIT became damaged somehow, which is quite rare, the VDM could
       continue to use the disk in degraded mode using a single VDIT.  While
       in degraded mode, you will not be able to create new virtual disks or
       modify the attributes of existing ones that live on the physical
       disk.  You will be able to do I/O to the file systems and databases
       you have stored on the disk, so your applications can continue to
       run.  Use the repair_vdit operation of the admpdisk(1M) command to
       repair a damaged VDIT.

       The VDM uses its own features to manage the VDITs on the disk.  As a
       disk is registered, the VDM will create partitions and aggregations
       to manage the various system areas, like the disk label and the
       VDITs.  These system areas have descriptive names that begin with a
       period.  The admvdisk(1M) and admpdisk(1M) commands by default will
       not list these system areas, since they are generally not of interest
       to system administrators.  These system virtual disks cannot be
       manipulated.

   PERSISTENCE
       Normally, any change to the attributes of an instance is written to
       the VDIT.  Such an instance is called "persistent", since changes to
       it will persist across system reboots.

       However, for certain VDM operations (like virtual disk copies and
       moves), non-persistent instances are used because the changes should
       be made only to the instances in memory.  Any changes to a non-
       persistent instance will be lost when the system is rebooted.

       The persistence for an instance is controlled by two states:
       persistence, and whether disk updates are enabled.  The table of
       these states is:

           State Name      Persistent      Updates Enabled
           ----------      ----------      ---------------

           Persistent         yes                yes

               This is the normal state for instances.  The instance is
               stored on disk, and changes to it will be written to disk.

           Floating           yes                no

               The instance is stored on disk, but changes to it will not
               be written to disk.  This state allows changes to the
               instance to be made in memory only.

               You cannot delete a floating instance.  Change it to be
               persistent before deleting it.  This restriction keeps the
               memory and disk views of the virtual disks consistent.

           Illegal            no                 yes

               This is an illegal state combination.

           Temporary          no                 no

               The instance is not stored on disk, and changes to it will
               also not be written to disk.  An instance in this state
               exists in memory only.

       The transition of an instance from one state to another may result in
       its attributes being written to or deleted from disk, as the
       following table shows.  Other transitions are not legal.

           Old State       New State       Action
           ---------       ---------       ------

           Persistent      Floating        No change is made to the instance
                                           on disk.  Further changes to the
                                           instance are not reflected on disk.

           Persistent      Temporary       The instance is deleted from disk,
                                           but will still exist in memory
                                           until it is either deleted or the
                                           system is rebooted.

           Floating        Persistent      The instance is written to disk.

           Temporary       Persistent      The instance is written to disk.

       We recommend that your custom-built applications always use
       persistent instances, and that you not alter the persistence of the
       instances after they are created.  You can get the in-memory instance
       and the on-disk instance out of sync if you do not manipulate the
       persistence of the instance properly.  This will result in behavior
       that you won't expect when the system is rebooted (like your changes
       being lost).

   REGISTERING AND DEREGISTERING DISKS
       In order for the VDM to use a disk, it must first be formatted.  This
       is done with the admpdisk(1M) command's initialize operation.  This
       command writes empty VDITs onto the disk.

       After the disk is initialized, the disk must be registered with the
       VDM so that it knows it exists.  This is done with the
       DG_VDM_REGISTER_DISK ioctl(2) command.  This command causes the VDM
       to read the VDIT from the disk and recreate the virtual disks in
       memory so they can be used.  The sysadm(1M) and admpdisk(1M) commands
       provide an easy interface for registering and deregistering disks.

       When a system is booted, the VDM will attempt to automatically
       register all disks that are configured on the system.  This makes the
       disks immediately available for use when the system is booted.

       If you want to remove a physical disk from a system, you must first
       deregister it from the VDM so it will stop using it.  This causes the
       VDM to write any final information to the VDIT, and then remove the
       instances from memory that are associated with that physical disk.
       In order to do this, those instances must not be open, so you must
       unmount any file systems and close any databases using those
       instances before you deregister the disk.

       You can register and deregister disks on the system while it is
       running if you need to add or remove disks from the system, as long
       as the disks are not currently in use.

       To avoid confusion, you should register and deregister groups of
       related physical disks together.  This means that if an aggregation
       spans multiple physical disks, things will be less confusing if you
       register or deregister all the physical disks that the aggregation
       lives on at the same time.  It will work properly if you do them
       separately, but you may get confusing messages on the operator's
       console about missing children from the disks that are not yet
       registered.

   MULTIPLE ROOT AND SWAP VIRTUAL DISKS
       You can set up your system with multiple root and swap virtual disks
       so that you can boot multiple revisions of DG/UX or multiple DG/UX
       configurations.  This can be done by naming the root and swap virtual
       disks something unique for each case, like "root_current" and
       "root_previous", and setting boot defaults for the physical disk.

       The easiest way to arrange things is to keep all the virtual disks
       for one boot together on one physical disk, and the other virtual
       disks for an alternate booting on a different physical disk.  Then
       for each physical disk, set the boot defaults for it naming the root
       and swap that are contained on it.

       Then when you boot each disk, you need only list the name of the disk
       and the kernel you want booted.  The bootstraps and the VDM will look
       at the boot defaults on the disk to determine where to load the
       kernel image from and what virtual disks to use for swapping and to
       mount as the root file system.  This makes the boot command lines
       much smaller and easier to type.

       If you want to put both root virtual disks on the same physical disk,
       you may.  In this case, before each time you want to reboot the
       system with the other root, change the boot defaults on the physical
       disk first, then reboot the system.

       The default root and swap virtual disks for a boot disk can be set
       with the DG_VDM_SET_BOOT_INFO command.  You can also use the
       admpdisk(1M) set_boot_defaults operation.

   CLUSTER DISKS
       The DG/UX Cluster Software is an optional DG/UX add-on that will
       automate many features of multi-system resource management, failover,
       and high availability.  A DG/UX cluster is a group of two or more
       interconnected computer systems (referred to as nodes) acting
       together in a closely coordinated way.  A cluster does what a server
       in a client/server environment does: manages computing resources and
       provides services to clients.

       Normally, only one system may use a VDM formatted physical disk at a
       time (it can only be registered on one host at a time).  This
       protects the VDIT and user data because all I/O will come from the
       single host.

       In a cluster system, however, the physical disks are actively shared
       among all nodes in the cluster.  They are registered on all nodes
       simultaneously.

       The VDM will distribute changes to the virtual disk information among
       the nodes in the cluster so that all nodes will always have the same
       view of the them.  For example, if a virtual disk is created on a
       cluster disk, the VDM will inform the other nodes in the cluster so
       that they, too, can create the virtual disk on their system.  The
       result is that virtual disk changes are visible on all nodes in the
       cluster at the same time.  The VDM does this work atomically, so the
       nodes will always be in sync.

       The VDM does not distribute the I/O to the virtual disks, only the
       attributes of the virtual disks.  I/O to a cluster virtual disk is
       permitted simultaneously on all nodes of a cluster.  The applications
       must cooperate to control the I/O to avoid overwriting data that has
       been written by other nodes.  The VDM cannot help in this control, it
       must be done by the applications themselves.

       This is not an added burden for cluster systems.  Such application
       coordination must already be done for I/O to the virtual disks by
       more than one application instance on a single node system.

       In order to be made available to a cluster, a physical disk must be
       connected to a shared SCSI bus that is connected to all cluster
       nodes.  The physical disk must then be put into cluster mode.  This
       is done with the DG_VDM_CLUSTER_DISK command.  The disk must first be
       registered on one node, then placed into cluster mode.  The disk can
       then be registered on the other nodes of the cluster.

       You must cluster and uncluster related groups of physical disks
       together, so that their cluster visibility is consistent.  This
       means, for example, that if you have an aggregation that spans two
       disks, both disks must be changed to cluster mode together.  The VDM
       enforces this rule and will return error information to help you
       identify other disks that must be included in the operation if the
       set of disks is not closed.

       Cluster disks may not be registered on non-cluster systems.  This is
       a safeguard to protect the data on the disks, since cluster
       operations on the disks cannot safely be done on non-cluster systems.
       If you wish to move a cluster disk to a non-cluster system, first
       uncluster it while it is still attached to the cluster, then move it
       to the non-cluster system.

       Non-cluster disks may be placed on the shared SCSI bus if desired.
       They will be registered to the first node that attempts to register
       them.  All other nodes will be denied all access to the disk.

       You may not uncluster the physical disk that the Cluster Membership
       Manager database virtual disk (usually called "cluster_db") is on
       while any node is joined to the cluster.  In order to uncluster this
       disk, you must bring down the cluster and run one node in cluster
       administration mode.

       Similarly, you may not rename the Cluster Membership Manager database
       while any node is joined to the cluster.  Use cluster administration
       mode if you need to rename this virtual disk.

       Subclusters, overlapping clusters, and shared SCSI busses that are
       not fully connected to all cluster nodes are not supported.

       All but one of the VDM commands are available on cluster disks.  You
       execute them just as you would if the disks were not clustered, so
       the cluster state is mostly invisible to the commands.  They may
       execute somewhat more slowly on cluster disks, because the VDM must
       distribute the operation to the other nodes.

       The operation you cannot do on cluster disks is:

           DG_VDM_UPDATE_INSTANCE (to change the persistence of
                                   a cluster instance)

       Some subdriver types and subdriver operations are not supported on
       cluster disks as well.  See the man pages for the various subdrivers
       for additional details.

       In general, to do these VDM and subdriver operations on cluster
       disks, uncluster the disks so they are registered on a single node,
       then do the operations, then cluster the disks again, making them
       available to the other nodes in the cluster.

       Virtual disk lists from sysadm(1M) or admvdisk(1M) will list only the
       virtual disk information visible to the node on which the command is
       executed.  Non-cluster disks on other nodes will not be listed.  This
       includes I/O performance statistics gathered by DSKIOCUSAGE.  The
       statistics will reflect only the I/O performed from the executing
       node.

       The admpdisk(1M) cluster and uncluster operations can be used to
       change the cluster mode of a physical disk.

       Boot defaults for root and swap virtual disks are not supported on
       cluster disks.  This information is kept in the cluster database
       instead.

       Cluster operations are supported on systems only if you have
       purchased and installed the separate DG/UX Cluster Software product.
       The VDM will reject cluster operations on non-cluster systems.

   M88K AND INTEL IX86 DISKS
       The VDM supports physical disks on both M88K and Intel (IX86)
       systems.  All VDM functionality is available and used identically on
       both platforms.

       However, the VDM disk format on the two systems is different.  This
       is transparent to all applications, but important to know from an
       operational standpoint.

       The VDM is able to use the entire physical disk for M88K disks.  This
       means the primary VDIT is placed near the beginning of the physical
       disk and, the secondary VDIT is placed near the end.  All the free
       space in the middle is available for creating user virtual disks.

       Intel disks, however, are PC-partitioned.  This allows the DG/UX
       system to coexist with other operating systems that may also be
       installed on the disk.  One of the possible four PC partitions is
       assigned to DG/UX, and all DG/UX data is stored within this PC
       partition.  The primary VDIT is placed near the beginning of this PC
       partition, and the secondary VDIT is placed near its end.  All the
       remaining free space within the PC partition is available for
       creating user virtual disks.

       The VDM will create temporary partitions over the PC partitions
       assigned to other operating systems, as well as any unassigned free
       space outside the PC partitions when the disk is registered.  These
       virtual disks cannot be manipulated.

       Beyond this disk format difference, the VDM operations to create,
       delete, list, and manipulate virtual disks are identical on both
       platforms.  Applications that issue VDM commands will work properly
       on both platforms, once recompiled for the target platform.

       The VDM does not support registering disks from alternate platforms.
       This means that M88K systems may register only M88K formatted disks,
       and Intel systems may register only Intel formatted disks.  You
       cannot move physical disks from one platform to another with this
       release of DG/UX.  If a disk is moved, the VDM will refuse to
       register it.  For a disk to be usable on the alternate platform, it
       must be reformatted with the native format, which will wipe out all
       the data on the disk.

   CLARiiON® DISKS
       CLARiiON® hardware disk arrays offer some of the same features as
       virtual disks do, such as caching, striping, and mirroring.  In
       general, the virtual disk features are more flexible, while the
       CLARiiON® features have better performance since they implemented in
       hardware.  You can freely mix and match the virtual disk and
       CLARiiON® disk features to suit your particular needs.  Both sets of
       features are fully compatible.

   CHANGE AND TOPOLOGY TICKETS
       The VDM maintains global and per-instance change and topology tickets
       to help applications determine what parts of the system have changed
       due to VDM commands being issued.

       The change ticket is incremented when any change is made to an
       instance.  This includes simple changes reported by the
       DG_VDM_GET_INSTANCE_INFO command, as well as the complex changes
       tracked by the topology tickets.

       The topology ticket is incremented when the connections to an
       instance are changed, like when a new child is linked to it.  The
       topology ticket also tracks instance creates and deletes, and disk
       registers and deregisters.

       In an application, remember the tickets for the instances you are
       manipulating, then do the operations you want, then get the tickets
       again.  If the new ticket values are different from the saved ones,
       then something changed with the instances, and the application should
       reevaluate the operation it just did.

       This is particularly useful for an application that loops listing
       instances and runs for long periods of time.  Without the tickets, it
       would have to retrieve all the information about all the instances it
       is interested in each time through the loop, in order to keep the
       information up-to-date with any changes that are made on the system.
       With the change and topology tickets, the application can cache large
       amounts of the information for much better performance, since it
       won't be changing, and instead update only those parts that have
       changed from loop to loop.

       Check the global change and topology tickets to determine if any
       changes have been made in the system at the top of each loop.  If the
       global tickets are the same as they were on the last loop iteration,
       then nothing has changed, and the application can continue to use its
       cached information.

       If either global ticket has changed, then the application should get
       the per-instance tickets for the instances it is interested in to
       determine what information has changed.  If the topology ticket
       changes, then the application should also re-evaluate the list of
       instances and registered physical disks it is caching, since
       instances may have been created or deleted, and disks may have been
       registered or deregistered.

       The global change and topology tickets are retrieved by the
       DG_VDM_GET_CHANGE_TICKET and DG_VDM_GET_TOPOLOGY_TICKET commands.
       The per-instance tickets are retrieved with the
       DG_VDM_GET_INSTANCE_INFO command.

   CONFIGURATION VARIABLES
       The VDM uses one configuration variable in the DG/UX system file.  It
       is called IOSTATS, and it controls whether the VDM will gather I/O
       performance statistics on virtual disk I/O.

       These statistics are reported for each virtual disk by the
       DSKIOCUSAGE command; they include the number of read and write
       requests, the number of blocks read and written, and the device busy
       and response times.  These statistics are reported by the nsar(1)
       performance tool, among others.

       The default for the configuration variable is "1", which means that
       I/O statistics should be gathered.  To turn off I/O statistics
       gathering, add a line with "IOSTATS 0" to your system build file.

       Disabling I/O statistics gathering may result in a small performance
       improvement but invalidates some of the reporting done by nsar(1) and
       other similar tools.

       The VDM shares the configuration variable with the disk device
       drivers.  Its setting affects both the VDM and the disk drivers
       simultaneously.

   HALT DUMPS TO VIRTUAL DISKS
       When the DG/UX system abnormally halts due to a hardware problem or
       an internal DG/UX problem, you are given the opportunity to take a
       halt dump to submit with a Software Trouble Report (STR).

       You can take the halt dump to a virtual disk that you have previously
       set up.  This is many times faster than taking the dump to tape.
       When prompted for the dump destination device, type in a
       specification of the form:

              vdm_dump(physical_disk_spec,virtual_disk_name)

       For example:

              vdm_dump(sd(ncsc(0,7),0,0),dump)

       The virtual disk you name must have been created prior to the halt.
       The halt dump process cannot create it.  Further, the virtual disk
       should not be used for any purpose other than to hold halt dumps.
       You should not create a file system on it because the halt dump will
       wipe out all data in the virtual disk when the dump is written there.

       The halt dump virtual disk must be a single simple partition.  It may
       use bad-block remapping if desired.

       After the dump is taken, repair the problem and reboot the system.
       While the system is up, use the -t option of the lsd(1M) command to
       transfer the halt dump from the virtual disk to a tape, so you can
       submit it for analysis.

       You can make the virtual disk dump specification the default for your
       system by using the -f option of the dg_sysctl(1M) command, and by
       setting the DUMP configuration variable in your system build file.

   SYSTEM CONSOLE ERROR MESSAGES
       If the VDM encounters a serious error condition, it will send a
       message to the operator's console to alert them that they must take
       some corrective action.  These messages will be as precise as
       possible, listing the names of virtual and physical disks involved,
       along with a status code that provides additional information.

       You can look up the status codes in the file
       /usr/release/dgux_<revision>.status.codes.  This is an ASCII text
       file and can be viewed with an editor or more(1).

       The messages will also be logged through syslogd(1M) and will be
       saved in the file /var/adm/messages so you can review them later.

   ADMVDISK, ADMPDISK, AND SYSADM
       The admvdisk(1M) command provides a convenient command line interface
       to the virtual disk functionality described here.  With it you can
       perform all of the VDM operations without having to build customized
       programs.  The sysadm(1M) menu-driven interface also allows you to
       perform the operations without having to remember command line
       options.

       The admpdisk(1M) command likewise provides a convenient interface to
       the physical disk functionality described here.  There are also
       sysadm(1M) menus for performing these operations.

       We recommend you use sysadm(1M), admvdisk(1M), and admpdisk(1M) for
       administering the physical and virtual disks on your system.  Build
       specialized custom programs using the VDM programming interface if
       there are special tasks you need to do that cannot be done with one
       of the standard DG/UX administration tools.

       If your custom use of the VDM has general applicability to other
       users, we would appreciate you filing a Request For Enhancement
       Software Trouble Report with your local Data General representative
       so we can evaluate it and add it to the standard administration
       tools.

PROGRAMMING INTERFACE
       The ioctl(2) system call is used for all communication with the VDM.
       Use the open(2) system call to open a channel to the /dev/vdm node,
       and issue all ioctl(2) commands through that channel.  The /dev/vdm
       device node exists whenever the VDM is configured into the system,
       and it may be opened by all users so they may issue commands to the
       VDM.  Privilege checks are done for each command that is issued.

       This is a very easy way to issue VDM commands, since the only other
       way would be to open individual virtual disks (which does require
       privilege) and issue the commands to the virtual disk itself.  This
       would be quite cumbersome to do and not even possible for virtual
       disks that are not exported (i.e., those that do not have device
       nodes in /dev/dsk and /dev/rdsk).

       The <sys/ioctl.h> include file is required for communicating with the
       VDM.  The <errno.h>, <sys/dg_sysctl.h>, <sys/types.h>, <stdio.h>, and
       <unistd.h> include files will be helpful.

   PACKET HANDLING
       All of the packets have version fields in them so we can expand them
       in the future if needed and still support existing applications using
       the old packets, without requiring them to be recompiled or relinked.
       Be sure to always set the proper version number in each packet.
       There is no need to zero the packets before using them.

       Many of the commands, like DG_VDM_CREATE_INSTANCE, are executed using
       multiple packets.  For create, you use two packets.  The first is the
       generic create packet.  You also build a type-specific create packet,
       as for a partition.  You put a pointer to the subdriver packet into
       the generic create packet, then issue the command to the VDM.

       Many of the listing operations use a key-based and array-based
       mechanism to return the information, since they can return long
       lists.  You allocate an array of one or more of the structures to be
       returned.  Then you initialize the key to zero and make the first
       call.

       The VDM will fill in as many of the array elements as it can,
       returning the number filled so you know what was done.  It also
       increments the key so it knows where in the list it was when the
       called ended.  You then process the entries in the array that were
       filled in.

       Next you issue the command again, being careful to not alter the key
       value.  The VDM will start filling in the array again, picking up in
       the list where it left off during the first call.

       The DG_VDM_LIST_INSTANCES command is a good example of this type of
       command.

   ERROR HANDLING
       In every case of an error generated by the framework or a subdriver,
       errno will be set, as well as the extended errno.  The extended errno
       points to a detailed text message that describes the error.  Use the
       dg_ext_errno(2) system call to get the extended errno; and the
       extended_strerror(3C) library call to translate it to the text
       string.  You can use the extended_perror(3C) library call to do both
       steps at once if you care to.

       If there is an extended error text string available for an error, it
       is preferable to have your application print it instead of the
       standard errno text string, since the extended text string is much
       more detailed.  See the DIAGNOSTICS section of this man page for a
       listing of the VDM extended errno text strings.

       The admvdisk(1M) and admpdisk(1M) commands always print out the
       extended errno text when there is an error.

FRAMEWORK-SPECIFIC COMMANDS
       The following VDM commands are used to manipulate instances.  Many of
       them require as input or return as output subdriver defines and/or
       structures.  See the various subdriver man pages for the details on
       the subdriver-specific information.

   DG_VDM_CREATE_INSTANCE
       Creates an instance.

   DG_VDM_UPDATE_INSTANCE
       Updates the generic information for an instance (like its name).

   DG_VDM_UPDATE_ATTRIBUTES
       Updates the subdriver-specific attributes for an instance.

   DG_VDM_DELETE_INSTANCE
       Deletes an instance.

   DG_VDM_EXPORT_INSTANCE
       Exports an instance, creating device nodes for it in /dev/dsk and
       /dev/rdsk.

   DG_VDM_UNEXPORT_INSTANCE
       Unexports an instance, removing the device nodes for it from /dev/dsk
       and /dev/rdsk.

   DG_VDM_GET_INSTANCE_INFO
       Returns generic information about an instance (like its name).

   DG_VDM_GET_ATTRIBUTES
       Returns the subdriver-specific attributes for an instance.

   DG_VDM_LIST_INSTANCES
       Returns the device numbers for all instances in the system.

   DG_VDM_IOCTL_SUBDRIVER
       Issues an ioctl(2) command directly to a subdriver.

   DG_VDM_INSERT_INSTANCE
       Inserts a new instance into the middle of an existing instance
       hierarchy.

   DG_VDM_EXTRACT_INSTANCE
       Extracts an instance from the middle of an existing instance
       hierarchy.

   DG_VDM_LINK_CHILD_INSTANCE
       Links a new child instance to a parent instance.

   DG_VDM_GET_CHILD_INSTANCE
       Returns the device numbers of the child instances that are owned by a
       parent instance.

   DG_VDM_GET_PARENT_INSTANCE
       Returns the device numbers of the parent instances which own a child
       instance.

   DG_VDM_UNLINK_CHILD_INSTANCE
       Unlinks a child instance from a parent instance.

   DG_VDM_REGISTER_DISK
       Introduces a DG/UX formatted disk to the system so that it can be
       used.  The instances that manage the data on the disk are
       automatically recreated.

   DG_VDM_DEREGISTER_DISK
       Removes a DG/UX formatted disk from the system, so that it can no
       longer be used.  All instances that manage some portion of the data
       on the disk are automatically removed from the system.

   DG_VDM_LIST_REGISTERED_DISKS
       Returns the device numbers of the physical disks that are registered
       with the VDM.

   DG_VDM_LIST_SUBDRIVERS
       Returns the subdriver IDs of the subdrivers configured with the VDM.

   DG_VDM_GET_CHANGE_TICKET
       Returns a ticket for the last attributes or topology change made that
       altered any instance in the system.

   DG_VDM_GET_SUBDRIVER_INFO
       Returns generic information about a subdriver (like its name).

   DG_VDM_LOGGING
       Turns kernel trace logging on or off for specific instances and/or
       for all instances managed by specific subdrivers.

   DG_VDM_SET_BOOT_INFO
       Sets the default root and swap instances to be used when booting from
       a disk.

   DG_VDM_GET_BOOT_INFO
       Returns the default root and swap instances which are used when
       booting from a disk.

   DG_VDM_GET_TOPOLOGY_TICKET
       Returns a ticket for the last topology change made that altered any
       instance in the system.

   DG_VDM_GET_INSTANCE_UNIQUE_NAME
       Returns the minimally unique name for an instance.

   DG_VDM_CLUSTER_DISK
       Changes the clustering mode of registered physical disks so that they
       are either available or unavailable for use by multiple nodes in a
       cluster.

COMMON DISK COMMANDS
       The following commands are common to all device drivers that manage
       physical disks.  The VDM and the subdrivers support the commands on
       virtual disks as well, because they present the same interfaces as
       physical disks.

   DSKIOCGET
       This command returns the size of the virtual disk in sectors.  For
       virtual disks, one sector is one disk block, or 512 bytes.  The
       command and associated structure is described in more detail in
       dsk(7).

   DSKIOCUSAGE
       This command returns I/O count and performance statistics on the I/O
       issued to a virtual disk.  The command and associated packet is
       described in more detail in dsk(7).

FRAMEWORK-SPECIFIC DEFINES
       The following defines are used in the VDM framework commands as well
       as some VDM subdriver commands.

   DG_VDM_IOCTL_PACKET_VERSION_0
       The version zero stamp used in all VDM ioctl(2) packets.

       The stamp indicates which version of the VDM interface is being used
       and allows the VDM to support previous versions without requiring
       that applications be recompiled.

   DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_1
       The stamp used in version one of the DG_VDM_GET_INSTANCE_INFO
       ioctl(2) packet.

   DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_2
       The stamp used in version two of the DG_VDM_GET_INSTANCE_INFO
       ioctl(2) packet.

   DG_VDM_MAX_INSTANCE_NAME_LENGTH
       The maximum length of a simple VDM instance name, in bytes, including
       the terminating null.

   DG_VDM_MAX_INSTANCE_UNIQUE_NAME_LENGTH
       The maximum length of a fully qualified unique VDM instance name, in
       bytes, including the terminating null.

   DG_VDM_MAX_SUBDRIVER_NAME_LENGTH
       The maximum length of a VDM subdriver name, in bytes, including the
       terminating null.

   DG_VDM_SUBDRIVER_ID_OF_A_NON_VDM_DEVICE
       The unique ID that identifies a device that is not a VDM instance,
       but rather a physical disk device.

   DG_VDM_NO_SUBDRIVER_ID
       The unique ID that indicates that the subdriver managing an instance
       isn't known because the instance itself is missing.

   DG_VDM_NO_DUPLICATE_NUMBER
       The unique ID that indicates that the duplicate number of an instance
       isn't known because the instance does not exist.

STRUCTURES
       The following VDM structures are used to manipulate instances.  Many
       of them require as input or return as output subdriver defines and/or
       structures.  See the various subdriver man pages for the details on
       the subdriver-specific information.

   dg_vdm_instance_id
       A VDM instance ID.  Each instance has a unique instance ID that
       distinguishes it from all other instances across all systems and
       across time.  Instance IDs are never changed once assigned, nor are
       they reused.

       struct      dg_vdm_instance_id
           {
           unsigned int    generation;
           unsigned int    system_id;
           };

       generation
              A unique generation number that distinguishes an instance from
              all other instances created on the same system.

       system_id
              A unique system ID that identifies the system that the
              instance was created on.

   dg_vdm_instance_specifier
       A VDM instance specifier, allowing an instance to be referenced
       either by its device number or its instance ID.

       Various VDM ioctl(2) commands require or return instance identifiers.
       In most situations, the instance is known to exist, so its device
       number is sufficient to reference it.  In other cases, however, the
       instance does not currently exist, so its instance ID must be used to
       reference it.

       In cases where the instance may or may not exist, depending on the
       situation, an instance specifier is used so that either the
       instance's device number or its instance ID can be used to reference
       it.  Instances may be missing for a variety of reasons, but the most
       common one is that the disk that the instance resides on is not
       registered.

       struct      dg_vdm_instance_specifier
           {
           unsigned int                    device_number_used : 1;
           union
               {
               dev_t                       device_number;
               struct dg_vdm_instance_id   id;
               } specifier_value;
           };

       device_number_used
              If set to one, the device number field of the specifier is
              being used to reference the instance.  Otherwise, the instance
              ID field is being used to reference the instance.

       specifier_value
              The specifier value for the instance being referenced.  The
              device_number_used field determines which of the two values
              (device_number or id) is being used in the union.

       device_number
              The device number of the instance being referenced.

       id     The instance ID of the instance being referenced.

   dg_vdm_create_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_CREATE_INSTANCE command.  The
       command creates an instance.

       struct      dg_vdm_create_instance_packet
           {
           int             version;
           unsigned int    subdriver_id;
           void *          subdriver_attributes_packet_ptr;
           unsigned int    persistent          : 1;
           unsigned int    enable_disk_updates : 1;
           char            instance_name [DG_VDM_MAX_INSTANCE_NAME_LENGTH];
           dev_t           device_number;
           };

       version
              The version of the packet.

       subdriver_id
              The ID of the subdriver that is to manage the instance.

       subdriver_attributes_packet_ptr
              A pointer to a subdriver-specific attributes packet (if any),
              which specifies any information the subdriver needs to create
              the instance.

       persistent
              If set to one, it indicates that the instance is to be stored
              on disk so that it will persist across system reboots.
              Otherwise, the instance is kept only in memory and will be
              lost when the system is next rebooted.  Normally, instances
              should be created persistent.

       enable_disk_updates
              If set to one, it indicates that changes to the instance's
              information and attributes are allowed to be stored on disk so
              that they will persist across system reboots.  Otherwise, the
              changes will be made only to the instance in memory, and those
              changes will be lost when the system is next rebooted.
              Normally, instances should be created with disk updates
              enabled.  Disk updates are disabled in order to make temporary
              changes to an instance in memory only.

       instance_name
              The name of the instance.  The name does not need to be
              unique, but making it unique will reduce confusion.  The name
              may be null.  The name must be null-terminated.

       device_number
              The returned device number of the created instance.

   dg_vdm_update_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_UPDATE_INSTANCE command.  The
       command updates the generic information for an instance (like its
       name).

       struct      dg_vdm_update_instance_packet
           {
           int             version;
           dev_t           device_number;
           unsigned int    update_persistent          : 1;
           unsigned int    update_enable_disk_updates : 1;
           unsigned int    update_instance_name       : 1;
           unsigned int    persistent                 : 1;
           unsigned int    enable_disk_updates        : 1;
           unsigned int    partially_exported         : 1;
           char            instance_name [DG_VDM_MAX_INSTANCE_NAME_LENGTH];
           };

       version
              The version of the packet.

       device_number
              The device number of the instance to update.

       update_persistent
              If set to one, it indicates that the persistent field should
              be used to update the instance.  Otherwise, the instance's
              persistence is not changed.

       update_enable_disk_updates
              If set to one, it indicates that the enable_disk_updates field
              should be used to update the instance.  Otherwise, the
              instance's disk update state will not be changed.

       update_instance_name
              If set to one, it indicates that the instance_name field
              should be used to update the instance.  Otherwise, the
              instance's name will not be changed.

       persistent
              If set to one, it indicates that the instance is to be stored
              on disk so that it will persist across system reboots.
              Otherwise, the instance is kept only in memory and will be
              lost when the system is next rebooted.  Normally, instances
              should be left persistent.  This field is used only if
              update_persistent is set to one.

       enable_disk_updates
              If set to one, it indicates that changes to the instance's
              information and attributes are allowed to be stored on disk so
              that they will persist across system reboots.  Otherwise, the
              changes will be made only to the instance in memory, and those
              changes will be lost when the system is next rebooted.
              Normally, instances should be left with disk updates enabled.
              Disk updates are disabled in order to make temporary changes
              to an instance in memory only.  This field is used only if
              update_enable_disk_updates is set to one.

       partially_exported
              A returned field indicating whether the new instance name was
              partially exported.  If set to one, it indicates that only the
              new long name of the instance was able to be exported.  The
              new short name was not exported because it conflicted with
              another instance having the same name, or it was null.  This
              field is valid only if update_instance_name is set to one and
              the instance is exported.

       instance_name
              The new name of the instance.  The name does not need to be
              unique, but making it unique will reduce confusion.  The name
              may be null.  The name must be null-terminated.  This field is
              used only if update_instance_name is set to one.

   dg_vdm_update_attributes_packet
       The VDM ioctl(2) packet for the DG_VDM_UPDATE_ATTRIBUTES command.
       The command updates the subdriver-specific attributes for an
       instance.

       struct      dg_vdm_update_attributes_packet
           {
           int             version;
           dev_t           instance_device_number;
           unsigned int    subdriver_id;
           void *          subdriver_attributes_packet_ptr;
           };

       version
              The version of the packet.

       instance_device_number
              The device number of the instance whose attributes are to be
              updated.

       subdriver_id
              The ID of the subdriver that manages the instance.  This
              ensures that the subdriver you think is managing the instance
              is really still managing the instance when you issue the
              command.

       subdriver_attributes_packet_ptr
              A pointer to a subdriver-specific attributes packet (if any),
              which specifies any information the subdriver needs to update
              the instance.

   dg_vdm_delete_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_DELETE_INSTANCE command.  The
       command deletes an instance.

       struct      dg_vdm_delete_instance_packet
           {
           int     version;
           dev_t   device_number;
           };

       version
              The version of the packet.

       device_number
              The device number of the instance to delete.

   dg_vdm_export_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_EXPORT_INSTANCE command.  The
       command exports an instance, creating device nodes for it in /dev/dsk
       and /dev/rdsk.

       struct      dg_vdm_export_instance_packet
           {
           int             version;
           dev_t           device_number;
           unsigned int    partially_exported : 1;
           };

       version
              The version of the packet.

       device_number
              The device number of the instance to export.

       partially_exported
              A returned field indicating whether the instance name was
              partially exported.  If set to one, it indicates that only the
              long name of the instance was able to be exported.  The short
              name was not exported because it conflicted with another
              instance having the same name, or it was null.

   dg_vdm_unexport_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_UNEXPORT_INSTANCE command.
       The command unexports an instance, removing the device nodes for it
       from /dev/dsk and /dev/rdsk.

       struct      dg_vdm_unexport_instance_packet
           {
           int     version;
           dev_t   device_number;
           };

       version
              The version of the packet.

       device_number
              The device number of the instance to unexport.

   dg_vdm_get_instance_info_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_INSTANCE_INFO command.
       The command returns generic information about an instance (like its
       name).

       Only the version and device_number fields are input fields.  All
       other fields are returned.

       There are three versions of this packet that can be returned by the
       system.  Unless otherwise stated below, all fields are returned for
       all versions.

       struct      dg_vdm_get_instance_info_packet
           {
           int                         version;
           dev_t                       device_number;
           unsigned int                subdriver_id;
           struct dg_vdm_instance_id   instance_id;
           unsigned int                duplicate_number;
           unsigned int                usable               : 1;
           unsigned int                open                 : 1;
           unsigned int                persistent           : 1;
           unsigned int                disk_updates_enabled : 1;
           unsigned int                exported             : 1;
           unsigned int                partially_exported   : 1;
           unsigned int                logging              : 1;
           char                        instance_name
                                           [DG_VDM_MAX_INSTANCE_NAME_LENGTH];
           int                         change_ticket;
           int                         topology_ticket;
           unsigned int                cluster_mode : 1;
           };

       version
              The version of the packet.  Set this to
              DG_VDM_IOCTL_PACKET_VERSION_0,
              DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_1, or
              DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_2, depending on which
              version of the packet you want to receive.

       device_number
              The device number of the instance to get information about.

       subdriver_id
              The ID of the subdriver that manages the instance.

       instance_id
              The unique instance ID that identifies the instance.

       duplicate_number
              The duplicate number of the instance.  The original instance
              is zero, the first copy is one, etc.

       usable If set to one, it indicates that the instance is ready to do
              work.  Otherwise, the instance is not able to do work yet for
              some reason.

       open   If set to one, it indicates that the instance is open or
              mmapped and is actively being used.  Otherwise, the instance
              is closed and unmapped.

       persistent
              If set to one, it indicates that the instance is stored on
              disk and will persist across system reboots.  Otherwise, the
              instance exists only in memory and will be lost when the
              system is next rebooted.

       disk_updates_enabled
              If set to one, it indicates that changes to the instance's
              information and attributes will be stored on disk so that they
              will persist across system reboots.  Otherwise, the changes
              will only be made to the instance in memory, and those changes
              will be lost when the system is next rebooted.

       exported
              If set to one, it indicates that the instance is exported.
              Otherwise, it is not exported.

       partially_exported
              If set to one, it indicates that only the long name of the
              instance is exported.  Otherwise, both the short and long name
              of the instance are exported.  The short name is not exported
              because it conflicts with another instance having the same
              name, or it is null.  This field is valid only if exported is
              set to one.

       logging
              If set to one, it indicates that kernel trace logging is
              active for the instance.  Otherwise, logging is not being done
              for the instance.

       instance_name
              The null-terminated name of the instance.  The name may be
              null.

       change_ticket
              The ticket value for the last time any attribute of this
              instance was altered (including topology changes).  If the
              current change ticket is different from the previous ticket
              that you have saved for this instance, then this instance has
              been changed.

              The attribute changes tracked by this ticket are:  update
              instance, update attributes, some subdriver ioctl(2) commands,
              child role changes, kernel trace logging, first open, last
              close, usability changes, and cluster mode changes.

              The topology changes tracked by this ticket are:  create,
              delete, insert, extract, link child, unlink child, register
              disk, and deregister disk.

              This field is returned only if the packet version is set to
              DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_1 or higher.

       topology_ticket
              The ticket value for the last time the topology of this
              instance was altered.  If the current topology ticket is
              different from the previous ticket that you have saved for
              this instance, then the topology for this instance has been
              changed.

              The topology changes tracked by this ticket are:  create,
              delete, insert, extract, link child, unlink child, register
              disk, and deregister disk.

              This field is returned only if the packet version is set to
              DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_1 or higher.

       cluster_mode
              If set to one, it indicates that the instance is in cluster
              mode, meaning it resides on one or more cluster physical
              disks.  If set to zero, it indicates that the instance is in
              non-cluster mode, meaning it resides on one or more non-
              cluster physical disks.

              This field is returned only if the packet version is set to
              DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_2.

   dg_vdm_get_attributes_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_ATTRIBUTES command.  The
       command returns the subdriver-specific attributes for an instance.

       struct      dg_vdm_get_attributes_packet
           {
           int             version;
           dev_t           instance_device_number;
           unsigned int    subdriver_id;
           void *          subdriver_attributes_packet_ptr;
           };

       version
              The version of the packet.

       instance_device_number
              The device number of the instance whose attributes are to be
              returned.

       subdriver_id
              The ID of the subdriver that manages the instance.  This
              ensures that the subdriver you think is managing the instance
              is really still managing the instance when you issue the
              command.

       subdriver_attributes_packet_ptr
              A pointer to the subdriver-specific attributes packet (if any)
              that you allocate.  The packet is filled in by the subdriver
              and returned.

   dg_vdm_list_instances_packet
       The VDM ioctl(2) packet for the DG_VDM_LIST_INSTANCES command.  The
       command returns the device numbers for all instances in the system.

       Each time the DG_VDM_LIST_INSTANCES command is issued, the device
       numbers of the next group of instances will be returned.  When there
       are no more instances to return, error ENOENT will be returned.

       Note that the information returned can become invalid if instances
       are created or deleted in between commands.

       struct      dg_vdm_list_instances_packet
           {
           int             version;
           unsigned int    key;
           unsigned int    available;
           unsigned int    filled;
           unsigned int    number_of_instances;
           dev_t *         device_numbers;
           };

       version
              The version of the packet.

       key    The key for the request.  Initialize the key to zero before
              issuing the command for the first time.  The key value will be
              updated by the VDM on each subsequent call, to keep track of
              its place in the list.  Do not further alter the key value,
              except to reset it to zero to start the listing over again.

       available
              The number of entries you have allocated in the device_numbers
              array.  If set to zero, no device numbers will be returned,
              but the number_of_instances field will still be returned.  You
              can use this to determine how many instances there are in the
              system, without having to list them all just to count them.

       filled The returned number of dev_t variables put into the
              device_numbers array by the VDM.  No device numbers will be
              returned if available is zero.

       number_of_instances
              The returned number of instances in the system.  This field is
              always returned.

       device_numbers
              A pointer to an array of dev_t variables that you have
              allocated (if any).  Put the number of dev_t variables you
              allocate into the available field.  The array will be filled
              with the device numbers of the instances in the system and
              returned.

   dg_vdm_ioctl_subdriver_packet
       The VDM ioctl(2) packet for the DG_VDM_IOCTL_SUBDRIVER command.  The
       command issues an ioctl(2) command directly to a subdriver.

       An ioctl(2) command can be issued to an instance by opening its
       /dev/dsk or /dev/rdsk device node, and issuing the command through
       the open file descriptor.  However, this poses a problem when issuing
       an ioctl(2) command to an arbitrary instance.  If the instance isn't
       exported, it has no device nodes that can be opened, so you can't
       issue commands to it.  Since most subordinate instances are not
       exported, this is a common problem.

       You can avoid this problem by issuing the command to the instance via
       the DG_VDM_IOCTL_SUBDRIVER command.  Specify the device number of the
       instance you want to send the command to, along with the command and
       its arguments, then issue the DG_VDM_IOCTL_SUBDRIVER command to the
       /dev/vdm device node, which always exists.  The VDM will redirect the
       command to the specified instance.  The instance does not need to be
       exported or open.  Since this is much more convenient than issuing
       commands directly to instance device nodes, most applications issue
       all ioctl(2) commands to instances using DG_VDM_IOCTL_SUBDRIVER.

       Additionally, some subdrivers support ioctl(2) commands that are not
       issued to an instance, but rather are issued directly to the
       subdriver.  The most common examples are commands that list
       information about all the instances managed by a subdriver.  Since
       the subdrivers themselves have no device nodes that can be opened,
       you can also use the DG_VDM_IOCTL_SUBDRIVER command to issue the
       commands to them.  Specify the subdriver ID to issue the command to,
       along with the command and its arguments, then issue the
       DG_VDM_IOCTL_SUBDRIVER command to the /dev/vdm device node.  The VDM
       will redirect the command to the specified subdriver.

       struct      dg_vdm_ioctl_subdriver_packet
           {
           int             version;
           unsigned int    subdriver_id;
           dev_t           instance_device_number;
           int             command;
           int             argument;
           };

       version
              The version of the packet.

       subdriver_id
              The ID of the subdriver to issue the command to.  Always
              supply this field, even if you are issuing the command to a
              given instance.  If you set instance_device_number to NODEV,
              the command will be issued directly to the subdriver.
              Otherwise, the subdriver_id will be verified to ensure that
              the subdriver you think is managing the instance is really
              still managing the instance when you issue the command.

       instance_device_number
              The device number of the instance to issue the command to.  If
              set to NODEV, the command will be issued directly to the
              subdriver specified in subdriver_id.  Otherwise, the command
              will be issued to the specified instance.

       command
              The command for the ioctl(2) command you are issuing to an
              instance or subdriver.

       argument
              The argument for the ioctl(2) command you are issuing to an
              instance or subdriver.

   dg_vdm_insert_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_INSERT_INSTANCE command.  The
       command inserts a new instance into the middle of an existing
       instance hierarchy.

       struct      dg_vdm_insert_instance_packet
           {
           int             version;
           dev_t           instance_to_change;
           dev_t           dummy_instance;
           unsigned int    subdriver_id;
           void *          attributes_packet_ptr;
           };

       version
              The version of the packet.

       instance_to_change
              The device number of the instance where you want to insert the
              new instance.  The existing functionality of the instance will
              be moved into the dummy_instance, then the new functionality
              will be set up in instance_to_change using subdriver_id and
              attributes_packet_ptr.

       dummy_instance
              The device number of a previously created dummy instance (see
              the vdmdummy(7) man page) which will be inserted into the
              hierarchy below the instance_to_change.  The old functionality
              of instance_to_change will be moved into the dummy_instance,
              and the new functionality will be moved into
              instance_to_change.

       subdriver_id
              The ID of the subdriver that is to manage the new
              functionality in instance_to_change.

       attributes_packet_ptr
              A pointer to a subdriver-specific attributes packet (if any),
              which specifies any information the subdriver needs to create
              the new functionality in instance_to_change.  This is a
              pointer to the subdriver's 'create packet', which is also used
              in the DG_VDM_CREATE_INSTANCE command.

   dg_vdm_extract_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_EXTRACT_INSTANCE command.  The
       command extracts an instance from the middle of an existing instance
       hierarchy.

       After the extract, the new_parent_device_number instance and its
       child must be deleted.

       struct      dg_vdm_extract_instance_packet
           {
           int     version;
           dev_t   parent_device_number;
           dev_t   new_parent_device_number;
           };

       version
              The version of the packet.

       parent_device_number
              The device number of the instance to be extracted.  The
              existing functionality of the instance will be moved into the
              new_parent_device_number instance, then the child's
              functionality will be moved up into the parent_device_number
              instance.  The parent must have exactly one child in order to
              be extracted, and the parent and child instances must be the
              same size in disk blocks.

       new_parent_device_number
              The device number of a previously created dummy instance (see
              the vdmdummy(7) man page) which will take on the old
              functionality of the parent_device_number instance.  The child
              of the parent_device_number will be extracted, become a dummy
              instance, and become the child of the new_parent_device_number
              instance.

   dg_vdm_link_child_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_LINK_CHILD_INSTANCE command.
       The command links a new child instance to a parent instance.

       struct      dg_vdm_link_child_instance_packet
           {
           int             version;
           dev_t           parent_device_number;
           unsigned int    parent_subdriver_id;
           dev_t           child_device_number;
           void *          child_packet_ptr;
           };

       version
              The version of the packet.

       parent_device_number
              The device number of the parent instance to which the child is
              to be linked.

       parent_subdriver_id
              The ID of the subdriver that manages the parent instance.
              This ensures that the subdriver you think is managing the
              instance is really still managing the instance when you issue
              the command.

       child_device_number
              The device number of the child instance being linked to the
              parent.

       child_packet_ptr
              A pointer to the subdriver-specific attributes packet (if
              any), which specifies any information the subdriver needs to
              link the child to the parent.  It specifies the role the child
              is to play with respect to the parent.  Many subdrivers don't
              need a child_packet_ptr, since the role is implicit.  In those
              cases, set child_packet_ptr to NULL.

   dg_vdm_child_instance_packet
       A sub-packet used in the DG_VDM_GET_CHILD_INSTANCE ioctl(2) command.
       The sub-packet is filled in by the VDM to identify a child of an
       instance.

       struct      dg_vdm_child_instance_packet
           {
           void *                              child_role_packet_ptr;
           struct dg_vdm_instance_specifier    child_instance;
           unsigned int                        child_subdriver_id;
           };

       child_role_packet_ptr
              A pointer to a packet you allocate that will be filled in by
              the parent subdriver to indicate the role the child instance
              plays for the parent.  If set to NULL, no child role
              information will be returned.

       child_instance
              The returned information identifying the child instance.  If
              the child exists, its device number will be returned.  If the
              child is missing, its instance ID will be returned.

       child_subdriver_id
              The returned ID of the subdriver managing the child instance.
              If the child is missing, the ID will be
              DG_VDM_NO_SUBDRIVER_ID.  If the child is not a VDM instance,
              the ID will be DG_VDM_SUBDRIVER_ID_OF_A_NON_VDM_DEVICE.

   dg_vdm_get_child_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_CHILD_INSTANCE command.
       The command returns the device numbers of the child instances that
       are owned by a parent instance.

       Each time the DG_VDM_GET_CHILD_INSTANCE command is issued, the device
       numbers of the next group of child instances will be returned.  When
       there are no more child instances to return, error ENOENT will be
       returned.

       Note that the information returned can become invalid if child
       instances are linked or unlinked in between commands.

       struct      dg_vdm_get_child_instance_packet
           {
           int                                     version;
           unsigned int                            key;
           dev_t                                   parent_device_number;
           unsigned int                            parent_subdriver_id;
           unsigned int                            available;
           unsigned int                            filled;
           unsigned int                            number_of_children;
           struct dg_vdm_child_instance_packet *   child_instance_array_ptr;
           };

       version
              The version of the packet.

       key    The key for the request.  Initialize the key to zero before
              issuing the command for the first time.  The key value will be
              updated by the VDM on each subsequent call, to keep track of
              its place in the list.  Do not further alter the key value,
              except to reset it to zero to start the listing over again.

       parent_device_number
              The device number of the parent instance whose child instances
              are to be listed.

       parent_subdriver_id
              The ID of the subdriver that manages the parent instance.
              This ensures that the subdriver you think is managing the
              instance is really still managing the instance when you issue
              the command.  This field is required only if you specify any
              non-null child_role_packet_ptr variables in the array pointed
              to by child_instance_array_ptr.

       available
              The number of entries you have allocated in the array pointed
              to by child_instance_array_ptr.  If set to zero, no child
              identification information will be returned, but the
              number_of_children field will still be returned.  You can use
              this to determine how many children the parent has, without
              having to list them all just to count them.

       filled The returned number of dg_vdm_child_instance_packet structures
              put into the array pointed to by child_instance_array_ptr by
              the VDM.  No child identifiers will be returned if available
              is zero.

       number_of_children
              The returned number of children the parent instance has.  This
              field is always returned.

       child_instance_array_ptr
              A pointer to an array of dg_vdm_child_instance_packet
              structures that you have allocated (if any).  Put the number
              of packets you allocate into the available field.  If you want
              child role information returned, allocate an array of role
              packets as well, and set the child_role_packet_ptr in each
              entry to its corresponding role packet.  If you do not want
              role information, set the child_role_packet_ptr in each entry
              to NULL.  The child information in the array will be filled in
              by the command and returned.

   dg_vdm_parent_instance_packet
       A sub-packet used in the DG_VDM_GET_PARENT_INSTANCE ioctl(2) command.
       The sub-packet is filled in by the VDM to identify a parent of an
       instance.

       struct      dg_vdm_parent_instance_packet
           {
           dev_t           parent_device_number;
           unsigned int    parent_subdriver_id;
           };

       parent_device_number
              The returned device number of the parent instance.

       parent_subdriver_id
              The returned ID of the subdriver managing the parent instance.

   dg_vdm_get_parent_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_PARENT_INSTANCE command.
       The command returns the device numbers of the parent instances which
       own a child instance.

       Each time the DG_VDM_GET_PARENT_INSTANCE command is issued, the
       device numbers of the next group of parent instances will be
       returned.  When there are no more parent instances to return, error
       ENOENT will be returned.

       Note that the information returned can become invalid if child
       instances are linked or unlinked in between commands.

       struct      dg_vdm_get_parent_instance_packet
           {
           int                                     version;
           unsigned int                            key;
           dev_t                                   child_device_number;
           unsigned int                            available;
           unsigned int                            filled;
           unsigned int                            number_of_parents;
           struct dg_vdm_parent_instance_packet *  parent_instance_array_ptr;
           };

       version
              The version of the packet.

       key    The key for the request.  Initialize the key to zero before
              issuing the command for the first time.  The key value will be
              updated by the VDM on each subsequent call, to keep track of
              its place in the list.  Do not further alter the key value,
              except to reset it to zero to start the listing over again.

       child_device_number
              The device number of the child instance whose parent instances
              are to be listed.

       available
              The number of entries you have allocated in the array pointed
              to by parent_instance_array_ptr.  If set to zero, no parent
              identification information will be returned, but the
              number_of_parents field will still be returned.  You can use
              this to determine how many parents the child has, without
              having to list them all just to count them.

       filled The returned number of dg_vdm_parent_instance_packet
              structures put into the array pointed to by
              parent_instance_array_ptr by the VDM.  No parent identifiers
              will be returned if available is zero.

       number_of_parents
              The returned number of parents the child instance has.  This
              field is always returned.

       parent_instance_array_ptr
              A pointer to an array of dg_vdm_parent_instance_packet
              structures that you have allocated (if any).  Put the number
              of packets you allocate into the available field.  The parent
              information in the array will be filled in by the command and
              returned.

   dg_vdm_unlink_child_instance_packet
       The VDM ioctl(2) packet for the DG_VDM_UNLINK_CHILD_INSTANCE command.
       The command unlinks a child instance from a parent instance.

       struct      dg_vdm_unlink_child_instance_packet
           {
           int                                 version;
           dev_t                               parent_device_number;
           struct dg_vdm_instance_specifier    child_instance;
           };

       version
              The version of the packet.

       parent_device_number
              The device number of the parent from whom the child instance
              is to be unlinked.

       child_instance
              The identifier for the child to be unlinked.  If the child
              exists, you may specify it by its device number or its
              instance ID.  If the child is missing, you must specify it by
              its instance ID.

   dg_vdm_register_disk_packet
       The VDM ioctl(2) packet for the DG_VDM_REGISTER_DISK command.  The
       command introduces a DG/UX formatted disk to the system so that it
       can be used.  The instances that manage the data on the disk are
       automatically recreated.

       In the event that some of the disks cannot be registered, error
       messages will be sent to the console, and errno will be set to the
       error reported by the first disk that failed to register.  Other
       disks in the packet will still be tried to see if they can be
       registered.

       struct      dg_vdm_register_disk_packet
           {
           int             version;
           unsigned int    number_of_disks;
           dev_t *         disk_array_ptr;
           unsigned int    any_partial_exports  : 1;
           unsigned int    any_failed_recreates : 1;
           };

       version
              The version of the packet.

       number_of_disks
              The number of disk device numbers present in the array pointed
              to by disk_array_ptr.

       disk_array_ptr
              A pointer to an array, that you allocate, of the device
              numbers of the disks which are to be registered.  In general,
              you should register disks that share instances together, to
              avoid having confusing messages sent to the console.

       any_partial_exports
              A returned value indicating whether any exported instances
              were partially exported (i.e., only their long names were
              exported).  If set to one, it indicates that at least one
              exported instance had a conflict with its short name, and
              therefore only its long name was exported.  This field will be
              returned even if there are registration errors, and it will be
              valid for those instances that were registered.

       any_failed_recreates
              A returned value indicating whether any recreates of the
              instances stored on the disks failed during the registration.
              If set to one, it indicates that at least one instance failed
              to be recreated.  Some instances may succeed in being
              recreated, while others may fail.  This field will be returned
              even if there are registration errors, and it will be valid
              for those instances that were registered.

   dg_vdm_deregister_disk_packet
       The VDM ioctl(2) packet for the DG_VDM_DEREGISTER_DISK command.  The
       command removes a DG/UX formatted disk from the system, so that it
       can no longer be used.  All instances that manage some portion of the
       data on the disk are automatically removed from the system.

       struct      dg_vdm_deregister_disk_packet
           {
           int     version;
           dev_t   physical_device_number;
           dev_t   failed_instance_device_number;
           };

       version
              The version of the packet.

       physical_device_number
              The device number of the disk to be deregistered.

       failed_instance_device_number
              The returned device number of the instance that caused the
              deregistration to fail (if any).  This field is valid only if
              the returned status from the command is -1.  If the field
              contains NODEV, then no particular instance caused the
              failure; some more general condition did.  The errno will
              contain the error that was reported from the failed instance.

   dg_vdm_list_registered_disks_packet
       The VDM ioctl(2) packet for the DG_VDM_LIST_REGISTERED_DISKS command.
       The command returns the device numbers of the physical disks that are
       registered with the VDM.

       Each time the DG_VDM_LIST_REGISTERED_DISKS command is issued, the
       device numbers of the next group of registered disks will be
       returned.  When there are no more disks to return, error ENOENT will
       be returned.

       Note that the information returned can become invalid if disks are
       registered or deregistered in between commands.

       struct      dg_vdm_list_registered_disks_packet
           {
           int             version;
           unsigned int    key;
           unsigned int    available;
           unsigned int    filled;
           unsigned int    number_of_registered_disks;
           dev_t *         physical_device_number;
           };

       version
              The version of the packet.

       key    The key for the request.  Initialize the key to zero before
              issuing the command for the first time.  The key value will be
              updated by the VDM on each subsequent call, to keep track of
              its place in the list.  Do not further alter the key value,
              except to reset it to zero to start the listing over again.

       available
              The number of entries you have allocated in the array pointed
              to by physical_device_number.  If set to zero, no registered
              disk information will be returned, but the
              number_of_registered_disks field will still be returned.  You
              can use this to determine how many registered disks there are
              in the system, without having to list them all just to count
              them.

       filled The returned number of dev_t variables put into the array
              pointed to by physical_device_number by the VDM.  No
              registered disk information will be returned if available is
              zero.

       number_of_registered_disks
              The returned number of registered disks in the system.  This
              field is always returned.

       physical_device_number
              A pointer to an array of dev_t variables that you have
              allocated (if any).  Put the number of packets you allocate
              into the available field.  The registered disk device numbers
              will be put into the array by the command and returned.

   dg_vdm_list_subdrivers_packet
       The VDM ioctl(2) packet for the DG_VDM_LIST_SUBDRIVERS command.  The
       command returns the subdriver IDs of the subdrivers configured with
       the VDM.

       Each time the DG_VDM_LIST_SUBDRIVERS command is issued, the subdriver
       IDs of the next group of subdrivers will be returned.  When there are
       no more subdrivers to return, error ENOENT will be returned.

       Note that the information returned can become invalid if subdrivers
       are configured or deconfigured in between commands.

       struct      dg_vdm_list_subdrivers_packet
           {
           int             version;
           unsigned int    key;
           unsigned int    available;
           unsigned int    filled;
           unsigned int    number_of_subdrivers;
           unsigned int *  subdriver_id;
           };

       version
              The version of the packet.

       key    The key for the request.  Initialize the key to zero before
              issuing the command for the first time.  The key value will be
              updated by the VDM on each subsequent call, to keep track of
              its place in the list.  Do not further alter the key value,
              except to reset it to zero to start the listing over again.

       available
              The number of entries you have allocated in the array pointed
              to by subdriver_id.  If set to zero, no subdriver information
              will be returned, but the number_of_subdrivers field will
              still be returned.  You can use this to determine how many
              subdrivers are configured with the VDM, without having to list
              them all just to count them.

       filled The returned number of subdriver IDs put into the array
              pointed to by subdriver_id by the VDM.  No subdriver
              information will be returned if available is zero.

       number_of_subdrivers
              The returned number of subdrivers configured with the VDM.
              This field is always returned.

       subdriver_id
              A pointer to an array of subdriver IDs that you have allocated
              (if any).  Put the number of packets you allocate into the
              available field.  The subdriver IDs in the array will be
              filled in by the command and returned.

   dg_vdm_get_change_ticket_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_CHANGE_TICKET command.
       The command returns a ticket for the last attributes or topology
       change made that altered any instance in the system.

       struct      dg_vdm_get_change_ticket_packet
           {
           int     version;
           int     change_ticket;
           };

       version
              The version of the packet.

       change_ticket
              The ticket value for the last time any attributes for any VDM
              instance was altered (including topology changes).  If the
              current change ticket is different from the previous ticket
              that you have saved, then some instance in the system has been
              changed.

              The attribute changes tracked by this ticket are:  update
              instance, update attributes, some subdriver ioctl(2) commands,
              child role changes, kernel trace logging, cluster mode
              changes, first open, last close, usability changes, and
              cluster mode changes.

              The topology changes tracked by this ticket are:  create,
              delete, insert, extract, link child, unlink child, register
              disk, and deregister disk.

   dg_vdm_get_subdriver_info_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_SUBDRIVER_INFO command.
       The command returns generic information about a subdriver (like its
       name).

       struct      dg_vdm_get_subdriver_info_packet
           {
           int             version;
           unsigned int    subdriver_id;
           char            subdriver_device_name
                               [DG_VDM_MAX_SUBDRIVER_NAME_LENGTH];
           char            subdriver_friendly_name
                               [DG_VDM_MAX_SUBDRIVER_NAME_LENGTH];
           unsigned int    instance_count;
           unsigned int    logging : 1;
           };

       version
              The version of the packet.

       subdriver_id
              The ID of the subdriver to get information about.

       subdriver_device_name
              The returned device name of the subdriver.  This is the name
              mentioned in the system configuration file used to build the
              kernel.

       subdriver_friendly_name
              The returned user-friendly name of the subdriver that
              describes its functionality.

       instance_count
              The returned number of instances the subdriver is managing.

       logging
              If set to one, it indicates that kernel trace logging is
              active for the subdriver (i.e., for all instances the
              subdriver manages).  Otherwise, logging is not being done for
              the subdriver.

   dg_vdm_log_packet
       The VDM ioctl(2) packet for the DG_VDM_LOGGING command.  The command
       turns kernel trace logging on or off for specific instances and/or
       for all instances managed by specific subdrivers.

       struct      dg_vdm_log_packet
           {
           int             version;
           unsigned int    logging : 1;
           unsigned int    number_of_instances;
           dev_t *         instance_array_ptr;
           unsigned int    number_of_subdrivers;
           unsigned int *  subdriver_array_ptr;
           };

       version
              The version of the packet.

       logging
              If set to one, it indicates that kernel trace logging is to be
              turned on for the specified instances and subdrivers.
              Otherwise, kernel trace logging is to be turned off for the
              instances and subdrivers specified.

       number_of_instances
              The number of instance device numbers in the instance array
              (if any).

       instance_array_ptr
              A pointer to an array of dev_t variables that you have
              allocated (if any).  Put the number of packets you allocate
              into the number_of_instances field.  The instances listed will
              have their kernel trace logging state changed.

       number_of_subdrivers
              The number of subdriver IDs in the subdriver array (if any).

       subdriver_array_ptr
              A pointer to an array of subdriver IDs that you have allocated
              (if any).  Put the number of packets you allocate into the
              number_of_subdrivers field.  All instances for the subdrivers
              listed will have their kernel trace logging state changed.

   dg_vdm_set_boot_info_packet
       The VDM ioctl(2) packet for the DG_VDM_SET_BOOT_INFO command.  The
       command sets the default root and swap instances to be used when
       booting from a disk.

       The named instances must exist, be exported, and be persistent.

       struct      dg_vdm_set_boot_info_packet
           {
           int             version;
           dev_t           disk_device_number;
           unsigned int    set_default_root : 1;
           unsigned int    set_default_swap : 1;
           dev_t           default_root;
           dev_t           default_swap;
           };

       version
              The version of the packet.

       disk_device_number
              The device number of the registered disk whose boot
              information is to be set or changed.

       set_default_root
              If set to one, it indicates that the default_root field is to
              be used to update the boot information on the disk.
              Otherwise, the default_root setting on the disk is not
              changed.

       set_default_swap
              If set to one, it indicates that the default_swap field is to
              be used to update the boot information on the disk.
              Otherwise, the default_swap setting on the disk is not
              changed.

       default_root
              The device number of the default root instance to use when
              booting from the disk.  The bootstrap will use this instance
              to locate the kernel image to boot if no virtual disk name is
              given on the boot command line.  The VDM will mount this
              instance as the root file system during the boot.  The
              instance does not have to reside on the specified disk, it may
              reside on any disk.  To clear the default root setting, set
              this field to NODEV.  This field is used only if
              set_default_root is set to one.

       default_swap
              The device number of the default swap instance to use when
              booting from the disk.  The VDM will use the instance as the
              swap device during the boot.  The instance does not have to
              reside on the specified disk, it may reside on any disk.  To
              clear the default swap setting, set this field to NODEV.  This
              field is used only if set_default_swap is set to one.

   dg_vdm_get_boot_info_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_BOOT_INFO command.  The
       command returns the default root and swap instances which are used
       when booting from a disk.

       struct      dg_vdm_get_boot_info_packet
           {
           int                                 version;
           dev_t                               disk_device_number;
           unsigned int                        default_root_set : 1;
           unsigned int                        default_swap_set : 1;
           struct dg_vdm_instance_specifier    default_root;
           struct dg_vdm_instance_specifier    default_swap;
           };

       version
              The version of the packet.

       disk_device_number
              The device number of the registered disk whose boot
              information is to be returned.

       default_root_set
              A returned flag indicating whether the default root instance
              is set for the specified disk.  If set to one, it indicates
              that the default root instance is set.  Otherwise, there is no
              default root instance set for the disk.

       default_swap_set
              A returned flag indicating whether the default swap instance
              is set for the specified disk.  If set to one, it indicates
              that the default swap instance is set.  Otherwise, there is no
              default swap instance set for the disk.

       default_root
              The returned default root instance.  If the instance exists,
              its device number will be returned.  Otherwise the instance is
              missing and its instance ID will be returned.  This field is
              valid only if default_root_set is one.

       default_swap
              The returned default swap instance.  If the instance exists,
              its device number will be returned.  Otherwise the instance is
              missing and its instance ID will be returned.  This field is
              valid only if default_swap_set is one.

   dg_vdm_get_topology_ticket_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_TOPOLOGY_TICKET command.
       The command returns a ticket for the last topology change made that
       altered any instance in the system.

       struct      dg_vdm_get_topology_ticket_packet
           {
           int     version;
           int     topology_ticket;
           };

       version
              The version of the packet.

       topology_ticket
              The ticket value for the last time the topology for any VDM
              instance was altered.  If the current topology ticket is
              different from the previous ticket that you have saved, then
              the topology for some instance in the system has been changed.

              The topology changes tracked by this ticket are:  create,
              delete, insert, extract, link child, unlink child, register
              disk, and deregister disk.

   dg_vdm_get_instance_unique_name_packet
       The VDM ioctl(2) packet for the DG_VDM_GET_INSTANCE_UNIQUE_NAME
       command.  The command returns the minimally unique name for an
       instance.

       struct      dg_vdm_get_instance_unique_name_packet
           {
           int     version;
           dev_t   device_number;
           char    instance_unique_name
                       [DG_VDM_MAX_INSTANCE_UNIQUE_NAME_LENGTH];
           };

       version
              The version of the packet.

       device_number
              The device number of the instance whose unique name is to be
              returned.

       instance_unique_name
              The returned minimally unique name of the instance.  The
              unique name is composed of as many as four components: the
              simple instance name, the instance's generation number, the
              instance's system ID, and the instance's duplicate number, in
              that order.  Only the leading components necessary to generate
              a unique name for the instance are returned.

   dg_vdm_cluster_disk_packet
       The VDM ioctl(2) packet for the DG_VDM_CLUSTER_DISK command.  Changes
       the clustering mode of registered physical disks so that they are
       either available or unavailable for use by multiple nodes in a
       cluster.

       struct      dg_vdm_cluster_disk_packet
           {
           int             version;
           unsigned int    cluster_mode : 1;
           unsigned int    number_of_disks;
           dev_t *         disk_array_ptr;
           dev_t           failed_disk;
           dev_t           failed_instance;
           };

       version
              The version of the packet.

       cluster_mode
              If set to one, it indicates that the disks listed in the array
              are to be changed from non-cluster mode to cluster mode.  If
              set to zero, it indicates that the disks are to be changed
              from cluster mode to non-cluster mode.

       number_of_disks
              The number of disk device numbers present in the array pointed
              to by disk_array_ptr.

       disk_array_ptr
              A pointer to an array, that you allocate, of the device
              numbers of the disks which are to have their clustering mode
              changed.  You must cluster or uncluster disks that share
              instances together, to ensure that all parts of the instance
              hierarchy will be grouped together.

              If you are changing disks to cluster mode, they must contain
              only instances that are legal in cluster mode. Once the disks
              are in cluster mode, they may be registered on the other nodes
              in the cluster.

              If you are changing disks to non-cluster mode, they must be
              deregistered on all other nodes of the cluster before the
              change.

       failed_disk
              The returned device number of the physical disk that caused
              the cluster mode change to fail (if any).  This field is valid
              only if the returned status from the command is -1.  If the
              field contains NODEV, then no physical disk could be reported.
              The errno will contain the error that was reported from the
              failed physical disk.

       failed_instance
              The returned device number of the instance that caused the
              cluster mode change to fail (if any).  This field is valid
              only if the returned status from the command is -1.  If the
              field contains NODEV, then no instance could be reported.  The
              errno will contain the error that was reported from the failed
              instance.

EXAMPLES
       The following code fragments illustrate how to use the packets and
       commands described in this man page.  The fragments are not complete
       and are not intended to be compilable or executable.  In particular,
       initialization code, instance locating code, and error handling are
       left out for brevity.

   Common includes and variables

       #include <errno.h>
       #include <sys/dg_sysctl.h>
       #include <sys/ioctl.h>
       #include <sys/types.h>
       #include <stdio.h>
       #include <unistd.h>

       int     status;             /* status from system call */
       int     vdm_channel;        /* channel to /dev/vdm node */

   Open a channel to issue commands to the VDM

       status = open ("/dev/vdm", O_RDONLY);

       vdm_channel = status;

   Handle an error from an ioctl(2) command

       char    *error_text_ptr;

       status = ioctl (vdm_channel,
                       command,
                       argument);

       if (status == -1)
           {
           error_text_ptr = extended_strerror (dg_ext_errno ());

           if (error_text_ptr == NULL)
               {
               error_text_ptr = strerror (errno);
               }

           printf ("%s\n", error_text_ptr);
           }

   Translate an instance name to a device number

       dev_t   instance;
       struct  dg_sysctl_name_to_device    name_to_device_pkt;

       name_to_device_pkt.device_name = "vdm(root)";

       status = dg_sysctl (DG_SYSCTL_NAME_TO_DEVICE,
                           &name_to_device_pkt);

       instance = name_to_device_pkt.device_number;

       printf ("Instance device number = 0x%08x\n", instance);

   Translate a device number to an instance name

       char    instance_name [DG_VDM_MAX_INSTANCE_UNIQUE_NAME_LENGTH];
       dev_t   instance;
       struct  dg_sysctl_device_to_name    device_to_name_pkt;

       device_to_name_pkt.device_number   = instance;
       device_to_name_pkt.device_name     = instance_name;
       device_to_name_pkt.max_name_length = sizeof (instance_name);

       status = dg_sysctl (DG_SYSCTL_DEVICE_TO_NAME,
                           &device_to_name_pkt);

       printf ("Name is '%s'\n", instance_name);

   Create an instance

       dev_t   aggr_instance;
       dev_t   piece_0_instance;
       dev_t   piece_1_instance;
       dev_t   pieces [2];
       struct  dg_vdm_create_instance_packet   create_pkt;
       struct  dg_vdmaggr_create_packet        aggr_create_pkt;

       create_pkt.version             = DG_VDM_IOCTL_PACKET_VERSION_0;
       create_pkt.subdriver_id        = DG_VDMAGGR_SUBDRIVER_ID;
       create_pkt.persistent          = 1;
       create_pkt.enable_disk_updates = 1;
       strcpy (create_pkt.instance_name, "inventory_db");
       create_pkt.subdriver_attributes_packet_ptr = &aggr_create_pkt;

       aggr_create_pkt.version          = DG_VDMAGGR_IOCTL_PACKET_VERSION_0;
       aggr_create_pkt.stripe_size      = 0;
       aggr_create_pkt.number_of_pieces = 2;
       aggr_create_pkt.piece_array_ptr  = pieces;

       pieces [0] = piece_0_instance;
       pieces [1] = piece_1_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_CREATE_INSTANCE,
                       &create_pkt);

       aggr_instance = create_pkt.device_number;

       printf ("Aggregation device number = 0x%08x\n", aggr_instance);

   Update an instance

       dev_t   update_instance;
       struct  dg_vdm_update_instance_packet   update_pkt;

       update_pkt.version                    = DG_VDM_IOCTL_PACKET_VERSION_0;
       update_pkt.device_number              = update_instance;
       update_pkt.update_persistent          = 0;
       update_pkt.update_enable_disk_updates = 0;
       update_pkt.update_instance_name       = 1;
       strcpy (update_pkt.instance_name, "old_inventory_db");

       status = ioctl (vdm_channel,
                       DG_VDM_UPDATE_INSTANCE,
                       &update_pkt);

       if (update_pkt.partially_exported)
           {
           printf ("Partially exported\n");
           }

   Update an instance's attributes

       dev_t   update_instance;
       struct  dg_vdm_update_attributes_packet     update_attrs_pkt;
       struct  dg_vdmpart_update_packet            part_update_pkt;

       update_attrs_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       update_attrs_pkt.instance_device_number = update_instance;
       update_attrs_pkt.subdriver_id           = DG_VDMPART_SUBDRIVER_ID;
       update_attrs_pkt.subdriver_attributes_packet_ptr = &part_update_pkt;

       part_update_pkt.version        = DG_VDMPART_IOCTL_PACKET_VERSION_0;
       part_update_pkt.change_in_size = 55000;

       status = ioctl (vdm_channel,
                       DG_VDM_UPDATE_ATTRIBUTES,
                       &update_attrs_pkt);

   Delete an instance

       dev_t   delete_instance;
       struct  dg_vdm_delete_instance_packet   delete_pkt;

       delete_pkt.version       = DG_VDM_IOCTL_PACKET_VERSION_0;
       delete_pkt.device_number = delete_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_DELETE_INSTANCE,
                       &delete_pkt);

   Export an instance

       dev_t   export_instance;
       struct  dg_vdm_export_instance_packet   export_pkt;

       export_pkt.version       = DG_VDM_IOCTL_PACKET_VERSION_0;
       export_pkt.device_number = export_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_EXPORT_INSTANCE,
                       &export_pkt);

       if (export_pkt.partially_exported)
           {
           printf ("Partially exported\n");
           }

   Unexport an instance

       dev_t   unexport_instance;
       struct  dg_vdm_unexport_instance_packet     unexport_pkt;

       unexport_pkt.version       = DG_VDM_IOCTL_PACKET_VERSION_0;
       unexport_pkt.device_number = unexport_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_UNEXPORT_INSTANCE,
                       &unexport_pkt);

   Get information about an instance

       dev_t   get_info_instance;
       struct  dg_vdm_get_instance_info_packet     get_info_pkt;

       get_info_pkt.version       = DG_VDM_GET_INSTANCE_INFO_PACKET_VERSION_2;
       get_info_pkt.device_number = get_info_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_INSTANCE_INFO,
                       &get_info_pkt);

       printf ("Subdriver ID         = 0x%08x\n",
               get_info_pkt.subdriver_id);
       printf ("Instance ID          = %08x,%08x\n",
               get_info_pkt.instance_id.generation,
               get_info_pkt.instance_id.system_id);
       printf ("Duplicate number     = %08x\n",
               get_info_pkt.duplicate_number);
       printf ("Usable               = %s\n",
               (get_info_pkt.usable) ? "true" : "false");
       printf ("Open                 = %s\n",
               (get_info_pkt.open) ? "true" : "false");
       printf ("Persistent           = %s\n",
               (get_info_pkt.persistent) ? "true" : "false");
       printf ("Disk updates enabled = %s\n",
               (get_info_pkt.disk_updates_enabled) ? "true" : "false");
       printf ("Exported             = %s\n",
               (get_info_pkt.exported) ? "true" : "false");
       printf ("Partially exported   = %s\n",
               (get_info_pkt.partially_exported) ? "true" : "false");
       printf ("Logging              = %s\n",
               (get_info_pkt.logging) ? "true" : "false");
       printf ("Change ticket        = %d\n",
               get_info_pkt.change_ticket);
       printf ("Topology ticket      = %d\n",
               get_info_pkt.topology_ticket);
       printf ("Cluster mode         = %s\n",
               (get_info_pkt.cluster_mode) ? "cluster" : "non-cluster");

   Get an instance's attributes

       dev_t   get_instance;
       struct  dg_vdm_get_attributes_packet    get_attrs_pkt;
       struct  dg_vdmaggr_get_packet           aggr_get_pkt;

       get_attrs_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       get_attrs_pkt.instance_device_number = get_instance;
       get_attrs_pkt.subdriver_id           = DG_VDMAGGR_SUBDRIVER_ID;
       get_attrs_pkt.subdriver_attributes_packet_ptr = &aggr_get_pkt;

       aggr_get_pkt.version = DG_VDMAGGR_IOCTL_PACKET_VERSION_0;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_ATTRIBUTES,
                       &get_attrs_pkt);

       printf ("Stripe size = %u\n", aggr_get_pkt.stripe_size);

   List the instances on the system

       dev_t   list_instance;
       struct  dg_vdm_list_instances_packet    list_instances_pkt;

       list_instances_pkt.version   = DG_VDM_IOCTL_PACKET_VERSION_0;
       list_instances_pkt.key       = 0;
       list_instances_pkt.available = 0;

       status = ioctl (vdm_channel,
                       DG_VDM_LIST_INSTANCES,
                       &list_instances_pkt);

       printf ("Number of instances = %d\n",
               list_instances_pkt.number_of_instances);

       list_instances_pkt.key            = 0;
       list_instances_pkt.available      = 1;
       list_instances_pkt.device_numbers = &list_instance;

       while (1)
           {
           status = ioctl (vdm_channel,
                           DG_VDM_LIST_INSTANCES,
                           &list_instances_pkt);

           if ((status == -1) && (errno == ENOENT))
               {
               break;
               }

           printf ("Instance device number = 0x%08x\n", list_instance);
           }

   Issue an ioctl(2) command directly to a subdriver or instance

       unsigned int    subdriver_id;
       dev_t           ioctl_instance;

       struct  dg_vdm_ioctl_subdriver_packet       ioctl_pkt;
       struct  dskget                              dskget_pkt;

       ioctl_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       ioctl_pkt.subdriver_id           = subdriver_id;
       ioctl_pkt.instance_device_number = ioctl_instance;
       ioctl_pkt.command                = DSKIOCGET;
       ioctl_pkt.argument               = (int) &dskget_pkt;

       status = ioctl (vdm_channel,
                       DG_VDM_IOCTL_SUBDRIVER,
                       &ioctl_pkt);

       printf ("Total blocks = %u\n",
               dskget_pkt.total_sectors *
               (dskget_pkt.bytes_per_sector / 512));

   Insert an instance

       dev_t   aggr_instance;
       dev_t   dummy_instance;
       dev_t   insert_instance;
       dev_t   piece_instance;
       dev_t   pieces [1];
       struct  dg_vdm_create_instance_packet   create_pkt;
       struct  dg_vdm_insert_instance_packet   insert_pkt;
       struct  dg_vdmaggr_create_packet        aggr_create_pkt;

       /*  Create a dummy instance. */

       create_pkt.version             = DG_VDM_IOCTL_PACKET_VERSION_0;
       create_pkt.subdriver_id        = DG_VDMDUMMY_SUBDRIVER_ID;
       create_pkt.persistent          = 1;
       create_pkt.enable_disk_updates = 1;
       create_pkt.instance_name [0]   = '\0';
       create_pkt.subdriver_attributes_packet_ptr = NULL;

       status = ioctl (vdm_channel,
                       DG_VDM_CREATE_INSTANCE,
                       &create_pkt);

       dummy_instance = create_pkt.device_number;

       /*  Insert an aggregation. */

       insert_pkt.version               = DG_VDM_IOCTL_PACKET_VERSION_0;
       insert_pkt.instance_to_change    = insert_instance;
       insert_pkt.dummy_instance        = dummy_instance;
       insert_pkt.subdriver_id          = DG_VDMAGGR_SUBDRIVER_ID;
       insert_pkt.attributes_packet_ptr = &aggr_create_pkt;

       aggr_create_pkt.version          = DG_VDMAGGR_IOCTL_PACKET_VERSION_0;
       aggr_create_pkt.stripe_size      = 0;
       aggr_create_pkt.number_of_pieces = 1;
       aggr_create_pkt.piece_array_ptr  = pieces;

       pieces [0] = dummy_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_INSERT_INSTANCE,
                       &insert_pkt);

       aggr_instance  = insert_instance;
       piece_instance = dummy_instance;

   Extract an instance

       dev_t   aggr_instance;
       dev_t   child_instance;
       dev_t   dummy_instance;
       dev_t   extract_instance;
       struct  dg_vdm_create_instance_packet   create_pkt;
       struct  dg_vdm_delete_instance_packet   delete_pkt;
       struct  dg_vdm_extract_instance_packet  extract_pkt;

       /*  Create a dummy instance. */

       create_pkt.version             = DG_VDM_IOCTL_PACKET_VERSION_0;
       create_pkt.subdriver_id        = DG_VDMDUMMY_SUBDRIVER_ID;
       create_pkt.persistent          = 1;
       create_pkt.enable_disk_updates = 1;
       create_pkt.instance_name [0]   = '\0';
       create_pkt.subdriver_attributes_packet_ptr = NULL;

       status = ioctl (vdm_channel,
                       DG_VDM_CREATE_INSTANCE,
                       &create_pkt);

       dummy_instance = create_pkt.device_number;

       /*  Extract the aggregation. */

       extract_pkt.version                  = DG_VDM_IOCTL_PACKET_VERSION_0;
       extract_pkt.parent_device_number     = extract_instance;
       extract_pkt.new_parent_device_number = dummy_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_EXTRACT_INSTANCE,
                       &extract_pkt);

       aggr_instance  = dummy_instance;
       dummy_instance = child_instance;

       /*  Delete the leftover instance and the child dummy instance. */

       delete_pkt.version       = DG_VDM_IOCTL_PACKET_VERSION_0;
       delete_pkt.device_number = aggr_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_DELETE_INSTANCE,
                       &delete_pkt);

       delete_pkt.device_number = dummy_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_DELETE_INSTANCE,
                       &delete_pkt);

   Link a child instance to a parent instance

       dev_t   link_instance;
       dev_t   new_piece_instance;
       struct  dg_vdm_link_child_instance_packet   link_pkt;
       struct  dg_vdmaggr_link_child_packet        aggr_link_pkt;

       link_pkt.version               = DG_VDM_IOCTL_PACKET_VERSION_0;
       link_pkt.parent_device_number  = link_instance;
       link_pkt.parent_subdriver_id   = DG_VDMAGGR_SUBDRIVER_ID;
       link_pkt.child_device_number   = new_piece_instance;
       link_pkt.child_packet_ptr      = &aggr_link_pkt;

       aggr_link_pkt.version      = DG_VDMAGGR_IOCTL_PACKET_VERSION_0;
       aggr_link_pkt.piece_number = 2;

       status = ioctl (vdm_channel,
                       DG_VDM_LINK_CHILD_INSTANCE,
                       &link_pkt);

   Get the children of an instance

       unsigned int    parent_subdriver_id;
       dev_t           child_instance;
       dev_t           parent_instance;

       struct  dg_vdm_child_instance_packet        child_pkt;
       struct  dg_vdm_get_child_instance_packet    get_child_pkt;
       struct  dg_vdmaggr_get_child_packet         aggr_get_child_pkt;

       get_child_pkt.version                  = DG_VDM_IOCTL_PACKET_VERSION_0;
       get_child_pkt.key                      = 0;
       get_child_pkt.parent_device_number     = parent_instance;
       get_child_pkt.parent_subdriver_id      = parent_subdriver_id;
       get_child_pkt.available                = 0;
       get_child_pkt.child_instance_array_ptr = NULL;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_CHILD_INSTANCE,
                       &get_child_pkt);

       printf ("Number of children = %d\n",
               get_child_pkt.number_of_children);

       get_child_pkt.key                      = 0;
       get_child_pkt.available                = 1;
       get_child_pkt.child_instance_array_ptr = &child_pkt;

       child_pkt.child_role_packet_ptr = &aggr_get_child_pkt;

       aggr_get_child_pkt.version = DG_VDMAGGR_IOCTL_PACKET_VERSION_0;

       while (1)
           {
           status = ioctl (vdm_channel,
                           DG_VDM_GET_CHILD_INSTANCE,
                           &get_child_pkt);

           if ((status == -1) && (errno == ENOENT))
               {
               break;
               }

           printf ("Piece %u\n", aggr_get_child_pkt.piece_number);

           if (child_pkt.child_instance.device_number_used)
               {
               child_instance = child_instance_pkt.child_instance.
                                specifier_value.device_number;

               printf ("Child device number = 0x%08x\n", child_instance);

               if (child_pkt.child_subdriver_id ==
                   DG_VDM_SUBDRIVER_ID_OF_A_NON_VDM_DEVICE)
                   {
                   printf ("  non-vdm child\n");
                   }
               else
                   {
                   printf ("  child subdriver 0x%08x\n",
                           child_pkt.child_subdriver_id);
                   }
               }
           else
               {
               printf ("  missing child ID %08x,%08x\n",
                       child_pkt.child_instance.specifier_value.id.generation,
                       child_pkt.child_instance.specifier_value.id.system_id);
               }

           printf ("\n");
           }

   Get the parents of an instance

       dev_t   child_instance;
       dev_t   parent_instance;
       struct  dg_vdm_parent_instance_packet        parent_pkt;
       struct  dg_vdm_get_parent_instance_packet    get_parent_pkt;

       get_parent_pkt.version             = DG_VDM_IOCTL_PACKET_VERSION_0;
       get_parent_pkt.key                 = 0;
       get_parent_pkt.child_device_number = child_instance;
       get_parent_pkt.available           = 0;
       get_parent_pkt.parent_instance_array_ptr = NULL;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_PARENT_INSTANCE,
                       &get_parent_pkt);

       printf ("Number of parents = %d\n",
               get_parent_pkt.number_of_parents);

       get_parent_pkt.key                       = 0;
       get_parent_pkt.available                 = 1;
       get_parent_pkt.parent_instance_array_ptr = &parent_pkt;

       while (1)
           {
           status = ioctl (vdm_channel,
                           DG_VDM_GET_PARENT_INSTANCE,
                           &get_parent_pkt);

           if ((status == -1) && (errno == ENOENT))
               {
               break;
               }

           parent_instance = parent_instance_pkt.parent_device_number;

           printf ("Parent device number = 0x%08x\n", parent_instance);

           printf ("Parent subdriver 0x%08x\n\n",
                   parent_pkt.parent_subdriver_id);
           }

   Unlink a child instance from a parent instance

       dev_t   unlink_instance;
       dev_t   child_instance;
       struct  dg_vdm_unlink_child_instance_packet   unlink_pkt;

       unlink_pkt.version               = DG_VDM_IOCTL_PACKET_VERSION_0;
       unlink_pkt.parent_device_number  = unlink_instance;
       unlink_pkt.child_instance.device_number_used = 1;
       unlink_pkt.child_instance.specifier_value.device_number =
           child_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_UNLINK_CHILD_INSTANCE,
                       &unlink_pkt);

   Register two disks

       dev_t   disk_0_device_number;
       dev_t   disk_1_device_number;
       dev_t   disks [2];
       struct  dg_vdm_register_disk_packet     register_pkt;

       register_pkt.version         = DG_VDM_IOCTL_PACKET_VERSION_0;
       register_pkt.number_of_disks = 2;
       register_pkt.disk_array_ptr  = disks;

       disks [0] = disk_0_device_number;
       disks [1] = disk_1_device_number;

       status = ioctl (vdm_channel,
                       DG_VDM_REGISTER_DISK,
                       &register_pkt);

       if (register_pkt.any_partial_exports)
           {
           printf ("There were partially exported instances\n");
           }

       if (register_pkt.any_failed_recreates)
           {
           printf ("There were failed instance recreates\n");
           }

   Deregister a disk

       dev_t   disk_device_number;
       dev_t   failed_instance;
       struct  dg_vdm_deregister_disk_packet   deregister_pkt;

       deregister_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       deregister_pkt.physical_device_number = disk_device_number;

       status = ioctl (vdm_channel,
                       DG_VDM_DEREGISTER_DISK,
                       &deregister_pkt);

       if (status == -1)
           {
           if (deregister_pkt.failed_instance_device_number != NODEV)
               {
               printf ("There is a failed instance\n");
               }
           }

   List the registered disks

       dev_t   disk_device_number;
       struct  dg_vdm_list_registered_disks_packet  list_disks_pkt;

       list_disks_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       list_disks_pkt.key                    = 0;
       list_disks_pkt.available              = 0;
       list_disks_pkt.physical_device_number = NULL;

       status = ioctl (vdm_channel,
                       DG_VDM_LIST_REGISTERED_DISKS,
                       &list_disks_pkt);

       printf ("Number of registered disks = %d\n",
               list_disks_pkt.number_of_registered_disks);

       list_disks_pkt.key                    = 0;
       list_disks_pkt.available              = 1;
       list_disks_pkt.physical_device_number = &disk_device_number;

       while (1)
           {
           status = ioctl (vdm_channel,
                           DG_VDM_LIST_REGISTERED_DISKS,
                           &list_disks_pkt);

           if ((status == -1)  && (errno == ENOENT))
               {
               break;
               }

           printf ("Disk device number = 0x%08x\n", disk_device_number);
           }

   List the configured subdrivers

       unsigned int    subdriver_id;
       struct  dg_vdm_list_subdrivers_packet   list_subdrivers_pkt;

       list_subdrivers_pkt.version      = DG_VDM_IOCTL_PACKET_VERSION_0;
       list_subdrivers_pkt.key          = 0;
       list_subdrivers_pkt.available    = 0;
       list_subdrivers_pkt.subdriver_id = NULL;

       status = ioctl (vdm_channel,
                       DG_VDM_LIST_SUBDRIVERS,
                       &list_subdrivers_pkt);

       printf ("Number of subdrivers = %d\n",
               list_subdrivers_pkt.number_of_subdrivers);

       list_subdrivers_pkt.key          = 0;
       list_subdrivers_pkt.available    = 1;
       list_subdrivers_pkt.subdriver_id = &subdriver_id;

       while (1)
           {
           status = ioctl (vdm_channel,
                           DG_VDM_LIST_SUBDRIVERS,
                           &list_subdrivers_pkt);

           if ((status == -1)  && (errno == ENOENT))
               {
               break;
               }

           printf ("Subdriver 0x%08x\n", subdriver_id);
           }

   Get the global change ticket

       struct  dg_vdm_get_change_ticket_packet     change_packet;

       change_packet.version = DG_VDM_IOCTL_PACKET_VERSION_0;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_CHANGE_TICKET,
                       &change_packet);

       printf ("Change ticket is = %d\n",
               change_packet.change_ticket);

   Get subdriver information

       unsigned in     subdriver_id;

       struct  dg_vdm_get_subdriver_info_packet    subdriver_packet;

       subdriver_packet.version      = DG_VDM_IOCTL_PACKET_VERSION_0;
       subdriver_packet.subdriver_id = subdriver_id;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_SUBDRIVER_INFO,
                       &subdriver_packet);

       printf ("Subdriver device name   = '%s'\n",
               subdriver_packet.subdriver_device_name);
       printf ("Subdriver friendly name = '%s'\n",
               subdriver_packet.subdriver_friendly_name);
       printf ("Instance count          = %u\n",
               subdriver_packet.instance_count);
       printf ("Logging                 = %s\n",
               (subdriver_packet.logging) ? "true" : "false");

   Set VDM I/O logging

       unsigned_int    log_subdriver;
       dev_t           log_instance;

       struct  dg_vdm_log_packet       log_packet;

       log_packet.version              = DG_VDM_IOCTL_PACKET_VERSION_0;
       log_packet.logging              = 1;
       log_packet.number_of_instances  = 1;
       log_packet.instance_array_ptr   = &log_instance;
       log_packet.number_of_subdrivers = 1;
       log_packet.subdriver_array_ptr  = &log_subdriver;

       status = ioctl (vdm_channel,
                       DG_VDM_LOGGING,
                       &log_packet);

   Set default boot information

       dev_t   root_instance;
       dev_t   swap_instance;
       dev_t   disk_device_number;
       struct  dg_vdm_set_defaults_packet      set_defaults_packet;

       set_defaults_packet.version            = DG_VDM_IOCTL_PACKET_VERSION_0;
       set_defaults_packet.disk_device_number = disk_device_number;
       set_defaults_packet.set_default_root   = 1;
       set_defaults_packet.set_default_swap   = 1;
       set_defaults_packet.default_root       = root_instance;
       set_defaults_packet.default_swap       = swap_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_SET_BOOT_INFO,
                       &set_defaults_packet);

   Get default boot information

       dev_t   disk_device_number;
       struct  dg_vdm_get_defaults_packet      get_defaults_packet;

       get_defaults_packet.version            = DG_VDM_IOCTL_PACKET_VERSION_0;
       get_defaults_packet.disk_device_number = disk_device_number;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_BOOT_INFO,
                       &get_defaults_packet);

       if (get_defaults_packet.default_root_set)
           {
           printf ("Default root set\n");
           printf ("Default root device number = 0x%08x\n",
                   get_defaults_packet.default_root);
           }
       else
           {
           printf ("Default root not set\n");
           }

       if (get_defaults_packet.default_swap_set)
           {
           printf ("Default swap set\n");
           printf ("Default swap device number = 0x%08x\n",
                   get_defaults_packet.default_swap);
           }
       else
           {
           printf ("Default swap not set\n");
           }

   Get the global topology ticket

       struct  dg_vdm_get_topology_ticket_packet     topology_packet;

       change_packet.version = DG_VDM_IOCTL_PACKET_VERSION_0;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_TOPOLOGY_TICKET,
                       &topology_packet);

       printf ("Topology ticket is = %d\n",
               topology_packet.topology_ticket);

   Get the minimally unique name for an instance

       dev_t   unique_instance;
       struct  dg_vdm_get_instance_unique_name_packet      unique_packet;

       unique_packet.version       = DG_VDM_IOCTL_PACKET_VERSION_0;
       unique_packet.device_number = unique_instance;

       status = ioctl (vdm_channel,
                       DG_VDM_GET_INSTANCE_UNIQUE_NAME,
                       &unique_packet);

       printf ("Unique name is = '%s'\n",
               unique_packet.instance_unique_name);

   Cluster two disks

       dev_t   disk_0_device_number;
       dev_t   disk_1_device_number;
       dev_t   disks [2];
       struct  dg_vdm_cluster_disk_packet      cluster_pkt;

       cluster_pkt.version         = DG_VDM_IOCTL_PACKET_VERSION_0;
       cluster_pkt.cluster_mode    = 1;
       cluster_pkt.number_of_disks = 2;
       cluster_pkt.disk_array_ptr  = disks;

       disks [0] = disk_0_device_number;
       disks [1] = disk_1_device_number;

       status = ioctl (vdm_channel,
                       DG_VDM_CLUSTER_DISK,
                       &cluster_pkt);

       if (status == -1)
           {
           if (cluster_pkt.failed_disk != NODEV)
               {
               printf ("There was a failed disk\n");
               }

           if (cluster_pkt.failed_instance)
               {
               printf ("There was a failed instance\n");
               }
           }

FILES
       /dev/dsk
              Directory for the block special device nodes for virtual
              disks.  These are the buffered access device nodes.

       /dev/rdsk
              Directory for the character special device nodes for virtual
              disks.  These are the unbuffered (or raw) access device nodes.

       /dev/vdm
              Device node for issuing all ioctl(2) commands.

       /usr/include/sys/ioctl.h
              ioctl(2) definitions.

ACCESS CONTROL
       Access control for the standard VDM framework commands is controlled
       by the VDM itself.

       Access control for the subdriver commands is controlled by the
       subdrivers themselves.  See the man pages for the subdrivers for a
       listing of these controls.

       All users may execute these commands: DG_VDM_GET_ATTRIBUTES,
       DG_VDM_GET_BOOT_INFO, DG_VDM_GET_CHANGE_TICKET,
       DG_VDM_GET_CHILD_INSTANCE, DG_VDM_GET_INSTANCE_INFO,
       DG_VDM_GET_INSTANCE_UNIQUE_NAME, DG_VDM_GET_PARENT_INSTANCE,
       DG_VDM_GET_SUBDRIVER_INFO, DG_VDM_GET_TOPOLOGY_TICKET,
       DG_VDM_IOCTL_SUBDRIVER (for unprivileged subdriver commands),
       DG_VDM_LIST_INSTANCES, DG_VDM_LIST_REGISTERED_DISKS,
       DG_VDM_LIST_SUBDRIVERS, DSKIOCGET, DSKIOCUSAGE.

       Only users with appropriate privilege may execute these commands:
       DG_VDM_CLUSTER_DISK, DG_VDM_CREATE_INSTANCE, DG_VDM_DELETE_INSTANCE,
       DG_VDM_DEREGISTER_DISK, DG_VDM_EXPORT_INSTANCE,
       DG_VDM_EXTRACT_INSTANCE, DG_VDM_INSERT_INSTANCE,
       DG_VDM_IOCTL_SUBDRIVER (for privileged subdriver commands),
       DG_VDM_LINK_CHILD_INSTANCE, DG_VDM_LOGGING, DG_VDM_REGISTER_DISK,
       DG_VDM_SET_BOOT_INFO, DG_VDM_UNEXPORT_INSTANCE,
       DG_VDM_UNLINK_CHILD_INSTANCE, DG_VDM_UPDATE_ATTRIBUTES,
       DG_VDM_UPDATE_INSTANCE.

       On a generic DG/UX system, appropriate privilege is granted by having
       an effective UID of 0 (root).  See the appropriate_privilege(5) man
       page for more information.

       On a system with DG/UX information security, appropriate privilege is
       granted by having one or more specific capabilities enabled in the
       effective capability set of the user.  See the cap_defaults(5) man
       page for the default capabilities for these commands.

RETURN VALUE
       The return value from the ioctl(2) system call used to issue the
       command will be one of the following:

       0      The command was successful.

       -1     An error occurred.  errno is set to indicate the error.

DIAGNOSTICS
       There are descriptive extended error message strings available for
       most of the error codes.  They can be retrieved with the
       dg_ext_errno(2), extended_strerror(3C), and extended_perror(3C)
       routines.

       Errno may be set to one of the DG/UX standard error codes.  See
       /usr/include/sys/errno.h for a listing of those error codes.

       Errno may also be set to one of the following standard VDM error
       codes.  These standard error codes may also be returned by the
       subdrivers.

       EACCES       You do not have permission to execute this operation.

       EBUSY        The virtual disk is still mounted, opened, referenced,
                    or mmapped.

       EBUSY        There are still VDM subdrivers registered.

       EBUSY        The VDM is still open.

       EBUSY        The VDM subdriver is still managing virtual disks.

       EBUSY        Cannot deregister the disk, it is still in use.

       EBUSY        The virtual disk cannot be linked to the same parent
                    more than once.

       EBUSY        The dump device has already been opened.

       EBUSY        An unprotected open already exists.

       EBUSY        The virtual disk is still mounted, opened, referenced,
                    or mmapped on other nodes in the cluster.

       EBUSY        Some parent of the changing virtual disk will not allow
                    the size change.

       EEXIST       The VDM subdriver is already registered.

       EEXIST       The virtual disk is already exported.

       EEXIST       The disk is already registered.

       EEXIST       Some of the disks are still registered on other nodes in
                    the cluster.

       EINVAL       The VDM subdriver name cannot be null.

       EINVAL       The virtual disk is not exported.

       EINVAL       The I/O request size is illegal.

       EINVAL       The sector size is not in even multiples of the number
                    of bytes per block.

       EINVAL       The virtual disk has too many children for this
                    operation to complete.

       EINVAL       The parent and child virtual disks are not the same
                    size.

       EINVAL       A different VDM subdriver is managing the virtual disk.

       EINVAL       The disk is not registered.

       EINVAL       The virtual disk cannot be linked or opened because it
                    would be its own ancestor.

       EINVAL       The internal VDM child reference is in an invalid state.

       EINVAL       Cannot open the virtual disk yet, it is not usable.

       EINVAL       The data read from disk is not the data that was
                    expected.

       EINVAL       The request for VDIT data from disk is not valid.

       EINVAL       The disk does not contain any VDITs (it does not appear
                    to be VDM formatted).

       EINVAL       The virtual disk name contains invalid characters.

       EINVAL       The virtual disk is not persistent.

       EINVAL       A VDIT entry on disk is corrupt.

       EINVAL       Cannot set or change the persistence of the virtual disk
                    in that way.

       EINVAL       The specified 'dummy' virtual disk must be of type
                    'dummy'.

       EINVAL       Cannot insert a virtual disk of type 'dummy'.

       EINVAL       Cannot insert a persistent 'dummy' virtual disk in this
                    case.

       EINVAL       Cannot extract a virtual disk of type 'physical'.

       EINVAL       Only virtual disks of type 'physical' may coalesce
                    themselves.

       EINVAL       Cannot update virtual disk attributes on non-VDM-
                    registered disks.

       EINVAL       Cannot execute the operation on a virtual disk that is
                    not yet usable.

       EINVAL       The I/O request offset is illegal.

       EINVAL       The disk cannot be registered (it appears to be LDM
                    formatted).

       EINVAL       The VDM is joined to a cluster.

       EINVAL       There is no outstanding unprotected open.

       EINVAL       The virtual disk structure is too complex for an
                    unprotected open.

       EINVAL       Cannot do unprotected opens on non-cluster disks.

       EINVAL       The corresponding node is not in the cluster.

       EINVAL       You must register all disks on all cluster nodes so the
                    parent and child virtual disks can be found.

       EINVAL       Some virtual disks were partially exported or could not
                    be recreated on other nodes in the cluster.

       EINVAL       There are too many disks listed for this operation to
                    process.

       EINVAL       Additional disks need to be included in order to make
                    this cluster mode change.

       EINVAL       The disk is not in DG/UX VDM format.

       EINVAL       The disk to be unclustered contains the active cluster
                    database.  Use cluster administration mode instead.

       EINVAL       Cannot do unprotected opens in cluster administration
                    mode.

       EINVAL       Cannot rename the active cluster database.  Use cluster
                    administration mode instead.

       EINVAL       Cannot manipulate a system virtual disk in this fashion.

       EINVAL       The parent virtual disk could not be linked to the child
                    virtual disk on some other node in the cluster.

       EINVAL       Cannot delete a floating virtual disk.

       EIO          Cannot write to the VDIT on the disk.

       EIO          Cannot complete the disk deregistration, some virtual
                    disks still remain.

       EIO          Cannot store the attributes on this disk because the
                    VDIT is closed.

       EIO          Cannot store the attributes on the disk because the VDIT
                    could not be coalesced.

       EIO          Cannot store the attributes on some of the required
                    disks.  The changes are incomplete.

       EIO          Cannot store the attributes on any of the required
                    disks.  The changes are incomplete.

       EIO          Cannot remove the attributes from some of the required
                    disks.  The changes are incomplete.

       EIO          Cannot remove the attributes from any of the required
                    disks.  The changes are incomplete.

       EIO          Cannot store the attributes on some of the required
                    disks.  The virtual disk was not created.

       EIO          The VDIT on disk is sealed.

       EIO          The connection hung up.

       EIO          A VDM operation was interrupted.

       ENAMETOOLONG The virtual disk name is too long.

       ENAMETOOLONG The VDM subdriver name is too long.

       ENOENT       There are no more virtual disks to list.

       ENOENT       There are no internal async I/O records available for
                    the virtual disk.

       ENOENT       There are no pended async I/O requests for the virtual
                    disk.

       ENOENT       There are no more VDM subdrivers to list.

       ENOENT       The primary or secondary VDIT on disk could not be
                    found.

       ENOENT       There are no more entries in the VDIT on disk.

       ENOENT       Could not locate the 'physical' virtual disk in the VDIT
                    on disk.

       ENOENT       There are no more registered disks to list.

       ENOENT       Cannot locate the true root virtual disk for the
                    registered disk.

       ENOENT       Cannot locate the master subdriver name entry for the
                    managing subdriver.

       ENOMEM       Insufficient system memory is available to complete the
                    operation.

       ENOSPC       The internal buffer is not big enough for the virtual
                    disk's attributes.

       ENOSPC       There are not enough resources available to update the
                    VDIT on the disk.

       ENOSPC       The VDIT on the disk is full.

       ENOSPC       The internal buffer is not big enough for the VDIT entry
                    from disk.

       ENOTUNIQ     The virtual disk name is ambiguous.

       ENOTUNIQ     The VDM subdriver name is not unique.

       ENXIO        The virtual disk could not be found.

       ENXIO        The VDM subdriver could not be found.

       ENXIO        The VDM is not configured.

       ENXIO        The starting I/O device address is illegal.

       ENXIO        Cannot register the disk, the vdmphys() subdriver is not
                    configured.

       ENXIO        Cannot register the disk, the vdmpart() subdriver is not
                    configured.

       ENXIO        Cannot register the disk, the vdmaggr() subdriver is not
                    configured.

       ENXIO        The cluster operation failed.

       EOPNOTSUPP   The VDM or one of its subdrivers does not support this
                    operation.

       EOPNOTSUPP   The VDM or one of its subdrivers does not support this
                    version of the interface.

       EOPNOTSUPP   The boot information entry version is not supported by
                    the VDM.

       EOPNOTSUPP   The subdriver entry version is not supported by the VDM.

       EOPNOTSUPP   The virtual disk entry version is not supported by the
                    VDM.

       EOPNOTSUPP   The 'physical' virtual disk attributes version is not
                    supported by the VDM.

       EOPNOTSUPP   The VDM does not support registering duplicated disks.

       EOPNOTSUPP   Operation is not supported on non-cluster disks.

       EOPNOTSUPP   Cluster operations are not supported when clusters is
                    not installed.

       EOPNOTSUPP   Operation is not supported on mixed cluster and non-
                    cluster disks.

       EOPNOTSUPP   Operation is not supported on cluster disks.

       EOPNOTSUPP   The disk and/or controller does not support cluster
                    access.

       EOPNOTSUPP   The virtual disk type is not supported on cluster disks.

       EOPNOTSUPP   Boot information is not supported on cluster disks.

       EOPNOTSUPP   The VDM does not support this version of the cluster
                    message.

       EOPNOTSUPP   The VDM does not support this version of the cluster
                    message header.

SEE ALSO
       admpdisk(1M), admvdisk(1M), dg_sysctl(2), ioctl(2), dsk(7), rdsk(7),
       vdmaggr(7), vdmcache(7), vdmdummy(7), vdmmirr(7), vdmmpio(7),
       vdmpart(7), vdmphys(7), vdmremap(7), vdmtest(7).


Licensed material--property of copyright holder(s)

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026