This is a sample C code that will use SCSI-2 capabilities to acquire/release a shared disk. The code is tested on Solaris 10.
The application reads standard input as sent by the Erlang port driver. It can be tested separately with echo -e option with the first 2 bytes as the command length (in bytes) followed by the command number.
To acquire disk lock use the own function, it forcibly break any previous ownership. Writes to disk are only allowed by the one holding the reservation. Similarly, a lock is released with the release function.
echo -e '\x00\x01\x02' | app
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stropts.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mhd.h>
#include <sys/param.h>
// MACROS
#define PACKET 2 /* 2 bytes length */
#define BUF_SIZE 256 /* Packet^Byte = 2^8 = 256 */
#define STATUS 1
#define OWN 2
#define RELEASE 3
#define REINSTATE_RESV_DELAY 0
#define MIN_OWNERSHIP_DELAY 1000 /* 1 second */
#define MAX_OWNERSHIP_DELAY 15000 /* 15 seconds */
// TYPEDEF
typedef unsigned char byte;
int read_exact(byte *buf, int len)
{
int i, got=0;
do {
if ((i = read(0, buf+got, len-got)) <= 0)
return(i);
got += i;
} while (got<len);
return(len);
}
int write_exact(byte *buf, int len)
{
int i, wrote = 0;
do {
if ((i = write(1, buf+wrote, len-wrote)) <= 0)
return (i);
wrote += i;
} while (wrote<len);
return (len);
}
int read_cmd(byte *buf)
{
int len;
if (read_exact(buf, 2) != 2)
return(-1);
len = (buf[0] << 8) | buf[1];
return read_exact(buf, len);
}
int write_cmd(byte *buf, int len)
{
byte li;
li = (len >> 8);
write_exact(&li, 1);
li = len;
write_exact(&li, 1);
return write_exact(buf, len);
}
// Multihost disk control operations
int open_device(char* device)
{
return open(device, O_RDWR | O_NDELAY);
}
// Forcefully acquires exclusive access rights to the multihost disk for the
// local host. Revokes all access rights to the multihost disk from remote
// hosts. Causes the disk to enter the exclusive access state.
int own(int fd)
{
struct mhioctkown t = {
REINSTATE_RESV_DELAY,
MIN_OWNERSHIP_DELAY,
MAX_OWNERSHIP_DELAY
};
return ioctl(fd, MHIOCTKOWN, &t);
}
// Probes a multihost disk to determine whether the local host has access rights
// to the disk. Returns 0 if the local host has access to the disk, 1 if it
// doesn't, and -1 with errno set to EIO if the probe failed for some other
// reason.
int status(int fd)
{
return ioctl(fd, MHIOCSTATUS);
}
// Relinquishes exclusive access rights to the multihost disk for the localhost.
// On success, causes the disk to enter the non- exclusive access state.
int release(int fd)
{
return ioctl(fd, MHIOCRELEASE);
}
int main(int argc, char *argv[]) {
int fn, fd, result;
byte buf[BUF_SIZE];
if(argc != 2) {
abort();
}
fd = open_device(argv[1]);
if(fd < 0) {
perror("open");
abort();
}
while (read_cmd(buf) > 0) {
fn = buf[0];
errno = 0;
switch(fn)
{
case STATUS:
result = status(fd);
break;
case OWN:
result = own(fd);
break;
case RELEASE:
result = release(fd);
break;
}
buf[0] = result;
strerror_r(errno, buf+1, sizeof(buf) - 2);
write_cmd(buf, 1 + strlen(buf+1));
}
return EXIT_FAILURE;
}
syntax highlighted by Code2HTML, v. 0.9.1
0 comments:
Post a Comment