Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

ioctl(2)

dsk(7)

rdsk(7)

vdm(7)



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


NAME
       vdmpart - Virtual Disk Manager Partition Subdriver

DESCRIPTION
       The Partition Subdriver enables you to subdivide the space on a
       physical disk so that you can store different information on
       different parts of a single physical disk.  Without it, you would
       have to devote an entire physical disk to one file system or
       database.  With it, you can subdivide the physical disk into discrete
       units, or "partitions", each of which can be used to store a
       different file system or database.

       Partitions also support software bad-block remapping.  If it is
       enabled, and a write to the partitioned device fails due to a media
       failure (i.e., a hard error on the disk), software bad-block
       remapping will redirect the block to the remap area on the disk to
       store the data, and the I/O will succeed.

       Pictorially, two partitions of a physical disk, both with software
       bad-block remapping enabled look like this:

                 0               49999   0               39999
                 +-------------------+   +-------------------+
                 | partition "swap"  |   | partition "root"  |
                 | starts at 1000    |   | starts at 51000   |
                 | is 50000 blocks   |   | is 40000 blocks   |
                 +-------------------+   +-------------------+
               1000  |          | 50999 51000 |          | 90999
                     |          |             |          |
                     |          |             |          |
                     |       +-------------------+       |
                     |       | remap instance    |       |
                     |       +-------------------+       |
                     |                 |                 |
                     |                 |                 |
                     +------------+    |    +------------+
                                  |    |    |
                             +-------------------+
                             | physical          |
                             | sd(ncsc(0,7),0,0  |
                             +-------------------+
                                       |
                                       |
                                   ----------
                                  (          )
                                  (          )
                                  (   disk   )
                                  (   drive  )
                                  (     1    )
                                  (          )
                                   ----------

       Partitions have up to two children.  In this example, each partition
       has one child that is the partitioned device (the physical instance),
       and another child that is the software bad-block remapping child.

       Typically, the remap child is not drawn in diagrams with partitions
       since it is of secondary importance to the partition itself.

       DG/UX supports up to approximately 90 partitions per gigabyte of
       physical disk size.  So, for disks up to 1 Gbyte, you can have
       approximately 90 partitions.  For disks between 1 Gbyte and 2 Gbytes,
       you can have approximately 180 partitions.  The actual number
       possible for any given physical disk depends on the amount of free
       space available in the VDIT (Virtual Disk Information Table) on the
       physical disk.  In general, enough free space exists to build as many
       partitions as you want.

       In order to use the Partition Subdriver, you must configure vdmpart()
       into your kernel.  It appears in all new system files by default, so
       it is usually already configured.

       For more details about how the Partition Subdriver fits into the
       Virtual Disk Manager, see the vdm(7) man page.

   MULTIPLE PARTITIONS
       Each partition you create acts like a disk all its own, hence the
       name "virtual disk".  Your application can think of a partition as an
       ordered set of disk blocks, the first of which is numbered zero, and
       the last of which is numbered N - 1, where N is the number of blocks
       in the partition.  The application does not need to worry about where
       the partition is stored on disk.

       The Partition Subdriver takes care of offsetting the I/Os to each
       partition by the starting block number of the partition to map it
       onto the blocks of the physical disk.

       In the example, the tops of the two partitions indicate the block
       numbers that the beginning and end of the partitions have from the
       application's perspective.  The bottom of the partitions indicate the
       blocks on the physical disk where the data for the partition is
       actually stored.

       You can have as many partitions on a physical disk as you want, as
       long as there is free space for them.  Partitions may not overlap,
       and must be wholly contained on the disk (they can't go off the end
       of the disk).

   BAD-BLOCK REMAPPING
       Software bad-block remapping is an optional feature used to prevent
       single block media failures from causing I/O failures to the
       applications.  It is enabled at the partition level by linking the
       remap child for the physical disk to the partition.  If the remap
       child is not linked to the partition, any media failures from the
       physical disk will result in unrecoverable I/O errors being sent to
       the application.

       By default, when you format a physical disk with sysadm(1M), software
       bad-block remapping will be enabled.  Further, by default when you
       create a partition on a physical disk that has software bad-block
       remapping enabled, the partition will also have it enabled.  You can
       override both defaults if you care to.

       We recommend that you enable software bad-block remapping on all
       disks and for all partitions as the default.  In some situations,
       however, you may safely choose to remove it.

       One situation where software bad-block remapping can be safely
       removed is if the disk is in a CLARiiON® RAID-5 stripe.  In this
       case, the RAID technology in the CLARiiON® is already protecting
       against single bad blocks on the disks, so you can safely disable
       software bad-block remapping for it.  It can be enabled without
       problems, but it would be redundant.

       NVRAM (Non-Volatile Random Access Memory) boards also do not need to
       have software bad-block remapping enabled for them, since they
       provide single-bit ECC (Error Correcting Code) to prevent single-bit
       errors from resulting in I/O failures.  These NVRAM boards are
       commonly used to hold Front-End Devices for VDM caches.  See
       vdmcache(1M) for more details.

       For more details about the Bad-Block Remapping Subdriver, see the
       vdmremap(7) man page.

   PARTITIONS OF NON-PHYSICAL VIRTUAL DISKS
       Normally, partitions are built on top of the physical instance for a
       physical disk.  This is the most natural way of creating them.

       However, since a partition does not know what type of virtual disk
       the partitioned child is, it can be built on top of any other type of
       virtual disk.

       For example, if you wanted to have two partitions mirrored across two
       physical disks, the usual way to create this is to create two
       partitions on each physical disk, with each distributed pair of
       partitions being the same size.  You would then build a mirror for
       each distributed pair of partitions.  Your applications would then
       open the two mirrors to do their work.

       Pictorially, this traditional arrangement looks like this:

            0               49999    0               39999
            +-------------------+    +-------------------+
            | mirror "swap"     |    | mirror "root"     |
            | is 50000 blocks   |    | is 40000 blocks   |
            +-------------------+    +-------------------+
               |             |          |             |
               |             |          |             |
               |             |          |             +----------+
               |             |         /                         |
               |             |        /                          |
               |             +--------------------+              |
               |                    /             |              |
       0       |       49999       /      0       |       49999  |
       +-------------------+      /       +-------------------+  |
       | image 1 of "swap" |     /        | image 2 of "swap" |  |
       | partition         |    /         | partition         |  |
       | starts at 1000    |   /          | starts at 2000    |  |
       | is 50000 blocks   |  /           | is 50000 blocks   |  |
       +-------------------+  |           +-------------------+  |
       1000 |          50999  |           2000 |          51999  |
            |                 |                |                 |
            |    0            |  39999         |    0            |  39999
            |    +-------------------+         |    +-------------------+
            |    | image 1 of "root" |         |    | image 2 of "root" |
            |    | partition         |         |    | partition         |
            |    | starts at 51000   |         |    | starts at 52000   |
            |    | is 40000 blocks   |         |    | is 40000 blocks   |
            |    +-------------------+         |    +-------------------+
            |    51000     |     90999         |    52000     |     91999
            |              |                   |              |
            |              |                   |              |
            +-----+        |                   +-----+        |
                  |        |                         |        |
             +-------------------+              +-------------------+
             | physical          |              | physical          |
             | sd(ncsc(0,7),0,0  |              | sd(ncsc(0,7),1,0  |
             +-------------------+              +-------------------+
                       |                                  |
                       |                                  |
                   ----------                         ----------
                  (          )                       (          )
                  (          )                       (          )
                  (   disk   )                       (   disk   )
                  (   drive  )                       (   drive  )
                  (     1    )                       (     2    )
                  (          )                       (          )
                   ----------                         ----------

       If having two mirrors is inconvenient for some reason, you could
       build this arrangement a different way.  First, create a partition on
       each physical disk that's the combined size of the two separate
       partitions.  Then build a mirror between those two partitions.
       Finally, build the two user partitions on top of the mirror.

       Pictorially, this alternate arrangement looks like the diagram below.

       Warning:  You cannot boot from the root virtual disk in this
                 alternate example.  Do not set up your root or usr virtual
                 disk in this fashion.

                   0               49999   0               39999
                   +-------------------+   +-------------------+
                   | partition "swap"  |   | partition "root"  |
                   | starts at 0       |   | starts at 50000   |
                   | is 50000 blocks   |   | is 40000 blocks   |
                   +-------------------+   +-------------------+
                   0         |     49999   50000     |     89999
                             |                       |
                             +-------+       +-------+
                                     |       |
                               0     |       | 89999
                               +-------------------+
                               | mirror            |
                               | is 90000 blocks   |
                               +-------------------+
                                    |         |
                                    |         |
                       +------------+         +-----------+
                       |                                  |
                       |                                  |
             0         |     89999              0         |     89999
             +-------------------+              +-------------------+
             | image 1 of mirror |              | image 2 of mirror |
             | partition         |              | partition         |
             | starts at 1000    |              | starts at 2000    |
             | is 90000 blocks   |              | is 90000 blocks   |
             +-------------------+              +-------------------+
             1000      |     90999              2000      |     91999
                       |                                  |
                       |                                  |
             +-------------------+              +-------------------+
             | physical          |              | physical          |
             | sd(ncsc(0,7),0,0  |              | sd(ncsc(0,7),1,0  |
             +-------------------+              +-------------------+
                       |                                  |
                       |                                  |
                   ----------                         ----------
                  (          )                       (          )
                  (          )                       (          )
                  (   disk   )                       (   disk   )
                  (   drive  )                       (   drive  )
                  (     1    )                       (     2    )
                  (          )                       (          )
                   ----------                         ----------

       There are pros and cons to each arrangement:

       Traditional Arrangement Pros:

       1.     It is a traditional arrangement and may be easier to
              understand.

       2.     The I/O to the two top level virtual disks is independent
              until it reaches the disk drives.  This may mean better
              performance because there is a smaller bottleneck.

       3.     You can boot from the traditional root by booting from one
              image of the mirror.

       Traditional Arrangement Cons:

       1.     There are two mirrors to manage.

       2.     If you want to add additional partitions, you have to create
              them on both physical disks and create another mirror.

       Alternate Arrangement Pros:

       1.     There is only one mirror to manage.

       2.     This creates "mirrored storage", which you can build
              additional partitions out of easily.

       Alternate Arrangement Cons:

       1.     It it a non-traditional arrangement and may be harder to
              understand.  A physical disk listing from admpdisk(1M), for
              instance, will show the two partitions of the mirror instead
              of the two top level partitions, so it may be harder to find
              things.

       2.     The single mirror represents a bottleneck and may cause
              performance problems.  The I/O from each top level partition
              will compete for mirror resources to be executed.

       3.     You cannot boot from the alternate root, since it is not a
              simple partition of the physical instance.  Do not set root or
              usr up this way because you will not be able to boot your
              system.

       You are free to choose the arrangement for your partitions that best
       fits your needs.

       Software bad-block remapping is only supported for partitions of the
       physical instance itself.  Partitions like the top level ones in the
       alternate example above implicitly have bad-block protection if the
       base partitions (the images of the mirror) have it enabled.

   USABILITY
       For you to be able to use a partition (i.e., open it), both both the
       partitioned child and the remap child must be usable.  This is
       usually the case, except when the remap child has been damaged for
       some reason, which is rare.

   EXPANDING AND SHRINKING PARTITIONS
       Partitions can be expanded on-line while they are open and the
       virtual disk is in use.  This will make the partition larger, by
       incorporating contiguous free space that immediately follows the
       partition.

       The application using the partition 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.

       Partitions 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 the data in the portion to be removed,
       be migrated out, and rewritten to other places in the virtual disk.

   INSERTING AND EXTRACTING PARTITIONS
       Partitions can be inserted and extracted, but it's not a useful thing
       to do.  If you insert a partition, it must cover the entire range of
       the partitioned child, otherwise it will implicitly shrink the
       virtual disk the application is using, causing I/O errors.  Further,
       because of this, there will be no free space left on the partitioned
       child for additional partitions.

       In order to extract a partition, it must have one child, the
       partitioned disk.  Further, the partition must span the entire
       physical disk to avoid causing I/O errors to the applications using
       it for the same reasons given above.  This is not possible for
       registered disks, since the VDM itself maintains several system
       partitions to manage things like the disk label and the VDITs.

       Since it is of no practical use to insert or extract partitions, we
       do not recommend it be done.

   CLUSTER DISKS
       Partitions may be created on cluster disks and may use software bad-
       block remapping if desired.

   BOOTING FROM PARTITIONS
       You can boot from partitions as long as they are simple partitions of
       the physical instance (e.g., you cannot boot from the root in the
       alternate swap and root example above).  They may have software bad-
       block remapping enabled if desired.

   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 partition that you have previously
       set up.  This is many times faster than taking the dump to tape.  For
       more details on this, see the vdm(7) man page.

PROGRAMMING INTERFACE
       The ioctl(2) system call is used for all communication with the
       Partition 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
       Partition Subdriver.  The <errno.h>, <sys/dg_sysctl.h>,
       <sys/types.h>, <stdio.h>, and <unistd.h> include files will be
       helpful.

SUBDRIVER-SPECIFIC COMMANDS
   DG_VDMPART_LIST_PARTITIONS
       List the partitions of a partitioned instance.

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).

SUBDRIVER-SPECIFIC DEFINES
   DG_VDMPART_SUBDRIVER_ID
       The unique ID that identifies the Partition Subdriver.

   DG_VDMPART_IOCTL_PACKET_VERSION_0
       The version zero stamp used in all Partition Subdriver ioctl(2)
       packets.

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

   DG_VDMPART_PARTITIONED_CHILD
       The value indicating that this child is the partitioned child.  The
       partitions reside on the partitioned instance.

   DG_VDMPART_REMAP_CHILD
       The value indicating that this child is the remap child.  The remap
       child is used for bad-block remapping for the partition.

STRUCTURES
   dg_vdmpart_create_packet
       The Partition Subdriver ioctl(2) packet for creating a new partition
       instance.  Put a pointer to this packet into the packet for the
       DG_VDM_CREATE_INSTANCE command.

       struct      dg_vdmpart_create_packet
           {
           int             version;
           dev_t           partitioned_instance;
           daddr_t         starting_block;
           unsigned int    size_in_blocks;
           dev_t           remap_device_number;
           };

       version
              The version of the packet.

       partitioned_instance
              The device number of the instance being partitioned.

       starting_block
              The starting block number of the partition.  Block numbers are
              zero-based.

       size_in_blocks
              The number of blocks in the partition.

       remap_device_number
              The device number of the bad-block remapping instance to use
              with the partition.  If bad-block remapping is not desired,
              set the field to NODEV.

   dg_vdmpart_get_packet
       The Partition Subdriver ioctl(2) packet for getting the attributes of
       a partition instance.  Put a pointer to this packet into the packet
       for the DG_VDM_GET_ATTRIBUTES command.

       struct      dg_vdmpart_get_packet
           {
           int             version;
           daddr_t         starting_block;
           unsigned int    size_in_blocks;
           };

       version
              The version of the packet.

       starting_block
              The returned starting block number of the partition.  Block
              numbers are zero-based.

       size_in_blocks
              The returned number of blocks in the partition.

   dg_vdmpart_update_attributes_packet
       The Partition Subdriver ioctl(2) packet for updating the attributes
       of a partition instance.  Put a pointer to this packet into the
       packet for the DG_VDM_UPDATE_ATTRIBUTES command.

       struct      dg_vdmpart_update_attributes_packet
           {
           int     version;
           int     change_in_size;
           };

       version
              The version of the packet.

       change_in_size
              The number of blocks by which to grow (if positive) or shrink
              (if negative) the partition.  Partitions may be grown while
              they are on-line and in use.  They may only be shrunk while
              they are off-line.

   dg_vdmpart_get_child_packet
       The Partition Subdriver ioctl(2) packet for getting child role
       information about the children of a partition instance.  Put a
       pointer to this packet into the child instance sub-packet for the
       DG_VDM_GET_CHILD_INSTANCE command.

       struct      dg_vdmpart_get_child_packet
           {
           int                     version;
           int                     child_type;
           union
               {
               struct
                   {
                   daddr_t         starting_block;
                   unsigned int    size_in_blocks;
                   } partitioned;
               } child;
           };

       version
              The version of the packet.

       child_type
              The returned type of the child.  The type will either be
              DG_VDMPART_PARTITIONED_CHILD or DG_VDMPART_REMAP_CHILD.  This
              identifies the role the child plays for the partition, and
              which fields of the child union are returned.  Note that child
              information is only returned for the partitioned child.  The
              remap child has no additional role information to return.

       child  A returned union of the structures used for child role
              information about the children of a partition.

       partitioned
              The returned structure containing the child role information
              about the partitioned child of a partition.

       child.partitioned.starting_block
              The returned starting block number of the partition.  Block
              numbers are zero-based.

       child.partitioned.size_in_blocks
              The returned number of blocks in the partition.

   dg_vdmpart_list_partitions_packet
       The Partition Subdriver ioctl(2) packet for listing the partitions of
       a partitioned instance.  Put a pointer to this packet into the
       argument field of the packet for the DG_VDM_IOCTL_SUBDRIVER command,
       and set the command field to DG_VDMPART_LIST_PARTITIONS.  Set the
       instance device number field to NODEV, so the command will be issued
       to the Partition Subdriver itself.

       Each time the DG_VDMPART_LIST_PARTITIONS command is issued, the
       device number of the next partition will be returned.  When there are
       no more partitions to return, error ENOENT will be returned.

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

       struct      dg_vdmpart_list_partitions_packet
           {
           int             version;
           dev_t           partitioned_instance;
           unsigned int    key;
           dev_t           partition_device_number;
           daddr_t         starting_block;
           unsigned int    size_in_blocks;
           };

       version
              The version of the packet.

       partitioned_instance
              The device number of the partitioned instance.  The partitions
              residing on this instance will be listed.

       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 Partition Subdriver 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.

       partition_device_number
              The returned device number of the next partition of the
              instance.

       starting_block
              The returned starting block number of the partition.  Block
              numbers are zero-based.

       length_in_blocks
              The returned number of blocks in the partition.

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 */

   Create a partition

       dev_t   part_instance;
       dev_t   phys_instance;
       dev_t   remap_instance;
       struct  dg_vdm_create_instance_packet   create_pkt;
       struct  dg_vdmpart_create_packet        part_create_pkt;

       create_pkt.version             = DG_VDM_IOCTL_PACKET_VERSION_0;
       create_pkt.subdriver_id        = DG_VDMPART_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 = &part_create_pkt;

       part_create_pkt.version = DG_VDMPART_IOCTL_PACKET_VERSION_0;
       part_create_pkt.partitioned_instance = phys_instance;
       part_create_pkt.starting_block       = 1000;
       part_create_pkt.size_in_blocks       = 300000;
       part_create_pkt.remap_device_number  = remap_instance;

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

       part_instance = create_pkt.device_number;

       printf ("Partition device number = 0x%08x\n", part_instance);

   Update a partition's attributes to expand it

       dev_t   update_instance;
       struct  dg_vdm_update_attributes_packet         update_attrs_pkt;
       struct  dg_vdmpart_update_attributes_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);

   Get a partition's attributes

       dev_t   get_instance;
       struct  dg_vdm_get_attributes_packet    get_attrs_pkt;
       struct  dg_vdmpart_get_packet           part_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_VDMPART_SUBDRIVER_ID;
       get_attrs_pkt.subdriver_attributes_packet_ptr = &part_get_pkt;

       part_get_pkt.version = DG_VDMPART_IOCTL_PACKET_VERSION_0;

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

       printf ("Starting block   = %lu\n",
               part_get_pkt.starting_block,
       printf ("Number of blocks = %u\n",
               part_get_pkt.size_in_blocks);

   Link a remap child to a partition (enable remapping)

       dev_t   link_instance;
       dev_t   remap_instance;
       struct  dg_vdm_link_child_instance_packet   link_pkt;

       link_pkt.version               = DG_VDM_IOCTL_PACKET_VERSION_0;
       link_pkt.parent_device_number  = link_instance;
       link_pkt.parent_subdriver_id   = DG_VDMPART_SUBDRIVER_ID;
       link_pkt.child_device_number   = remap_instance;
       link_pkt.child_packet_ptr      = NULL;

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

   Get the children of a partition

       int     i;
       dev_t   part_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_vdmpart_get_child_packet         part_get_child_pkt;

       get_child_pkt.version = DG_VDM_IOCTL_PACKET_VERSION_0;
       get_child_pkt.key                      = 0;
       get_child_pkt.parent_device_number     = part_instance;
       get_child_pkt.parent_subdriver_id      = DG_VDMPART_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 = &part_get_child_pkt;

       part_get_child_pkt.version = DG_VDMPART_IOCTL_PACKET_VERSION_0;

       i = 0;

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

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

           printf ("Child %d\n", i);

           switch (part_get_child_pkt.child_type)
               {
               case DG_VDMPART_PARTITIONED_CHILD:

                   printf ("Partition of\n");

                   break;

               case DG_VDMPART_REMAP_CHILD:

                   printf ("Remapping with\n");

                   remap_found = 1;

                   break;
               }

           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);
               }

           if (part_get_child_pkt.child_type == DG_VDMPART_PARTITIONED_CHILD)
               {
               printf ("    Start = %lu, blocks = %u\n",
                       part_get_child_pkt.child.partitioned.starting_block,
                       part_get_child_pkt.child.partitioned.size_in_blocks);
               }

           printf ("\n");
           i++;
           }

   Unlink a remap child from a partition (disable remapping)

       dev_t   unlink_instance;
       dev_t   remap_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 =
           remap_instance;

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

   List the partitions on a physical instance

       int     i;
       dev_t   phys_instance
       struct  dg_vdm_ioctl_subdriver_packet       ioctl_pkt;
       struct  dg_vdmpart_list_partitions_packet   list_partitions_pkt;

       ioctl_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       ioctl_pkt.subdriver_id           = DG_VDMPART_SUBDRIVER_ID;
       ioctl_pkt.instance_device_number = NODEV;
       ioctl_pkt.command                = DG_VDMPART_LIST_PARTITIONS;
       ioctl_pkt.argument               = (int) &list_partitions_pkt;

       list_partitions_pkt.version = DG_VDMPART_IOCTL_PACKET_VERSION_0;
       list_partitions_pkt.partitioned_instance = phys_instance;
       list_partitions_pkt.key                  = 0;

       i = 0;

       while (1)
           {
           status = ioctl (vdm_channel,
                           DG_VDM_IOCTL_SUBDRIVER,
                           &ioctl_pkt);

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

           printf ("Partition %d\n", i);

           printf ("Partition device number = 0x%08x\n",
                   list_partitions_pkt.partition_device_number);

           printf ("    Start = %lu, blocks = %u\n",
                   list_partitions_pkt.starting_block,
                   list_partitions_pkt.size_in_blocks);

           printf ("\n");
           i++;
           }

   Get the size of a partition

       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_VDMPART_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 Partition Subdriver commands is controlled by
       the subdriver itself.

       All users may execute these commands: DG_VDM_GET_ATTRIBUTES,
       DG_VDM_GET_CHILD_INSTANCE, DG_VDMPART_LIST_PARTITIONS, DSKIOCGET,
       DSKIOCUSAGE.

       Only users with appropriate privilege may execute these commands:
       DG_VDM_CREATE_INSTANCE, DG_VDM_LINK_CHILD_INSTANCE,
       DG_VDM_UNLINK_CHILD_INSTANCE, DG_VDM_UPDATE_ATTRIBUTES.

       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  There are still remapped partitions on the virtual disk.

       EBUSY  Cannot create or modify the partition.  It would overlap
              another partition.

       EBUSY  Cannot shrink a partition while it is open.

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

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

       EINVAL The partition is already remapped.

       EINVAL The partition is not remapped.

       EINVAL Cannot create or modify the partition.  Its size would be zero
              or negative.

       ENOENT There are no more partitions to list.

       ENXIO  There are no partitions on the virtual disk.

       ENXIO  The remap virtual disk does not belong to the partitioned
              virtual disk.

       ENXIO  Cannot create or modify the partition.  It does not fit on the
              partitioned virtual disk.

SEE ALSO
       ioctl(2), dsk(7), rdsk(7), vdm(7).


Licensed material--property of copyright holder(s)

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