Commit b75add94 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] remove max_anon limit

From: Tim Hockin <thockin@sun.com>

Remove the max_anon via dynamically allocation.  We also change the
idr_pre_get() interface to take a gfp mask, which should have always been
there.
parent 7de09205
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/acct.h> #include <linux/acct.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/writeback.h> /* for the emergency remount stuff */ #include <linux/writeback.h> /* for the emergency remount stuff */
#include <linux/idr.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -535,22 +537,26 @@ void emergency_remount(void) ...@@ -535,22 +537,26 @@ void emergency_remount(void)
* filesystems which don't use real block-devices. -- jrs * filesystems which don't use real block-devices. -- jrs
*/ */
enum {Max_anon = 256}; static struct idr unnamed_dev_idr;
static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */ static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
int set_anon_super(struct super_block *s, void *data) int set_anon_super(struct super_block *s, void *data)
{ {
int dev; int dev;
spin_lock(&unnamed_dev_lock); spin_lock(&unnamed_dev_lock);
dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon); if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0) {
if (dev == Max_anon) {
spin_unlock(&unnamed_dev_lock); spin_unlock(&unnamed_dev_lock);
return -EMFILE; return -ENOMEM;
} }
set_bit(dev, unnamed_dev_in_use); dev = idr_get_new(&unnamed_dev_idr, NULL);
spin_unlock(&unnamed_dev_lock); spin_unlock(&unnamed_dev_lock);
s->s_dev = MKDEV(0, dev);
if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) {
idr_remove(&unnamed_dev_idr, dev);
return -EMFILE;
}
s->s_dev = MKDEV(0, dev & MINORMASK);
return 0; return 0;
} }
...@@ -559,14 +565,20 @@ EXPORT_SYMBOL(set_anon_super); ...@@ -559,14 +565,20 @@ EXPORT_SYMBOL(set_anon_super);
void kill_anon_super(struct super_block *sb) void kill_anon_super(struct super_block *sb)
{ {
int slot = MINOR(sb->s_dev); int slot = MINOR(sb->s_dev);
generic_shutdown_super(sb); generic_shutdown_super(sb);
spin_lock(&unnamed_dev_lock); spin_lock(&unnamed_dev_lock);
clear_bit(slot, unnamed_dev_in_use); idr_remove(&unnamed_dev_idr, slot);
spin_unlock(&unnamed_dev_lock); spin_unlock(&unnamed_dev_lock);
} }
EXPORT_SYMBOL(kill_anon_super); EXPORT_SYMBOL(kill_anon_super);
void __init unnamed_dev_init(void)
{
idr_init(&unnamed_dev_idr);
}
void kill_litter_super(struct super_block *sb) void kill_litter_super(struct super_block *sb)
{ {
if (sb->s_root) if (sb->s_root)
......
...@@ -1045,6 +1045,7 @@ struct super_block *sget(struct file_system_type *type, ...@@ -1045,6 +1045,7 @@ struct super_block *sget(struct file_system_type *type,
void *data); void *data);
struct super_block *get_sb_pseudo(struct file_system_type *, char *, struct super_block *get_sb_pseudo(struct file_system_type *, char *,
struct super_operations *ops, unsigned long); struct super_operations *ops, unsigned long);
void unnamed_dev_init(void);
/* Alas, no aliases. Too much hassle with bringing module.h everywhere */ /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
#define fops_get(fops) \ #define fops_get(fops) \
......
...@@ -58,7 +58,7 @@ struct idr { ...@@ -58,7 +58,7 @@ struct idr {
*/ */
void *idr_find(struct idr *idp, int id); void *idr_find(struct idr *idp, int id);
int idr_pre_get(struct idr *idp); int idr_pre_get(struct idr *idp, unsigned gfp_mask);
int idr_get_new(struct idr *idp, void *ptr); int idr_get_new(struct idr *idp, void *ptr);
void idr_remove(struct idr *idp, int id); void idr_remove(struct idr *idp, int id);
void idr_init(struct idr *idp); void idr_init(struct idr *idp);
......
...@@ -460,6 +460,7 @@ asmlinkage void __init start_kernel(void) ...@@ -460,6 +460,7 @@ asmlinkage void __init start_kernel(void)
fork_init(num_physpages); fork_init(num_physpages);
proc_caches_init(); proc_caches_init();
buffer_init(); buffer_init();
unnamed_dev_init();
security_scaffolding_startup(); security_scaffolding_startup();
vfs_caches_init(num_physpages); vfs_caches_init(num_physpages);
radix_tree_init(); radix_tree_init();
......
...@@ -426,7 +426,7 @@ sys_timer_create(clockid_t which_clock, ...@@ -426,7 +426,7 @@ sys_timer_create(clockid_t which_clock,
spin_lock_init(&new_timer->it_lock); spin_lock_init(&new_timer->it_lock);
do { do {
if (unlikely(!idr_pre_get(&posix_timers_id))) { if (unlikely(!idr_pre_get(&posix_timers_id, GFP_KERNEL))) {
error = -EAGAIN; error = -EAGAIN;
new_timer->it_id = (timer_t)-1; new_timer->it_id = (timer_t)-1;
goto out; goto out;
......
...@@ -62,13 +62,13 @@ ...@@ -62,13 +62,13 @@
* to the rest of the functions. The structure is defined in the * to the rest of the functions. The structure is defined in the
* header. * header.
* int idr_pre_get(struct idr *idp) * int idr_pre_get(struct idr *idp, unsigned gfp_mask)
* This function should be called prior to locking and calling the * This function should be called prior to locking and calling the
* following function. It pre allocates enough memory to satisfy the * following function. It pre allocates enough memory to satisfy the
* worst possible allocation. It can sleep, so must not be called * worst possible allocation. Unless gfp_mask is GFP_ATOMIC, it can
* with any spinlocks held. If the system is REALLY out of memory * sleep, so must not be called with any spinlocks held. If the system is
* this function returns 0, other wise 1. * REALLY out of memory this function returns 0, other wise 1.
* int idr_get_new(struct idr *idp, void *ptr); * int idr_get_new(struct idr *idp, void *ptr);
...@@ -135,11 +135,11 @@ static inline void free_layer(struct idr *idp, struct idr_layer *p) ...@@ -135,11 +135,11 @@ static inline void free_layer(struct idr *idp, struct idr_layer *p)
spin_unlock(&idp->lock); spin_unlock(&idp->lock);
} }
int idr_pre_get(struct idr *idp) int idr_pre_get(struct idr *idp, unsigned gfp_mask)
{ {
while (idp->id_free_cnt < idp->layers + 1) { while (idp->id_free_cnt < idp->layers + 1) {
struct idr_layer *new; struct idr_layer *new;
new = kmem_cache_alloc(idr_layer_cache, GFP_KERNEL); new = kmem_cache_alloc(idr_layer_cache, gfp_mask);
if(new == NULL) if(new == NULL)
return (0); return (0);
free_layer(idp, new); free_layer(idp, new);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment