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 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/acct.h>
#include <linux/blkdev.h>
......@@ -33,6 +34,7 @@
#include <linux/security.h>
#include <linux/vfs.h>
#include <linux/writeback.h> /* for the emergency remount stuff */
#include <linux/idr.h>
#include <asm/uaccess.h>
......@@ -535,22 +537,26 @@ void emergency_remount(void)
* 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))];
static struct idr unnamed_dev_idr;
static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
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) {
if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0) {
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);
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;
}
......@@ -559,14 +565,20 @@ EXPORT_SYMBOL(set_anon_super);
void kill_anon_super(struct super_block *sb)
{
int slot = MINOR(sb->s_dev);
generic_shutdown_super(sb);
spin_lock(&unnamed_dev_lock);
clear_bit(slot, unnamed_dev_in_use);
idr_remove(&unnamed_dev_idr, slot);
spin_unlock(&unnamed_dev_lock);
}
EXPORT_SYMBOL(kill_anon_super);
void __init unnamed_dev_init(void)
{
idr_init(&unnamed_dev_idr);
}
void kill_litter_super(struct super_block *sb)
{
if (sb->s_root)
......
......@@ -1045,6 +1045,7 @@ struct super_block *sget(struct file_system_type *type,
void *data);
struct super_block *get_sb_pseudo(struct file_system_type *, char *,
struct super_operations *ops, unsigned long);
void unnamed_dev_init(void);
/* Alas, no aliases. Too much hassle with bringing module.h everywhere */
#define fops_get(fops) \
......
......@@ -58,7 +58,7 @@ struct idr {
*/
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);
void idr_remove(struct idr *idp, int id);
void idr_init(struct idr *idp);
......
......@@ -460,6 +460,7 @@ asmlinkage void __init start_kernel(void)
fork_init(num_physpages);
proc_caches_init();
buffer_init();
unnamed_dev_init();
security_scaffolding_startup();
vfs_caches_init(num_physpages);
radix_tree_init();
......
......@@ -426,7 +426,7 @@ sys_timer_create(clockid_t which_clock,
spin_lock_init(&new_timer->it_lock);
do {
if (unlikely(!idr_pre_get(&posix_timers_id))) {
if (unlikely(!idr_pre_get(&posix_timers_id, GFP_KERNEL))) {
error = -EAGAIN;
new_timer->it_id = (timer_t)-1;
goto out;
......
......@@ -62,13 +62,13 @@
* to the rest of the functions. The structure is defined in the
* 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
* following function. It pre allocates enough memory to satisfy the
* worst possible allocation. It can sleep, so must not be called
* with any spinlocks held. If the system is REALLY out of memory
* this function returns 0, other wise 1.
* worst possible allocation. Unless gfp_mask is GFP_ATOMIC, it can
* sleep, so must not be called with any spinlocks held. If the system is
* REALLY out of memory this function returns 0, other wise 1.
* 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)
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) {
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)
return (0);
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