vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
NAME
vdmcache - Disk Cache Subdriver of the Virtual Disk Manager
SYNOPSIS
#include <types.h>
#include <ioctl.h>
ioctl(int fildes, int command, int argument);
DESCRIPTION
The Cache Subdriver is a pseudo-device driver that works under the
Virtual Disk Management (VDM) framework (see vdm(7)). The purpose of
the Cache Subdriver is to provide the capability to use a relatively
small and fast block device as a stable cache for a relatively large
and slow block device. A stable device is one whose contents are non-
volatile. For example, a non-volatile card can be used as a front end
device for a SCSI-disk, or a fast SCSI-disk as a front end for an
optical storage jukebox.
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 Cache Subdriver is defined by
DGVDMCACHESUBDRIVERID.
Unless otherwise noted, the version field in the following structures
is an input field that must be set to DGVDMCACHEPACKETVERSION0.
Additionally, all packets must have every byte set to zero before it
is used.
DGVDMCREATEINSTANCE
The subdriverattributespacketptr field points to the following
structure:
struct dgvdmcachecreatepacket
{
int version;
devt childdevicenumber;
};
The childdevicenumber field is an input field indicating the back
end virtual disk instances that are to be cached.
DGVDMLINKCHILDINSTANCE
This command adds a front end device to a cache instance. The
childpacketptr is not used by Cache Subdriver because the children
added to a cache instance are always front end devices.
To add an instance as the front end of a cache device, it must be
formatted first. This is accomplished using admpdisk(1M) command
(note that the admpdisk(1M) command can be used to format virtual
disks as well as physical disks).
Licensed material--property of copyright holder(s) 1
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
The childdevicenumber field is an input field indicating the block
device that has been formatted as a cache front end device. This
device is used to cache the data for the back end device. A cache
device may have more than one front end device and may share front
end devices with other cache devices.
Cache devices that have no front end device associated with them, are
in passthru mode. By this, it is meant that data being written to the
cache goes directly to the back end device without being cached.
If an attempt is made to add a front end that has not been properly
formatted, the call will fail and errno will be set to EINVAL.
DGVDMUNLINKCHILDINSTANCE
This command removes a front end device from a cache instance.
The childdevicenumber field is an input field indicating the front
end device that is to be removed from the cache instance. Any data
stored on the front end for the cache instance is first flushed to
the back end device. The cache device will no longer use it to store
data; however, other cache devices may still use it.
DGVDMGETCHILDINSTANCE
The childpacketptr is not used by the Cache Subdriver.
The childdevicenumber field is returned in the VDM packet. The
first child returned is always the back end device. If any additional
children are returned, they are front end devices.
DGVDMGETATTRIBUTES
The subdriverattributespacketptr field points to the following
structure:
struct dgvdmcachegetattributespacket
{
int version;
unsigned long flags;
unsigned long state;
unsigned long readcount;
unsigned long writecount;
unsigned long readmisscount;
unsigned long writemisscount;
unsigned long readhitcount;
unsigned long writehitcount;
unsigned long readpurgecount;
unsigned long writepurgecount;
unsigned long allocatepurgecount;
unsigned long bedwritecount;
unsigned long bedreadcount;
unsigned long totalbufferscount;
unsigned long totaldatablockscount;
unsigned long dirtybufferscount;
unsigned long allocatedbufferscount;
unsigned long allocateddatablockscount;
Licensed material--property of copyright holder(s) 2
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
unsigned long statestallcount;
unsigned long flushstallcount;
unsigned int cachereads : 1;
unsigned int cachewrites : 1;
unsigned int cacheonlymetadata : 1;
unsigned int asyncflushonfirstwrite : 1;
unsigned int asyncflushonallwrites : 1;
unsigned int disabledmatovme : 1;
unsigned int readretention;
unsigned int writeretention;
unsigned int searchpercentage;
unsinged int flushertype;
};
The flags field is an input field. If set to DG_VDMCACHE_RESET_STATS
the statistics are return and reset to zero.
The state field is an output field. It returns the current state of
the cache device. The current states are:
DGVDMCACHESTATEUP - The cache device is up and available.
DGVDMCACHESTATEDOWN - The cache device is being shutdown.
DGVDMCACHESTATERECOVERING - The cache device is up recovering
data from a front-end device.
DGVDMCACHESTATESEALEDBEDFAILED - The cache device is in an
error state. All I/O is disallowed because I/O to the back-end device
failed. Once the back-end device it fixed, removing and re-creating
the cache device will fix the problem.
DGVDMCACHESTATESEALEDFEDFAILED - The cache device is in an
error state. All I/O is disallowed because I/O to the front-end
device failed. Unlinking the front-end will fix the problem.
DGVDMCACHESTATESEALEDCACHEFAILED - The cache device is in an
error state. All I/O is disallowed because internal cache structures
are corrupted. The user data should be fine. Removing and re-
creating the cache device may fix the problem. However, system dump
should be taken if possible and an str filed on the bug.
The readcount field is an output field. It returns the total number
of reads issued to the cache device.
The writecount field is an output field. It returns the total number
of writes issued to the cache device.
The readmisscount field is an output field. It returns the total
number of times the buffer was not in the cache on a read.
The writemisscount field is an output field. It returns the total
number of times the buffer was not in the cache on a write.
Licensed material--property of copyright holder(s) 3
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
The readhitcount field is an output field. It returns the total
number of times the buffer was in the cache on a read.
The writehitcount field is an output field. It returns the total
number of times the buffer was in the cache on a write.
The readpurgecount field is an output field. It returns the total
number of reads that cause another buffer to flushed and removed from
the cache because it overlap the new request.
The writepurgecount field is an output field. It returns the total
number of writes that cause another buffer to flushed and removed
from the cache because it overlap the new request.
The allocationpurgecount field is an output field. It returns the
total number of I/O that cause another buffer to flushed and removed
from the cache to free up space.
The bedreadcount field is an output field. It returns the total
number of reads issued to the back-end device.
The bedwritecount field is an output field. It returns the total
number of writes issued to the back-end device.
The totalbufferscount field is an output field. It returns the
total number of buffers available on all of the front-end devices.
The totaldatablockscount field is an output field. It returns the
total number of 512 byte blocks available to hold the data area of
each buffer on all the front-end devices.
The dirtybufferscount field is an output field. It returns the
number buffers that have data in them that is newer then the data on
the back-end device.
The allocatedbufferscount field is an output field. It returns the
number of buffers containing data on all of the front-end devices.
The allocateddatablockscount field is an output field. It returns
the number of 512 byte blocks containing data on all of the front-end
devices.
The statestallcount field is an output field. It returns the total
number of times an I/O had to wait on a buffer that another I/O was
using.
The flushstallcount field is an output field. It returns the total
number of times an I/O had to wait on a buffer that was being flushed
to the back-end device.
The cachereads field is an output field. It represents the current
policy value.
The cachewrites field is an output field. It represents the current
Licensed material--property of copyright holder(s) 4
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
policy value.
The cacheonlymetadata field is an output field. It represents the
current policy value.
The asyncflushonfirstwrite field is an output field. It
represents the current policy value.
The asyncflushonallwrites field is an output field. It
represents the current policy value.
The disabledmatovme field is an output field. It represents the
current policy value.
The readretention field is an output field. It represents the
current policy value.
The writeretention field is an output field. It represents the
current policy value.
The searchpercentage field is an output field. It represents the
current policy value.
The flushertype field is an output field. It represents the current
policy value.
DGVDMUPDATEATTRIBUTES
The subdriverattributespacketptr field points to the following
structure:
struct dgvdmcacheupdateattributespacket
{
int version;
unsigned int cachereads : 1;
unsigned int cachewrites : 1;
unsigned int cacheonlymetadata : 1;
unsigned int asyncflushonfirstwrite : 1;
unsigned int asyncflushonallwrites : 1;
unsigned int disabledmatovme : 1;
int readretention;
int writeretention;
int searchpercentage;
int flushertype;
};
The cachereads field is an input bit field. If set to 1, the cache
device will cache reads if a front end device is present. Default 1.
The cachewrites field is an input bit field. If set to 1, the cache
device will cache writes if a front end device is present. Default
1.
The cacheonlymetadata field is an input field. Cache attempts to
Licensed material--property of copyright holder(s) 5
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
cache only DG/UX file system meta data. It is however, possible for
user data to be cached, if the data matches the meta data test.
Default 0.
The readretention field is an input field. This value is added to a
counter associated with a block buffer each time the block is read.
When free space is required to write a new entry in the cache and
none can be found in search, the buffers with the lowest retention
values are purged first. Thus, buffers with high retention values are
retained in the cache as long as possible. These retention values can
be used to give preference to the different types of I/O performed on
the buffers. Default 1.
The writeretention field is an input field. This value is added to a
counter associated with a block buffer each time the block is
written. Default 1. See readretention above for more information.
The asyncflushonfirstwrite field is an input field. The first
time a buffer is written to the cache, an async request to flush the
data to the back-end device is issued. Default 1.
The asyncflushonallwrites field is an input field. Any time a
buffer is written to the cache, an async request to flush the data to
the back-end device is issued. Default 0.
The disabledmatovme field is an input field. Disable Direct
Memory Access to VME memory on systems that allow the disk
controllers to move data to and from a VME device. If feature
disabled or system does not support the feature, all data transfers
to and from the NVRAM VME Memory board must be copied through main
memory. Default 0.
The searchpercentage field is an input field. This value is used to
control the amount of searching performed to find free space in the
cache. If the value is zero, no searching will be done and free
space will be obtained by purging a buffer in the cache with the
lowest retention value. A value of 100, indicates that the entire
cache should be searched before a buffer is purged to make space
available. Default 10%.
The flushertype field is an input field. The value of this field is
used to determine what type of flushing algorithm is used for the
cache. It can be set to DGVDMCACHEPOLICYNOFLUSHER indicating
that no separate thread of control is used to write dirty buffers
from the front end device to the back end device. If
DGVDMCACHEPOLICYCYCLEFLUSHER is used for the flushertype value,
a thread of control is used to constantly search through the front
end device flushing dirty buffers to the back end device. Default
DG_VDMCACHE_POLICY_CYCLE_FLUSHER.
IOCTLS
The ioctls supported by the Cache Subdriver are listed below. The
ioctl(2) command can be issued to the Cache Subdriver in two ways:
Licensed material--property of copyright holder(s) 6
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
1. Issue the command to an exported instance of the Cache
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.
DSKIOCGET
This command returns the size of an instance and is described in more
detail in dsk(7).
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 in a non-volatile RAM board
that is mapped into kernel memory. If the device queried is not a
non-volatile RAM board, the call will fail and errno is set to
EINVAL.
DGVDMCACHEGETFEDSTATS
The argument field points to the following structure:
struct dgvdmcachefedstatspacket
{
int version;
unsigned int flags;
devt feddevicenumber;
unsigned long readcount;
unsigned long writecount;
unsigned long totalbufferscount;
unsigned long totaldatablockscount;
unsigned long allocatedbuffernodescount;
unsigned long allocateddatablockscount;
unsigned long dirtybufferscount;
unsigned long buffernodesawaitingrecoverycount;
unsigned long datablocksawaitingrecoverycount;
};
The flags field is an input field. If set to DG_VDMCACHE_RESET_STATS
the statistics are return and reset to zero.
The field is an input field. It is the device number of the front-
end device the request should get the statistics from.
The readcount field is an output field. It returns the total number
of reads issued to the front-end device
The writecount field is an output field. It returns the total number
Licensed material--property of copyright holder(s) 7
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
of writes issued to the front-end device.
The totalbufferscount field is an output field. It returns the
total number of buffers available on the front-end device.
The totaldatablockscount field is an output field. It returns the
total number of 512 byte blocks available to hold the data area of
each buffer on the front-end device.
The allocatedbufferscount field is an output field. It returns the
number of buffers containing data on the front-end devices.
The allocateddatablockscount field is an output field. It returns
the number of 512 byte blocks containing data on the front-end
device.
The dirtybufferscount field is an output field. It returns the
number buffers that have data in them that is newer then the data on
the back-end device.
The buffersnodesawaitingrecoverycount is an output field. It
returns the number of buffers that can not be recovered because the
back-end device is not available.
The datablocksawaitingrecoverycount It returns the number of data
blocks that can not be recovered because the back-end device is not
available.
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 the vdmioctl() function described in the
* vdm(7) man page. The vdmioctl() function issues ioctl(2) commands
* to the /dev/vdm device node.
*/
int main (void)
{
int status;
devt feddevicenumber;
devt beddevicenumber;
devt cachedevicenumber;
struct dgsysctlnametodevice nametodevicepkt;
extern int errno;
Licensed material--property of copyright holder(s) 8
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
struct dgvdmcreateinstancepacket createinstancepkt;
struct dgvdmexportinstancepacket exportpkt;
struct dgvdmlinkchildinstancepacket linkchildpkt;
struct dgvdmupdateattributespacket updateattributespkt;
struct dgvdmgetattributespacket getattributespkt;
struct dgvdmphyscreatepacket createphyspkt;
struct dgvdmcachecreatepacket createcachepkt;
struct dgvdmcachechangeupdateattributespacket changepolicypkt;
struct dgvdmcachecachegetattributespacket cachestatspkt;
/*
* Create a physical instance for the nvram board.
*/
nametodevicepkt.devicename = "nvrd(0)";
status = dgsysctl(DGSYSCTLNAMETODEVICE, &nametodevicepkt);
if (status == -1)
{
eperror("nvrd(0)");
exit(1);
}
/*
* Create a fed
*/
initvdmpacket(createinstancepkt);
initvdmpacket(createphyspkt);
createphyspkt.childdevicenumber = nametodevicepkt.devicenumber;
createinstancepkt.subdriverid = DGVDMPHYSSUBDRIVERID;
createinstancepkt.subdriverattributespacketptr = &createphyspkt;
strcpy (createinstancepkt.instancename, "fed");
status = vdmioctl(DGVDMCREATEINSTANCE,(int)&createinstancepkt);
if (status == -1)
{
eperror("create fed");
exit(1);
}
feddevicenumber = createinstancepkt.devicenumber;
/*
* Create a physical instance for the back-end device.
*/
nametodevicepkt.devicename = "sd(insc(),0)";
status = dgsysctl(DGSYSCTLNAMETODEVICE, &nametodevicepkt);
if (status == -1)
{
Licensed material--property of copyright holder(s) 9
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
eperror("sd(insc(),0)");
exit(1);
}
/*
* Create bed
*/
initvdmpacket(createphyspkt);
initvdmpacket(createinstancepkt);
createphyspkt.childdevicenumber = nametodevicepkt.devicenumber;
createinstancepkt.subdriverid = DGVDMPHYSSUBDRIVERID;
createinstancepkt.subdriverattributespacketptr = &createphyspkt;
strcpy (createinstancepkt.instancename, "bed");
status = vdmioctl(DGVDMCREATEINSTANCE,(int)&createinstancepkt);
if (status == -1)
{
eperror("create bed");
exit(1);
}
beddevicenumber = createinstancepkt.devicenumber;
/*
* Create a cache device.
*/
initvdmpacket(createcachepkt);
initvdmpacket(createinstancepkt);
createcachepkt.childdevicenumber = beddevicenumber;
createinstancepkt.subdriverid = DGVDMCACHESUBDRIVERID;
createinstancepkt.subdriverattributespacketptr = &createcachepkt;
strcpy (createinstancepkt.instancename, "cache");
status = vdmioctl(DGVDMCREATEINSTANCE,(int)&createinstancepkt);
if (status == -1)
{
eperror("create cache");
exit(1);
}
cachedevicenumber = createinstancepkt.devicenumber;
/*
* Export cache device.
*/
initvdmpacket(exportpkt);
Licensed material--property of copyright holder(s) 10
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
exportpkt.devicenumber = cachedevicenumber;
status = vdmioctl(DGVDMEXPORTINSTANCE,(int)&exportpkt);
if (status == -1)
{
eperror("export cache");
exit(1);
}
/*
* Export fed device.
*/
initvdmpacket(exportpkt);
exportpkt.devicenumber = feddevicenumber;
status = vdmioctl(DGVDMEXPORTINSTANCE,(int)&exportpkt);
if (status == -1)
{
eperror("export a");
fprintf(stderr,"dgexterrno = %o, Subsystem %o, Sequence Number %o\n",
((unsigned int)dgexterrno()),
((((unsigned int)dgexterrno()) & 0x7fff0000) >> 16),
(((unsigned int)dgexterrno()) & 0x0000ffff));
exit(1);
}
/*
* Export bed device.
*/
initvdmpacket(exportpkt);
exportpkt.devicenumber = beddevicenumber;
status = vdmioctl(DGVDMEXPORTINSTANCE,(int)&exportpkt);
if (status == -1)
{
eperror("export b");
exit(1);
}
/*
* Link a front-end to the cache device.
*/
initvdmpacket(linkchildpkt);
linkchildpkt.parentdevicenumber = cachedevicenumber;
linkchildpkt.childdevicenumber = feddevicenumber;
linkchildpkt.parentsubdriverid = DGVDMCACHESUBDRIVERID;
status = vdmioctl(DGVDMLINKCHILDINSTANCE,(int)&linkchildpkt);
if (status == -1)
{
eperror("link fed to bed");
Licensed material--property of copyright holder(s) 11
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
exit(1);
}
/*
* Change the cache policy for best NFS performance.
*/
initvdmpacket(updateattributespkt);
initvdmpacket(changepolicypkt);
changepolicypkt.cachereads = FALSE;
changepolicypkt.cachewrites = TRUE;
changepolicypkt.cacheonlymetadata = FALSE;
changepolicypkt.asyncflushonfirstwrite = TRUE;
changepolicypkt.asyncflushonallwrites = FALSE;
changepolicypkt.disabledmatovme = FALSE;
changepolicypkt.readretention = 0;
changepolicypkt.writeretention = 1;
changepolicypkt.searchpercentage = 25;
changepolicypkt.flushertype = DGVDMCACHEPOLICYCYCLEFLUSHER;
updateattributespkt.instancedevicenumber = cachedevicenumber;
updateattributespkt.subdriverid = DGVDMCACHESUBDRIVERID;
updateattributespkt.subdriverattributespacketptr = &changepolicypkt;
status = vdmioctl(DGVDMUPDATEATTRIBUTES,(int)&updateattributespkt);
if (status == -1)
{
eperror("change policy");
exit(1);
}
/*
* Get the cache statistics.
*/
initvdmpacket(getattributespkt);
initvdmpacket(cachestatspkt);
getattributespkt.instancedevicenumber = cachedevicenumber;
getattributespkt.subdriverid = DGVDMCACHESUBDRIVERID;
getattributespkt.subdriverattributespacketptr = &cachestatspkt;
status = vdmioctl(DGVDMGETATTRIBUTES,(int)&getattributespkt);
if (status == -1)
{
eperror("cache stats");
exit(1);
}
fprintf(stdout,"\n totalbufferscount %d\n",
cachestatspkt.totalbufferscount);
Licensed material--property of copyright holder(s) 12
vdmcache(7) DG/UX 5.4R3.00 vdmcache(7)
fprintf(stdout," totaldatablockscount %d\n",
cachestatspkt.totaldatablockscount);
exit(0);
}
FILES
Files in or under /dev
SEE ALSO
admpdisk(1M), vdm(7), ioctl(2).
Licensed material--property of copyright holder(s) 13