Recent changes (master)

Jens Axboe
2015-12-05T13:00:07Z

The following changes since commit 0b139881150f7179688243c224a07b57eedbdfa0:

posix_fadvise() returns positive error values (2015-12-03 15:08:08 -0700)

are available in the git repository at:

git://git.kernel.dk/fio.git master

for you to fetch changes up to a6a3469ea8753a999b9bb9bea33299700d3094eb:

workqueue: fix potential ABBA deadlock in stats summing (2015-12-04 13:15:36 -0700)

----------------------------------------------------------------
Jens Axboe (3):
io_u: make io_u_quiesce() return how many IOs it completed
workqueue: properly account ->cur_depth
workqueue: fix potential ABBA deadlock in stats summing

Li Zhong (1):
powerpc: enable cpu clock for powerpc64

arch/arch-ppc.h | 24 ++++++++++++++++++++++++
backend.c | 30 ++++++++++++++++++++++++++----
io_u.c | 10 ++++++++--
ioengine.h | 2 +-
workqueue.c | 38 +++++++++++++++++++++++++++++---------
5 files changed, 88 insertions(+), 16 deletions(-)

---

Diff of recent changes:

diff --git a/arch/arch-ppc.h b/arch/arch-ppc.h
index aed41f9..161c39c 100644
--- a/arch/arch-ppc.h
+++ b/arch/arch-ppc.h
@@ -67,6 +67,21 @@ static inline unsigned int mfspr(unsigned int reg)
#define SPRN_ATBL 0x20E /* Alternate Time Base Lower */
#define SPRN_ATBU 0x20F /* Alternate Time Base Upper */

+#ifdef __powerpc64__
+static inline unsigned long long get_cpu_clock(void)
+{
+ unsigned long long rval;
+
+ asm volatile(
+ "90: mfspr %0, %1;\n"
+ " cmpwi %0,0;\n"
+ " beq- 90b;\n"
+ : "=r" (rval)
+ : "i" (SPRN_TBRL));
+
+ return rval;
+}
+#else
static inline unsigned long long get_cpu_clock(void)
{
unsigned int tbl, tbu0, tbu1;
@@ -87,6 +102,7 @@ static inline unsigned long long get_cpu_clock(void)
ret = (((unsigned long long)tbu0) << 32) | tbl;
return ret;
}
+#endif

#if 0
static void atb_child(void)
@@ -136,4 +152,12 @@ static inline int arch_init(char *envp[])
* #define ARCH_HAVE_CPU_CLOCK
*/

+/*
+ * Let's have it defined for ppc64
+ */
+
+#ifdef __powerpc64__
+#define ARCH_HAVE_CPU_CLOCK
+#endif
+
#endif
diff --git a/backend.c b/backend.c
index 4a689eb..10622ef 100644
--- a/backend.c
+++ b/backend.c
@@ -1358,16 +1358,38 @@ static void io_workqueue_fn(struct thread_data *td, struct io_u *io_u)

td->cur_depth++;

- ret = td_io_queue(td, io_u);
+ do {
+ ret = td_io_queue(td, io_u);
+ if (ret != FIO_Q_BUSY)
+ break;
+ ret = io_u_queued_complete(td, 1);
+ if (ret > 0)
+ td->cur_depth -= ret;
+ io_u_clear(io_u, IO_U_F_FLIGHT);
+ } while (1);

dprint(FD_RATE, "io_u %p ret %d by %u\n", io_u, ret, gettid());

io_queue_event(td, io_u, &ret, ddir, NULL, 0, NULL);

- if (ret == FIO_Q_QUEUED)
- ret = io_u_queued_complete(td, 1);
+ if (ret == FIO_Q_COMPLETED)
+ td->cur_depth--;
+ else if (ret == FIO_Q_QUEUED) {
+ unsigned int min_evts;

- td->cur_depth--;
+ if (td->o.iodepth == 1)
+ min_evts = 1;
+ else
+ min_evts = 0;
+
+ ret = io_u_queued_complete(td, min_evts);
+ if (ret > 0)
+ td->cur_depth -= ret;
+ } else if (ret == FIO_Q_BUSY) {
+ ret = io_u_queued_complete(td, td->cur_depth);
+ if (ret > 0)
+ td->cur_depth -= ret;
+ }
}

/*
diff --git a/io_u.c b/io_u.c
index d45a6f0..f86367b 100644
--- a/io_u.c
+++ b/io_u.c
@@ -542,8 +542,10 @@ static inline enum fio_ddir get_rand_ddir(struct thread_data *td)
return DDIR_WRITE;
}

-void io_u_quiesce(struct thread_data *td)
+int io_u_quiesce(struct thread_data *td)
{
+ int completed = 0;
+
/*
* We are going to sleep, ensure that we flush anything pending as
* not to skew our latency numbers.
@@ -563,7 +565,11 @@ void io_u_quiesce(struct thread_data *td)
int fio_unused ret;

ret = io_u_queued_complete(td, 1);
+ if (ret > 0)
+ completed += ret;
}
+
+ return completed;
}

static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
@@ -1856,7 +1862,7 @@ int io_u_queued_complete(struct thread_data *td, int min_evts)
for (ddir = DDIR_READ; ddir < DDIR_RWDIR_CNT; ddir++)
td->bytes_done[ddir] += icd.bytes_done[ddir];

- return 0;
+ return ret;
}

/*
diff --git a/ioengine.h b/ioengine.h
index c557f7a..37f0336 100644
--- a/ioengine.h
+++ b/ioengine.h
@@ -214,7 +214,7 @@ extern void requeue_io_u(struct thread_data *, struct io_u **);
extern int __must_check io_u_sync_complete(struct thread_data *, struct io_u *);
extern int __must_check io_u_queued_complete(struct thread_data *, int);
extern void io_u_queued(struct thread_data *, struct io_u *);
-extern void io_u_quiesce(struct thread_data *);
+extern int io_u_quiesce(struct thread_data *);
extern void io_u_log_error(struct thread_data *, struct io_u *);
extern void io_u_mark_depth(struct thread_data *, unsigned int);
extern void fill_io_buffer(struct thread_data *, void *, unsigned int, unsigned int);
diff --git a/workqueue.c b/workqueue.c
index 3442375..7cd83bf 100644
--- a/workqueue.c
+++ b/workqueue.c
@@ -217,13 +217,32 @@ static void sum_val(uint64_t *dst, uint64_t *src)
}
#endif

-static void sum_ddir(struct thread_data *dst, struct thread_data *src,
- enum fio_ddir ddir)
+static void pthread_double_unlock(pthread_mutex_t *lock1,
+ pthread_mutex_t *lock2)
+{
+#ifndef CONFIG_SFAA
+ pthread_mutex_unlock(lock1);
+ pthread_mutex_unlock(lock2);
+#endif
+}
+
+static void pthread_double_lock(pthread_mutex_t *lock1, pthread_mutex_t *lock2)
{
#ifndef CONFIG_SFAA
- pthread_mutex_lock(&dst->io_wq.stat_lock);
- pthread_mutex_lock(&src->io_wq.stat_lock);
+ if (lock1 < lock2) {
+ pthread_mutex_lock(lock1);
+ pthread_mutex_lock(lock2);
+ } else {
+ pthread_mutex_lock(lock2);
+ pthread_mutex_lock(lock1);
+ }
#endif
+}
+
+static void sum_ddir(struct thread_data *dst, struct thread_data *src,
+ enum fio_ddir ddir)
+{
+ pthread_double_lock(&dst->io_wq.stat_lock, &src->io_wq.stat_lock);

sum_val(&dst->io_bytes[ddir], &src->io_bytes[ddir]);
sum_val(&dst->io_blocks[ddir], &src->io_blocks[ddir]);
@@ -231,10 +250,7 @@ static void sum_ddir(struct thread_data *dst, struct thread_data *src,
sum_val(&dst->this_io_bytes[ddir], &src->this_io_bytes[ddir]);
sum_val(&dst->bytes_done[ddir], &src->bytes_done[ddir]);

-#ifndef CONFIG_SFAA
- pthread_mutex_unlock(&src->io_wq.stat_lock);
- pthread_mutex_unlock(&dst->io_wq.stat_lock);
-#endif
+ pthread_double_unlock(&dst->io_wq.stat_lock, &src->io_wq.stat_lock);
}

static void update_accounting(struct submit_worker *sw)
@@ -283,8 +299,12 @@ static void *worker_thread(void *data)

if (td->io_u_queued || td->cur_depth ||
td->io_u_in_flight) {
+ int ret;
+
pthread_mutex_unlock(&sw->lock);
- io_u_quiesce(td);
+ ret = io_u_quiesce(td);
+ if (ret > 0)
+ td->cur_depth -= ret;
pthread_mutex_lock(&sw->lock);
}