Skip to content

Commit c5e8843

Browse files
mcgrofBrian Maly
authored andcommitted
shmem: add support to ignore swap
In doing experimentations with shmem having the option to avoid swap becomes a useful mechanism. One of the *raves* about brd over shmem is you can avoid swap, but that's not really a good reason to use brd if we can instead use shmem. Using brd has its own good reasons to exist, but just because "tmpfs" doesn't let you do that is not a great reason to avoid it if we can easily add support for it. I don't add support for reconfiguring incompatible options, but if we really wanted to we can add support for that. To avoid swap we use mapping_set_unevictable() upon inode creation, and put a WARN_ON_ONCE() stop-gap on writepages() for reclaim. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Luis Chamberlain <[email protected]> Acked-by: Christian Brauner <[email protected]> Tested-by: Xin Hao <[email protected]> Reviewed-by: Davidlohr Bueso <[email protected]> Cc: Adam Manzanares <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Davidlohr Bueso <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Kees Cook <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Pankaj Raghav <[email protected]> Cc: Yosry Ahmed <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit 2c6efe9) Orabug: 38034039 Conflicts: Documentation/mm/unevictable-lru.rst - handle rename from Documentation/vm/unevictable-lru.rst Reviewed-by: Anthony Yznaga <[email protected]> Reviewed-by: Junxiao Bi <[email protected]> Signed-off-by: Stephen Brennan <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent 7fb6eca commit c5e8843

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

Documentation/filesystems/tmpfs.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ everything stored therein is lost.
1313

1414
tmpfs puts everything into the kernel internal caches and grows and
1515
shrinks to accommodate the files it contains and is able to swap
16-
unneeded pages out to swap space, and supports THP.
16+
unneeded pages out to swap space, if swap was enabled for the tmpfs
17+
mount. tmpfs also supports THP.
1718

1819
tmpfs extends ramfs with a few userspace configurable options listed and
1920
explained further below, some of which can be reconfigured dynamically on the
@@ -33,8 +34,8 @@ configured in size at initialization and you cannot dynamically resize them.
3334
Contrary to brd ramdisks, tmpfs has its own filesystem, it does not rely on the
3435
block layer at all.
3536

36-
Since tmpfs lives completely in the page cache and on swap, all tmpfs
37-
pages will be shown as "Shmem" in /proc/meminfo and "Shared" in
37+
Since tmpfs lives completely in the page cache and optionally on swap,
38+
all tmpfs pages will be shown as "Shmem" in /proc/meminfo and "Shared" in
3839
free(1). Notice that these counters also include shared memory
3940
(shmem, see ipcs(1)). The most reliable way to get the count is
4041
using df(1) and du(1).
@@ -83,6 +84,8 @@ nr_inodes The maximum number of inodes for this instance. The default
8384
is half of the number of your physical RAM pages, or (on a
8485
machine with highmem) the number of lowmem RAM pages,
8586
whichever is the lower.
87+
noswap Disables swap. Remounts must respect the original settings.
88+
By default swap is enabled.
8689
========= ============================================================
8790

8891
These parameters accept a suffix k, m or g for kilo, mega and giga and

Documentation/vm/unevictable-lru.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ The unevictable list addresses the following classes of unevictable pages:
4444

4545
* Those owned by ramfs.
4646

47+
* Those owned by tmpfs with the noswap mount option.
48+
4749
* Those mapped into SHM_LOCK'd shared memory regions.
4850

4951
* Those mapped into VM_LOCKED [mlock()ed] VMAs.

include/linux/shmem_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct shmem_sb_info {
3838
kuid_t uid; /* Mount uid for root directory */
3939
kgid_t gid; /* Mount gid for root directory */
4040
bool full_inums; /* If i_ino should be uint or ino_t */
41+
bool noswap; /* ignores VM reclaim / swap requests */
4142
ino_t next_ino; /* The next per-sb inode number to use */
4243
ino_t __percpu *ino_batch; /* The next per-cpu inode number to use */
4344
struct mempolicy *mpol; /* default memory policy for mappings */

mm/shmem.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,12 @@ struct shmem_options {
116116
bool full_inums;
117117
int huge;
118118
int seen;
119+
bool noswap;
119120
#define SHMEM_SEEN_BLOCKS 1
120121
#define SHMEM_SEEN_INODES 2
121122
#define SHMEM_SEEN_HUGE 4
122123
#define SHMEM_SEEN_INUMS 8
124+
#define SHMEM_SEEN_NOSWAP 16
123125
};
124126

125127
#ifdef CONFIG_TMPFS
@@ -1346,6 +1348,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
13461348
struct address_space *mapping = page->mapping;
13471349
struct inode *inode = mapping->host;
13481350
struct shmem_inode_info *info = SHMEM_I(inode);
1351+
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
13491352
swp_entry_t swap;
13501353
pgoff_t index;
13511354

@@ -1359,7 +1362,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
13591362
if (WARN_ON_ONCE(!wbc->for_reclaim))
13601363
goto redirty;
13611364

1362-
if (WARN_ON_ONCE(info->flags & VM_LOCKED))
1365+
if (WARN_ON_ONCE((info->flags & VM_LOCKED) || sbinfo->noswap))
13631366
goto redirty;
13641367

13651368
if (!total_swap_pages)
@@ -2298,6 +2301,8 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
22982301
info->flags = flags & VM_NORESERVE;
22992302
INIT_LIST_HEAD(&info->shrinklist);
23002303
INIT_LIST_HEAD(&info->swaplist);
2304+
if (sbinfo->noswap)
2305+
mapping_set_unevictable(inode->i_mapping);
23012306
simple_xattrs_init(&info->xattrs);
23022307
cache_no_acl(inode);
23032308

@@ -3356,6 +3361,7 @@ enum shmem_param {
33563361
Opt_uid,
33573362
Opt_inode32,
33583363
Opt_inode64,
3364+
Opt_noswap,
33593365
};
33603366

33613367
static const struct constant_table shmem_param_enums_huge[] = {
@@ -3377,6 +3383,7 @@ const struct fs_parameter_spec shmem_fs_parameters[] = {
33773383
fsparam_u32 ("uid", Opt_uid),
33783384
fsparam_flag ("inode32", Opt_inode32),
33793385
fsparam_flag ("inode64", Opt_inode64),
3386+
fsparam_flag ("noswap", Opt_noswap),
33803387
{}
33813388
};
33823389

@@ -3480,6 +3487,10 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
34803487
ctx->full_inums = true;
34813488
ctx->seen |= SHMEM_SEEN_INUMS;
34823489
break;
3490+
case Opt_noswap:
3491+
ctx->noswap = true;
3492+
ctx->seen |= SHMEM_SEEN_NOSWAP;
3493+
break;
34833494
}
34843495
return 0;
34853496

@@ -3577,6 +3588,14 @@ static int shmem_reconfigure(struct fs_context *fc)
35773588
err = "Current inum too high to switch to 32-bit inums";
35783589
goto out;
35793590
}
3591+
if ((ctx->seen & SHMEM_SEEN_NOSWAP) && ctx->noswap && !sbinfo->noswap) {
3592+
err = "Cannot disable swap on remount";
3593+
goto out;
3594+
}
3595+
if (!(ctx->seen & SHMEM_SEEN_NOSWAP) && !ctx->noswap && sbinfo->noswap) {
3596+
err = "Cannot enable swap on remount if it was disabled on first mount";
3597+
goto out;
3598+
}
35803599

35813600
if (ctx->seen & SHMEM_SEEN_HUGE)
35823601
sbinfo->huge = ctx->huge;
@@ -3597,6 +3616,10 @@ static int shmem_reconfigure(struct fs_context *fc)
35973616
sbinfo->mpol = ctx->mpol; /* transfers initial ref */
35983617
ctx->mpol = NULL;
35993618
}
3619+
3620+
if (ctx->noswap)
3621+
sbinfo->noswap = true;
3622+
36003623
raw_spin_unlock(&sbinfo->stat_lock);
36013624
mpol_put(mpol);
36023625
return 0;
@@ -3651,6 +3674,8 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root)
36513674
seq_printf(seq, ",huge=%s", shmem_format_huge(sbinfo->huge));
36523675
#endif
36533676
shmem_show_mpol(seq, sbinfo->mpol);
3677+
if (sbinfo->noswap)
3678+
seq_printf(seq, ",noswap");
36543679
return 0;
36553680
}
36563681

@@ -3694,6 +3719,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
36943719
ctx->inodes = shmem_default_max_inodes();
36953720
if (!(ctx->seen & SHMEM_SEEN_INUMS))
36963721
ctx->full_inums = IS_ENABLED(CONFIG_TMPFS_INODE64);
3722+
sbinfo->noswap = ctx->noswap;
36973723
} else {
36983724
sb->s_flags |= SB_NOUSER;
36993725
}

0 commit comments

Comments
 (0)