Allocating a lot of memory for a kernel module using vmalloc

I am trying to allocate more memory for a kernel module using vmalloc()

. I cannot allocate more than 2GB of memory on 64-bit Linux (3.10.0-514.2.2.el7.x86_64) with 64GB of RAM.

These are the relevant parts of the code:

...

static int logical_block_size = 512;
module_param(logical_block_size, int, 0);
static int nsectors = 1024; /* How big the drive is */
module_param(nsectors, int, 0);

...

/*
 * The internal representation of our device.
*/
static struct sbd_device {
    unsigned long size;
    spinlock_t lock;
    u8 *data;
    struct gendisk *gd;
} Device;

...

static int __init sbd_init(void) {
    /*
     * Set up our internal device.
     */
   Device.size = nsectors * logical_block_size;
   spin_lock_init(&Device.lock);
   Device.data = vmalloc(Device.size);
   ...

      

Is there a limit to the amount of memory that can be allocated through vmalloc

? Is there another way to allocate a large amount of memory for the kernel module?

+3


source to share


2 answers


You reference the code here: Simple Block Driver in the comments, which is important to answer your question.

The reason is that you are trying to allocate 16 Exabytes of data. This calculation sbd_init()

is the reason:

Device.size = nsectors * logical_block_size;

      

Device.size unsigned long

, while the module parameters nsectors

and logical_block_size

are integers.

Now when you set locgical_block_size to 1024

and nsectors to 2097152

(which is up to 2GB of space) the computation is done as a signed integer, thus the result is:



1024 * 2097152 = -2147483648

      

If this is implicitly pointed to unsigned long

(by assigning Device.size) the result will be 18446744071562067968

, which is then passed to vmalloc()

(possibly) slightly larger physical memory, and vmalloc is an area reserved which is 32TB on Linux x86_64.

The solution is to do the calculation like unsigned long

:

Device.size = (unsigned long) nsectors * logical_block_size;

      

Then it should work as expected.

0


source


Earlier versions of the Linux kernel had a 64MB limit of memory that vmalloc()

can be allocated, but in the version 3.10.*

it should theoretically be limited by physical memory.



0


source







All Articles