Re: [PATCH] vmalloc: respect the GFP_NOIO and GFP_NOFS flags

From: Mikulas Patocka
Date: Mon Jul 03 2017 - 18:57:42 EST




On Mon, 3 Jul 2017, Michal Hocko wrote:

> We can add a warning (or move it from kvmalloc) and hope that the
> respective maintainers will fix those places properly. The reason I
> didn't add the warning to vmalloc and kept it in kvmalloc was to catch
> only new users rather than suddenly splat on existing ones. Note that
> there are users with panic_on_warn enabled.
>
> Considering how many NOFS users we have in tree I would rather work with
> maintainers to fix them.

So - do you want this patch?

I still believe that the previous patch that pushes
memalloc_noio/nofs_save into __vmalloc is better than this.

Currently there are 28 __vmalloc callers that use GFP_NOIO or GFP_NOFS,
three of them already use memalloc_noio_save, 25 don't.

Mikulas

---
drivers/block/drbd/drbd_bitmap.c | 8 +++++---
drivers/infiniband/hw/mlx4/qp.c | 21 +++++++++++++++++----
drivers/infiniband/sw/rdmavt/qp.c | 19 +++++++++++++------
drivers/infiniband/ulp/ipoib/ipoib_cm.c | 7 +++++--
drivers/md/dm-bufio.c | 2 +-
drivers/mtd/ubi/io.c | 11 +++++++++--
fs/btrfs/free-space-tree.c | 7 ++++++-
fs/ext4/super.c | 21 +++++++++++++++++----
fs/gfs2/dir.c | 29 +++++++++++++++++++++--------
fs/gfs2/quota.c | 8 ++++++--
fs/nfs/blocklayout/extent_tree.c | 7 ++++++-
fs/ntfs/malloc.h | 11 +++++++++--
fs/ubifs/debug.c | 5 ++++-
fs/ubifs/lprops.c | 5 ++++-
fs/ubifs/lpt_commit.c | 10 ++++++++--
fs/ubifs/orphan.c | 5 ++++-
fs/ubifs/ubifs.h | 1 +
fs/xfs/kmem.c | 2 +-
mm/page_alloc.c | 2 +-
mm/vmalloc.c | 6 ++++++
net/ceph/ceph_common.c | 14 ++++++++++++--
21 files changed, 156 insertions(+), 45 deletions(-)

Index: linux-2.6/drivers/block/drbd/drbd_bitmap.c
===================================================================
--- linux-2.6.orig/drivers/block/drbd/drbd_bitmap.c
+++ linux-2.6/drivers/block/drbd/drbd_bitmap.c
@@ -26,6 +26,7 @@

#include <linux/bitmap.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>
#include <linux/string.h>
#include <linux/drbd.h>
#include <linux/slab.h>
@@ -408,9 +409,10 @@ static struct page **bm_realloc_pages(st
bytes = sizeof(struct page *)*want;
new_pages = kzalloc(bytes, GFP_NOIO | __GFP_NOWARN);
if (!new_pages) {
- new_pages = __vmalloc(bytes,
- GFP_NOIO | __GFP_ZERO,
- PAGE_KERNEL);
+ unsigned noio;
+ noio = memalloc_noio_save();
+ new_pages = vmalloc(bytes);
+ memalloc_noio_restore(noio);
if (!new_pages)
return NULL;
}
Index: linux-2.6/drivers/infiniband/hw/mlx4/qp.c
===================================================================
--- linux-2.6.orig/drivers/infiniband/hw/mlx4/qp.c
+++ linux-2.6/drivers/infiniband/hw/mlx4/qp.c
@@ -37,6 +37,7 @@
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>

#include <rdma/ib_cache.h>
#include <rdma/ib_pack.h>
@@ -814,14 +815,26 @@ static int create_qp_common(struct mlx4_

qp->sq.wrid = kmalloc_array(qp->sq.wqe_cnt, sizeof(u64),
gfp | __GFP_NOWARN);
- if (!qp->sq.wrid)
+ if (!qp->sq.wrid) {
+ unsigned noio;
+ if (!(gfp & __GFP_IO))
+ noio = memalloc_noio_save();
qp->sq.wrid = __vmalloc(qp->sq.wqe_cnt * sizeof(u64),
- gfp, PAGE_KERNEL);
+ gfp | __GFP_FS | __GFP_IO, PAGE_KERNEL);
+ if (!(gfp & __GFP_IO))
+ memalloc_noio_restore(noio);
+ }
qp->rq.wrid = kmalloc_array(qp->rq.wqe_cnt, sizeof(u64),
gfp | __GFP_NOWARN);
- if (!qp->rq.wrid)
+ if (!qp->rq.wrid) {
+ unsigned noio;
+ if (!(gfp & __GFP_IO))
+ noio = memalloc_noio_save();
qp->rq.wrid = __vmalloc(qp->rq.wqe_cnt * sizeof(u64),
- gfp, PAGE_KERNEL);
+ gfp | __GFP_FS | __GFP_IO, PAGE_KERNEL);
+ if (!(gfp & __GFP_IO))
+ memalloc_noio_restore(noio);
+ }
if (!qp->sq.wrid || !qp->rq.wrid) {
err = -ENOMEM;
goto err_wrid;
Index: linux-2.6/drivers/infiniband/sw/rdmavt/qp.c
===================================================================
--- linux-2.6.orig/drivers/infiniband/sw/rdmavt/qp.c
+++ linux-2.6/drivers/infiniband/sw/rdmavt/qp.c
@@ -49,6 +49,7 @@
#include <linux/bitops.h>
#include <linux/lockdep.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>
#include <linux/slab.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_hdrs.h>
@@ -719,11 +720,14 @@ struct ib_qp *rvt_create_qp(struct ib_pd
sz = sizeof(struct rvt_sge) *
init_attr->cap.max_send_sge +
sizeof(struct rvt_swqe);
- if (gfp == GFP_NOIO)
+ if (gfp == GFP_NOIO) {
+ unsigned noio;
+ noio = memalloc_noio_save();
swq = __vmalloc(
sqsize * sz,
- gfp | __GFP_ZERO, PAGE_KERNEL);
- else
+ gfp | __GFP_FS | __GFP_IO | __GFP_ZERO, PAGE_KERNEL);
+ memalloc_noio_restore(noio);
+ } else
swq = vzalloc_node(
sqsize * sz,
rdi->dparms.node);
@@ -786,12 +790,15 @@ struct ib_qp *rvt_create_qp(struct ib_pd
qp->r_rq.wq = vmalloc_user(
sizeof(struct rvt_rwq) +
qp->r_rq.size * sz);
- else if (gfp == GFP_NOIO)
+ else if (gfp == GFP_NOIO) {
+ unsigned noio;
+ noio = memalloc_noio_save();
qp->r_rq.wq = __vmalloc(
sizeof(struct rvt_rwq) +
qp->r_rq.size * sz,
- gfp | __GFP_ZERO, PAGE_KERNEL);
- else
+ GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+ memalloc_noio_restore(noio);
+ } else
qp->r_rq.wq = vzalloc_node(
sizeof(struct rvt_rwq) +
qp->r_rq.size * sz,
Index: linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_cm.c
===================================================================
--- linux-2.6.orig/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>
#include <linux/moduleparam.h>
#include <linux/sched/signal.h>

@@ -1132,9 +1133,11 @@ static int ipoib_cm_tx_init(struct ipoib
{
struct ipoib_dev_priv *priv = ipoib_priv(p->dev);
int ret;
+ unsigned noio;

- p->tx_ring = __vmalloc(ipoib_sendq_size * sizeof *p->tx_ring,
- GFP_NOIO, PAGE_KERNEL);
+ noio = memalloc_noio_save();
+ p->tx_ring = vmalloc(ipoib_sendq_size * sizeof *p->tx_ring);
+ memalloc_noio_restore(noio);
if (!p->tx_ring) {
ret = -ENOMEM;
goto err_tx;
Index: linux-2.6/drivers/mtd/ubi/io.c
===================================================================
--- linux-2.6.orig/drivers/mtd/ubi/io.c
+++ linux-2.6/drivers/mtd/ubi/io.c
@@ -89,6 +89,7 @@
#include <linux/crc32.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/sched/mm.h>
#include "ubi.h"

static int self_check_not_bad(const struct ubi_device *ubi, int pnum);
@@ -1342,11 +1343,14 @@ static int self_check_write(struct ubi_d
size_t read;
void *buf1;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
+ unsigned nofs;

if (!ubi_dbg_chk_io(ubi))
return 0;

- buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ buf1 = vmalloc(len);
+ memalloc_nofs_restore(nofs);
if (!buf1) {
ubi_err(ubi, "cannot allocate memory to check writes");
return 0;
@@ -1406,11 +1410,14 @@ int ubi_self_check_all_ff(struct ubi_dev
int err;
void *buf;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
+ unsigned nofs;

if (!ubi_dbg_chk_io(ubi))
return 0;

- buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ buf = vmalloc(len);
+ memalloc_nofs_restore(nofs);
if (!buf) {
ubi_err(ubi, "cannot allocate memory to check for 0xFFs");
return 0;
Index: linux-2.6/fs/btrfs/free-space-tree.c
===================================================================
--- linux-2.6.orig/fs/btrfs/free-space-tree.c
+++ linux-2.6/fs/btrfs/free-space-tree.c
@@ -18,6 +18,7 @@

#include <linux/kernel.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>
#include "ctree.h"
#include "disk-io.h"
#include "locking.h"
@@ -154,6 +155,7 @@ static inline u32 free_space_bitmap_size
static u8 *alloc_bitmap(u32 bitmap_size)
{
void *mem;
+ unsigned nofs;

/*
* The allocation size varies, observed numbers were < 4K up to 16K.
@@ -167,7 +169,10 @@ static u8 *alloc_bitmap(u32 bitmap_size)
if (mem)
return mem;

- return __vmalloc(bitmap_size, GFP_NOFS | __GFP_ZERO, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ mem = __vmalloc(bitmap_size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+ memalloc_nofs_restore(nofs);
+ return mem;
}

int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
Index: linux-2.6/fs/ext4/super.c
===================================================================
--- linux-2.6.orig/fs/ext4/super.c
+++ linux-2.6/fs/ext4/super.c
@@ -40,6 +40,7 @@
#include <linux/dax.h>
#include <linux/cleancache.h>
#include <linux/uaccess.h>
+#include <linux/sched/mm.h>

#include <linux/kthread.h>
#include <linux/freezer.h>
@@ -185,8 +186,14 @@ void *ext4_kvmalloc(size_t size, gfp_t f
void *ret;

ret = kmalloc(size, flags | __GFP_NOWARN);
- if (!ret)
- ret = __vmalloc(size, flags, PAGE_KERNEL);
+ if (!ret) {
+ unsigned nofs;
+ if (!(flags & __GFP_FS))
+ nofs = memalloc_nofs_save();
+ ret = __vmalloc(size, flags | __GFP_FS, PAGE_KERNEL);
+ if (!(flags & __GFP_FS))
+ memalloc_nofs_restore(nofs);
+ }
return ret;
}

@@ -195,8 +202,14 @@ void *ext4_kvzalloc(size_t size, gfp_t f
void *ret;

ret = kzalloc(size, flags | __GFP_NOWARN);
- if (!ret)
- ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL);
+ if (!ret) {
+ unsigned nofs;
+ if (!(flags & __GFP_FS))
+ nofs = memalloc_nofs_save();
+ ret = __vmalloc(size, flags | __GFP_FS | __GFP_ZERO, PAGE_KERNEL);
+ if (!(flags & __GFP_FS))
+ memalloc_nofs_restore(nofs);
+ }
return ret;
}

Index: linux-2.6/fs/gfs2/dir.c
===================================================================
--- linux-2.6.orig/fs/gfs2/dir.c
+++ linux-2.6/fs/gfs2/dir.c
@@ -62,6 +62,7 @@
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>
#include <linux/bio.h>

#include "gfs2.h"
@@ -360,8 +361,11 @@ static __be64 *gfs2_dir_get_hash_table(s
}

hc = kmalloc(hsize, GFP_NOFS | __GFP_NOWARN);
- if (hc == NULL)
- hc = __vmalloc(hsize, GFP_NOFS, PAGE_KERNEL);
+ if (hc == NULL) {
+ unsigned nofs = memalloc_nofs_save();
+ hc = vmalloc(hsize);
+ memalloc_nofs_restore(nofs);
+ }

if (hc == NULL)
return ERR_PTR(-ENOMEM);
@@ -1172,8 +1176,11 @@ static int dir_double_exhash(struct gfs2
return PTR_ERR(hc);

hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
- if (hc2 == NULL)
- hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL);
+ if (hc2 == NULL) {
+ unsigned nofs = memalloc_nofs_save();
+ hc2 = vmalloc(hsize_bytes * 2);
+ memalloc_nofs_restore(nofs);
+ }

if (!hc2)
return -ENOMEM;
@@ -1333,8 +1340,11 @@ static void *gfs2_alloc_sort_buffer(unsi

if (size < KMALLOC_MAX_SIZE)
ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN);
- if (!ptr)
- ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL);
+ if (!ptr) {
+ unsigned nofs = memalloc_nofs_save();
+ ptr = vmalloc(size);
+ memalloc_nofs_restore(nofs);
+ }
return ptr;
}

@@ -2000,9 +2010,12 @@ static int leaf_dealloc(struct gfs2_inod
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));

ht = kzalloc(size, GFP_NOFS | __GFP_NOWARN);
- if (ht == NULL)
- ht = __vmalloc(size, GFP_NOFS | __GFP_NOWARN | __GFP_ZERO,
+ if (ht == NULL) {
+ unsigned nofs = memalloc_nofs_save();
+ ht = __vmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
PAGE_KERNEL);
+ memalloc_nofs_restore(nofs);
+ }
if (!ht)
return -ENOMEM;

Index: linux-2.6/fs/gfs2/quota.c
===================================================================
--- linux-2.6.orig/fs/gfs2/quota.c
+++ linux-2.6/fs/gfs2/quota.c
@@ -59,6 +59,7 @@
#include <linux/bit_spinlock.h>
#include <linux/jhash.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>

#include "gfs2.h"
#include "incore.h"
@@ -1353,9 +1354,12 @@ int gfs2_quota_init(struct gfs2_sbd *sdp
bm_size *= sizeof(unsigned long);
error = -ENOMEM;
sdp->sd_quota_bitmap = kzalloc(bm_size, GFP_NOFS | __GFP_NOWARN);
- if (sdp->sd_quota_bitmap == NULL)
- sdp->sd_quota_bitmap = __vmalloc(bm_size, GFP_NOFS |
+ if (sdp->sd_quota_bitmap == NULL) {
+ unsigned nofs = memalloc_nofs_save();
+ sdp->sd_quota_bitmap = __vmalloc(bm_size, GFP_KERNEL |
__GFP_ZERO, PAGE_KERNEL);
+ memalloc_nofs_restore(nofs);
+ }
if (!sdp->sd_quota_bitmap)
return error;

Index: linux-2.6/fs/nfs/blocklayout/extent_tree.c
===================================================================
--- linux-2.6.orig/fs/nfs/blocklayout/extent_tree.c
+++ linux-2.6/fs/nfs/blocklayout/extent_tree.c
@@ -3,6 +3,7 @@
*/

#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>

#include "blocklayout.h"

@@ -570,6 +571,8 @@ ext_tree_prepare_commit(struct nfs4_layo
retry:
ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count, &arg->lastbytewritten);
if (unlikely(ret)) {
+ unsigned nofs;
+
ext_tree_free_commitdata(arg, buffer_size);

buffer_size = ext_tree_layoutupdate_size(bl, count);
@@ -581,7 +584,9 @@ retry:
if (!arg->layoutupdate_pages)
return -ENOMEM;

- start_p = __vmalloc(buffer_size, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ start_p = vmalloc(buffer_size);
+ memalloc_nofs_restore(nofs);
if (!start_p) {
kfree(arg->layoutupdate_pages);
return -ENOMEM;
Index: linux-2.6/fs/ntfs/malloc.h
===================================================================
--- linux-2.6.orig/fs/ntfs/malloc.h
+++ linux-2.6/fs/ntfs/malloc.h
@@ -23,6 +23,7 @@
#define _LINUX_NTFS_MALLOC_H

#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>
#include <linux/slab.h>
#include <linux/highmem.h>

@@ -47,8 +48,14 @@ static inline void *__ntfs_malloc(unsign
return kmalloc(PAGE_SIZE, gfp_mask & ~__GFP_HIGHMEM);
/* return (void *)__get_free_page(gfp_mask); */
}
- if (likely((size >> PAGE_SHIFT) < totalram_pages))
- return __vmalloc(size, gfp_mask, PAGE_KERNEL);
+ if (likely((size >> PAGE_SHIFT) < totalram_pages)) {
+ unsigned nofs;
+ if (!(gfp_mask & __GFP_FS))
+ nofs = memalloc_nofs_save();
+ return __vmalloc(size, gfp_mask | __GFP_FS, PAGE_KERNEL);
+ if (!(gfp_mask & __GFP_FS))
+ memalloc_nofs_restore(nofs);
+ }
return NULL;
}

Index: linux-2.6/fs/ubifs/debug.c
===================================================================
--- linux-2.6.orig/fs/ubifs/debug.c
+++ linux-2.6/fs/ubifs/debug.c
@@ -818,10 +818,13 @@ void ubifs_dump_leb(const struct ubifs_i
struct ubifs_scan_leb *sleb;
struct ubifs_scan_node *snod;
void *buf;
+ unsigned nofs;

pr_err("(pid %d) start dumping LEB %d\n", current->pid, lnum);

- buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ buf = vmalloc(c->leb_size);
+ memalloc_nofs_restore(nofs);
if (!buf) {
ubifs_err(c, "cannot allocate memory for dumping LEB %d", lnum);
return;
Index: linux-2.6/fs/ubifs/lprops.c
===================================================================
--- linux-2.6.orig/fs/ubifs/lprops.c
+++ linux-2.6/fs/ubifs/lprops.c
@@ -1034,6 +1034,7 @@ static int scan_check_cb(struct ubifs_in
struct ubifs_scan_node *snod;
int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty, ret;
void *buf = NULL;
+ unsigned nofs;

cat = lp->flags & LPROPS_CAT_MASK;
if (cat != LPROPS_UNCAT) {
@@ -1091,7 +1092,9 @@ static int scan_check_cb(struct ubifs_in
}
}

- buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ buf = vmalloc(c->leb_size);
+ memalloc_nofs_restore(nofs);
if (!buf)
return -ENOMEM;

Index: linux-2.6/fs/ubifs/lpt_commit.c
===================================================================
--- linux-2.6.orig/fs/ubifs/lpt_commit.c
+++ linux-2.6/fs/ubifs/lpt_commit.c
@@ -1630,11 +1630,14 @@ static int dbg_check_ltab_lnum(struct ub
int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
int ret;
void *buf, *p;
+ unsigned nofs;

if (!dbg_is_chk_lprops(c))
return 0;

- buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ buf = p = vmalloc(c->leb_size);
+ memalloc_nofs_restore(nofs);
if (!buf) {
ubifs_err(c, "cannot allocate memory for ltab checking");
return 0;
@@ -1881,9 +1884,12 @@ static void dump_lpt_leb(const struct ub
{
int err, len = c->leb_size, node_type, node_num, node_len, offs;
void *buf, *p;
+ unsigned nofs;

pr_err("(pid %d) start dumping LEB %d\n", current->pid, lnum);
- buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ buf = p = vmalloc(c->leb_size);
+ memalloc_nofs_restore(nofs);
if (!buf) {
ubifs_err(c, "cannot allocate memory to dump LPT");
return;
Index: linux-2.6/fs/ubifs/orphan.c
===================================================================
--- linux-2.6.orig/fs/ubifs/orphan.c
+++ linux-2.6/fs/ubifs/orphan.c
@@ -880,12 +880,15 @@ static int dbg_scan_orphans(struct ubifs
{
int lnum, err = 0;
void *buf;
+ unsigned nofs;

/* Check no-orphans flag and skip this if no orphans */
if (c->no_orphs)
return 0;

- buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
+ nofs = memalloc_nofs_save();
+ buf = vmalloc(c->leb_size);
+ memalloc_nofs_restore(nofs);
if (!buf) {
ubifs_err(c, "cannot allocate memory to check orphans");
return 0;
Index: linux-2.6/mm/vmalloc.c
===================================================================
--- linux-2.6.orig/mm/vmalloc.c
+++ linux-2.6/mm/vmalloc.c
@@ -1671,6 +1671,12 @@ static void *__vmalloc_area_node(struct
const gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO;
const gfp_t alloc_mask = gfp_mask | __GFP_HIGHMEM | __GFP_NOWARN;

+ /*
+ * vmalloc uses GFP_KERNEL for some internal allocations (e.g page tables)
+ * so the given set of flags has to be compatible.
+ */
+ WARN_ON_ONCE((gfp_mask & GFP_KERNEL) != GFP_KERNEL);
+
nr_pages = get_vm_area_size(area) >> PAGE_SHIFT;
array_size = (nr_pages * sizeof(struct page *));

Index: linux-2.6/net/ceph/ceph_common.c
===================================================================
--- linux-2.6.orig/net/ceph/ceph_common.c
+++ linux-2.6/net/ceph/ceph_common.c
@@ -17,6 +17,7 @@
#include <linux/statfs.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>


#include <linux/ceph/ceph_features.h>
@@ -179,13 +180,22 @@ EXPORT_SYMBOL(ceph_compare_options);

void *ceph_kvmalloc(size_t size, gfp_t flags)
{
+ void *ptr;
+ unsigned noio;
+
if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
- void *ptr = kmalloc(size, flags | __GFP_NOWARN);
+ ptr = kmalloc(size, flags | __GFP_NOWARN);
if (ptr)
return ptr;
}

- return __vmalloc(size, flags, PAGE_KERNEL);
+ if ((flags & (__GFP_FS | __GFP_IO)) != (__GFP_FS | __GFP_IO))
+ noio = memalloc_noio_save();
+ ptr = __vmalloc(size, flags | __GFP_FS | __GFP_IO, PAGE_KERNEL);
+ if ((flags & (__GFP_FS | __GFP_IO)) != (__GFP_FS | __GFP_IO))
+ memalloc_noio_restore(noio);
+
+ return ptr;
}


Index: linux-2.6/mm/page_alloc.c
===================================================================
--- linux-2.6.orig/mm/page_alloc.c
+++ linux-2.6/mm/page_alloc.c
@@ -7249,7 +7249,7 @@ void *__init alloc_large_system_hash(con
if (flags & HASH_EARLY)
table = memblock_virt_alloc_nopanic(size, 0);
else if (hashdist)
- table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
+ table = vmalloc(size);
else {
/*
* If bucketsize is not a power-of-two, we may free
Index: linux-2.6/drivers/md/dm-bufio.c
===================================================================
--- linux-2.6.orig/drivers/md/dm-bufio.c
+++ linux-2.6/drivers/md/dm-bufio.c
@@ -406,7 +406,7 @@ static void *alloc_buffer_data(struct dm
if (gfp_mask & __GFP_NORETRY)
noio_flag = memalloc_noio_save();

- ptr = __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
+ ptr = __vmalloc(c->block_size, gfp_mask | __GFP_FS | __GFP_IO, PAGE_KERNEL);

if (gfp_mask & __GFP_NORETRY)
memalloc_noio_restore(noio_flag);
Index: linux-2.6/fs/xfs/kmem.c
===================================================================
--- linux-2.6.orig/fs/xfs/kmem.c
+++ linux-2.6/fs/xfs/kmem.c
@@ -67,7 +67,7 @@ kmem_zalloc_large(size_t size, xfs_km_fl
nofs_flag = memalloc_nofs_save();

lflags = kmem_flags_convert(flags);
- ptr = __vmalloc(size, lflags | __GFP_ZERO, PAGE_KERNEL);
+ ptr = __vmalloc(size, lflags | __GFP_FS | __GFP_IO | __GFP_ZERO, PAGE_KERNEL);

if (flags & KM_NOFS)
memalloc_nofs_restore(nofs_flag);
Index: linux-2.6/fs/ubifs/ubifs.h
===================================================================
--- linux-2.6.orig/fs/ubifs/ubifs.h
+++ linux-2.6/fs/ubifs/ubifs.h
@@ -30,6 +30,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/sched/mm.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>