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));
 		}