'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(¤t->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(¤t->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(¤t->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(¤t->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_struct
的mmap_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(¤t->mm->mmap_sem);
替换为mmap_read_lock(current->mm);
,将up_read(¤t->mm->mmap_sem);
替换为mmap_read_unlock(current->mm);
。
我一直在我的 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(¤t->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(¤t->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(¤t->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(¤t->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_struct
的mmap_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(¤t->mm->mmap_sem);
替换为mmap_read_lock(current->mm);
,将up_read(¤t->mm->mmap_sem);
替换为mmap_read_unlock(current->mm);
。