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,
®ister_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)