Skip to content

Instantly share code, notes, and snippets.

@featherchen
Last active September 12, 2022 17:03
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 featherchen/c51f37ac678711bf6df3832b7ae7b437 to your computer and use it in GitHub Desktop.
Save featherchen/c51f37ac678711bf6df3832b7ae7b437 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <linux/fiemap.h>
#define FILE_INTERVAL (1<<13) /* 8Kb */
#define CHUNK_SIZE (1<<12)
long long interval(struct timeval t1, struct timeval t2)
{
long long val = 0;
val += (t2.tv_usec - t1.tv_usec);
val += (t2.tv_sec - t1.tv_sec) * 1000 * 1000;
return val;
}
int dumping(int fd, int file_size){
off_t data, hole = 0;
off_t len, off = 0;
int i=0;
while (hole < file_size) {
data = lseek(fd, hole, SEEK_DATA);
if (data < 0) {
if (hole == 0) {
/* No SEEK_HOLE/DATA by FS */
data = 0;
hole = file_size;
} else if(errno == ENXIO){
/* The end of file */
return 0;
} else{
return -1;
}
} else {
hole = lseek(fd, data, SEEK_HOLE);
if (hole < 0) {
if(errno == ENXIO){
/* The end of file */
return 0;
}
fprintf(stderr, "Can't seek file hole");
return -1;
}
}
len = hole - data;
off = data;
i++;
}
return 0;
}
int main(int argc, char **argv) {
struct fiemap fiemap = {};
struct timeval t1, t2;
char data[CHUNK_SIZE];
memset(data, 'a', CHUNK_SIZE);
struct stat st;
int fd, off, file_size = FILE_INTERVAL;
if (argc != 3 && argc != 2) {
printf("usage: %s <path> [size]\n", argv[0]);
return 1;
}
if (argc == 3)
file_size = atoi(argv[2]);
if (file_size < FILE_INTERVAL)
file_size = FILE_INTERVAL;
file_size -= file_size % FILE_INTERVAL;
fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
perror("open");
return 1;
}
for (off = 0; off < file_size; off += FILE_INTERVAL) {
if (pwrite(fd, &data, CHUNK_SIZE, off) != CHUNK_SIZE) {
perror("pwrite");
close(fd);
return 1;
}
}
if (ftruncate(fd, file_size)) {
perror("ftruncate");
close(fd);
return 1;
}
if (fstat(fd, &st) < 0) {
perror("fstat");
close(fd);
return 1;
}
assert(file_size == st.st_size);
printf("size: %ld\n", st.st_size);
printf("actual size: %ld\n", st.st_blocks * 512);
fiemap.fm_length = FIEMAP_MAX_OFFSET;
gettimeofday(&t1, NULL);
if (ioctl(fd, FS_IOC_FIEMAP, &fiemap) < 0) {
perror("fiemap");
close(fd);
return 1;
}
gettimeofday(&t2, NULL);
printf("fiemap time = %lld us\n", interval(t1, t2));
gettimeofday(&t1, NULL);
if (dumping(fd, file_size) < 0) {
printf("error");
close(fd);
return 1;
}
gettimeofday(&t2, NULL);
printf("SEEK time = %lld us\n", interval(t1, t2));
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment