Convert to using uint64_t's for everything. (doesn't yet work). --- diff/drivers/md/dm-iostats.c 2002-12-17 11:24:35.000000000 +0000 +++ source/drivers/md/dm-iostats.c 2002-12-17 11:30:58.000000000 +0000 @@ -18,17 +18,17 @@ #define IOF_LATENCY 1 struct iostats_c { + spinlock_t lock; unsigned long flags; struct dm_dev *dev; - atomic_t ios[2]; + uint64_t ios[2]; /* * These fields are only present if we are recording the * io latency. */ - spinlock_t lock; - struct timespec start[2]; - struct timespec end[2]; + uint64_t start[2]; + uint64_t end[2]; }; /* @@ -55,7 +55,7 @@ if (latency) size = sizeof(*ic); else - size = (size_t) &((struct iostats_c *) NULL)->lock; + size = (size_t) &((struct iostats_c *) NULL)->start; ic = kmalloc(size, GFP_KERNEL); if (!ic) { @@ -76,8 +76,6 @@ kfree(ic); return -ENXIO; } - atomic_set(&ic->ios[READ], 0); - atomic_set(&ic->ios[WRITE], 0); ti->private = ic; return 0; @@ -90,46 +88,19 @@ kfree(ic); } -static void timespec_sum(struct timespec *lhs, struct timespec *rhs) -{ - lhs->tv_sec += rhs->tv_sec; - lhs->tv_nsec += rhs->tv_nsec; - - if (lhs->tv_nsec > 1000000000L) { - lhs->tv_sec++; - lhs->tv_nsec -= 1000000000L; - } -} - -static void reset_latency(struct iostats_c *ic, int rw) -{ - int flags; - - spin_lock_irqsave(&ic->lock, flags); - memset(&ic->start[rw], 0, sizeof(struct timespec)); - memset(&ic->end[rw], 0, sizeof(struct timespec)); - spin_unlock_irqrestore(&ic->lock, flags); -} - /* read/write statistics mapping */ static int iostats_map(struct dm_target *ti, struct buffer_head *bh, int rw) { int flags; - struct timespec now; struct iostats_c *ic = (struct iostats_c *) ti->private; - if (!test_bit(IOF_LATENCY, &ic->flags)) - atomic_inc(&ic->ios[rw]); + spin_lock_irqsave(&ic->lock, flags); - else { - if (atomic_inc_and_test(&ic->ios[rw])) - reset_latency(ic, rw); + ic->ios[rw]++; + if (test_bit(IOF_LATENCY, &ic->flags)) + ic->start[rw] += jiffies; - jiffies_to_timespec(jiffies, &now); - spin_lock_irqsave(&ic->lock, flags); - timespec_sum(&ic->start[rw], &now); - spin_unlock_irqrestore(&ic->lock, flags); - } + spin_unlock_irqrestore(&ic->lock, flags); /* map */ bh->b_rdev = ic->dev->dev; @@ -144,24 +115,30 @@ int rw, int error) { int flags; - struct timespec now; struct iostats_c *ic = ti->private; - if (test_bit(IOF_LATENCY, &ic->flags)) { - jiffies_to_timespec(jiffies, &now); + spin_lock_irqsave(&ic->lock, flags); - spin_lock_irqsave(&ic->lock, flags); - timespec_sum(&ic->end[rw], &now); - spin_unlock_irqrestore(&ic->lock, flags); - } + if (test_bit(IOF_LATENCY, &ic->flags)) + ic->end[rw] += (uint64_t) jiffies; + + spin_unlock_irqrestore(&ic->lock, flags); } -/* - * Converts a timespec to milliseconds - */ -static inline unsigned long to_milli(struct timespec *ts) +static void div64(uint64_t a, uint64_t b, uint64_t *n) { - return (ts->tv_sec * 1000) + (ts->tv_nsec / 1000000); + sector_t acc, prev, i; + + *n = 0; + while (a >= b) { + for (acc = b, prev = 0, i = 1; + acc <= a; + prev = acc, acc <<= 1, i <<= 1) + ; + + a -= prev; + *n += i >> 1; + } } /* @@ -169,11 +146,20 @@ */ static unsigned long calc_latency(struct iostats_c *ic, int rw) { - unsigned long start_total = to_milli(&ic->start[rw]); - unsigned long end_total = to_milli(&ic->end[rw]); - unsigned long count = atomic_read(&ic->ios[rw]); + uint64_t delta, n; + unsigned long latency; - return count ? ((end_total - start_total) / count) : 0; + if (!ic->ios[rw]) + return 0; + + delta = ic->end[rw] - ic->start[rw]; + div64(delta, ic->ios[rw], &n); + latency = (unsigned long) n; + + latency *= 1000; + latency /= HZ; + + return (unsigned long) delta; } static int iostats_status(struct dm_target *ti, status_type_t type, @@ -184,16 +170,14 @@ switch (type) { case STATUSTYPE_INFO: if (!test_bit(IOF_LATENCY, &ic->flags)) { - snprintf(result, maxlen, "%s %u %u", + snprintf(result, maxlen, "%s %Lu %Lu", kdevname(to_kdev_t(ic->dev->bdev->bd_dev)), - atomic_read(&ic->ios[READ]), - atomic_read(&ic->ios[WRITE])); + ic->ios[READ], ic->ios[WRITE]); } else { - snprintf(result, maxlen, "%s %u %u %lu %lu", + snprintf(result, maxlen, "%s %Lu %Lu %lu %lu", kdevname(to_kdev_t(ic->dev->bdev->bd_dev)), - atomic_read(&ic->ios[READ]), - atomic_read(&ic->ios[WRITE]), + ic->ios[READ], ic->ios[WRITE], calc_latency(ic, READ), calc_latency(ic, WRITE)); }