Commit a4147415 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'akpm' (patches from Andrew)

Merge misc fixes from Andrew Morton:
 "13 patches.

  Subsystems affected by this patch series: resource, squashfs, hfsplus,
  modprobe, and mm (hugetlb, slub, userfaultfd, ksm, pagealloc, kasan,
  pagemap, and ioremap)"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  mm/ioremap: fix iomap_max_page_shift
  docs: admin-guide: update description for kernel.modprobe sysctl
  hfsplus: prevent corruption in shrinking truncate
  mm/filemap: fix readahead return types
  kasan: fix unit tests with CONFIG_UBSAN_LOCAL_BOUNDS enabled
  mm: fix struct page layout on 32-bit systems
  ksm: revert "use GET_KSM_PAGE_NOLOCK to get ksm page in remove_rmap_item_from_tree()"
  userfaultfd: release page in error path to avoid BUG_ON
  squashfs: fix divide error in calculate_skip()
  kernel/resource: fix return code check in __request_free_mem_region
  mm, slub: move slub_debug static key enabling outside slab_mutex
  mm/hugetlb: fix cow where page writtable in child
  mm/hugetlb: fix F_SEAL_FUTURE_WRITE
parents f36edc55 86d0c164
...@@ -483,10 +483,11 @@ modprobe ...@@ -483,10 +483,11 @@ modprobe
======== ========
The full path to the usermode helper for autoloading kernel modules, The full path to the usermode helper for autoloading kernel modules,
by default "/sbin/modprobe". This binary is executed when the kernel by default ``CONFIG_MODPROBE_PATH``, which in turn defaults to
requests a module. For example, if userspace passes an unknown "/sbin/modprobe". This binary is executed when the kernel requests a
filesystem type to mount(), then the kernel will automatically request module. For example, if userspace passes an unknown filesystem type
the corresponding filesystem module by executing this usermode helper. to mount(), then the kernel will automatically request the
corresponding filesystem module by executing this usermode helper.
This usermode helper should insert the needed module into the kernel. This usermode helper should insert the needed module into the kernel.
This sysctl only affects module autoloading. It has no effect on the This sysctl only affects module autoloading. It has no effect on the
......
...@@ -598,13 +598,15 @@ void hfsplus_file_truncate(struct inode *inode) ...@@ -598,13 +598,15 @@ void hfsplus_file_truncate(struct inode *inode)
res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
if (res) if (res)
break; break;
hfs_brec_remove(&fd);
mutex_unlock(&fd.tree->tree_lock);
start = hip->cached_start; start = hip->cached_start;
if (blk_cnt <= start)
hfs_brec_remove(&fd);
mutex_unlock(&fd.tree->tree_lock);
hfsplus_free_extents(sb, hip->cached_extents, hfsplus_free_extents(sb, hip->cached_extents,
alloc_cnt - start, alloc_cnt - blk_cnt); alloc_cnt - start, alloc_cnt - blk_cnt);
hfsplus_dump_extent(hip->cached_extents); hfsplus_dump_extent(hip->cached_extents);
mutex_lock(&fd.tree->tree_lock);
if (blk_cnt > start) { if (blk_cnt > start) {
hip->extent_state |= HFSPLUS_EXT_DIRTY; hip->extent_state |= HFSPLUS_EXT_DIRTY;
break; break;
...@@ -612,7 +614,6 @@ void hfsplus_file_truncate(struct inode *inode) ...@@ -612,7 +614,6 @@ void hfsplus_file_truncate(struct inode *inode)
alloc_cnt = start; alloc_cnt = start;
hip->cached_start = hip->cached_blocks = 0; hip->cached_start = hip->cached_blocks = 0;
hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW); hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
mutex_lock(&fd.tree->tree_lock);
} }
hfs_find_exit(&fd); hfs_find_exit(&fd);
......
...@@ -131,6 +131,7 @@ static void huge_pagevec_release(struct pagevec *pvec) ...@@ -131,6 +131,7 @@ static void huge_pagevec_release(struct pagevec *pvec)
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
loff_t len, vma_len; loff_t len, vma_len;
int ret; int ret;
struct hstate *h = hstate_file(file); struct hstate *h = hstate_file(file);
...@@ -146,6 +147,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -146,6 +147,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND; vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
vma->vm_ops = &hugetlb_vm_ops; vma->vm_ops = &hugetlb_vm_ops;
ret = seal_check_future_write(info->seals, vma);
if (ret)
return ret;
/* /*
* page based offset in vm_pgoff could be sufficiently large to * page based offset in vm_pgoff could be sufficiently large to
* overflow a loff_t when converted to byte offset. This can * overflow a loff_t when converted to byte offset. This can
......
...@@ -394,7 +394,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops) ...@@ -394,7 +394,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops)
{ {
struct inode *inode = rac->mapping->host; struct inode *inode = rac->mapping->host;
loff_t pos = readahead_pos(rac); loff_t pos = readahead_pos(rac);
loff_t length = readahead_length(rac); size_t length = readahead_length(rac);
struct iomap_readpage_ctx ctx = { struct iomap_readpage_ctx ctx = {
.rac = rac, .rac = rac,
}; };
...@@ -402,7 +402,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops) ...@@ -402,7 +402,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops)
trace_iomap_readahead(inode, readahead_count(rac)); trace_iomap_readahead(inode, readahead_count(rac));
while (length > 0) { while (length > 0) {
loff_t ret = iomap_apply(inode, pos, length, 0, ops, ssize_t ret = iomap_apply(inode, pos, length, 0, ops,
&ctx, iomap_readahead_actor); &ctx, iomap_readahead_actor);
if (ret <= 0) { if (ret <= 0) {
WARN_ON_ONCE(ret == 0); WARN_ON_ONCE(ret == 0);
......
...@@ -211,11 +211,11 @@ static long long read_indexes(struct super_block *sb, int n, ...@@ -211,11 +211,11 @@ static long long read_indexes(struct super_block *sb, int n,
* If the skip factor is limited in this way then the file will use multiple * If the skip factor is limited in this way then the file will use multiple
* slots. * slots.
*/ */
static inline int calculate_skip(int blocks) static inline int calculate_skip(u64 blocks)
{ {
int skip = blocks / ((SQUASHFS_META_ENTRIES + 1) u64 skip = blocks / ((SQUASHFS_META_ENTRIES + 1)
* SQUASHFS_META_INDEXES); * SQUASHFS_META_INDEXES);
return min(SQUASHFS_CACHED_BLKS - 1, skip + 1); return min((u64) SQUASHFS_CACHED_BLKS - 1, skip + 1);
} }
......
...@@ -3216,5 +3216,37 @@ void mem_dump_obj(void *object); ...@@ -3216,5 +3216,37 @@ void mem_dump_obj(void *object);
static inline void mem_dump_obj(void *object) {} static inline void mem_dump_obj(void *object) {}
#endif #endif
/**
* seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it
* @seals: the seals to check
* @vma: the vma to operate on
*
* Check whether F_SEAL_FUTURE_WRITE is set; if so, do proper check/handling on
* the vma flags. Return 0 if check pass, or <0 for errors.
*/
static inline int seal_check_future_write(int seals, struct vm_area_struct *vma)
{
if (seals & F_SEAL_FUTURE_WRITE) {
/*
* New PROT_WRITE and MAP_SHARED mmaps are not allowed when
* "future write" seal active.
*/
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
return -EPERM;
/*
* Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as
* MAP_SHARED and read-only, take care to not allow mprotect to
* revert protections on such mappings. Do this only for shared
* mappings. For private mappings, don't need to mask
* VM_MAYWRITE as we still want them to be COW-writable.
*/
if (vma->vm_flags & VM_SHARED)
vma->vm_flags &= ~(VM_MAYWRITE);
}
return 0;
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */ #endif /* _LINUX_MM_H */
...@@ -97,10 +97,10 @@ struct page { ...@@ -97,10 +97,10 @@ struct page {
}; };
struct { /* page_pool used by netstack */ struct { /* page_pool used by netstack */
/** /**
* @dma_addr: might require a 64-bit value even on * @dma_addr: might require a 64-bit value on
* 32-bit architectures. * 32-bit architectures.
*/ */
dma_addr_t dma_addr; unsigned long dma_addr[2];
}; };
struct { /* slab, slob and slub */ struct { /* slab, slob and slub */
union { union {
......
...@@ -997,9 +997,9 @@ static inline loff_t readahead_pos(struct readahead_control *rac) ...@@ -997,9 +997,9 @@ static inline loff_t readahead_pos(struct readahead_control *rac)
* readahead_length - The number of bytes in this readahead request. * readahead_length - The number of bytes in this readahead request.
* @rac: The readahead request. * @rac: The readahead request.
*/ */
static inline loff_t readahead_length(struct readahead_control *rac) static inline size_t readahead_length(struct readahead_control *rac)
{ {
return (loff_t)rac->_nr_pages * PAGE_SIZE; return rac->_nr_pages * PAGE_SIZE;
} }
/** /**
...@@ -1024,7 +1024,7 @@ static inline unsigned int readahead_count(struct readahead_control *rac) ...@@ -1024,7 +1024,7 @@ static inline unsigned int readahead_count(struct readahead_control *rac)
* readahead_batch_length - The number of bytes in the current batch. * readahead_batch_length - The number of bytes in the current batch.
* @rac: The readahead request. * @rac: The readahead request.
*/ */
static inline loff_t readahead_batch_length(struct readahead_control *rac) static inline size_t readahead_batch_length(struct readahead_control *rac)
{ {
return rac->_batch_count * PAGE_SIZE; return rac->_batch_count * PAGE_SIZE;
} }
......
...@@ -198,7 +198,17 @@ static inline void page_pool_recycle_direct(struct page_pool *pool, ...@@ -198,7 +198,17 @@ static inline void page_pool_recycle_direct(struct page_pool *pool,
static inline dma_addr_t page_pool_get_dma_addr(struct page *page) static inline dma_addr_t page_pool_get_dma_addr(struct page *page)
{ {
return page->dma_addr; dma_addr_t ret = page->dma_addr[0];
if (sizeof(dma_addr_t) > sizeof(unsigned long))
ret |= (dma_addr_t)page->dma_addr[1] << 16 << 16;
return ret;
}
static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr)
{
page->dma_addr[0] = addr;
if (sizeof(dma_addr_t) > sizeof(unsigned long))
page->dma_addr[1] = upper_32_bits(addr);
} }
static inline bool is_page_pool_compiled_in(void) static inline bool is_page_pool_compiled_in(void)
......
...@@ -1805,7 +1805,7 @@ static struct resource *__request_free_mem_region(struct device *dev, ...@@ -1805,7 +1805,7 @@ static struct resource *__request_free_mem_region(struct device *dev,
REGION_DISJOINT) REGION_DISJOINT)
continue; continue;
if (!__request_region_locked(res, &iomem_resource, addr, size, if (__request_region_locked(res, &iomem_resource, addr, size,
name, 0)) name, 0))
break; break;
......
...@@ -654,8 +654,20 @@ static char global_array[10]; ...@@ -654,8 +654,20 @@ static char global_array[10];
static void kasan_global_oob(struct kunit *test) static void kasan_global_oob(struct kunit *test)
{ {
volatile int i = 3; /*
char *p = &global_array[ARRAY_SIZE(global_array) + i]; * Deliberate out-of-bounds access. To prevent CONFIG_UBSAN_LOCAL_BOUNDS
* from failing here and panicing the kernel, access the array via a
* volatile pointer, which will prevent the compiler from being able to
* determine the array bounds.
*
* This access uses a volatile pointer to char (char *volatile) rather
* than the more conventional pointer to volatile char (volatile char *)
* because we want to prevent the compiler from making inferences about
* the pointer itself (i.e. its array bounds), not the data that it
* refers to.
*/
char *volatile array = global_array;
char *p = &array[ARRAY_SIZE(global_array) + 3];
/* Only generic mode instruments globals. */ /* Only generic mode instruments globals. */
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
...@@ -703,8 +715,9 @@ static void ksize_uaf(struct kunit *test) ...@@ -703,8 +715,9 @@ static void ksize_uaf(struct kunit *test)
static void kasan_stack_oob(struct kunit *test) static void kasan_stack_oob(struct kunit *test)
{ {
char stack_array[10]; char stack_array[10];
volatile int i = OOB_TAG_OFF; /* See comment in kasan_global_oob. */
char *p = &stack_array[ARRAY_SIZE(stack_array) + i]; char *volatile array = stack_array;
char *p = &array[ARRAY_SIZE(stack_array) + OOB_TAG_OFF];
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK); KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK);
...@@ -715,7 +728,9 @@ static void kasan_alloca_oob_left(struct kunit *test) ...@@ -715,7 +728,9 @@ static void kasan_alloca_oob_left(struct kunit *test)
{ {
volatile int i = 10; volatile int i = 10;
char alloca_array[i]; char alloca_array[i];
char *p = alloca_array - 1; /* See comment in kasan_global_oob. */
char *volatile array = alloca_array;
char *p = array - 1;
/* Only generic mode instruments dynamic allocas. */ /* Only generic mode instruments dynamic allocas. */
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
...@@ -728,7 +743,9 @@ static void kasan_alloca_oob_right(struct kunit *test) ...@@ -728,7 +743,9 @@ static void kasan_alloca_oob_right(struct kunit *test)
{ {
volatile int i = 10; volatile int i = 10;
char alloca_array[i]; char alloca_array[i];
char *p = alloca_array + i; /* See comment in kasan_global_oob. */
char *volatile array = alloca_array;
char *p = array + i;
/* Only generic mode instruments dynamic allocas. */ /* Only generic mode instruments dynamic allocas. */
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
......
...@@ -4056,6 +4056,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, ...@@ -4056,6 +4056,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
* See Documentation/vm/mmu_notifier.rst * See Documentation/vm/mmu_notifier.rst
*/ */
huge_ptep_set_wrprotect(src, addr, src_pte); huge_ptep_set_wrprotect(src, addr, src_pte);
entry = huge_pte_wrprotect(entry);
} }
page_dup_rmap(ptepage, true); page_dup_rmap(ptepage, true);
......
...@@ -16,16 +16,16 @@ ...@@ -16,16 +16,16 @@
#include "pgalloc-track.h" #include "pgalloc-track.h"
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
static bool __ro_after_init iomap_max_page_shift = PAGE_SHIFT; static unsigned int __ro_after_init iomap_max_page_shift = BITS_PER_LONG - 1;
static int __init set_nohugeiomap(char *str) static int __init set_nohugeiomap(char *str)
{ {
iomap_max_page_shift = P4D_SHIFT; iomap_max_page_shift = PAGE_SHIFT;
return 0; return 0;
} }
early_param("nohugeiomap", set_nohugeiomap); early_param("nohugeiomap", set_nohugeiomap);
#else /* CONFIG_HAVE_ARCH_HUGE_VMAP */ #else /* CONFIG_HAVE_ARCH_HUGE_VMAP */
static const bool iomap_max_page_shift = PAGE_SHIFT; static const unsigned int iomap_max_page_shift = PAGE_SHIFT;
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
int ioremap_page_range(unsigned long addr, int ioremap_page_range(unsigned long addr,
......
...@@ -776,11 +776,12 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) ...@@ -776,11 +776,12 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item)
struct page *page; struct page *page;
stable_node = rmap_item->head; stable_node = rmap_item->head;
page = get_ksm_page(stable_node, GET_KSM_PAGE_NOLOCK); page = get_ksm_page(stable_node, GET_KSM_PAGE_LOCK);
if (!page) if (!page)
goto out; goto out;
hlist_del(&rmap_item->hlist); hlist_del(&rmap_item->hlist);
unlock_page(page);
put_page(page); put_page(page);
if (!hlist_empty(&stable_node->hlist)) if (!hlist_empty(&stable_node->hlist))
......
...@@ -2258,25 +2258,11 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user) ...@@ -2258,25 +2258,11 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
static int shmem_mmap(struct file *file, struct vm_area_struct *vma) static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct shmem_inode_info *info = SHMEM_I(file_inode(file)); struct shmem_inode_info *info = SHMEM_I(file_inode(file));
int ret;
if (info->seals & F_SEAL_FUTURE_WRITE) { ret = seal_check_future_write(info->seals, vma);
/* if (ret)
* New PROT_WRITE and MAP_SHARED mmaps are not allowed when return ret;
* "future write" seal active.
*/
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
return -EPERM;
/*
* Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as
* MAP_SHARED and read-only, take care to not allow mprotect to
* revert protections on such mappings. Do this only for shared
* mappings. For private mappings, don't need to mask
* VM_MAYWRITE as we still want them to be COW-writable.
*/
if (vma->vm_flags & VM_SHARED)
vma->vm_flags &= ~(VM_MAYWRITE);
}
/* arm64 - allow memory tagging on RAM-based files */ /* arm64 - allow memory tagging on RAM-based files */
vma->vm_flags |= VM_MTE_ALLOWED; vma->vm_flags |= VM_MTE_ALLOWED;
...@@ -2375,8 +2361,18 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm, ...@@ -2375,8 +2361,18 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
pgoff_t offset, max_off; pgoff_t offset, max_off;
ret = -ENOMEM; ret = -ENOMEM;
if (!shmem_inode_acct_block(inode, 1)) if (!shmem_inode_acct_block(inode, 1)) {
/*
* We may have got a page, returned -ENOENT triggering a retry,
* and now we find ourselves with -ENOMEM. Release the page, to
* avoid a BUG_ON in our caller.
*/
if (unlikely(*pagep)) {
put_page(*pagep);
*pagep = NULL;
}
goto out; goto out;
}
if (!*pagep) { if (!*pagep) {
page = shmem_alloc_page(gfp, info, pgoff); page = shmem_alloc_page(gfp, info, pgoff);
......
...@@ -318,6 +318,16 @@ kmem_cache_create_usercopy(const char *name, ...@@ -318,6 +318,16 @@ kmem_cache_create_usercopy(const char *name,
const char *cache_name; const char *cache_name;
int err; int err;
#ifdef CONFIG_SLUB_DEBUG
/*
* If no slub_debug was enabled globally, the static key is not yet
* enabled by setup_slub_debug(). Enable it if the cache is being
* created with any of the debugging flags passed explicitly.
*/
if (flags & SLAB_DEBUG_FLAGS)
static_branch_enable(&slub_debug_enabled);
#endif
mutex_lock(&slab_mutex); mutex_lock(&slab_mutex);
err = kmem_cache_sanity_check(name, size); err = kmem_cache_sanity_check(name, size);
......
...@@ -3828,15 +3828,6 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) ...@@ -3828,15 +3828,6 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags) static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags)
{ {
#ifdef CONFIG_SLUB_DEBUG
/*
* If no slub_debug was enabled globally, the static key is not yet
* enabled by setup_slub_debug(). Enable it if the cache is being
* created with any of the debugging flags passed explicitly.
*/
if (flags & SLAB_DEBUG_FLAGS)
static_branch_enable(&slub_debug_enabled);
#endif
s->flags = kmem_cache_flags(s->size, flags, s->name); s->flags = kmem_cache_flags(s->size, flags, s->name);
#ifdef CONFIG_SLAB_FREELIST_HARDENED #ifdef CONFIG_SLAB_FREELIST_HARDENED
s->random = get_random_long(); s->random = get_random_long();
......
...@@ -174,8 +174,10 @@ static void page_pool_dma_sync_for_device(struct page_pool *pool, ...@@ -174,8 +174,10 @@ static void page_pool_dma_sync_for_device(struct page_pool *pool,
struct page *page, struct page *page,
unsigned int dma_sync_size) unsigned int dma_sync_size)
{ {
dma_addr_t dma_addr = page_pool_get_dma_addr(page);
dma_sync_size = min(dma_sync_size, pool->p.max_len); dma_sync_size = min(dma_sync_size, pool->p.max_len);
dma_sync_single_range_for_device(pool->p.dev, page->dma_addr, dma_sync_single_range_for_device(pool->p.dev, dma_addr,
pool->p.offset, dma_sync_size, pool->p.offset, dma_sync_size,
pool->p.dma_dir); pool->p.dma_dir);
} }
...@@ -195,7 +197,7 @@ static bool page_pool_dma_map(struct page_pool *pool, struct page *page) ...@@ -195,7 +197,7 @@ static bool page_pool_dma_map(struct page_pool *pool, struct page *page)
if (dma_mapping_error(pool->p.dev, dma)) if (dma_mapping_error(pool->p.dev, dma))
return false; return false;
page->dma_addr = dma; page_pool_set_dma_addr(page, dma);
if (pool->p.flags & PP_FLAG_DMA_SYNC_DEV) if (pool->p.flags & PP_FLAG_DMA_SYNC_DEV)
page_pool_dma_sync_for_device(pool, page, pool->p.max_len); page_pool_dma_sync_for_device(pool, page, pool->p.max_len);
...@@ -331,13 +333,13 @@ void page_pool_release_page(struct page_pool *pool, struct page *page) ...@@ -331,13 +333,13 @@ void page_pool_release_page(struct page_pool *pool, struct page *page)
*/ */
goto skip_dma_unmap; goto skip_dma_unmap;
dma = page->dma_addr; dma = page_pool_get_dma_addr(page);
/* When page is unmapped, it cannot be returned our pool */ /* When page is unmapped, it cannot be returned to our pool */
dma_unmap_page_attrs(pool->p.dev, dma, dma_unmap_page_attrs(pool->p.dev, dma,
PAGE_SIZE << pool->p.order, pool->p.dma_dir, PAGE_SIZE << pool->p.order, pool->p.dma_dir,
DMA_ATTR_SKIP_CPU_SYNC); DMA_ATTR_SKIP_CPU_SYNC);
page->dma_addr = 0; page_pool_set_dma_addr(page, 0);
skip_dma_unmap: skip_dma_unmap:
/* This may be the last page returned, releasing the pool, so /* This may be the last page returned, releasing the pool, so
* it is not safe to reference pool afterwards. * it is not safe to reference pool afterwards.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment