Skip to content

Instantly share code, notes, and snippets.

@osandov
Created November 9, 2016 23:20
Show Gist options
  • Save osandov/d08aabe5d4dec15517e9fde17012fd3b to your computer and use it in GitHub Desktop.
Save osandov/d08aabe5d4dec15517e9fde17012fd3b to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#define SECTORSIZE 4096
#define NUM_EXTENTS 128
static pthread_barrier_t barrier;
static int create_test_file(const char *path)
{
int fd;
int ret;
off_t off;
long flags;
fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (fd == -1) {
perror("open");
return -1;
}
if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) {
perror("ioctl");
close(fd);
return -1;
}
flags |= FS_NOCOW_FL;
if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == -1) {
perror("ioctl");
close(fd);
return -1;
}
for (off = 0; off < 2 * SECTORSIZE * NUM_EXTENTS; off += SECTORSIZE * 2) {
ret = fallocate(fd, 0, off, 2 * SECTORSIZE);
if (ret == -1) {
perror("fallocate");
close(fd);
return -1;
}
}
close(fd);
return 0;
}
struct race_thread_data {
int fd;
int thread_id;
};
static void *race_thread(void *arg)
{
struct race_thread_data *data = arg;
off_t off;
ssize_t ret;
void *buf;
if ((errno = posix_memalign(&buf, SECTORSIZE, SECTORSIZE))) {
perror("malloc");
return NULL;
}
memset(buf, 0, SECTORSIZE);
for (off = (NUM_EXTENTS - 2) * SECTORSIZE; off >= 0; off -= SECTORSIZE * 2) {
pthread_barrier_wait(&barrier);
ret = pread(data->fd, buf, SECTORSIZE,
off + SECTORSIZE * data->thread_id);
if (ret == -1)
perror("pread");
}
free(buf);
return NULL;
}
int main(int argc, char **argv)
{
struct race_thread_data data[2];
pthread_t thread;
int fd;
if (argc != 2) {
fprintf(stderr, "usage: %s PATH\n", argv[0]);
return EXIT_FAILURE;
}
errno = pthread_barrier_init(&barrier, NULL, 2);
if (errno) {
perror("pthread_barrier_init");
return EXIT_FAILURE;
}
if (create_test_file(argv[1]) == -1)
return EXIT_FAILURE;
sync();
system("echo 3 > /proc/sys/vm/drop_caches");
fd = open(argv[1], O_RDONLY | O_DIRECT);
if (fd == -1) {
perror("open");
return EXIT_FAILURE;
}
data[0].fd = fd;
data[0].thread_id = 0;
errno = pthread_create(&thread, NULL, race_thread, &data[0]);
if (errno) {
perror("pthread_create");
close(fd);
return EXIT_FAILURE;
}
data[1].fd = fd;
data[1].thread_id = 1;
race_thread(&data[1]);
pthread_join(thread, NULL);
close(fd);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment