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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox