From 6c519166e10ec5c72944ba3560fad12f8b8c78fd Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:13 +0300 Subject: [PATCH 01/17] quota: allocate dquot_hash with kmalloc() dquot_init() allocates a single page for dquot_hash with __get_free_pages(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_pages() with kmalloc() and get rid of the order variable that remained 0 for more than 20 years. Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-1-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/quota/dquot.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 64cf42721496..9850de3955d3 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -3022,7 +3022,7 @@ static const struct ctl_table fs_dqstats_table[] = { static int __init dquot_init(void) { int i, ret; - unsigned long nr_hash, order; + unsigned long nr_hash; struct shrinker *dqcache_shrinker; printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__); @@ -3035,8 +3035,7 @@ static int __init dquot_init(void) SLAB_PANIC), NULL); - order = 0; - dquot_hash = (struct hlist_head *)__get_free_pages(GFP_KERNEL, order); + dquot_hash = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!dquot_hash) panic("Cannot create dquot hash table"); @@ -3046,7 +3045,7 @@ static int __init dquot_init(void) panic("Cannot create dquot stat counters"); /* Find power-of-two hlist_heads which can fit into allocation */ - nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct hlist_head); + nr_hash = PAGE_SIZE / sizeof(struct hlist_head); dq_hash_bits = ilog2(nr_hash); nr_hash = 1UL << dq_hash_bits; @@ -3054,8 +3053,8 @@ static int __init dquot_init(void) for (i = 0; i < nr_hash; i++) INIT_HLIST_HEAD(dquot_hash + i); - pr_info("VFS: Dquot-cache hash table entries: %ld (order %ld," - " %ld bytes)\n", nr_hash, order, (PAGE_SIZE << order)); + pr_info("VFS: Dquot-cache hash table entries: %ld (%ld bytes)\n", + nr_hash, PAGE_SIZE); dqcache_shrinker = shrinker_alloc(0, "dquota-cache"); if (!dqcache_shrinker) From cb7907e36c1054987a9709efc422b30e10ce839f Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:14 +0300 Subject: [PATCH 02/17] proc: replace __get_free_page() with kmalloc() A few functions in fs/proc/base.c use __get_free_page() to allocate a temporary buffer. kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-2-275e36a83f0e@kernel.org Reviewed-by: Jan Kara Signed-off-by: Christian Brauner (Amutable) --- fs/proc/base.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index d9acfa89c894..e129dc509b79 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -261,7 +261,7 @@ static ssize_t get_mm_proctitle(struct mm_struct *mm, char __user *buf, if (pos >= PAGE_SIZE) return 0; - page = (char *)__get_free_page(GFP_KERNEL); + page = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!page) return -ENOMEM; @@ -284,7 +284,7 @@ static ssize_t get_mm_proctitle(struct mm_struct *mm, char __user *buf, ret = len; } } - free_page((unsigned long)page); + kfree(page); return ret; } @@ -347,7 +347,7 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf, if (count > arg_end - pos) count = arg_end - pos; - page = (char *)__get_free_page(GFP_KERNEL); + page = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!page) return -ENOMEM; @@ -371,7 +371,7 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf, count -= got; } - free_page((unsigned long)page); + kfree(page); return len; } @@ -908,7 +908,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf, if (!mm) return 0; - page = (char *)__get_free_page(GFP_KERNEL); + page = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!page) return -ENOMEM; @@ -949,7 +949,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf, mmput(mm); free: - free_page((unsigned long) page); + kfree(page); return copied; } @@ -1016,7 +1016,7 @@ static ssize_t environ_read(struct file *file, char __user *buf, if (!mm || !mm->env_end) return 0; - page = (char *)__get_free_page(GFP_KERNEL); + page = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!page) return -ENOMEM; @@ -1062,7 +1062,7 @@ static ssize_t environ_read(struct file *file, char __user *buf, mmput(mm); free: - free_page((unsigned long) page); + kfree(page); return ret; } From bc24c5557912073b4f61c0aa137a6faa7a187934 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:15 +0300 Subject: [PATCH 03/17] ocfs2/dlm: replace __get_free_page() with kmalloc() A few places in ocsfs2 allocate temporary buffers with __get_free_page() or get_zeroed_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() and get_zeroed_page() with kmalloc() and kzalloc() respectively. Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-3-275e36a83f0e@kernel.org Reviewed-by: Joseph Qi Reviewed-by: Jan Kara Signed-off-by: Christian Brauner (Amutable) --- fs/ocfs2/dlm/dlmdebug.c | 24 +++++++++--------------- fs/ocfs2/dlm/dlmdomain.c | 8 +++++--- fs/ocfs2/dlm/dlmmaster.c | 5 ++--- fs/ocfs2/dlm/dlmrecovery.c | 4 ++-- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c index fe4fdd09bae3..6ca8b3b68eef 100644 --- a/fs/ocfs2/dlm/dlmdebug.c +++ b/fs/ocfs2/dlm/dlmdebug.c @@ -260,10 +260,10 @@ void dlm_print_one_mle(struct dlm_master_list_entry *mle) { char *buf; - buf = (char *) get_zeroed_page(GFP_ATOMIC); + buf = kzalloc(PAGE_SIZE, GFP_ATOMIC); if (buf) { dump_mle(mle, buf, PAGE_SIZE - 1); - free_page((unsigned long)buf); + kfree(buf); } } @@ -280,7 +280,7 @@ static struct dentry *dlm_debugfs_root; /* begin - utils funcs */ static int debug_release(struct inode *inode, struct file *file) { - free_page((unsigned long)file->private_data); + kfree(file->private_data); return 0; } @@ -327,17 +327,15 @@ static int debug_purgelist_open(struct inode *inode, struct file *file) struct dlm_ctxt *dlm = inode->i_private; char *buf = NULL; - buf = (char *) get_zeroed_page(GFP_NOFS); + buf = kzalloc(PAGE_SIZE, GFP_NOFS); if (!buf) - goto bail; + return -ENOMEM; i_size_write(inode, debug_purgelist_print(dlm, buf, PAGE_SIZE - 1)); file->private_data = buf; return 0; -bail: - return -ENOMEM; } static const struct file_operations debug_purgelist_fops = { @@ -384,17 +382,15 @@ static int debug_mle_open(struct inode *inode, struct file *file) struct dlm_ctxt *dlm = inode->i_private; char *buf = NULL; - buf = (char *) get_zeroed_page(GFP_NOFS); + buf = kzalloc(PAGE_SIZE, GFP_NOFS); if (!buf) - goto bail; + return -ENOMEM; i_size_write(inode, debug_mle_print(dlm, buf, PAGE_SIZE - 1)); file->private_data = buf; return 0; -bail: - return -ENOMEM; } static const struct file_operations debug_mle_fops = { @@ -775,17 +771,15 @@ static int debug_state_open(struct inode *inode, struct file *file) struct dlm_ctxt *dlm = inode->i_private; char *buf = NULL; - buf = (char *) get_zeroed_page(GFP_NOFS); + buf = kzalloc(PAGE_SIZE, GFP_NOFS); if (!buf) - goto bail; + return -ENOMEM; i_size_write(inode, debug_state_print(dlm, buf, PAGE_SIZE - 1)); file->private_data = buf; return 0; -bail: - return -ENOMEM; } static const struct file_operations debug_state_fops = { diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index dc9da9133c8e..97bb9400e24b 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -63,7 +63,7 @@ static inline void byte_copymap(u8 dmap[], unsigned long smap[], static void dlm_free_pagevec(void **vec, int pages) { while (pages--) - free_page((unsigned long)vec[pages]); + kfree(vec[pages]); kfree(vec); } @@ -75,9 +75,11 @@ static void **dlm_alloc_pagevec(int pages) if (!vec) return NULL; - for (i = 0; i < pages; i++) - if (!(vec[i] = (void *)__get_free_page(GFP_KERNEL))) + for (i = 0; i < pages; i++) { + vec[i] = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!vec[i]) goto out_free; + } mlog(0, "Allocated DLM hash pagevec; %d pages (%lu expected), %lu buckets per page\n", pages, (unsigned long)DLM_HASH_PAGES, diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 93eff38fdadd..aee3b4c56dcc 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -2548,7 +2548,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, /* preallocate up front. if this fails, abort */ ret = -ENOMEM; - mres = (struct dlm_migratable_lockres *) __get_free_page(GFP_NOFS); + mres = kmalloc(PAGE_SIZE, GFP_NOFS); if (!mres) { mlog_errno(ret); goto leave; @@ -2725,8 +2725,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, if (wake) wake_up(&res->wq); - if (mres) - free_page((unsigned long)mres); + kfree(mres); dlm_put(dlm); diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 128872bd945d..9b97bf73df22 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -837,7 +837,7 @@ int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data, } /* this will get freed by dlm_request_all_locks_worker */ - buf = (char *) __get_free_page(GFP_NOFS); + buf = kmalloc(PAGE_SIZE, GFP_NOFS); if (!buf) { kfree(item); dlm_put(dlm); @@ -933,7 +933,7 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data) } } leave: - free_page((unsigned long)data); + kfree(data); } From 4948580c76d970bf364f4e225c24ea827f7b3138 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:16 +0300 Subject: [PATCH 04/17] nilfs2: replace get_zeroed_page() with kzalloc() nilfs_ioctl_wrap_copy() allocates a temporary buffer with get_zeroed_page(). kzalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of get_zeroed_page() with kzalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-4-275e36a83f0e@kernel.org Reviewed-by: Viacheslav Dubeyko Signed-off-by: Christian Brauner (Amutable) --- fs/nilfs2/ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index e0a606643e87..b73f2c5d10f0 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -69,7 +69,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, if (argv->v_index > ~(__u64)0 - argv->v_nmembs) return -EINVAL; - buf = (void *)get_zeroed_page(GFP_NOFS); + buf = kzalloc(PAGE_SIZE, GFP_NOFS); if (unlikely(!buf)) return -ENOMEM; maxmembs = PAGE_SIZE / argv->v_size; @@ -107,7 +107,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, } argv->v_nmembs = total; - free_pages((unsigned long)buf, 0); + kfree(buf); return ret; } From eb28dd9d34a842ecc7847ab29c586ef9ba98e53d Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:17 +0300 Subject: [PATCH 05/17] NFS: replace __get_free_page() with kmalloc() in nfs_show_devname() nfs_show_devname() allocates a tmemporary buffer __get_free_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-5-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/nfs/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 4cd420b14ce3..8f8a03a68d3d 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -623,7 +623,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss) int nfs_show_devname(struct seq_file *m, struct dentry *root) { - char *page = (char *) __get_free_page(GFP_KERNEL); + char *page = kmalloc(PAGE_SIZE, GFP_KERNEL); char *devname, *dummy; int err = 0; if (!page) @@ -633,7 +633,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root) err = PTR_ERR(devname); else seq_escape(m, devname, " \t\n\\"); - free_page((unsigned long)page); + kfree(page); return err; } EXPORT_SYMBOL_GPL(nfs_show_devname); From 7c031f1d478fde2fdb0769ebe76bcaf02749242e Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:18 +0300 Subject: [PATCH 06/17] NFS: remove unused page and page2 in nfs4_replace_transport() Temporary buffers page and page2 allocated by nfs4_replace_transport() and passed to nfs4_try_replacing_one_location() are never used. Remove them and the code that allocates and frees memory for these buffers. Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-6-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/nfs/nfs4namespace.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 14f72baf3b30..2a03f02bba7c 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -481,7 +481,6 @@ int nfs4_submount(struct fs_context *fc, struct nfs_server *server) * Returns zero on success, or a negative errno value. */ static int nfs4_try_replacing_one_location(struct nfs_server *server, - char *page, char *page2, const struct nfs4_fs_location *location) { struct net *net = rpc_net_ns(server->client); @@ -541,21 +540,12 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, int nfs4_replace_transport(struct nfs_server *server, const struct nfs4_fs_locations *locations) { - char *page = NULL, *page2 = NULL; int loc, error; error = -ENOENT; if (locations == NULL || locations->nlocations <= 0) goto out; - error = -ENOMEM; - page = (char *) __get_free_page(GFP_USER); - if (!page) - goto out; - page2 = (char *) __get_free_page(GFP_USER); - if (!page2) - goto out; - for (loc = 0; loc < locations->nlocations; loc++) { const struct nfs4_fs_location *location = &locations->locations[loc]; @@ -564,14 +554,11 @@ int nfs4_replace_transport(struct nfs_server *server, location->rootpath.ncomponents == 0) continue; - error = nfs4_try_replacing_one_location(server, page, - page2, location); + error = nfs4_try_replacing_one_location(server, location); if (error == 0) break; } out: - free_page((unsigned long)page); - free_page((unsigned long)page2); return error; } From 06040e75202d7f4fb6aa8f8daf3ffe5aa3e1c9da Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:19 +0300 Subject: [PATCH 07/17] NFSD: replace __get_free_page() with kmalloc() in nfsd_buffered_readdir() nfsd_buffered_readdir() allocates a staging buffer with __get_free_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-7-275e36a83f0e@kernel.org Acked-by: Jeff Layton Signed-off-by: Christian Brauner (Amutable) --- fs/nfsd/vfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index eafdf7b7890f..c99e54b23cd9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -2407,7 +2407,7 @@ static __be32 nfsd_buffered_readdir(struct file *file, struct svc_fh *fhp, loff_t offset; struct readdir_data buf = { .ctx.actor = nfsd_buffered_filldir, - .dirent = (void *)__get_free_page(GFP_KERNEL) + .dirent = kmalloc(PAGE_SIZE, GFP_KERNEL) }; if (!buf.dirent) @@ -2458,7 +2458,7 @@ static __be32 nfsd_buffered_readdir(struct file *file, struct svc_fh *fhp, offset = vfs_llseek(file, 0, SEEK_CUR); } - free_page((unsigned long)(buf.dirent)); + kfree((buf.dirent)); if (host_err) return nfserrno(host_err); From 02d7d892d26ebbcbc542b9b914522f713ce1735b Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:20 +0300 Subject: [PATCH 08/17] libfs: simple_transaction_get(): replace get_zeroed_page() with kzalloc() simple_transaction_get() allocates memory with get_zeroed_page(). That memory is used as a file local buffer that is accessed using copy_from_user() and simple_read_from_buffer(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of get_zeroed_page() with kzalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-8-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/libfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index 1bbea5e7bae3..80a330c8296f 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1258,7 +1258,7 @@ char *simple_transaction_get(struct file *file, const char __user *buf, size_t s if (size > SIMPLE_TRANSACTION_LIMIT - 1) return ERR_PTR(-EFBIG); - ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL); + ar = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!ar) return ERR_PTR(-ENOMEM); @@ -1267,7 +1267,7 @@ char *simple_transaction_get(struct file *file, const char __user *buf, size_t s /* only one write allowed per open */ if (file->private_data) { spin_unlock(&simple_transaction_lock); - free_page((unsigned long)ar); + kfree(ar); return ERR_PTR(-EBUSY); } @@ -1294,7 +1294,7 @@ EXPORT_SYMBOL(simple_transaction_read); int simple_transaction_release(struct inode *inode, struct file *file) { - free_page((unsigned long)file->private_data); + kfree(file->private_data); return 0; } EXPORT_SYMBOL(simple_transaction_release); From de9f4f0b2c0f31c3a9483dedd0e9bb7dcb409a13 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:21 +0300 Subject: [PATCH 09/17] jfs: replace __get_free_page() with kmalloc() jfs_readdir() allocates dirent_buf with __get_free_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-9-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/jfs/jfs_dtree.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index ac0f79fafaca..8ce6e4458cc2 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -2729,7 +2729,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) struct ldtentry *d; struct dtslot *t; int d_namleft, len, outlen; - unsigned long dirent_buf; + void *dirent_buf; char *name_ptr; u32 dir_index; int do_index = 0; @@ -2884,7 +2884,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) } } - dirent_buf = __get_free_page(GFP_KERNEL); + dirent_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (dirent_buf == 0) { DT_PUTPAGE(mp); jfs_warn("jfs_readdir: __get_free_page failed!"); @@ -2893,7 +2893,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) } while (1) { - jfs_dirent = (struct jfs_dirent *) dirent_buf; + jfs_dirent = dirent_buf; jfs_dirents = 0; overflow = fix_page = 0; @@ -2903,7 +2903,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) if (stbl[i] < 0) { jfs_err("JFS: Invalid stbl[%d] = %d for inode %ld, block = %lld", i, stbl[i], (long)ip->i_ino, (long long)bn); - free_page(dirent_buf); + kfree(dirent_buf); DT_PUTPAGE(mp); return -EIO; } @@ -2911,7 +2911,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) d = (struct ldtentry *) & p->slot[stbl[i]]; if (((long) jfs_dirent + d->namlen + 1) > - (dirent_buf + PAGE_SIZE)) { + ((long)dirent_buf + PAGE_SIZE)) { /* DBCS codepages could overrun dirent_buf */ index = i; overflow = 1; @@ -3014,7 +3014,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) /* unpin previous leaf page */ DT_PUTPAGE(mp); - jfs_dirent = (struct jfs_dirent *) dirent_buf; + jfs_dirent = dirent_buf; while (jfs_dirents--) { ctx->pos = jfs_dirent->position; if (!dir_emit(ctx, jfs_dirent->name, @@ -3037,13 +3037,13 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) DT_GETPAGE(ip, bn, mp, PSIZE, p, rc); if (rc) { - free_page(dirent_buf); + kfree(dirent_buf); return rc; } } out: - free_page(dirent_buf); + kfree(dirent_buf); return rc; } From 2f6702dc6fdcf0ccc85417140e9ee1ce6a64863c Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:22 +0300 Subject: [PATCH 10/17] jbd2: replace __get_free_pages() with kmalloc() jbd2_alloc() falls back from kmem_cache_alloc() to __get_free_pages() for allocations larger than PAGE_SIZE. But kmalloc() can handle such cases with essentially the same fallback. Replace use of __get_free_pages() with kmalloc() and simplify jbd2_free() as both kmem_cache_alloc() and kmalloc() allocations can be freed with kfree(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-10-275e36a83f0e@kernel.org Reviewed-by: Jan Kara Signed-off-by: Christian Brauner (Amutable) --- fs/jbd2/journal.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 4f397fcdb13c..1137b471e490 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -2784,7 +2784,7 @@ void *jbd2_alloc(size_t size, gfp_t flags) if (size < PAGE_SIZE) ptr = kmem_cache_alloc(get_slab(size), flags); else - ptr = (void *)__get_free_pages(flags, get_order(size)); + ptr = kmalloc(size, flags); /* Check alignment; SLUB has gotten this wrong in the past, * and this can lead to user data corruption! */ @@ -2795,10 +2795,7 @@ void *jbd2_alloc(size_t size, gfp_t flags) void jbd2_free(void *ptr, size_t size) { - if (size < PAGE_SIZE) - kmem_cache_free(get_slab(size), ptr); - else - free_pages((unsigned long)ptr, get_order(size)); + kfree(ptr); }; /* From 263873f40e895ed6df7a1bae001f70009f5fa925 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:23 +0300 Subject: [PATCH 11/17] isofs: replace __get_free_page() with kmalloc() isofs_readdir() allocates a temporary buffer with __get_free_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-11-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/isofs/dir.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 2fd9948d606e..6d220eab531e 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -13,6 +13,7 @@ */ #include #include +#include #include "isofs.h" int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode) @@ -255,7 +256,7 @@ static int isofs_readdir(struct file *file, struct dir_context *ctx) struct iso_directory_record *tmpde; struct inode *inode = file_inode(file); - tmpname = (char *)__get_free_page(GFP_KERNEL); + tmpname = kmalloc(PAGE_SIZE, GFP_KERNEL); if (tmpname == NULL) return -ENOMEM; @@ -263,7 +264,7 @@ static int isofs_readdir(struct file *file, struct dir_context *ctx) result = do_isofs_readdir(inode, file, ctx, tmpname, tmpde); - free_page((unsigned long) tmpname); + kfree(tmpname); return result; } From 3db329857c6003bfd0a6cc61d01e0b750fe5d32c Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:24 +0300 Subject: [PATCH 12/17] fuse: replace __get_free_page() with kmalloc() fuse_do_ioctl allocates memory for struct iov array using __get_free_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-12-275e36a83f0e@kernel.org Acked-by: Miklos Szeredi Signed-off-by: Christian Brauner (Amutable) --- fs/fuse/ioctl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c index fdc175e93f74..3614ea603913 100644 --- a/fs/fuse/ioctl.c +++ b/fs/fuse/ioctl.c @@ -10,6 +10,7 @@ #include #include +#include #define FUSE_VERITY_ENABLE_ARG_MAX_PAGES 256 static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args, @@ -252,7 +253,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, err = -ENOMEM; ap.folios = fuse_folios_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.descs); - iov_page = (struct iovec *) __get_free_page(GFP_KERNEL); + iov_page = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!ap.folios || !iov_page) goto out; @@ -400,7 +401,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, } err = 0; out: - free_page((unsigned long) iov_page); + kfree(iov_page); while (ap.num_folios) folio_put(ap.folios[--ap.num_folios]); kfree(ap.folios); From cf080236f386a6c275abb052786e7f5e63799af8 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:25 +0300 Subject: [PATCH 13/17] fs/select: replace __get_free_page() with kmalloc() poll_get_entry() allocates new memory for poll_table entries using __get_free_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-13-275e36a83f0e@kernel.org Reviewed-by: Jan Kara Signed-off-by: Christian Brauner (Amutable) --- fs/select.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/select.c b/fs/select.c index 75978b18f48f..6fa63e48cdee 100644 --- a/fs/select.c +++ b/fs/select.c @@ -150,7 +150,7 @@ void poll_freewait(struct poll_wqueues *pwq) } while (entry > p->entries); old = p; p = p->next; - free_page((unsigned long) old); + kfree(old); } } EXPORT_SYMBOL(poll_freewait); @@ -165,7 +165,7 @@ static struct poll_table_entry *poll_get_entry(struct poll_wqueues *p) if (!table || POLL_TABLE_FULL(table)) { struct poll_table_page *new_table; - new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL); + new_table = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!new_table) { p->error = -ENOMEM; return NULL; From aca4fd395d178b8f811db55797a8b3c773d61538 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:26 +0300 Subject: [PATCH 14/17] fs/namespace: use __getname() to allocate mntpath buffer mnt_warn_timestamp_expiry() allocates memory for a path with __get_free_page() although there is a dedicated helper for allocation of file paths: __getname(). Replace __get_free_page() for allocation of a path buffer with __getname(). Christian Brauner says: Pass PATH_MAX (not PAGE_SIZE) to d_path() to match the size that __getname() actually allocates, and drop the now-unnecessary NULL check around __putname() since __putname() handles NULL. Both per Jan Kara's review feedback, acked by the author. Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-14-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/namespace.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index fe919abd2f01..d67c2f61b3df 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3303,9 +3303,9 @@ static void mnt_warn_timestamp_expiry(const struct path *mountpoint, (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) { char *buf, *mntpath; - buf = (char *)__get_free_page(GFP_KERNEL); + buf = __getname(); if (buf) - mntpath = d_path(mountpoint, buf, PAGE_SIZE); + mntpath = d_path(mountpoint, buf, PATH_MAX); else mntpath = ERR_PTR(-ENOMEM); if (IS_ERR(mntpath)) @@ -3318,8 +3318,7 @@ static void mnt_warn_timestamp_expiry(const struct path *mountpoint, (unsigned long long)sb->s_time_max); sb->s_iflags |= SB_I_TS_EXPIRY_WARNED; - if (buf) - free_page((unsigned long)buf); + __putname(buf); } } From 1b27d11b17b729e12a4abf09031a1aa5cc05d56d Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:27 +0300 Subject: [PATCH 15/17] configfs: replace __get_free_pages() with kzalloc() configfs allocates staging buffers __get_free_pages(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_pages() with kzalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-15-275e36a83f0e@kernel.org Reviewed-by: Jan Kara Signed-off-by: Christian Brauner (Amutable) --- fs/configfs/file.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/configfs/file.c b/fs/configfs/file.c index ef8c3cd10cc6..a48cece775a3 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -59,7 +59,7 @@ static int fill_read_buffer(struct file *file, struct configfs_buffer *buffer) ssize_t count = -ENOENT; if (!buffer->page) - buffer->page = (char *) get_zeroed_page(GFP_KERNEL); + buffer->page = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!buffer->page) return -ENOMEM; @@ -184,7 +184,7 @@ static int fill_write_buffer(struct configfs_buffer *buffer, int copied; if (!buffer->page) - buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0); + buffer->page = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buffer->page) return -ENOMEM; @@ -381,8 +381,7 @@ static int configfs_release(struct inode *inode, struct file *filp) struct configfs_buffer *buffer = filp->private_data; module_put(buffer->owner); - if (buffer->page) - free_page((unsigned long)buffer->page); + kfree(buffer->page); mutex_destroy(&buffer->mutex); kfree(buffer); return 0; From 6ff17653e94d97735d426a4924df7be51fd63abd Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:28 +0300 Subject: [PATCH 16/17] binfmt_misc: replace __get_free_page() with kmalloc() bm_entry_read() allocates temporary buffer using __get_free_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of __get_free_page() with kmalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-16-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/binfmt_misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index b3d8fd70e8b1..84349fcb93f1 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -704,7 +704,7 @@ bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) ssize_t res; char *page; - page = (char *) __get_free_page(GFP_KERNEL); + page = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!page) return -ENOMEM; @@ -712,7 +712,7 @@ bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page)); - free_page((unsigned long) page); + kfree(page); return res; } From c1fe8d334f93ebdba07c8a28c07fbd619e673633 Mon Sep 17 00:00:00 2001 From: "Mike Rapoport (Microsoft)" Date: Sat, 23 May 2026 20:54:29 +0300 Subject: [PATCH 17/17] bfs: replace get_zeroed_page() with kzalloc() bfs_dump_imap() allocates temporary buffer with get_zeroed_page(). kmalloc() is a better API for such use and it also provides better scalability and more debugging possibilities. Replace use of get_zeroed_page() with kzalloc(). Signed-off-by: Mike Rapoport (Microsoft) Link: https://patch.msgid.link/20260523-b4-fs-v1-17-275e36a83f0e@kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/bfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 9c3e90390824..e41efdd35db9 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -311,7 +311,7 @@ void bfs_dump_imap(const char *prefix, struct super_block *s) { #ifdef DEBUG int i; - char *tmpbuf = (char *)get_zeroed_page(GFP_KERNEL); + char *tmpbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!tmpbuf) return; @@ -323,7 +323,7 @@ void bfs_dump_imap(const char *prefix, struct super_block *s) strcat(tmpbuf, "0"); } printf("%s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf); - free_page((unsigned long)tmpbuf); + kfree(tmpbuf); #endif }