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