'struct mm_struct' has no member named 'mmap_sem' 从 5.4.21 切换到 5.10.0-rc5 后模块构建出错

'struct mm_struct' has no member named 'mmap_sem' error in the module build after switching from 5.4.21 to 5.10.0-rc5

我一直在我的 linux 设备驱动程序中使用此功能。这是为用户虚拟地址(所需页数)固定用户页面并获取它的内核地址。顺便说一句,它在linux-5.4.21中使用过。 (我觉得这个方法可能有点问题,但是很管用所以我就用了)

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;
}

但是今天,当我尝试针对内核 5.10.0-rc5 构建模块时,我遇到了这个错误消息。这意味着随着内核升级,结构 mm_struct 被更改。

/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

我应该如何为 5.10.0-rc5 更改它?我在 5.10.0-rc5 中搜索了 get_user_pages 的使用,但似乎没有锁定它。那么,我可以删除 down_read 和 up_read 行吗? 可能我会随它去。(删除线)。

在Linux内核5.8中,struct mm_structmmap_sem成员重命名为mmap_lock并添加了新的mmap锁定API。

你可以这样做:

#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 */

然后将down_read(&current->mm->mmap_sem);替换为mmap_read_lock(current->mm);,将up_read(&current->mm->mmap_sem);替换为mmap_read_unlock(current->mm);