On Sun, Feb 09 2014, Matthew Eaton wrote: > On Sun, Feb 9, 2014 at 12:57 PM, Jens Axboe <axboe@xxxxxxxxx> wrote: > > On Sat, Feb 08 2014, Matthew Eaton wrote: > >> On Thu, Feb 6, 2014 at 11:21 AM, Jens Axboe <axboe@xxxxxxxxx> wrote: > >> > Hi, > >> > > >> > I've been late on this release, originally wanted it out around > >> > Christmas. But various issues here and there prevented that. However, I > >> > now think we are getting pretty close. It'd be great if folks running on > >> > non-linux systems could compile and ensure that everything is in working > >> > order, because otherwise I'm going to assume that it is... > >> > > >> > Similarly, if you know of bugs (particularly regressions from previous > >> > releases), speak up now so we can get them fixed before 2.1.5 is cut. > >> > > >> > I'll wait until Monday to tag the release. > >> > > >> > -- > >> > Jens Axboe > >> > > >> > >> Hi Jens, > >> > >> I was messing around with the openfiles flag in one of my job files > >> last week but was unable to get it to work. Fio would keep defaulting > >> to opening all files set by nrfiles, but I'm not sure if I was doing > >> something wrong. This was with fio 2.1.4 on linux. Can you check on > >> this? > > > > It'd be easier if you include your job file / command line! > > > > -- > > Jens Axboe > > > > Hi Jens, > > Here's an example. In fio output I get f=50 instead of f=10 which I > believe is the number of simultaneous opens? Also strange to me is > that write io is 2000 MB instead of 1024 MB. > > [job] > bs=1m > rw=write > size=1g > nrfiles=50 > openfiles=10 > directory=temp > > job: (g=0): rw=write, bs=1M-1M/1M-1M/1M-1M, ioengine=sync, iodepth=1 > fio-2.1.4 > Starting 1 process > job: Laying out IO file(s) (50 file(s) / 1023MB) > Jobs: 1 (f=50): [W] [-.-% done] [0KB/539.0MB/0KB /s] [0/539/0 iops] > [eta 00m:00s] > job: (groupid=0, jobs=1): err= 0: pid=15131: Sun Feb 9 16:18:55 2014 > write: io=2000.0MB, bw=697785KB/s, iops=681, runt= 2935msec > clat (usec): min=167, max=145348, avg=1399.89, stdev=6030.76 > lat (usec): min=175, max=145359, avg=1413.43, stdev=6031.10 > clat percentiles (usec): > | 1.00th=[ 175], 5.00th=[ 207], 10.00th=[ 253], 20.00th=[ 262], > | 30.00th=[ 274], 40.00th=[ 290], 50.00th=[ 302], 60.00th=[ 358], > | 70.00th=[ 516], 80.00th=[ 572], 90.00th=[ 5984], 95.00th=[ 6624], > | 99.00th=[ 7328], 99.50th=[10816], 99.90th=[115200], 99.95th=[140288], > | 99.99th=[144384] > bw (KB /s): min=81160, max=1503620, per=100.00%, avg=778889.75, > stdev=604179.56 > lat (usec) : 250=7.50%, 500=61.95%, 750=18.25% > lat (msec) : 10=11.70%, 20=0.20%, 50=0.15%, 100=0.10%, 250=0.15% > cpu : usr=2.97%, sys=25.70%, ctx=504, majf=0, minf=33 > IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0% > submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% > complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% > issued : total=r=0/w=2000/d=0, short=r=0/w=0/d=0 > > Run status group 0 (all jobs): > WRITE: io=2000.0MB, aggrb=697785KB/s, minb=697785KB/s, > maxb=697785KB/s, mint=2935msec, maxt=2935msec > > Disk stats (read/write): > sdb: ios=0/2740, merge=0/2, ticks=0/360280, in_queue=376924, util=90.05% Can you try this patch? diff --git a/backend.c b/backend.c index a607134..32bc265 100644 --- a/backend.c +++ b/backend.c @@ -52,6 +52,7 @@ #include "server.h" #include "lib/getrusage.h" #include "idletime.h" +#include "err.h" static pthread_t disk_util_thread; static struct fio_mutex *disk_thread_mutex; @@ -478,6 +479,12 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes) break; while ((io_u = get_io_u(td)) != NULL) { + if (IS_ERR(io_u)) { + io_u = NULL; + ret = FIO_Q_BUSY; + goto reap; + } + /* * We are only interested in the places where * we wrote or trimmed IOs. Turn those into @@ -574,6 +581,7 @@ sync_done: * completed io_u's first. Note that we can get BUSY even * without IO queued, if the system is resource starved. */ +reap: full = queue_full(td) || (ret == FIO_Q_BUSY && td->cur_depth); if (full || !td->o.iodepth_batch_complete) { min_events = min(td->o.iodepth_batch_complete, @@ -692,7 +700,14 @@ static uint64_t do_io(struct thread_data *td) break; io_u = get_io_u(td); - if (!io_u) { + if (IS_ERR_OR_NULL(io_u)) { + int err = PTR_ERR(io_u); + + io_u = NULL; + if (err == -EBUSY) { + ret = FIO_Q_BUSY; + goto reap; + } if (td->o.latency_target) goto reap; break; @@ -1124,6 +1139,9 @@ static int keep_running(struct thread_data *td) if (diff < td_max_bs(td)) return 0; + if (fio_files_done(td)) + return 0; + return 1; } diff --git a/err.h b/err.h new file mode 100644 index 0000000..5c024ee --- /dev/null +++ b/err.h @@ -0,0 +1,44 @@ +#ifndef FIO_ERR_H +#define FIO_ERR_H + +/* + * Kernel pointers have redundant information, so we can use a + * scheme where we can return either an error code or a dentry + * pointer with the same return value. + * + * This should be a per-architecture thing, to allow different + * error and pointer decisions. + */ +#define MAX_ERRNO 4095 + +#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) + +static inline void *ERR_PTR(long error) +{ + return (void *) error; +} + +static inline long PTR_ERR(const void *ptr) +{ + return (long) ptr; +} + +static inline long IS_ERR(const void *ptr) +{ + return IS_ERR_VALUE((unsigned long)ptr); +} + +static inline long IS_ERR_OR_NULL(const void *ptr) +{ + return !ptr || IS_ERR_VALUE((unsigned long)ptr); +} + +static inline int PTR_ERR_OR_ZERO(const void *ptr) +{ + if (IS_ERR(ptr)) + return PTR_ERR(ptr); + else + return 0; +} + +#endif diff --git a/file.h b/file.h index d7e05f4..19413fc 100644 --- a/file.h +++ b/file.h @@ -176,5 +176,6 @@ extern void dup_files(struct thread_data *, struct thread_data *); extern int get_fileno(struct thread_data *, const char *); extern void free_release_files(struct thread_data *); void fio_file_reset(struct thread_data *, struct fio_file *); +int fio_files_done(struct thread_data *); #endif diff --git a/filesetup.c b/filesetup.c index d1702e2..975579a 100644 --- a/filesetup.c +++ b/filesetup.c @@ -639,7 +639,7 @@ static int get_file_sizes(struct thread_data *td) } if (f->real_file_size == -1ULL && td->o.size) - f->real_file_size = td->o.size / td->o.nr_files; + f->real_file_size = (td->o.size + td_min_bs(td) - 1) / td->o.nr_files; } return err; @@ -801,7 +801,7 @@ int setup_files(struct thread_data *td) * total size divided by number of files. if that is * zero, set it to the real file size. */ - f->io_size = o->size / o->nr_files; + f->io_size = (o->size + td_min_bs(td) - 1) / o->nr_files; if (!f->io_size) f->io_size = f->real_file_size - f->file_offset; } else if (f->real_file_size < o->file_size_low || @@ -1386,3 +1386,15 @@ void fio_file_reset(struct thread_data *td, struct fio_file *f) if (td->o.random_generator == FIO_RAND_GEN_LFSR) lfsr_reset(&f->lfsr, td->rand_seeds[FIO_RAND_BLOCK_OFF]); } + +int fio_files_done(struct thread_data *td) +{ + struct fio_file *f; + unsigned int i; + + for_each_file(td, f, i) + if (!fio_file_done(f)) + return 0; + + return 1; +} diff --git a/io_u.c b/io_u.c index 64ff73c..acc1a7b 100644 --- a/io_u.c +++ b/io_u.c @@ -11,6 +11,7 @@ #include "trim.h" #include "lib/rand.h" #include "lib/axmap.h" +#include "err.h" struct io_completion_data { int nr; /* input */ @@ -985,6 +986,9 @@ static struct fio_file *get_next_file_rand(struct thread_data *td, if (!fio_file_open(f)) { int err; + if (td->nr_open_files >= td->o.open_files) + return ERR_PTR(-EBUSY); + err = td_io_open_file(td, f); if (err) continue; @@ -1027,6 +1031,9 @@ static struct fio_file *get_next_file_rr(struct thread_data *td, int goodf, if (!fio_file_open(f)) { int err; + if (td->nr_open_files >= td->o.open_files) + return ERR_PTR(-EBUSY); + err = td_io_open_file(td, f); if (err) { dprint(FD_FILE, "error %d on open of %s\n", @@ -1080,6 +1087,9 @@ static struct fio_file *__get_next_file(struct thread_data *td) else f = get_next_file_rand(td, FIO_FILE_open, FIO_FILE_closing); + if (IS_ERR(f)) + return f; + td->file_service_file = f; td->file_service_left = td->file_service_nr - 1; out: @@ -1099,14 +1109,14 @@ static struct fio_file *get_next_file(struct thread_data *td) return __get_next_file(td); } -static int set_io_u_file(struct thread_data *td, struct io_u *io_u) +static long set_io_u_file(struct thread_data *td, struct io_u *io_u) { struct fio_file *f; do { f = get_next_file(td); - if (!f) - return 1; + if (IS_ERR_OR_NULL(f)) + return PTR_ERR(f); io_u->file = f; get_file(f); @@ -1400,6 +1410,7 @@ struct io_u *get_io_u(struct thread_data *td) struct fio_file *f; struct io_u *io_u; int do_scramble = 0; + long ret = 0; io_u = __get_io_u(td); if (!io_u) { @@ -1425,11 +1436,17 @@ struct io_u *get_io_u(struct thread_data *td) if (read_iolog_get(td, io_u)) goto err_put; } else if (set_io_u_file(td, io_u)) { + ret = -EBUSY; dprint(FD_IO, "io_u %p, setting file failed\n", io_u); goto err_put; } f = io_u->file; + if (!f) { + dprint(FD_IO, "io_u %p, setting file failed\n", io_u); + goto err_put; + } + assert(fio_file_open(f)); if (ddir_rw(io_u->ddir)) { @@ -1478,7 +1495,7 @@ out: err_put: dprint(FD_IO, "get_io_u failed\n"); put_io_u(td, io_u); - return NULL; + return ERR_PTR(ret); } void io_u_log_error(struct thread_data *td, struct io_u *io_u) -- Jens Axboe -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html