Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ vdmremap(7) — DG/UX 5.4R3.00

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

vdm(7)

vdmphys(7)

vdmpart(7)

ioctl(2)



vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


NAME
       vdmremap - Remap Subdriver of the Virtual Disk Manager

SYNOPSIS
       #include <types.h>
       #include <ioctl.h>

       ioctl(int fildes, int command, int argument);

DESCRIPTION
       The Remap Subdriver is a pseudo-device driver that works under the
       Virtual Disk Management (VDM) framework (see vdm(7)).  The purpose of
       the Remap Subdriver is to provide the capability to map bad blocks
       belonging to a virtual device (the remapped device) to blocks set
       aside in a remap area associated with the same virtual device.

STRUCTURES
       The structures defined in this section are pointed to by fields
       described in VDM commands (see vdm(7)).  The VDM command and the
       field in the argument structure will be described.  For many VDM
       commands, a subdriver ID is required as an input value.  The
       subdriver ID for the Remap Subdriver is defined by
       DGVDMREMAPSUBDRIVERID.

       Unless otherwise noted, the version field in the following structures
       is an input field that must be set to
       DGVDMREMAPIOCTLPACKETVERSION0.  Additionally, all packets must
       have every byte set to zero before it is used.

   DGVDMCREATEINSTANCE
       The subdriverattributespacketptr field points to the following
       structure:

       struct dgvdmremapcreatepacket
            {
            int                version;
            devt              primaryremaptable;
            devt              secondaryremaptable;
            devt              remaparea;
            };

       Each remap instance has associated with it a remap table holding
       information about the blocks that have been remapped. This table must
       be stored on stable storage and is itself not protected by software
       remapping.  The table is replicated to increase its availability.

       The primaryremaptable field is an input field containing the device
       number of the instance holding the primary copy of the remap table.
       The secondaryremaptable is an input field and it contains the
       device number of the instance holding the secondary copy of the remap
       table. The remaparea is an input field holding the device number of
       the remap area. The remap area consists of a set of spare blocks to
       be used to remap blocks in the remapped device.




Licensed material--property of copyright holder(s)                         1




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


       The size (in blocks) of the primary and secondary remap table
       instances is limited to:

          DGVDMREMAPMAXREMAPTABLEBLOCKS

       and the number of entries in the remap table is limited by:

          DGVDMREMAPMAXBLOCKSREMAPPABLE

       Since each block in the remap area requires one remap table entry,
       the maximum remap area size (in blocks) is equal to the maximum
       number of entries in the remap table.

       The request for the creation of a remap instance  will fail if the
       primary and secondary table instances are not the same size or if
       these instances are not large enough to hold the remap table needed
       for a remap area of the size of remaparea.  The errno will be set to
       EINVAL.

   DGVDMLINKCHILDINSTANCE
       A remap instance is limited to three children required at its
       creation: the two remap tables and the remap area; therefore, a child
       instance cannot be added to a remap instance.

   DGVDMUNLINKCHILDINSTANCE
       This command results in a child being removed from an instance.
       Since remap instances are required to always have three children, it
       is not possible to delete a child from a remap instance.

   DGVDMGETCHILDINSTANCE
       The childpacketptr points to the following structure:

       struct dgvdmremapgetchildpacket
           {
           int                 version;
           int                 childfunction;
           }

       The childfunction is an output field and is set to one of the
       following three values: DGVDMREMAPPRIMARYTABLE,
       DGVDMREMAPSECONDARYTABLE, and DGVDMREMAPREMAPAREA, depending on
       whether the child returned is the primary remap table, the secondary
       remap table or the remap area.

   DGVDMGETATTRIBUTES
       This command is not supported by the Remap Subdriver.  If an attempt
       is made to perform this operation, the command will fail and errno
       will be set to EOPNOTSUPP.

   DGVDMUPDATEATTRIBUTES
       The attributes of the remap area are set at creation and cannot be
       changed. This operation is not supported by the Remap Subdriver.  If
       an attempt is made to perform this operation, the command will fail
       and errno will be set to EOPNOTSUPP.



Licensed material--property of copyright holder(s)                         2




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


IOCTLS
       The ioctls supported by the Remap Subdriver are listed below.  The
       ioctl(2) command can be issued to the Remap Subdriver in two ways:

       1.     Issue the command to an exported instance of the Remap
              Subdriver.  In this case, the fd is an open file descriptor of
              the device node created when the instance was exported.  The
              command and the argument are described below.

       2.     Use the DGVDMIOCTLSUBDRIVER command described in more
              detail in vdm(7).  In this case, the fd is an open file
              descriptor of /dev/vdm device node.  The argument is a pointer
              to a structure that contains command and argument fields.  The
              values supplied for these fields are described below.

   DGVDMREMAPLISTREMAPTABLE
       This command lists the entries in the remap table of a remap
       instance.  These entries are returned in ascending block number
       order.  The argument is a pointer to the following structure:

       struct dgvdmremaplistremaptable
           {
           int             version;
           daddrt             badblock;
           int                 remapindex;
           int                 status;
           keyt               key;
           };

       The badblock field is an output field containing the number of the
       remapped bad block. The remapindex is an output field that contains
       the index into the remap area of the new remap block.  The status
       field is an output field containing the status of the remap entry.
       Possible values for the status of a remap entry include:
       DGVDMREMAPMAPPEDBBENTRY: the bad block has been mapped to a new
       block. All I/O is being redirected to this new block;
       DGVDMREMAPUNMAPPEDBBENTRY: although the original block has a
       remap block associated with it, the contents of the remap block are
       undetermined.  Until a write is performed to the new block, reads
       directed to the original block will fail with  errno set to EIO;
       DGVDMREMAPFORCEREMAPBBENTRY: similar to the unmapped case.
       However, no attempt to recover the original bad block will be made
       before remapping the bad block; and DGVDMREMAPPSEUDOBBENTRY: an
       entry with this status corresponds to a block that does not
       necessarily need remapping but whose contents are undetermined. Reads
       to pseudo bad blocks fail with errno set to EIO. The first write to a
       pseudo bad block sets its contents and deletes the corresponding
       remap table entry.

       The key is an input field and should be set to 0 when the list should
       start at the beginning.  All subsequent calls to list the partitions,
       the key field should not be read or written.





Licensed material--property of copyright holder(s)                         3




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


   DGVDMREMAPFORCEREMAP
       This command forces a block in the remapped device to be mapped to a
       new block in the remap area. This command allows a block to be
       remapped without having to wait for a failure when performing I/O to
       it.  The Remap Subdriver will not check to see if the block being
       remapped falls in a range of blocks that has been designated as
       remappable. The argument is a pointer to the following structure:

       struct dgvdmremapforceremap
           {
           int                  version;
           daddrt              blocknumber;
           }

       The blocknumber is an input field containing the block to be
       remapped.  The operation will fail with errno set to ENOSPC if there
       are no available blocks in the remap area.

   DGVDMREMAPRECOVERBADBLOCK
       This command attempts to recover a block that has been remapped. The
       recovery involves reading the contents of the block in the remap
       area, writing these contents to the block to be recovered, verifying
       that the data has been written to the recovered block, and deleting
       the corresponding remap table entry. If errors are encountered when
       performing I/O to the block to be recovered, this operation will fail
       with errno set to EIO, and the remap entry for the block to be
       recovered is left in the remapped state.  The argument is a pointer
       to the following structure:

       struct dgvdmremaprecoverblock
           {
           int                 version;
           daddrt             blocknumber;
           }

       The blocknumber is an input field containing the block to be
       recovered. If the block to be recovered is not in the remap table, or
       if it is in one of the unremapped states, this operation fails with
       errno set to EINVAL.

   DSKIOCGET
       This command returns the size of an instance. A remap instance does
       not have a size attribute, and therefore, does not support this
       command. To obtain the size of the remap area, issue a DSKIOCGET
       command to the remap area instance.

   DSKIOCUSAGE
       This command returns statistics associated with the use of an
       instance and is described in more detail in dsk(7).

   DSKIOCGETADDRESS
       This command returns the logical address at which a given memory
       address to the specified instance should be mapped.




Licensed material--property of copyright holder(s)                         4




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


EXAMPLE
       #include <errno.h>
       #include <fcntl.h>
       #include <stdio.h>
       #include <string.h>
       #include <sys/dgsysctl.h>
       #include <sys/ioctl.h>
       #include <unistd.h>


       /*
        *  This example makes use of functions defined in the vdm(7) man page,
        *  the vdmpart(7) man page, and the vdmphys(7) man page. These functions
        *  defined in vdm(7) all begin with a vdm prefix, the functions
        *  defined in the vdmpart(7) man page begin with a vdmpart prefix, and
        *  the functions defined in the vdmphys(7) man page begin with a vdmphys
        *  prefix.
        */

       /***********************************************************************
        *  This macro initializes a packet used by the Remap Subdriver.
        ***********************************************************************/
       #define vdmremapinitpacket(p) \
               (bzero((char *)&p, sizeof(p)), \
               p.version = DGVDMPARTIOCTLPACKETVERSION0);

       /***********************************************************************
        *  This function creates a remap instance using the given instances
        *  containing the primary and secondary remap tables and a remap
        *  area.
        ***********************************************************************/
       devt vdmremapcreateinstance (
       char * instancename,
       devt  primaryremaptable,
       devt  secondaryremaptable,
       devt  remaparea
                                      )
       {
       struct dgvdmremapcreatepacket createpkt;
       devt                            devicenumber;

       vdmremapinitpacket(createpkt);

       createpkt.primaryremaptable = primaryremaptable;
       createpkt.secondaryremaptable = secondaryremaptable;
       createpkt.remaparea = remaparea;

       devicenumber = vdmcreateinstance(
                          instancename, DGVDMREMAPSUBDRIVERID, &createpkt);

       return (devicenumber);
       }

       #define BADBLOCKTABLEBLOCK     2



Licensed material--property of copyright holder(s)                         5




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


       #define NODENUMBERFORNONFILES 012345670123
       #define BADBLOCKTABLEDATASIZE (512-8)

       /***********************************************************************
        *  This function formats the remap table.
        ***********************************************************************/
       int
       vdmremapformatremaptable(devt tabledevicenumber)
       {
       struct blocktag
           {
           struct selfidtag
               {
               unsigned char blockkind;
               unsigned int  blocknumber : 24;
               unsigned int  filenodenumber;
               } selfid;
           char data[BADBLOCKTABLEDATASIZE];
           } buffer;

       int tabledesc;
       int byteswritten;
       int blocknum;
       int numberofblocks;
       int i;
       int status;

       tabledesc = vdmopendevice(tabledevicenumber, OWRONLY, 0);
       if (tabledesc < 0)
           {
           status = -1;
           goto returnstatus;
           }

       /*
        *  Get the number of blocks in the table.
        */
       status = vdmgetdisksize(tabledesc, &numberofblocks);
       if (status != 0)
           {
           goto closeandreturnstatus;
           }

       /*
        *  Format up the block.
        */
       buffer.selfid.blockkind = BADBLOCKTABLEBLOCK;
       buffer.selfid.filenodenumber = NODENUMBERFORNONFILES;
       for (i = 0; i < BADBLOCKTABLEDATASIZE; i++)
           {
           buffer.data[i] = 0;
           }

       /*



Licensed material--property of copyright holder(s)                         6




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


        *  Write the buffer to each block.
        */
       for (blocknum = 0; blocknum < numberofblocks; blocknum++)
           {
           buffer.selfid.blocknumber = blocknum;
           byteswritten = write(tabledesc, &buffer, sizeof(buffer));
           if (byteswritten != sizeof(buffer))
            {
            status = -1;
            goto closeandreturnstatus;
            }
           }

       closeandreturnstatus:

       close(tabledesc);

       returnstatus:

       return (status);
       }


       int vdmremapexample (void)
       {
       devt physdevicenumber;
       devt primaryremaptable;
       devt secondaryremaptable;
       devt remaparea;
       devt remapinstance;
       int   status;

       /*
        *  Create a physical instance.
        */
       physdevicenumber = vdmphyscreateinstance("a", "sd(insc(),0)", ORDWR);
       if (physdevicenumber == NODEV)
           {
           perror("sd(insc(),0)");
           exit(1);
           }

       /*
        *  Create remap tables and the remap area.
        */
       primaryremaptable = vdmpartcreateinstance(
                      ".PrimaryBadBlockTable",
                               0, DGVDMREMAPMAXREMAPTABLEBLOCKS,
                               physdevicenumber, NODEV);
       if (primaryremaptable == NODEV)
           {
           perror("Primary Bad Block Table");
           exit(1);
           }



Licensed material--property of copyright holder(s)                         7




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


       status = vdmremapformatremaptable(primaryremaptable);
       if (status != 0)
           {
           perror("Format of Primary Bad Block Table");
           exit(1);
           }

       secondaryremaptable = vdmpartcreateinstance(
                      ".SecondaryBadBlockTable",
                               DGVDMREMAPMAXREMAPTABLEBLOCKS,
                               DGVDMREMAPMAXREMAPTABLEBLOCKS,
                               physdevicenumber, NODEV);
       if (secondaryremaptable == NODEV)
           {
           perror("Secondary Bad Block Table");
           exit(1);
           }

       status = vdmremapformatremaptable(secondaryremaptable);
       if (status != 0)
           {
           perror("Format of Secondary Bad Block Table");
           exit(1);
           }

       remaparea = vdmpartcreateinstance(
                      ".RemapArea",
                               DGVDMREMAPMAXREMAPTABLEBLOCKS * 2,
                               DGVDMREMAPMAXBLOCKSREMAPPABLE,
                               physdevicenumber, NODEV);
       if (remaparea == NODEV)
           {
           perror("Remap Area");
           exit(1);
           }

       /*
        *  Create the remap instance.
        */
       remapinstance = vdmremapcreateinstance(
                               ".Remap",
                               primaryremaptable,
                               secondaryremaptable,
                               remaparea);
       if (remapinstance == NODEV)
           {
           perror("Remap Instance");
           exit(1);
           }

       exit(0);
       }





Licensed material--property of copyright holder(s)                         8




vdmremap(7)                    DG/UX 5.4R3.00                    vdmremap(7)


FILES
       Files in or under /dev

SEE ALSO
       vdm(7), vdmphys(7), vdmpart(7) ioctl(2).




















































Licensed material--property of copyright holder(s)                         9


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