[PATCH] shmem: add shmem_size option, set filesystem size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Adds a kernel configuration option and command line parameter to
specify the size of the shmem filesystem.  It is currently hard-coded
to 50% of memory.  Users should have the option to set this value as
they see fit.

A specific case where this is necessary would be if the initramfs were
larger than half of the memory, such as a 2.5GB filesystem with 4GB of
memory.  Without this option, this causes a kernel panic.  With this
option, the user may specify something like 75%, which would allow the
filesystem into memory, while still leaving enough resources to run
a functioning system.

This patch creates the SHMEM_SIZE configuration option and the
shmem_size parameter, which may be specified in bytes, human notation
(1G, 100M, etc.) or percentage (75%).  The default remains unchanged.
This patch has no impact unless the values are changed.

Signed-off-by: Gary B. Genett <me@xxxxxxxxxxxxxxx>
---
 Documentation/admin-guide/kernel-parameters.rst |  1 +
 Documentation/admin-guide/kernel-parameters.txt |  5 +++
 init/Kconfig                                    |  8 ++++
 mm/shmem.c                                      | 57 +++++++++++++++++++++++--
 4 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst
index d05d531b4ec9..33122a6df04f 100644
--- a/Documentation/admin-guide/kernel-parameters.rst
+++ b/Documentation/admin-guide/kernel-parameters.rst
@@ -149,6 +149,7 @@ parameter is applicable::
 	APPARMOR AppArmor support is enabled.
 	SERIAL	Serial support is enabled.
 	SH	SuperH architecture is enabled.
+	SHMEM	Full shmem filesystem is enabled.
 	SMP	The kernel is an SMP kernel.
 	SPARC	Sparc architecture is enabled.
 	SWSUSP	Software suspend (hibernation) is enabled.
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index c7ac2f3ac99f..aeac92577569 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4307,6 +4307,11 @@
 	shapers=	[NET]
 			Maximal number of shapers.

+	shmem_size=	[SHMEM]
+			Size of shmem filesystem.  Can be specified as a plain
+			integer, in memory size notation (such as 1024M or 1G),
+			or as a percentage (50%).
+
 	simeth=		[IA-64]
 	simscsi=

diff --git a/init/Kconfig b/init/Kconfig
index b4daad2bac23..7b07f5c448af 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1537,6 +1537,14 @@ config SHMEM
 	  option replaces shmem and tmpfs with the much simpler ramfs code,
 	  which may be appropriate on small systems without swap.

+config SHMEM_SIZE
+	string "Hard-set the shmem filesystem size"
+	default 0
+	depends on SHMEM
+	help
+	  Size of shmem filesystem.  Can be specified as a plain integer, in
+	  memory size notation (such as 1024M or 1G), or as a percentage (50%).
+
 config AIO
 	bool "Enable AIO support" if EXPERT
 	default y
diff --git a/mm/shmem.c b/mm/shmem.c
index cd570cc79c76..ad6109524ad1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -95,6 +95,12 @@ static struct vfsmount *shm_mnt;
 /* Symlink up to this size is kmalloc'ed instead of using a swappable page */
 #define SHORT_SYMLINK_LEN 128

+/* Default size of shmem filesystem (defaults to 50% of memory) */
+#define SHMEM_SIZE_DEFAULT ((totalram_pages * PAGE_SIZE) / 2)
+/* Final initialized size of shmem filesystem, and stored parameter value */
+unsigned long shmem_size_final;
+char shmem_size_param[20];
+
 /*
  * shmem_fallocate communicates with shmem_fault or shmem_writepage via
  * inode->i_private (with i_mutex making sure that it has only one user at
@@ -123,16 +129,56 @@ struct shmem_options {
 };

 #ifdef CONFIG_TMPFS
+static void shmem_size_parse(void)
+{
+	char *str, *t;
+
+	sprintf(shmem_size_param, "%s", "0");
+	str = strstr(boot_command_line, "shmem_size=");
+	if (str) {
+		t = strsep(&str, " ");
+		t += 11;
+		sprintf(shmem_size_param, "%s", t);
+	}
+}
+
+static void shmem_size(char *str, char *val)
+{
+	char *rest;
+	unsigned long mem = memparse(val, &rest);
+
+	if (*rest == '%') {
+		mem *= (totalram_pages * PAGE_SIZE);
+		do_div(mem, 100);
+	}
+	if (mem > 0) {
+		pr_info("shmem: found %s value: %s (%ld pages, %ld bytes)\n",
+			str, val, (mem / PAGE_SIZE), mem);
+		shmem_size_final = (mem / PAGE_SIZE);
+	}
+}
+
+static void shmem_size_init(void)
+{
+	char tmp[20];
+
+	sprintf(tmp, "%ld", SHMEM_SIZE_DEFAULT);
+	shmem_size("default", tmp);
+#ifdef CONFIG_SHMEM_SIZE
+	shmem_size("kernel configuration", CONFIG_SHMEM_SIZE);
+#endif
+	shmem_size_parse();
+	shmem_size("kernel parameter", shmem_size_param);
+}
+
 static unsigned long shmem_default_max_blocks(void)
 {
-	return totalram_pages() / 2;
+	return shmem_size_final;
 }

 static unsigned long shmem_default_max_inodes(void)
 {
-	unsigned long nr_pages = totalram_pages();
-
-	return min(nr_pages - totalhigh_pages(), nr_pages / 2);
+	return min(totalram_pages - totalhigh_pages, shmem_size_final);
 }
 #endif

@@ -3887,6 +3933,9 @@ int __init shmem_init(void)
 {
 	int error;

+#ifdef CONFIG_TMPFS
+	shmem_size_init();
+#endif
 	shmem_init_inodecache();

 	error = register_filesystem(&shmem_fs_type);
--
2.15.2





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux