From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Teigland Date: Wed, 25 Jul 2007 11:09:22 -0500 Subject: [Cluster-devel] [PATCH] dlm: fix basts for granted PR waiting CW In-Reply-To: <20070725160105.GB8834@redhat.com> References: <20070725160105.GB8834@redhat.com> Message-ID: <20070725160922.GD8834@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 iterations, default 0 (forever)\n"); printf(" -d number of dirs, default 10\n"); printf(" -f 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); }