Recently (Subversion revision 633) code was added to scst_vdisk.c that

performs a.o. 64-bit division. While gcc supports 64-bit divisions on 32-bit
CPU's, gcc generates a function call for these 64-bit divisions (see also
http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html for the
entire list). Unfortunately there is no implementation available for these
functions in the Linux kernel. Which means that loading kernel modules
that contain 64-bit divisions on a 32-bit system will fail and that insmod/
modprobe will complain about undefined references to e.g. __umoddi3. AFAIK the
proper approach in the Linux kernel is to use the do_div() macro for
performing 64-bit divisions. This macro is defined in <asm/div64.h>. The patch
below converts the call to div_s64_rem() by a call to do_div().

The patch below has been verified as follows:
- Reran scripts/run-regression-tests -k 2.6.24.7 -k 2.6.25.20 -k 2.6.26.8 -k 2.6.27.12 -k 2.6.28.1
  on a 64-bit system and verified that the output of the re*/sparse* files did
  not contain any compilation errors.
- Verified that the patched SCST source compiles fine on CentOS 5.2, 32-bit.
- Verified that the scst_vdisk module loads correctly on CentOS 5.2, 32-bit.

Signed-off-by: Bart Van Assche <bart.vanassche@gmail.com>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@640 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-01-26 17:23:46 +00:00
parent 3943177f67
commit a5589e099a
+8 -16
View File
@@ -39,21 +39,7 @@
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#include <linux/math64.h>
#else
#include <asm/div64.h>
static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
{
unsigned long long d = dividend;
unsigned int dd = divisor, r;
r = do_div(d, dd);
*remainder = r;
return d;
}
#endif
#define LOG_PREFIX "dev_vdisk"
@@ -242,7 +228,6 @@ struct scst_vdisk_thr {
static struct kmem_cache *vdisk_thr_cachep;
#define DEF_NUM_THREADS 5
static int num_threads = DEF_NUM_THREADS;
module_param_named(num_threads, num_threads, int, 0);
@@ -1406,9 +1391,16 @@ static int vdisk_rigid_geo_pg(unsigned char *p, int pcontrol,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x3a, 0x98/* 15K RPM */, 0, 0};
int32_t ncyl, n, rem;
uint64_t dividend;
memcpy(p, geo_m_pg, sizeof(geo_m_pg));
ncyl = div_s64_rem(virt_dev->nblocks, DEF_HEADS * DEF_SECTORS, &rem);
/*
* Divide virt_dev->nblocks by (DEF_HEADS * DEF_SECTORS) and store
* the quotient in ncyl and the remainder in rem.
*/
dividend = virt_dev->nblocks;
rem = do_div(dividend, DEF_HEADS * DEF_SECTORS);
ncyl = dividend;
if (rem != 0)
ncyl++;
memcpy(&n, p + 2, sizeof(u32));