[Cluster-devel] [PATCH] dlm: fix basts for granted PR waiting CW
David Teigland
teigland at redhat.com
Wed Jul 25 16:09:22 UTC 2007
On Wed, Jul 25, 2007 at 11:01:05AM -0500, David Teigland wrote:
> Fix a long standing bug where a blocking callback would be missed
> when there's a granted lock in PR mode and waiting locks in both
> PR and CW modes (and the PR lock was added to the waiting queue
> before the CW lock). The logic simply compared the numerical values
> of the modes to determine if a blocking callback was required, but in
> the one case of PR and CW, the lower valued CW mode blocks the higher
> valued PR mode. We just need to add a special check for this PR/CW
> case in the tests that decide when a blocking callback is needed.
Attached is a test I used in the past to trigger this bug (and others as
well). I'd run two instances of the test on each of four nodes, like
this:
node01: rand_direct -d4 -f10 rand_direct -d8 -f10
node02: rand_direct -d4 -f10 -u rand_direct -d8 -f10
node03: rand_direct -d4 -f10 rand_direct -d8 -f10
node04: rand_direct -d4 -f10 rand_direct -d8 -f10
Dave
-------------- next part --------------
/* tests to run:
on two nodes: prealloc file, rand_direct -d1 -f1
on two nodes: prealloc file, rand_direct -d1 -f1 -b
*/
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/times.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <fcntl.h>
#define ONEMB 1048576
char *prog_name;
int quiet = 0;
int verbose = 0;
int delay = 0;
int enable_seeks = 0;
int enable_unlinks = 0;
int enable_buffered = 0;
int iterations = 0; /* forever */
int num_dirs = 10;
int num_files = 100;
int iobuf_size = ONEMB;
char *iobuf, **p_iobuf;
#define die(fmt, args...) \
{ \
fprintf(stderr, "%s: ", prog_name); \
fprintf(stderr, fmt, ##args); \
exit(EXIT_FAILURE); \
}
void usage(void)
{
printf("Usage:\n");
printf("\n");
printf("%s [options]\n", prog_name);
printf("\n");
printf("Options:\n");
printf("\n");
printf(" -b random mix of buffered and direct io\n");
printf(" -s enable seeks before reads and writes\n");
printf(" -u enable unlinks\n");
printf(" -i <n> iterations, default 0 (forever)\n");
printf(" -d <n> number of dirs, default 10\n");
printf(" -f <n> number of files per dir, default 100\n");
}
int rand_int(int a, int b)
{
return a + (int) (((float)(b - a + 1)) * random() / (RAND_MAX+1.0));
}
int do_read(int fd)
{
read(fd, iobuf, iobuf_size);
return 0;
}
int do_write(int fd)
{
int rv;
memset(iobuf, 0x55, iobuf_size);
rv = write(fd, iobuf, iobuf_size);
if (rv != iobuf_size)
die("write size %d vs %d\n", rv, iobuf_size);
return 0;
}
int do_seek(int fd)
{
int off, rv;
off = rand_int(0, ONEMB*100);
off -= (off % 4096);
rv = lseek(fd, off, SEEK_SET);
return 0;
}
int rand_dio(void)
{
if (rand_int(0, 1))
return O_DIRECT;
return 0;
}
int main(int argc, char *argv[])
{
int i, j, flags, rv, c, fd, op, dir, file, ops = 0;
char path[64];
srandom(time(NULL));
prog_name = argv[0];
while ((c = getopt(argc, argv, "bqvsui:d:f:y:")) != -1) {
switch (c) {
case 'q':
quiet = 1;
break;
case 'v':
verbose = 1;
break;
case 'b':
enable_buffered = 1;
break;
case 's':
enable_seeks = 1;
break;
case 'u':
enable_unlinks = 1;
break;
case 'i':
iterations = atoi(optarg);
break;
case 'd':
num_dirs = atoi(optarg);
break;
case 'f':
num_files = atoi(optarg);
break;
case 'y':
delay = atoi(optarg);
break;
case 'h':
default:
usage();
exit(2);
}
}
for (i = 0; i < num_dirs; i++) {
memset(path, 0, sizeof(path));
sprintf(path, "dir%.10u", i);
mkdir(path, 0755);
}
p_iobuf = &iobuf;
rv = posix_memalign((void *)p_iobuf, ONEMB, iobuf_size);
if (rv) {
perror("memalign error");
exit(-2);
}
while (1) {
op = rand_int(0, 5);
dir = rand_int(0, num_dirs-1);
file = rand_int(0, num_files-1);
memset(path, 0, sizeof(path));
sprintf(path, "dir%.10u/file%.10u", dir, file);
if (verbose)
printf("%s %d\n", path, op);
if (op == 0) {
/* open (write, append, create)
close */
fd = open(path, O_WRONLY|O_CREAT|O_APPEND|O_DIRECT, 0644);
if (fd < 0)
die("open %s error %d errno %d\n",
path, fd, errno);
close(fd);
ops++;
} else if (op == 1 || op == 2) {
/* open (read, write)
write
close */
if (enable_buffered)
flags = rand_dio();
else
flags = O_DIRECT;
fd = open(path, O_RDWR | flags);
if (fd > 0) {
if (enable_seeks)
do_seek(fd);
do_write(fd);
close(fd);
ops++;
}
} else if (op == 3 || op == 4) {
/* open (read)
read
close */
if (enable_buffered)
flags = rand_dio();
else
flags = O_DIRECT;
fd = open(path, O_RDONLY | flags);
if (fd > 0) {
if (enable_seeks)
do_seek(fd);
do_read(fd);
close(fd);
ops++;
}
} else if (op == 5) {
if (enable_unlinks) {
unlink(path);
ops++;
}
} else {
exit(-1);
}
if (!quiet)
printf("%u:%d\n", ops, op);
if (delay)
sleep(delay);
if (iterations && ops == iterations)
break;
}
exit(EXIT_SUCCESS);
}
More information about the Cluster-devel
mailing list