From: Mark Hills <mark-UrrBsZIrrsb10XsdtD+oqA@public.gmane.org>
To: linux-bcache-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [PATCH 2/7] Provide 64-bit arithmetic functions
Date: Sat, 10 Sep 2011 14:45:34 +0100 [thread overview]
Message-ID: <1315662339-3115-2-git-send-email-mark@pogo.org.uk> (raw)
In-Reply-To: <1315662339-3115-1-git-send-email-mark-UrrBsZIrrsb10XsdtD+oqA@public.gmane.org>
Building on x86 (32-bit) gives linkage errors against __udivdi3 and
__umoddi3, which gcc uses to modulo and divide operations on 64-bit
numbers. eg. sector_t when divided by block_size, bucket_size
ERROR: "__udivdi3" [block/bcache.ko] undefined!
ERROR: "__umoddi3" [block/bcache.ko] undefined!
The recommended way to handle this in the kernel seems to be the do_div()
function. But since block_size, bucket_size etc. are restricted to powers
of 2 anyway, should we really be storing block size as a shift and a mask?
To get things running I just provided the following implementation in the
code, borrowed from a old patch by David Howells [1]
[1] http://lkml.org/lkml/2006/8/14/305
---
block/bcache_util.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 95 insertions(+), 0 deletions(-)
diff --git a/block/bcache_util.c b/block/bcache_util.c
index ea707c9..8e147de 100644
--- a/block/bcache_util.c
+++ b/block/bcache_util.c
@@ -1,6 +1,7 @@
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/debugfs.h>
+#include <linux/log2.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/types.h>
@@ -659,3 +660,97 @@ uint64_t crc64(const void *data, size_t len)
return crc ^ 0xffffffffffffffff;
}
EXPORT_SYMBOL(crc64);
+
+/*
+ * calculate:
+ * Q = a / b
+ * R = a % b
+ * by long division (repeated shift and conditional subtract)
+ * - base2 long division does not require any usage of actual division or
+ * multiplication instructions
+ */
+u64 __udivmoddi4(u64 a, u64 b, u64 *_r)
+{
+ u64 acc, Q;
+ u32 A;
+ int M;
+
+ /* dispose of trivialities first */
+ if (b >= a) {
+ if (b == a) {
+ if (_r)
+ *_r = 0;
+ return 1;
+ }
+ if (_r)
+ *_r = a;
+ return 0;
+ }
+
+ /* divide by two until at least one argument is odd */
+ while (!((a | b) & 1)) {
+ a >>= 1;
+ b >>= 1;
+ }
+
+ /* handle it as 64-bit divide by 32-bit if we can */
+ if (b <= 0xffffffffULL) {
+ acc = do_div(a, b);
+ if (_r)
+ *_r = acc;
+ return a;
+ }
+
+ /* skip any steps that don't need to be done given the magnitude of the
+ * divisor:
+ * - the divisor is at least 33 bits in size (log2(b) >= 32)
+ * - load the accumulator with as many bits of the dividend as we can
+ * - decant the remainder into a 32-bit variable since we will have
+ * fewer than 32-bits remaining
+ */
+ M = ilog2(b >> 32) + 32;
+ acc = a >> (63 - M);
+ A = a;
+ A <<= M - 31;
+
+ Q = 0;
+
+ for (;;) {
+ if (acc >= b) {
+ /* reduce the accumulator if we can */
+ acc -= b;
+ Q |= 1ULL;
+ }
+
+ if (M >= 63)
+ break;
+
+ /* shift next-MSB from dividend into LSB of accumulator */
+ acc = acc << 1;
+ if (A & 0x80000000U)
+ acc |= 1ULL;
+ A <<= 1;
+ Q <<= 1;
+ M++;
+ }
+
+ /* the accumulator is left holding the remainder */
+ if (_r)
+ *_r = acc;
+
+ return Q;
+}
+
+u64 __udivdi3(u64 a, u64 b)
+{
+ return __udivmoddi4(a, b, NULL);
+}
+EXPORT_SYMBOL(__udivdi3);
+
+u64 __umoddi3(u64 a, u64 b)
+{
+ u64 r;
+ __udivmoddi4(a, b, &r);
+ return r;
+}
+EXPORT_SYMBOL(__umoddi3);
--
1.7.4.4
next prev parent reply other threads:[~2011-09-10 13:45 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-10 13:44 First observations with bcache Mark Hills
[not found] ` <1109101110320.2733-4jfXtw+jRJ582hYKe6nXyg@public.gmane.org>
2011-09-10 13:45 ` [PATCH 1/7] Use exported call to up/down read Mark Hills
[not found] ` <1315662339-3115-1-git-send-email-mark-UrrBsZIrrsb10XsdtD+oqA@public.gmane.org>
2011-09-10 13:45 ` Mark Hills [this message]
2011-09-10 13:45 ` [PATCH 3/7] Break fuzz test to allow building as module Mark Hills
2011-09-10 13:45 ` [PATCH 4/7] Don't require linkage against closure_lock Mark Hills
2011-09-10 13:45 ` [PATCH 5/7] Allow closure debugging without CONFIG_DEBUG_FS Mark Hills
2011-09-10 13:45 ` [PATCH 6/7] Temporary fix to pr_latency() Mark Hills
2011-09-10 13:45 ` [PATCH 7/7] Don't require latency_warn_ms from bcache_util.o Mark Hills
2011-09-10 21:39 ` [PATCH 1/7] Use exported call to up/down read Kent Overstreet
2011-09-22 6:13 ` First observations with bcache Kent Overstreet
2011-09-22 23:14 ` Mark Hills
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1315662339-3115-2-git-send-email-mark@pogo.org.uk \
--to=mark-urrbszirrsb10xsdtd+oqa@public.gmane.org \
--cc=linux-bcache-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.