Home > database >  'struct mm_struct' has no member named 'mmap_sem' error in the module build afte
'struct mm_struct' has no member named 'mmap_sem' error in the module build afte

Time:03-25

I've been using this function in my linux device driver. This is to pin user pages for user virtual address (required number of pages) and get kernel address of it. By the ways, it was used in linux-5.4.21. (I think this method may have some problem. but it worked so I was using it)

static unsigned long uvirt_to_kvirt_ppin(unsigned long uvirt, unsigned long length, struct page *pages)
{
    int res;
    int offs;
    uint64_t *kvpaddr;
    uint64_t kvaddr;
    uint64_t paddr;

    offs = uvirt % PAGE_SIZE;
    down_read(&current->mm->mmap_sem);
    res = get_user_pages( uvirt, length>>PAGE_SHIFT, FOLL_WRITE, &pages, NULL);
    if (res) {
        kvpaddr = kmap(pages);
        kvaddr = ((unsigned long long int)(kvpaddr) offs);
        paddr = page_to_phys(pages)   offs;
    }
    else {
        printk("get_user_pages failed! res = %x\n", res);
        return -1;
    }
    up_read(&current->mm->mmap_sem);
    return kvaddr;
}

But today, when I was trying to build the module now against kernel 5.10.0-rc5, I met with this error message. This means as kernel was upgraded, the structure mm_struct was chagned.

/home/ckim/prj/abdsn/ab21sim/ab21tsim/QEMU/qemu_test/test_ldd_vanila/axpu_ldd_kc.c: In function ??uvirt_to_kvirt_ppin??:
/home/ckim/prj/abdsn/ab21sim/ab21tsim/QEMU/qemu_test/test_ldd_vanila/axpu_ldd_kc.c:246:26: error: ??struct mm_struct?? has no member named ??mmap_sem??; did you mean ??mmap_base???
  246 |  down_read(&current->mm->mmap_sem);
      |                          ^~~~~~~~
      |                          mmap_base
/home/ckim/prj/abdsn/ab21sim/ab21tsim/QEMU/qemu_test/test_ldd_vanila/axpu_ldd_kc.c:257:27: error: ??struct mm_struct?? has no member named ??mmap_sem??; did you mean ??mmap_base???
  257 |     up_read(&current->mm->mmap_sem);
      |                           ^~~~~~~~
      |                           mmap_base

How should I change it for 5.10.0-rc5? I searched the use of get_user_pages in 5.10.0-rc5 but there seems to be no locking around it. So, can I just remove the down_read and up_read lines? Probably I'll just go with it.(removing the lines).

CodePudding user response:

In Linux kernel 5.8, the mmap_sem member of struct mm_struct was renamed to mmap_lock and a new mmap locking API was added.

You could do something like this:

#include <linux/mm.h>
#ifndef MMAP_LOCK_INITIALIZER

/* Define mmap locking API for pre-5.8 kernels. */

/* This one should not be needed in a driver. */
static inline void mmap_init_lock(struct mm_struct *mm)
{
       init_rwsem(&mm->mmap_sem);
}

static inline void mmap_write_lock(struct mm_struct *mm)
{
       down_write(&mm->mmap_sem);
}

static inline int mmap_write_lock_killable(struct mm_struct *mm)
{
       return down_write_killable(&mm->mmap_sem);
}

static inline bool mmap_write_trylock(struct mm_struct *mm)
{
       return down_write_trylock(&mm->mmap_sem) != 0;
}

static inline void mmap_write_unlock(struct mm_struct *mm)
{
       up_write(&mm->mmap_sem);
}

static inline void mmap_write_downgrade(struct mm_struct *mm)
{
       downgrade_write(&mm->mmap_sem);
}

static inline void mmap_read_lock(struct mm_struct *mm)
{
       down_read(&mm->mmap_sem);
}

static inline int mmap_read_lock_killable(struct mm_struct *mm)
{
       return down_read_killable(&mm->mmap_sem);
}

static inline bool mmap_read_trylock(struct mm_struct *mm)
{
       return down_read_trylock(&mm->mmap_sem) != 0;
}

static inline void mmap_read_unlock(struct mm_struct *mm)
{
       up_read(&mm->mmap_sem);
}

#endif /* MMAP_LOCK_INITIALIZER */

Then replace down_read(&current->mm->mmap_sem); with mmap_read_lock(current->mm); and replace up_read(&current->mm->mmap_sem); with mmap_read_unlock(current->mm);.

  • Related