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)



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


NAME
       vdmremap - Virtual Disk Manager Bad-Block Remapping Subdriver

DESCRIPTION
       The Bad-Block Remapping Subdriver is used to prevent single-block
       media failures from causing I/O failures to the applications.  This
       is done by intercepting I/O to the failed blocks and redirecting it
       to a remap area with good blocks to store the data.

       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.

       Pictorially, a remap instance looks like this:

                               +-------------------+
                               | remap instance    |
                               +-------------------+
                                   |     |     |
                +------------------+     |     +----------------+
                |                        |                      |
                |                        |                      |
       +-------------------+   +-------------------+   +-------------------+
       | primary table     |   | remap area        |   | secondary table   |
       | partition         |   | partition         |   | partition         |
       | starts at 17      |   | starts at 19      |   | starts at 119     |
       | is 2 blocks       |   | is 100 blocks     |   | is 2 blocks       |
       +-------------------+   +-------------------+   +-------------------+
                |                        |                      |
                |                        |                      |
                +------------------+     |     +----------------+
                                   |     |     |
                               +-------------------+
                               | physical          |
                               | sd(ncsc(0,7),0,0) |
                               +-------------------+
                                         |
                                         |
                                     ----------
                                    (          )
                                    (          )
                                    (   disk   )
                                    (   drive  )
                                    (     1    )
                                    (          )
                                     ----------

       Remap instances refer to their children by the roles that they play.
       They always have three children: a primary bad-block table, a remap
       area, and a redundant secondary bad-block table.

   WHEN TO USE BAD-BLOCK REMAPPING
       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.

   MAPPING BAD BLOCKS
       Without bad-block remapping enabled, a read or write to a bad block
       on the disk (a hard error) will result in an error return for the
       I/O.  There is no way for an application to recover from this
       situation, since there's no place else for it to write its data.

       With bad-block remapping enabled, the data can be redirected to a
       different known good block on the disk, and the I/O will succeed.

       If a write fails with bad-block remapping enabled, the remap instance
       will mark the failed block as bad in the primary and secondary remap
       tables.  The data for the failed block will be written into the next
       available block in the remap area.  The remaining good blocks in the
       I/O are written to the original locations on the disk.  Subsequent
       reads to the remapped block will be intercepted by the remap instance
       and the data will be read from the remap area block instead of the
       original failed block.

       This write remapping is transparent to the application, since the I/O
       will succeed after the data blocks are safely on disk.  An error
       message will be sent to the operator's console to inform them of the
       bad block on the disk.

       If a read fails with bad-block remapping enabled, the situation is a
       bit different.  Since the original data was only written to the
       original disk block which is now bad, the data is gone.  It cannot be
       reconstructed, so it is lost.  A read to such a block requires the
       remap instance to return an I/O error to the application because the
       data is no longer available.  Additionally, the block is entered into
       the remap tables as "needing to be remapped".  The next time a write
       to the block is done, the remap instance will intercept it and
       redirect the data to the next available block in the remap area.

       Additionally, if you know beforehand that a given block on a disk is
       bad, you can force the remap instance to cause it to be mapped before
       it ever causes a failure.  Sometimes disk manufacturers will ship a
       list of known bad blocks with a disk.  You should enter these bad
       blocks into the bad-block table before loading the disk with your
       data.

       If a bad block resulted from some transient condition (like shaking
       the disk drive), you can tell the remap instance to recover the
       block.  It will attempt to write and read the already remapped data
       to the block.  If the write and read are successful, the data will be
       left in the repaired block and it will be removed from the bad-block
       table.

       Each physical disk that has bad-block remapping enabled has its own
       remap instance.  There can be only one remap instance per physical
       disk.  Always ensure that the remap child you are linking to a
       partition is the remap instance for the disk the partition resides
       on.

       The remap instance maintains duplicate copies of the bad-block
       information in the primary and secondary bad-block tables.  If a bad
       block inside one of the tables renders it unusable, the remap
       instance will continue running using the other table.  If a bad block
       occurs in the remap area itself, the bad block will be mapped to
       itself so that it is never used again, and the user data will be
       mapped to a different remap area block.

       Bad blocks on modern SCSI disks are rare due to their reliability.
       In addition, most modern disks implement hardware bad-block remapping
       that is done within the disk drive itself.  This means that if any
       bad blocks do occur, they will likely be handled by the disk drive,
       and DG/UX software bad-block remapping will not be involved.

       The primary and secondary remap tables must be formatted before they
       can be used.  The only way to format them is to install bad-block
       remapping on a disk with admpdisk(1M).

   BAD BLOCK REMAP STATES
       These are the states a bad block can be in:

       Unmapped    The bad block has been noticed due to a read I/O failure
                   and has not yet been remapped.  The next write to the
                   block will do the remapping.

       Mapped      The bad block has been fully remapped.  Reads and writes
                   to the block are intercepted and redirected to the
                   remapped block in the remap area.

       Forced      The operator has forced the remap instance to list a
                   block as bad (perhaps because the disk manufacturer told
                   them it was bad).  It is considered unmapped until the
                   next write is done to it, at which time it will be
                   converted to the mapped state.

       Pseudo      The block does not necessarily need remapping but its
                   contents are undetermined.  It is treated as an unmapped
                   block.

       Bad Remap   The bad block occurred inside the bad-block remapping
                   area and it has been mapped to itself to prevent it from
                   being used anymore.

       These states will be listed when you list bad blocks for a disk.

   USABILITY
       A remap instance is always usable, as long as the three partitions it
       uses are usable.  This is almost always the case, except when the
       child partitions have been damaged in some way, which is rare.

   EXPANDING AND SHRINKING REMAP INSTANCES
       You cannot expand or shrink the remap instance itself (since it has
       no size), nor the three child partitions it uses.  The sizes are
       determined when you initially create the remap instance and cannot be
       changed later.

   INSERTING AND EXTRACTING REMAP INSTANCES
       Remap instances cannot be inserted or extracted.  They can only be
       created and deleted.

   CLUSTER DISKS
       All bad-block remapping functionality is available on cluster disks.
       Bad blocks detected from one node will be atomically distributed to
       the other nodes so that the remap instances on them will know about
       the new bad block.

       You may initially create cluster virtual disks with or without
       remapping enabled, as your needs dictate.

       However, you cannot change whether a virtual disk is using remapping
       while it is clustered.  To enable or disable remapping for a cluster
       virtual disk, uncluster the disk, make the change, then put the disk
       back into cluster mode.

   ADMPDISK
       The admpdisk(1M) command provides an easy-to-use interface for
       listing and managing bad blocks.  See the descriptions for the
       list_mapped_blocks, verify, map_block, and unmap_block commands for
       more details.

PROGRAMMING INTERFACE
       The ioctl(2) system call is used for all communication with the Bad-
       Block Remapping 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
       Bad-Block Remapping 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_VDMREMAP_LIST_REMAP_TABLE
       List the entries in the bad-block tables of a remap instance.

   DG_VDMREMAP_FORCE_REMAP
       Forcibly remap a block onto a spare block in the remap area.

   DG_VDMREMAP_RECOVER_BAD_BLOCK
       Attempt to recover a block that has been marked bad and already
       remapped onto a block in the remap area.

COMMON DISK COMMANDS
       Since the Remap Subdriver does not issue its I/O through its
       children, it does not support either the DSKIOCGET or the DSKIOCUSAGE
       command.

SUBDRIVER-SPECIFIC DEFINES
   DG_VDMREMAP_SUBDRIVER_ID
       The unique ID that identifies the Remap Subdriver.

   DG_VDMREMAP_IOCTL_PACKET_VERSION_0
       The version zero stamp used in all Remap Subdriver ioctl(2) packets.

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

   DG_VDMREMAP_MAX_REMAP_TABLE_BLOCKS
       The number of blocks in the bad-block table.

   DG_VDMREMAP_TABLE_ENTRIES_PER_BLOCK
       The number of entries in a block of the bad-block table.

   DG_VDMREMAP_MAX_BLOCKS_REMAPPABLE
       The maximum number of blocks that can be remapped per physical disk.

   DG_VDMREMAP_PRIMARY_TABLE_CHILD
       The value indicating that this child is the primary remap table.  The
       remap tables contain entries that record which blocks are remapped
       and where in the remap area they are remapped to.  The remap tables
       are replicated.

   DG_VDMREMAP_SECONDARY_TABLE_CHILD
       The value indicating that this child is the secondary remap table.
       The remap tables contain entries that record which blocks are
       remapped and where in the remap area they are remapped to.  The remap
       tables are replicated.

   DG_VDMREMAP_REMAP_AREA_CHILD
       The value indicating that this child is the remap area.  Bad blocks
       are remapped to spare blocks within the remap area.

   DG_VDMREMAP_UNMAPPED_BB_ENTRY
       The status indicating that the listed bad block has not yet been
       remapped.

   DG_VDMREMAP_MAPPED_BB_ENTRY
       The status indicating that the listed bad block has been remapped.

   DG_VDMREMAP_FORCED_BB_ENTRY
       The status indicating that the listed bad block has been forced to be
       remapped.

   DG_VDMREMAP_PSEUDO_BB_ENTRY
       The status indicating that the listed bad block is a pseudo bad
       block.

   DG_VDMREMAP_BAD_REMAP_BB_ENTRY
       The status indicating that the listed remap block has gone bad and
       will not be used anymore.

STRUCTURES
   dg_vdmremap_create_packet
       The Remap Subdriver ioctl(2) packet for creating a new remap
       instance.  Put a pointer to this packet into the packet for the
       DG_VDM_CREATE_INSTANCE command.

       The three partitions must be properly initialized before creating the
       remap instance to use them.

       struct      dg_vdmremap_create_packet
           {
           int     version;
           dev_t   primary_remap_table;
           dev_t   secondary_remap_table;
           dev_t   remap_area;
           };

       version
              The version of the packet.

       primary_remap_table
              The device number of the partition for the primary copy of the
              bad-block table.

       secondary_remap_table
              The device number of the partition for the secondary copy of
              the bad-block table.

       remap_area
              The device number of the partition for the remap area.

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

       struct      dg_vdmremap_get_child_packet
           {
           int     version;
           int     child_type;
           };

       version
              The version of the packet.

       child_type
              The returned type of the child.  The type will be
              DG_VDMREMAP_PRIMARY_TABLE_CHILD,
              DG_VDMREMAP_SECONDARY_TABLE_CHILD, or
              DG_VDMREMAP_REMAP_AREA_CHILD.  This identifies the role the
              child plays for the remap instance.

   dg_vdmremap_list_remap_table
       The Remap Subdriver ioctl(2) packet for listing the entries in the
       remap tables for a remap 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_VDMREMAP_LIST_REMAP_TABLE.
       Put the device number of the remap instance to query in the instance
       device number field.

       Each time the DG_VDMREMAP_LIST_REMAP_TABLE command is issued, the
       information for the next bad-block entry will be returned.  When
       there are no more entries to return, error ENOENT will be returned.

       Note that the information returned can become invalid if blocks are
       remapped in between commands.

       struct      dg_vdmremap_list_remap_table
           {
           int             version;
           daddr_t         bad_block;
           daddr_t         remap_index;
           int             status;
           unsigned int    key;
           };

       version
              The version of the packet.

       bad_block
              The returned block number of the block that has been remapped.
              Block numbers are zero-based.

       remap_index
              The returned block number in the remap area where the block
              has been remapped to.  Block numbers are zero-based.

       status The returned status of the remap entry, indicating what the
              state of the remapped block is.  The status will be
              DG_VDMREMAP_UNMAPPED_BB_ENTRY, DG_VDMREMAP_MAPPED_BB_ENTRY,
              DG_VDMREMAP_FORCED_BB_ENTRY, DG_VDMREMAP_PSEUDO_BB_ENTRY, or
              DG_VDMREMAP_BAD_REMAP_BB_ENTRY.

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

   dg_vdmremap_force_remap
       The Remap Subdriver ioctl(2) packet for forcing the remapping of a
       block for a remap 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_VDMREMAP_FORCE_REMAP.  Put the device
       number of the remap instance to update in the instance device number
       field.

       struct      dg_vdmremap_force_remap
           {
           int         version;
           daddr_t     block_number;
           };

       version
              The version of the packet.

       block_number
              The block number of the block to be force remapped.  Block
              numbers are zero-based.

   dg_vdmremap_recover_block
       The Remap Subdriver ioctl(2) packet for attempting to recover a block
       that has been remapped for a remap 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_VDMREMAP_RECOVER_BAD_BLOCK.  Put the device number of the remap
       instance to update in the instance device number field.

       struct      dg_vdmremap_recover_block
           {
           int         version;
           daddr_t     block_number;
           };

       version
              The version of the packet.

       block_number
              The block number of the block to attempt recovery on.  Block
              numbers are zero-based.

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 remap instance using already formatted children

       dev_t   remap_instance;
       dev_t   primary_instance;
       dev_t   area_instance;
       dev_t   secondary_instance;
       struct  dg_vdm_create_instance_packet   create_pkt;
       struct  dg_vdmremap_create_packet       remap_create_pkt;

       create_pkt.version             = DG_VDM_IOCTL_PACKET_VERSION_0;
       create_pkt.subdriver_id        = DG_VDMREMAP_SUBDRIVER_ID;
       create_pkt.persistent          = 1;
       create_pkt.enable_disk_updates = 1;
       strcpy (create_pkt.instance_name, ".Remap");
       create_pkt.subdriver_attributes_packet_ptr = &remap_create_pkt;

       remap_create_pkt.version = DG_VDMREMAP_IOCTL_PACKET_VERSION_0;
       remap_create_pkt.primary_remap_table = primary_instance;
       remap_create_pkt.secondary_remap_table = secondary_instance;
       remap_create_pkt.remap_area = area_instance;

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

       remap_instance = create_pkt.device_number;

       printf ("Remap device number = 0x%08x\n", remap_instance);

   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 remap instance

       int     i;
       dev_t   remap_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_vdmremap_get_child_packet        remap_get_child_pkt;

       get_child_pkt.version                  = DG_VDM_IOCTL_PACKET_VERSION_0;
       get_child_pkt.key                      = 0;
       get_child_pkt.parent_device_number     = remap_instance;
       get_child_pkt.parent_subdriver_id      = DG_VDMREMAP_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 = &remap_get_child_pkt;

       remap_get_child_pkt.version = DG_VDMREMAP_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 (remap_get_child_pkt.child_type)
               {
               case DG_VDMREMAP_PRIMARY_TABLE_CHILD:

                   printf ("Primary table\n");

                   break;

               case DG_VDMREMAP_SECONDARY_TABLE_CHILD:

                   printf ("Secondary table\n");

                   break;

               case DG_VDMREMAP_REMAP_AREA_CHILD:

                   printf ("Remap area\n");

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

           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 bad blocks for a remap instance

       int     blocks_listed;
       char *  status_text_ptr;
       dev_t   remap_instance;
       struct  dg_vdm_ioctl_subdriver_packet       ioctl_pkt;
       struct  dg_vdmremap_list_remap_table        list_remap_pkt;

       ioctl_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       ioctl_pkt.subdriver_id           = DG_VDMREMAP_SUBDRIVER_ID;
       ioctl_pkt.instance_device_number = remap_instance;
       ioctl_pkt.command                = DG_VDMREMAP_LIST_REMAP_TABLE;
       ioctl_pkt.argument               = (int) &list_remap_pkt;

       list_remap_pkt.version = DG_VDMREMAP_IOCTL_PACKET_VERSION_0;
       list_remap_pkt.key     = 0;

       printf ("\n");
       printf (" Bad block   Remapped to    Status\n");
       printf ("----------   -----------   --------\n");

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

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

           switch (list_remap_pkt.status)
               {
               case DG_VDMREMAP_UNMAPPED_BB_ENTRY:

                   status_text_ptr = "Unmapped";
                   break;

               case DG_VDMREMAP_MAPPED_BB_ENTRY:

                   status_text_ptr = "Mapped";
                   break;

               case DG_VDMREMAP_FORCED_BB_ENTRY:

                   status_text_ptr = "Forced";
                   break;

               case DG_VDMREMAP_PSEUDO_BB_ENTRY:

                   status_text_ptr = "Pseudo";
                   break;

               case DG_VDMREMAP_BAD_REMAP_BB_ENTRY:

                   status_text_ptr = "Bad remap";
                   break;
               }

           printf ("%10ld    %10ld   %s (%d)\n",
                   list_remap_pkt.bad_block,
                   list_remap_pkt.remap_index,
                   status_text_ptr,
                   list_remap_pkt.status);

           blocks_listed++;
           }

       printf ("\nNumber of blocks listed = %d\n", blocks_listed);

   Force a bad block to be remapped

       dev_t   remap_instance;
       daddr_t bad_block;
       struct  dg_vdm_ioctl_subdriver_packet       ioctl_pkt;
       struct  dg_vdmremap_force_remap             force_remap_pkt;

       ioctl_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       ioctl_pkt.subdriver_id           = DG_VDMREMAP_SUBDRIVER_ID;
       ioctl_pkt.instance_device_number = ioctl_instance;
       ioctl_pkt.command                = DG_VDMREMAP_FORCE_REMAP;
       ioctl_pkt.argument               = (int) &force_remap_pkt;

       force_remap_pkt.version      = DG_VDMREMAP_IOCTL_PACKET_VERSION_0;
       force_remap_pkt.block_number = bad_block;

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

   Recover a bad block

       dev_t   remap_instance;
       daddr_t bad_block;
       struct  dg_vdm_ioctl_subdriver_packet       ioctl_pkt;
       struct  dg_vdmremap_recover_block           recover_remap_pkt;

       ioctl_pkt.version                = DG_VDM_IOCTL_PACKET_VERSION_0;
       ioctl_pkt.subdriver_id           = DG_VDMREMAP_SUBDRIVER_ID;
       ioctl_pkt.instance_device_number = ioctl_instance;
       ioctl_pkt.command                = DG_VDMREMAP_RECOVER_BAD_BLOCK;
       ioctl_pkt.argument               = (int) &recover_remap_pkt;

       recover_remap_pkt.version      = DG_VDMREMAP_IOCTL_PACKET_VERSION_0;
       recover_remap_pkt.block_number = bad_block;

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

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 Bad-Block Remapping Subdriver commands is
       controlled by the subdriver itself.

       All users may execute this command: DG_VDM_GET_CHILD_INSTANCE,
       DG_VDMREMAP_LIST_REMAP_TABLE.

       Only users with appropriate privilege may execute these commands:
       DG_VDM_CREATE_INSTANCE, DG_VDMREMAP_FORCE_REMAP,
       DG_VDMREMAP_RECOVER_BAD_BLOCK.

       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 remap virtual disk is already enabled for I/O.

       EINVAL The sizes of the replicated remap tables and the remap area do
              not match.

       EINVAL The block cannot be remapped because it is in a partition that
              is not remapped or it is outside the boundaries of the disk.

       EINVAL An entry for the block already exists in the remap table.

       EIO    A bad block was found in the remap tables on disk.

       ENOENT The remap entry for the remap block could not be found.

       ENOENT There are no more remap blocks to list.

       ENOSPC There are no free remap blocks left in the remap area.

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