Recently (Subversion revision 633) code was added to scst_vdisk.c that
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 26 Jan 2009 17:23:46 +0000 (17:23 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 26 Jan 2009 17:23:46 +0000 (17:23 +0000)
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: https://scst.svn.sourceforge.net/svnroot/scst/trunk@640 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/src/dev_handlers/scst_vdisk.c

index 847a550..803ce5e 100644 (file)
 #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));