From: Tim Hockin <thockin@sun.com>
To: Linux Kernel mailing list <linux-kernel@vger.kernel.org>,
torvalds@osdl.org, akpm@osdl.org, viro@math.psu.edu
Subject: PATCH - raise max_anon limit
Date: Fri, 6 Feb 2004 14:15:45 -0800 [thread overview]
Message-ID: <20040206221545.GD9155@sun.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 326 bytes --]
Attached is a patch to raise the limit of anonymous block devices. The
sysctl allows the admin to set the order of pages allocated for the unnamed
bitmap from 1 page to the full MINORBITS limit.
what think?
Tim
--
Tim Hockin
Sun Microsystems, Linux Software Engineering
thockin@sun.com
All opinions are my own, not Sun's
[-- Attachment #2: max_anon_sysctl-2.6.2-4.diff --]
[-- Type: text/plain, Size: 7245 bytes --]
===== fs/namespace.c 1.52 vs edited =====
--- 1.52/fs/namespace.c Tue Feb 3 21:37:02 2004
+++ edited/fs/namespace.c Thu Feb 5 17:20:55 2004
@@ -25,6 +25,7 @@
extern int __init init_rootfs(void);
extern int __init sysfs_init(void);
+extern void __init max_anon_init(void);
/* spinlock for vfsmount related operations, inplace of dcache_lock */
spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
@@ -1171,6 +1172,7 @@
d++;
i--;
} while (i);
+ max_anon_init();
sysfs_init();
init_rootfs();
init_mount_tree();
===== fs/super.c 1.110 vs edited =====
--- 1.110/fs/super.c Sun Oct 5 01:07:55 2003
+++ edited/fs/super.c Fri Feb 6 12:56:58 2004
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
+#include <linux/init.h>
#include <linux/acct.h>
#include <linux/blkdev.h>
#include <linux/quotaops.h>
@@ -34,6 +35,7 @@
#include <linux/vfs.h>
#include <linux/writeback.h> /* for the emergency remount stuff */
#include <asm/uaccess.h>
+#include <asm/semaphore.h>
void get_filesystem(struct file_system_type *fs);
@@ -535,16 +537,101 @@
* filesystems which don't use real block-devices. -- jrs
*/
-enum {Max_anon = 256};
-static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
+int max_anon_order; /* = 0 */
+static int max_anon;
+static unsigned long *unnamed_dev_in_use;
static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
+static int set_max_anon_order(int old_order, int new_order)
+{
+ unsigned long *new_map;
+ unsigned long *old_map;
+ int new_bytes;
+ int old_bytes;
+
+ /*
+ * you can only raise the order, or we have to handle the case of
+ * having used bits that will not exist after lowering the order
+ */
+ if (new_order < old_order) {
+ /* the sysctl proc_handler has already stored the value */
+ max_anon_order = old_order;
+ return -EINVAL;
+ }
+
+ /*
+ * writing too high a value clamps to the highest value
+ * max order is : 2^MINORBITS / 8 (bits per byte) / 2^PAGE_SHIFT
+ */
+ if (new_order > (MINORBITS - PAGE_SHIFT - 3))
+ new_order = MINORBITS - PAGE_SHIFT - 3;
+
+ if (new_order == old_order)
+ return 0;
+
+ new_map = (unsigned long *)__get_free_pages(GFP_KERNEL, new_order);
+ if (!new_map) {
+ printk(KERN_ERR "Could not allocate new anonymous device map");
+ max_anon_order = old_order;
+ return -ENOMEM;
+ }
+ new_bytes = (1U << new_order) * PAGE_SIZE;
+
+ old_bytes = (1U << old_order) * PAGE_SIZE;
+
+ /* zero and copy old bit array, save the state */
+ memset(new_map, 0, new_bytes);
+ spin_lock(&unnamed_dev_lock);
+ old_map = unnamed_dev_in_use;
+ memcpy(new_map, old_map, old_bytes);
+ unnamed_dev_in_use = new_map;
+ max_anon = new_bytes * 8;
+ spin_unlock(&unnamed_dev_lock);
+ free_pages((unsigned long)old_map, old_order);
+ max_anon_order = new_order;
+
+ return 0;
+}
+
+int max_anon_sysctl_handler(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp)
+{
+ int ret;
+ int old_order;
+ static DECLARE_MUTEX(max_anon_sem);
+
+ down(&max_anon_sem);
+ old_order = max_anon_order;
+ ret = proc_dointvec(table, write, filp, buffer, lenp);
+ if (ret)
+ goto out;
+ if (write)
+ ret = set_max_anon_order(old_order, max_anon_order);
+out:
+ up(&max_anon_sem);
+ return ret;
+}
+
+void __init max_anon_init(void)
+{
+ int new_bytes;
+
+ unnamed_dev_in_use = (unsigned long *)__get_free_pages(GFP_ATOMIC,
+ max_anon_order);
+ if (!unnamed_dev_in_use) {
+ panic("Could not initialize anonymous device map");
+ }
+ new_bytes = (1U << max_anon_order) * PAGE_SIZE;
+ memset(unnamed_dev_in_use, 0, new_bytes);
+ max_anon = new_bytes * 8;
+}
+
int set_anon_super(struct super_block *s, void *data)
{
int dev;
spin_lock(&unnamed_dev_lock);
- dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
- if (dev == Max_anon) {
+ dev = find_first_zero_bit(unnamed_dev_in_use, max_anon);
+ if (dev == max_anon) {
spin_unlock(&unnamed_dev_lock);
return -EMFILE;
}
===== include/linux/fs.h 1.283 vs edited =====
--- 1.283/include/linux/fs.h Mon Jan 19 15:38:10 2004
+++ edited/include/linux/fs.h Thu Feb 5 17:20:55 2004
@@ -19,6 +19,7 @@
#include <linux/cache.h>
#include <linux/radix-tree.h>
#include <linux/kobject.h>
+#include <linux/sysctl.h>
#include <asm/atomic.h>
struct iovec;
@@ -1045,6 +1046,8 @@
void *data);
struct super_block *get_sb_pseudo(struct file_system_type *, char *,
struct super_operations *ops, unsigned long);
+int max_anon_sysctl_handler(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp);
/* Alas, no aliases. Too much hassle with bringing module.h everywhere */
#define fops_get(fops) \
===== include/linux/sysctl.h 1.59 vs edited =====
--- 1.59/include/linux/sysctl.h Sun Feb 1 11:17:41 2004
+++ edited/include/linux/sysctl.h Thu Feb 5 17:20:55 2004
@@ -615,6 +615,7 @@
FS_LEASE_TIME=15, /* int: maximum time to wait for a lease break */
FS_DQSTATS=16, /* disc quota usage statistics */
FS_XFS=17, /* struct: control xfs parameters */
+ FS_MAX_ANON_ORDER=18, /* int: max anonymous blockdevs oreder */
};
/* /proc/sys/fs/quota/ */
===== kernel/sysctl.c 1.59 vs edited =====
--- 1.59/kernel/sysctl.c Tue Feb 3 21:30:55 2004
+++ edited/kernel/sysctl.c Thu Feb 5 17:20:55 2004
@@ -38,6 +38,7 @@
#include <linux/security.h>
#include <linux/initrd.h>
#include <linux/times.h>
+#include <linux/fs.h>
#include <asm/uaccess.h>
#ifdef CONFIG_ROOT_NFS
@@ -63,6 +64,7 @@
extern int min_free_kbytes;
extern int printk_ratelimit_jiffies;
extern int printk_ratelimit_burst;
+extern int max_anon_order;
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535;
@@ -813,6 +815,14 @@
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = FS_MAX_ANON_ORDER,
+ .procname = "max-anon-order",
+ .data = &max_anon_order,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &max_anon_sysctl_handler,
},
{ .ctl_name = 0 }
};
===== Documentation/sysctl/fs.txt 1.2 vs edited =====
--- 1.2/Documentation/sysctl/fs.txt Mon Dec 30 04:29:09 2002
+++ edited/Documentation/sysctl/fs.txt Thu Feb 5 17:31:17 2004
@@ -23,6 +23,7 @@
- inode-max
- inode-nr
- inode-state
+- max-anon-order
- overflowuid
- overflowgid
- super-max
@@ -116,6 +117,19 @@
preshrink is nonzero when the nr_inodes > inode-max and the
system needs to prune the inode list instead of allocating
more.
+
+==============================================================
+
+max-anon-order
+
+Unnamed block devices are dummy devices used by virtual filesystems which
+don't use real block-devices, such as NFS. The maximum number of unnamed
+block devices is controlled by this sysctl value. The value represents a
+power-of-two page size. For example, setting the default order, 0, results
+in 2^0 = 1 page being allocated for the anonymous device bitmap. Setting
+the order to 2 results in 2^2 = 4 pages being allocated for the bitmap.
+Once increased, this value can not be decreased. There is a limit of
+2^MINORBITS bits available at maximum.
==============================================================
next reply other threads:[~2004-02-06 22:16 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-02-06 22:15 Tim Hockin [this message]
2004-02-07 8:55 ` PATCH - raise max_anon limit Andrew Morton
2004-02-07 9:48 ` viro
2004-02-11 20:33 ` Tim Hockin
2004-02-11 20:38 ` Linus Torvalds
2004-02-11 21:09 ` Tim Hockin
2004-02-11 21:53 ` Andrew Morton
2004-02-11 22:28 ` Tim Hockin
2004-02-11 22:48 ` Andrew Morton
[not found] ` <20040211233852.GN9155@sun.com>
[not found] ` <20040211155754.5068332c.akpm@osdl.org>
[not found] ` <20040212003840.GO9155@sun.com>
[not found] ` <20040211164233.5f233595.akpm@osdl.org>
2004-02-12 1:08 ` Tim Hockin
2004-02-12 1:20 ` Andrew Morton
2004-02-12 2:22 ` Tim Hockin
2004-02-12 17:26 ` Jim Houston
2004-02-12 18:49 ` Tim Hockin
2004-02-13 2:01 ` Jamie Lokier
2004-02-12 22:03 ` Andrew Morton
2004-02-13 1:12 ` George Anzinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040206221545.GD9155@sun.com \
--to=thockin@sun.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
--cc=viro@math.psu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox