[PATCH] fio: add size detection for block devices
authorJens Axboe <axboe@suse.de>
Tue, 8 Nov 2005 08:20:58 +0000 (09:20 +0100)
committerJens Axboe <axboe@suse.de>
Tue, 8 Nov 2005 08:20:58 +0000 (09:20 +0100)
fio.c

diff --git a/fio.c b/fio.c
index f5461514c821ecc381afda6f801a29d362470a08..6366f22b80df777e564004f8118cfb18e9b49811 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -39,6 +39,7 @@
 #include <semaphore.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
+#include <sys/ioctl.h>
 #include <asm/unistd.h>
 #include <asm/types.h>
 #include <asm/bitops.h>
 #include "list.h"
 #include "md5.h"
 
+#ifndef BLKGETSIZE64
+#define BLKGETSIZE64   _IOR(0x12,114,size_t)
+#endif
+
 #define MAX_JOBS       (1024)
 
 /*
@@ -1417,6 +1422,11 @@ static int create_file(struct thread_data *td)
                return 1;
        }
 
+       if (ftruncate(td->fd, td->file_size) == -1) {
+               td->error = errno;
+               return 1;
+       }
+
        td->io_size = td->file_size;
        b = malloc(td->max_bs);
        memset(b, 0, td->max_bs);
@@ -1461,9 +1471,58 @@ static int file_exists(struct thread_data *td)
        return errno != ENOENT;
 }
 
-static int setup_file(struct thread_data *td)
+static int get_file_size(struct thread_data *td)
 {
+       size_t bytes = 0;
        struct stat st;
+
+       if (fstat(td->fd, &st) == -1) {
+               td->error = errno;
+               return 1;
+       }
+
+       /*
+        * if block device, get size via BLKGETSIZE64 ioctl. try that as well
+        * if this is a link, fall back to st.st_size if it fails
+        */
+       if (S_ISBLK(st.st_mode) || S_ISLNK(st.st_mode)) {
+               if (ioctl(td->fd, BLKGETSIZE64, &bytes)) {
+                       if (S_ISBLK(st.st_mode)) {
+                               td->error = errno;
+                               return 1;
+                       } else
+                               bytes = st.st_size;
+               }
+       } else
+               bytes = st.st_size;
+
+       if (td_read(td)) {
+               if (td->file_size > bytes)
+                       bytes = td->file_size;
+       } else {
+               if (!td->file_size)
+                       td->file_size = 1024 * 1024 * 1024;
+
+               bytes = td->file_size;
+       }
+
+       if (td->file_offset > bytes) {
+               fprintf(stderr, "Client%d: offset larger than length\n", td->thread_number);
+               return 1;
+       }
+
+       td->io_size = bytes - td->file_offset;
+       if (td->io_size == 0) {
+               fprintf(stderr, "Client%d: no io blocks\n", td->thread_number);
+               td->error = EINVAL;
+               return 1;
+       }
+
+       return 0;
+}
+
+static int setup_file(struct thread_data *td)
+{
        int flags = 0;
 
        if (!file_exists(td)) {
@@ -1498,35 +1557,16 @@ static int setup_file(struct thread_data *td)
                return 1;
        }
 
-       if (td_read(td)) {
-               if (fstat(td->fd, &st) == -1) {
-                       td->error = errno;
-                       return 1;
-               }
-
-               if (td->file_size > st.st_size)
-                       st.st_size = td->file_size;
-       } else {
-               if (!td->file_size)
-                       td->file_size = 1024 * 1024 * 1024;
-
-               st.st_size = td->file_size;
-       }
-
-       if (td->file_offset > st.st_size) {
-               fprintf(stderr, "Client%d: offset larger than length\n", td->thread_number);
+       if (get_file_size(td))
                return 1;
-       }
 
-       td->io_size = st.st_size - td->file_offset;
-       if (td->io_size == 0) {
-               fprintf(stderr, "Client%d: no io blocks\n", td->thread_number);
-               td->error = EINVAL;
+       if (!td_read(td) && ftruncate(td->fd, td->file_size) == -1) {
+               td->error = errno;
                return 1;
        }
 
        if (td->invalidate_cache) {
-               if (fadvise(td->fd, 0, st.st_size, POSIX_FADV_DONTNEED) < 0) {
+               if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_DONTNEED) < 0) {
                        td->error = errno;
                        return 1;
                }