Skip to content

Instantly share code, notes, and snippets.

@OjaswinM
Created November 30, 2023 09:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OjaswinM/e67accee3cbb7832bd3f1a9543c01da9 to your computer and use it in GitHub Desktop.
Save OjaswinM/e67accee3cbb7832bd3f1a9543c01da9 to your computer and use it in GitHub Desktop.
Performing atomic writes using pwritev2() syscall
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/uio.h>
#include <errno.h>
#define RWF_ATOMIC (0x00000020)
int main(int argc, char *argv[]) {
int ret = 0;
char *random_data;
if (argc != 4) {
printf("Usage: %s <file> <off (KB)> <len (KB)>\n", argv[0]);
return 1;
}
char *filename = argv[1];
// Convert user-supplied buffer size (in KB) to bytes
int off_in_KB = atoi(argv[2]);
size_t off = off_in_KB * 1024;
int len_in_KB = atoi(argv[3]);
size_t len = len_in_KB * 1024;
// Open a file for writing
int fd = open(filename, O_DIRECT | O_WRONLY | O_CREAT | O_DSYNC, 0666);
if (fd == -1) {
ret = errno;
perror("open");
return ret;
}
// Allocate a buffer to read random data
posix_memalign(&random_data, 512, len);
if (random_data == NULL) {
ret = errno;
perror("malloc");
close(fd);
return ret;
}
// Read random data from /dev/urandom
int urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1) {
ret = errno;
perror("open /dev/urandom");
free(random_data);
close(fd);
return ret;
}
ssize_t bytes_read = read(urandom_fd, random_data, len);
if (bytes_read != len) {
ret = errno;
perror("read /dev/urandom");
free(random_data);
close(urandom_fd);
close(fd);
return ret;
}
// Create an iovec structure for the random data
struct iovec iov;
iov.iov_base = random_data;
iov.iov_len = bytes_read;
printf("iov.iov_base: %p\n", iov.iov_base);
printf("iov.iov_len: %d\n", iov.iov_len);
// Write the random data using pwritev2
int flags = RWF_ATOMIC;
ssize_t bytes_written = pwritev2(fd, &iov, 1, off, flags);
if (bytes_written == -1) {
ret = errno;
perror("pwritev2");
free(random_data);
close(urandom_fd);
close(fd);
return ret;
}
printf("Wrote %zd bytes of random data to the file.\n", bytes_written);
// Close file and /dev/urandom
free(random_data);
close(urandom_fd);
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment