vdmaggr(7) DG/UX R4.11 vdmaggr(7)
NAME
vdmaggr - Virtual Disk Manager Aggregation Subdriver
DESCRIPTION
The Aggregation Subdriver enables you to combine separate virtual
disks into a single, large virtual disk that can be larger than the
size of any single physical disk. The aggregation pieces may be on
different physical disks or at different places on a single physical
disk. You can use aggregations to gather small chunks of free space
on several disks together to form a single virtual disk that is a
usable size.
Aggregations also support software disk striping, where the data
blocks are stored round-robin fashion among the aggregation pieces to
provide a more balanced I/O load to the physical disks. This can
improve performance.
Pictorially, an aggregation containing two pieces looks like this:
+-------------------+
| aggregation "X11" |
| is 120000 blocks |
+-------------------+
| |
+-------+ +-------+
| |
+-------------------+ +-------------------+
| piece 0 | | piece 1 |
| partition | | partition |
| starts at 50000 | | starts at 1000 |
| 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 )
( ) ( )
---------- ----------
Aggregations refer to their children as pieces. So in this example,
the aggregation has two pieces, each of which is a partition living
on a different disk drive.
The current revision of DG/UX supports aggregations that have up to
approximately 120 pieces. The actual number possible for any given
aggregation depends on the amount of free space available in the
VDITs (Virtual Disk Information Tables) on the physical disks that
the aggregation spans. In general, enough free space exists to build
several maximum sized aggregations.
In order to use the Aggregation Subdriver, you must configure
vdmaggr() into your kernel. It appears in all new system files by
default, so it is usually already configured.
For more details about how the Aggregation Subdriver fits into the
Virtual Disk Manager, see the vdm(7) man page.
SOFTWARE DISK STRIPING
In the example above, the aggregation is not striped. The first N
blocks of the aggregation will be written to blocks zero through (N -
1) of piece zero, where N is the size of piece zero. The next M
blocks will be written to blocks zero through (M - 1) of piece one,
where M is the size of piece one.
This unstriped aggregation is the default organization when you
create an aggregation. It is good for general purpose data storage,
as well as for applications that read or write large sequential I/Os,
especially if there is only one thread or process doing the I/O.
Here is what the data blocks for an unstriped aggregation look like:
0 119999
+-------------------+
| aggregation "X11" |
| is 120000 blocks |
+-------------------+
| |
+-------+ +-------+
0 | 39999 40000 | 119999
+-------------------+ +-------------------+
| 0, 1, 2, 3, 4, 5, | | 40000, 40001, |
| 6, 7, 8, 9, 10, | | 40002, 40003, |
| 11, 12, 13, 14, ..| | 40004, 40005, .. |
| | | |
| piece 0 | | piece 1 |
| partition | | partition |
| is 40000 blocks | | is 80000 blocks |
+-------------------+ +-------------------+
| |
| |
| |
---------- ----------
( ) ( )
( ) ( )
( disk ) ( disk )
( drive ) ( drive )
( 1 ) ( 2 )
( ) ( )
---------- ----------
A striped aggregation, on the other hand, organizes the data blocks
within the aggregation in a round-robin fashion. The splitting of
I/O requests is done on stripe size boundaries. The stripe size is
settable when you create the aggregation.
Striping is most useful when your application does small, fixed sized
random reads and writes, especially if multiple threads or processes
are doing I/O to the same virtual disk at the same time. By placing
the data blocks in a round-robin fashion, the likelihood that a
second I/O request will need to access a different disk to get the
data blocks increases.
This means that different I/O requests can be processed in parallel
more often, and that increases performance. One request would be
reading or writing to the first disk, while a second request would
likely be accessing the second disk. Since the disks are physically
separate, they can truly process the two I/O requests in parallel.
The parallelism increases as you stripe the aggregation across more
physical disks.
The same two I/O requests would have to be processed serially if the
aggregation was not striped and the requests both fell onto the same
piece of the aggregation. This is because they would both be
directed to the same physical disk, which can process only one
request at a time. This would limit the performance of the
application.
Here is what the data blocks for a striped aggregation look like
using a stripe size of four blocks:
0 119999
+-------------------+
| aggregation "X11" |
| is 120000 blocks |
+-------------------+
| |
+-------+ +-------+
| |
+-------------------+ +-------------------+
| 0, 1, 2, 3, | | 4, 5, 6, 7, |
| 8, 9, 10, 11, | | 12, 13, 14, 15, |
| 16, 17, 18, 19 .. | | 20, 21, 22, 23 .. |
| | | |
| piece 0 | | piece 1 |
| partition | | partition |
| is 60000 blocks | | is 60000 blocks |
+-------------------+ +-------------------+
| |
| |
| |
---------- ----------
( ) ( )
( ) ( )
( disk ) ( disk )
( drive ) ( drive )
( 1 ) ( 2 )
( ) ( )
---------- ----------
Notice that the sizes of the partitions had to change in order to use
software disk striping. There are additional rules for building
striped aggregations that are required to make the striping work
properly. They are:
1. All of the pieces of a striped aggregation must be the same
size.
2. The stripe size must divide evenly into the size of a piece
(i.e., no remainder).
3. The stripe size must be less than or equal to the piece size.
4. Striped aggregations cannot be expanded or shrunk, since
adding or removing pieces would remove chunks of data from all
parts of the aggregation.
Choose the stripe size to match the average size of the I/Os that the
application reads and writes. Choosing a stripe size smaller than
the I/O size will mean that all I/Os will have to be broken up and
issued in multiple requests to read or write the data. This will
severely reduce performance. Choosing a stripe size that is a larger
multiple of the I/O size may also work well for some applications.
Good stripe sizes are powers of two, like 16, 32, 64, 128, and 256.
This is because most disk drives tend to transfer data well at block
sizes that are powers of two, and applications tend to choose powers
of two for their I/O sizes. However, no limits are placed on the
stripe size, so you may set it to any value that best matches your
application's needs.
To ensure that software striping is working efficiently with the
physical disks, align the start of each piece of the aggregation on a
stripe block boundary on the physical disk. Further, each piece of a
striped aggregation should reside on a different physical disk.
If you build a DG/UX file system on a striped aggregation, you should
set the data element size of the file system to the stripe size.
Alternately, you can set the stripe size to be a larger multiple of
the data element size. This will help ensure that the file system
issues stripe-aligned I/O requests to the virtual disk. You may want
to set other file system parameters according to your application's
needs.
Generally, you should not use software disk striping and CLARiiON®
hardware disk striping together, since the two mechanisms will both
be striping the data and will be working at cross purposes.
It is hard to predict when software disk striping will benefit
performance. If used incorrectly, it can have a negative impact on
performance as well. To determine if it will help your applications,
run performance tests of it on both a non-striped and striped
aggregation, and choose the data organization that best meets your
needs.
USABILITY
For you to be able to use an aggregation (i.e., open it), all of its
pieces must be available and usable. If any pieces are missing, the
aggregation cannot be opened, and the data in it is unavailable.
This means that using aggregations reduces the availability of the
data. For example, if an aggregation is spread over four disks, a
failure of any one of the disks means that the whole aggregation is
unavailable. This risk is greater than if all of the data were
stored in a single partition on a single disk drive.
EXPANDING AND SHRINKING AGGREGATIONS
Aggregations can be expanded on-line while they are open and the
virtual disk is in use. The application using the aggregation must
be prepared for such an expansion. The DG/UX file system is, so you
can expand DG/UX file systems on-line, without unmounting them. The
users can continue to read and write to the file system while it is
being expanded. However, most database software is not prepared to
have its regions expanded. Instead, simply add another region to the
database.
Aggregations can likewise be shrunk, but only when the virtual disk
is closed and not in use. Applications like the DG/UX file system
can be made to handle on-line expansions relatively easily, but on-
line shrinking would be more difficult to build, so the VDM does not
permit it. A shrink requires that the data in the portion to be
removed be migrated out and rewritten to other places in the virtual
disk.
There are several ways an aggregation can be expanded or shrunk.
They are:
1. Link a new child piece to the end of the aggregation. This
adds additional space to the end of the aggregation.
2. If the last piece of the aggregation is a simple partition,
the partition itself can be expanded. This also adds space to
the end of the aggregation.
In this case, the application doing the expansion must issue a
DSKIOCGET ioctl(2) command to the aggregation after the
partition is expanded to inform the aggregation that a child
piece has changed size.
3. Unlink an old child piece from the end of the aggregation.
This removes space from the end of the aggregation.
4. If the last piece of the aggregation is a simple partition,
the partition itself can be shrunk. This also removes space
from the end of the aggregation.
In this case, the application doing the shrink must issue a
DSKIOCGET ioctl(2) command to the aggregation after the
partition is shrunk to inform the aggregation that a child
piece has changed size.
5. If you have a single partition that you wish to expand, but
there is no contiguous free space following it, insert an
aggregation on top of it, then link additional pieces to the
aggregation to expand it.
In order to successfully expand or shrink a virtual disk, the
application that owns the data must be involved in the size change
and probably should initiate it to guarantee that it has placed the
data in the proper state before, during, and after the size change.
The DG/UX file system is such an application, and the tools that
manage them can initiate both file system expansions and shrinks.
The Aggregation Subdriver also permits pieces to be added or removed
in the middle of an aggregation, but only when the aggregation is
closed. Doing so, however, renders the data in the aggregation
useless, since the new or removed piece changes the block numbers of
the blocks in the later pieces. The sysadm(1M) menus and the
admvdisk(1M) commands only permit you to add or remove pieces at the
end of an aggregation for this reason.
CLUSTER DISKS
Aggregations may be created on cluster disks and may be striped if
desired. The pieces for an aggregation must either all be on cluster
disks or all be on non-cluster disks. An aggregation may not span
both cluster and non-cluster disks.
However, the current revision of DG/UX does not permit aggregations
to be expanded or shrunk in any fashion while the disks they reside
on are clustered.
To change the size of a cluster aggregation, first close it on all
but one node (i.e., unmount if it is a file system, shut it down if
it is a database). Then deregister the disks on all but one node.
Be sure to deregister all the disks that the aggregation spans. On
the remaining node, uncluster the affected disks, then expand or
shrink the aggregation as desired. Finally, cluster the disks again,
then register them on the other cluster nodes.
BOOTING FROM AGGREGATIONS
You can boot from aggregations as long as all of the pieces to the
virtual disk live on the same physical disk. This is a bootstrap
limitation because it can only accept one disk specification on the
boot command line.
This means that root can be an aggregation, but must have all of its
pieces on one physical disk. The same is true of usr (so that you
can boot standalone sysadm).
PROGRAMMING INTERFACE
The ioctl(2) system call is used for all communication with the
Aggregation Subdriver. Use the open(2) system call to open a channel
to the /dev/vdm node, and issue all ioctl(2) commands through that
channel. See vdm(7) for more details on the programming interface.
The <sys/ioctl.h> include file is required for communicating with the
Aggregation Subdriver. The <errno.h>, <sys/dg_sysctl.h>,
<sys/types.h>, <stdio.h>, and <unistd.h> include files will be
helpful.
SUBDRIVER-SPECIFIC COMMANDS
The Aggregation Subdriver has no subdriver-specific commands.
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).
This command is also used to trigger parent instances to get the
sizes of their children again after one of the children has changed
size. After you change the size of the child, you must issue
DSKIOCGET commands to all the ancestors of the child, so that they
will update their sizes as well.
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).
SUBDRIVER-SPECIFIC DEFINES
DG_VDMAGGR_SUBDRIVER_ID
The unique ID that identifies the Aggregation Subdriver.
DG_VDMAGGR_IOCTL_PACKET_VERSION_0
The version zero stamp used in all Aggregation Subdriver ioctl(2)
packets.
The stamp indicates which version of the Aggregation Subdriver
interface is being used and allows the Aggregation Subdriver to
support previous versions without requiring that applications be
recompiled.
STRUCTURES
dg_vdmaggr_create_packet
The Aggregation Subdriver ioctl(2) packet for creating a new
aggregation instance. Put a pointer to this packet into the packet
for the DG_VDM_CREATE_INSTANCE command.
struct dg_vdmaggr_create_packet
{
int version;
unsigned int stripe_size;
unsigned short number_of_pieces;
dev_t * piece_array_ptr;
};
version
The version of the packet.
stripe_size
The number of disk blocks in a stripe, if the aggregation is
to be striped, or zero if it is not to be striped. If the
aggregation is to be striped, all the pieces must be the same
size, the stripe size must evenly divide into the size of a
piece, and the stripe size must be less than or equal to the
size of a piece.
number_of_pieces
The number of pieces in the aggregation.
piece_array_ptr
A pointer to an array of dev_t variables identifying the
instances that are the pieces of the aggregation. Put the
number of entries in the array in number_of_pieces.
dg_vdmaggr_get_packet
The Aggregation Subdriver ioctl(2) packet for getting the attributes
of an aggregation instance. Put a pointer to this packet into the
packet for the DG_VDM_GET_ATTRIBUTES command.
struct dg_vdmaggr_get_packet
{
int version;
unsigned int stripe_size;
};
version
The version of the packet.
stripe_size
The returned stripe size of the aggregation if it is striped,
or zero if it is not striped.
dg_vdmaggr_update_packet
The Aggregation Subdriver ioctl(2) packet for updating the attributes
of an aggregation instance. Put a pointer to this packet into the
packet for the DG_VDM_UPDATE_ATTRIBUTES command.
Modifying the stripe size of an aggregation will destroy all the data
in the aggregation.
struct dg_vdmaggr_update_packet
{
int version;
unsigned int stripe_size;
};
version
The version of the packet.
stripe_size
The new number of disk blocks in a stripe, if the aggregation
is to be striped, or zero if it is not to be striped. If the
aggregation is to be striped, all the pieces must be the same
size, the stripe size must evenly divide into the size of a
piece, and the stripe size must be less than or equal to the
size of a piece.
dg_vdmaggr_get_child_packet
The Aggregation Subdriver ioctl(2) packet for getting child role
information about a piece of an aggregation instance. Put a pointer
to this packet into the child instance sub-packet for the
DG_VDM_GET_CHILD_INSTANCE command.
struct dg_vdmaggr_get_child_packet
{
int version;
unsigned int piece_number;
};
version
The version of the packet.
piece_number
The returned piece number of the child. Piece numbers are
zero-based.
dg_vdmaggr_link_child_packet
The Aggregation Subdriver ioctl(2) packet for linking a new piece
into an aggregation instance. Put a pointer to this packet into the
packet for the DG_VDM_LINK_CHILD_INSTANCE command.
Linking a new piece into a striped aggregation will destroy all the
data in the aggregation.
struct dg_vdmaggr_link_child_packet
{
int version;
unsigned int piece_number;
};
version
The version of the packet.
piece_number
The piece number for the new piece. Piece numbers are zero-
based. If the aggregation is open, the piece can be added
only at the end of the aggregation.
EXAMPLES
The following code fragments illustrate the use of 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 */
Create an aggregation
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 aggregation's stripe size
dev_t update_instance;
struct dg_vdm_update_attributes_packet update_attrs_pkt;
struct dg_vdmaggr_update_packet aggr_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_VDMAGGR_SUBDRIVER_ID;
update_attrs_pkt.subdriver_attributes_packet_ptr = &aggr_update_pkt;
aggr_update_pkt.version = DG_VDMAGGR_IOCTL_PACKET_VERSION_0;
aggr_update_pkt.stripe_size = 32;
status = ioctl (vdm_channel,
DG_VDM_UPDATE_ATTRIBUTES,
&update_attrs_pkt);
Get an aggregation'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);
Insert an aggregation
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 aggregation
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 piece to an aggregation
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 aggregation
dev_t aggr_instance;
dev_t child_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 = aggr_instance;
get_child_pkt.parent_subdriver_id = DG_VDMAGGR_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");
}
Unlink a piece from an aggregation
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);
Get the size of an aggregation
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 = DG_VDMAGGR_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));
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. See the vdm(7) man page for a listing of these
controls.
Access control for the Aggregation Subdriver commands is controlled
by the subdriver itself. Below is the listing of these commands.
All users may execute these commands: DSKIOCGET (to get the size of
an instance), and DSKIOCUSAGE.
Only users with appropriate privilege may execute these commands:
DSKIOCGET (to change the size of a parent 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 be set to one of the standard error codes provided by the
VDM framework. See vdm(7) for a listing of those error codes.
Errno may also be set to one of the following error codes that are
specific to this subdriver:
EBUSY The piece number is not valid while the aggregation is open.
EBUSY Cannot update an aggregation's attributes while it is open.
EBUSY Cannot resize a striped aggregation while it is open.
EBUSY Cannot resize any piece of an open aggregation except for the
last one.
EINVAL There are no aggregation pieces specified.
EINVAL The aggregation piece number is not valid.
EINVAL Cannot remove the last piece from an aggregation.
EINVAL All pieces in a striped aggregation must be the same size.
EINVAL The aggregation stripe size must evenly divide into the piece
size.
EINVAL The aggregation stripe size must be less than or equal to the
piece size.
ENXIO The virtual disk is not a piece of the aggregation.
SEE ALSO
ioctl(2), dsk(7), rdsk(7), vdm(7).
Licensed material--property of copyright holder(s)