从 5.4.21 切换到 5.10.0-rc5 后,模块构建中出现“struct mm_struct”没有名为“mmap_sem”的成员错误

问题描述 投票:0回答:1

我一直在我的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 行吗? 也许我会随它去。(删除线条)。

c memory-management linux-kernel linux-device-driver
1个回答
9
投票

在 Linux 内核 5.8 中,

mmap_sem
struct mm_struct
成员被重命名为
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);

© www.soinside.com 2019 - 2024. All rights reserved.