summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-09 02:54:55 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-09 02:54:55 +0000
commit493c987f7a352ca64fdb4dc03a21e24cbaf46f55 (patch)
tree184cddc0925e082c0500afd042f92e9f340fe890 /fs
parent2d25612a92c62b5708d6d43f38d28c6141173328 (diff)
Merge with Linux 2.4.0-pre3-test6.
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_aout.c30
-rw-r--r--fs/dcache.c86
-rw-r--r--fs/file.c18
-rw-r--r--fs/inode.c102
-rw-r--r--fs/namei.c18
-rw-r--r--fs/open.c1
-rw-r--r--fs/proc/proc_misc.c20
7 files changed, 140 insertions, 135 deletions
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index ade9091a5..b16b0db6a 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -321,21 +321,33 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
#endif
if (N_MAGIC(ex) == OMAGIC) {
+ unsigned long text_addr, map_size;
loff_t pos;
+
+ text_addr = N_TXTADDR(ex);
+
#if defined(__alpha__) || defined(__sparc__)
pos = fd_offset;
- do_brk(N_TXTADDR(ex) & PAGE_MASK,
- ex.a_text+ex.a_data + PAGE_SIZE - 1);
- bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
- ex.a_text+ex.a_data, &pos);
+ map_size = ex.a_text+ex.a_data + PAGE_SIZE - 1;
#else
pos = 32;
- do_brk(0, ex.a_text+ex.a_data);
- bprm->file->f_op->read(bprm->file, (char *) 0,
- ex.a_text+ex.a_data, &pos);
+ map_size = ex.a_text+ex.a_data;
#endif
- flush_icache_range((unsigned long) 0,
- (unsigned long) ex.a_text+ex.a_data);
+
+ error = do_brk(text_addr & PAGE_MASK, map_size);
+ if (error != (text_addr & PAGE_MASK)) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+ }
+
+ error = bprm->file->f_op->read(bprm->file, (char *)text_addr,
+ ex.a_text+ex.a_data, &pos);
+ if (error < 0) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+ }
+
+ flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
} else {
static unsigned long error_time, error_time2;
if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
diff --git a/fs/dcache.c b/fs/dcache.c
index c0c94ff1e..1841eef97 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -33,7 +33,7 @@ spinlock_t dcache_lock = SPIN_LOCK_UNLOCKED;
/* Right now the dcache depends on the kernel lock */
#define check_lock() if (!kernel_locked()) BUG()
-kmem_cache_t *dentry_cache;
+static kmem_cache_t *dentry_cache;
/*
* This is the single most critical data structure when it comes
@@ -67,6 +67,7 @@ static inline void d_free(struct dentry *dentry)
if (dname_external(dentry))
kfree(dentry->d_name.name);
kmem_cache_free(dentry_cache, dentry);
+ dentry_stat.nr_dentry--;
}
/*
@@ -117,58 +118,54 @@ static inline void dentry_iput(struct dentry * dentry)
* they too may now get deleted.
*
* no dcache lock, please.
- *
- * Note: dput() itself is inlined and uses __dput() for slow path (after
- * decrementing the ->d_count on the argument and finding it zero).
*/
-void __dput(struct dentry *dentry)
+void dput(struct dentry *dentry)
{
- struct dentry * parent;
+ if (!dentry)
+ return;
+
repeat:
- spin_lock(&dcache_lock);
- if (atomic_read(&dentry->d_count))
- goto out;
+ if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
+ return;
+
+ /* dput on a free dentry? */
+ if (!list_empty(&dentry->d_lru))
+ BUG();
/*
* AV: ->d_delete() is _NOT_ allowed to block now.
*/
if (dentry->d_op && dentry->d_op->d_delete) {
- if (dentry->d_op->d_delete(dentry)) {
- list_del(&dentry->d_hash);
- goto kill_it;
- }
+ if (dentry->d_op->d_delete(dentry))
+ goto unhash_it;
}
+ /* Unreachable? Get rid of it */
if (list_empty(&dentry->d_hash))
goto kill_it;
- if (!list_empty(&dentry->d_lru)) {
- dentry_stat.nr_unused--;
- list_del(&dentry->d_lru);
- }
list_add(&dentry->d_lru, &dentry_unused);
dentry_stat.nr_unused++;
/*
* Update the timestamp
*/
dentry->d_reftime = jiffies;
-
-out:
spin_unlock(&dcache_lock);
return;
-kill_it:
- if (!list_empty(&dentry->d_lru)) {
- dentry_stat.nr_unused--;
- list_del(&dentry->d_lru);
- }
- list_del(&dentry->d_child);
- /* drops the lock, at that point nobody can reach this dentry */
- dentry_iput(dentry);
- parent = dentry->d_parent;
- d_free(dentry);
- if (dentry == parent)
- return;
- dentry = parent;
- if (atomic_dec_and_test(&dentry->d_count))
+
+unhash_it:
+ list_del(&dentry->d_hash);
+
+kill_it: {
+ struct dentry *parent;
+ list_del(&dentry->d_child);
+ /* drops the lock, at that point nobody can reach this dentry */
+ dentry_iput(dentry);
+ parent = dentry->d_parent;
+ d_free(dentry);
+ if (dentry == parent)
+ return;
+ dentry = parent;
goto repeat;
+ }
}
/**
@@ -329,11 +326,14 @@ void prune_dcache(int count)
list_del(tmp);
INIT_LIST_HEAD(tmp);
dentry = list_entry(tmp, struct dentry, d_lru);
- if (!atomic_read(&dentry->d_count)) {
- prune_one_dentry(dentry);
- if (!--count)
- break;
- }
+
+ /* Unused dentry with a count? */
+ if (atomic_read(&dentry->d_count))
+ BUG();
+
+ prune_one_dentry(dentry);
+ if (!--count)
+ break;
}
spin_unlock(&dcache_lock);
}
@@ -539,7 +539,7 @@ int shrink_dcache_memory(int priority, unsigned int gfp_mask)
{
int count = 0;
if (priority)
- count = dentry_stat.nr_unused / priority;
+ count = dentry_stat.nr_unused >> (priority >> 2);
prune_dcache(count);
/* FIXME: kmem_cache_shrink here should tell us
the number of pages freed, and it should
@@ -608,6 +608,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
} else
INIT_LIST_HEAD(&dentry->d_child);
+ dentry_stat.nr_dentry++;
return dentry;
}
@@ -705,7 +706,12 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
if (memcmp(dentry->d_name.name, str, len))
continue;
}
- dget(dentry);
+ atomic_inc(&dentry->d_count);
+ if (atomic_read(&dentry->d_count) == 1) {
+ dentry_stat.nr_unused--;
+ list_del(&dentry->d_lru);
+ INIT_LIST_HEAD(&dentry->d_lru); /* make "list_empty()" work */
+ }
spin_unlock(&dcache_lock);
return dentry;
}
diff --git a/fs/file.c b/fs/file.c
index 7bdf29179..2f8ea1918 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -24,11 +24,9 @@ struct file ** alloc_fd_array(int num)
struct file **new_fds;
int size = num * sizeof(struct file *);
- if (size < PAGE_SIZE)
+ if (size <= PAGE_SIZE)
new_fds = (struct file **) kmalloc(size, GFP_KERNEL);
- else if (size == PAGE_SIZE)
- new_fds = (struct file **) __get_free_page(GFP_KERNEL);
- else
+ else
new_fds = (struct file **) vmalloc(size);
return new_fds;
}
@@ -44,10 +42,8 @@ void free_fd_array(struct file **array, int num)
if (num <= NR_OPEN_DEFAULT) /* Don't free the embedded fd array! */
return;
- else if (size < PAGE_SIZE)
+ else if (size <= PAGE_SIZE)
kfree(array);
- else if (size == PAGE_SIZE)
- free_page((unsigned long) array);
else
vfree(array);
}
@@ -137,10 +133,8 @@ fd_set * alloc_fdset(int num)
fd_set *new_fdset;
int size = num / 8;
- if (size < PAGE_SIZE)
+ if (size <= PAGE_SIZE)
new_fdset = (fd_set *) kmalloc(size, GFP_KERNEL);
- else if (size == PAGE_SIZE)
- new_fdset = (fd_set *) __get_free_page(GFP_KERNEL);
else
new_fdset = (fd_set *) vmalloc(size);
return new_fdset;
@@ -157,10 +151,8 @@ void free_fdset(fd_set *array, int num)
if (num <= __FD_SETSIZE) /* Don't free an embedded fdset */
return;
- else if (size < PAGE_SIZE)
+ else if (size <= PAGE_SIZE)
kfree(array);
- else if (size == PAGE_SIZE)
- free_page((unsigned long) array);
else
vfree(array);
}
diff --git a/fs/inode.c b/fs/inode.c
index 3dbd9f54e..28fbd0098 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -26,7 +26,7 @@
/* inode dynamic allocation 1999, Andrea Arcangeli <andrea@suse.de> */
-#define INODE_PARANOIA 1
+/* #define INODE_PARANOIA 1 */
/* #define INODE_DEBUG 1 */
/*
@@ -327,6 +327,7 @@ static void dispose_list(struct list_head * head)
truncate_inode_pages(&inode->i_data, 0);
clear_inode(inode);
destroy_inode(inode);
+ inodes_stat.nr_inodes--;
}
}
@@ -548,6 +549,7 @@ struct inode * get_empty_inode(void)
if (inode)
{
spin_lock(&inode_lock);
+ inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
inode->i_sb = NULL;
inode->i_dev = 0;
@@ -579,6 +581,7 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s
/* We released the lock, so.. */
old = find_inode(sb, ino, head, find_actor, opaque);
if (!old) {
+ inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head);
inode->i_sb = sb;
@@ -752,78 +755,55 @@ void iput(struct inode *inode)
{
if (inode) {
struct super_operations *op = NULL;
- int destroy = 0;
if (inode->i_sb && inode->i_sb->s_op)
op = inode->i_sb->s_op;
if (op && op->put_inode)
op->put_inode(inode);
- spin_lock(&inode_lock);
- if (atomic_dec_and_test(&inode->i_count)) {
- if (!inode->i_nlink) {
- list_del(&inode->i_hash);
- INIT_LIST_HEAD(&inode->i_hash);
- list_del(&inode->i_list);
- INIT_LIST_HEAD(&inode->i_list);
- inode->i_state|=I_FREEING;
- spin_unlock(&inode_lock);
-
- if (inode->i_data.nrpages)
- truncate_inode_pages(&inode->i_data, 0);
+ if (!atomic_dec_and_lock(&inode->i_count, &inode_lock))
+ return;
- destroy = 1;
- if (op && op->delete_inode) {
- void (*delete)(struct inode *) = op->delete_inode;
- /* s_op->delete_inode internally recalls clear_inode() */
- delete(inode);
- } else
- clear_inode(inode);
- if (inode->i_state != I_CLEAR)
- BUG();
+ if (!inode->i_nlink) {
+ list_del(&inode->i_hash);
+ INIT_LIST_HEAD(&inode->i_hash);
+ list_del(&inode->i_list);
+ INIT_LIST_HEAD(&inode->i_list);
+ inode->i_state|=I_FREEING;
+ spin_unlock(&inode_lock);
- spin_lock(&inode_lock);
- } else {
- if (!list_empty(&inode->i_hash)) {
- if (!(inode->i_state & I_DIRTY)) {
- list_del(&inode->i_list);
- list_add(&inode->i_list,
- &inode_unused);
- }
- inodes_stat.nr_unused++;
- } else {
- /* magic nfs path */
+ if (inode->i_data.nrpages)
+ truncate_inode_pages(&inode->i_data, 0);
+
+ if (op && op->delete_inode) {
+ void (*delete)(struct inode *) = op->delete_inode;
+ /* s_op->delete_inode internally recalls clear_inode() */
+ delete(inode);
+ } else
+ clear_inode(inode);
+ if (inode->i_state != I_CLEAR)
+ BUG();
+ } else {
+ if (!list_empty(&inode->i_hash)) {
+ if (!(inode->i_state & I_DIRTY)) {
list_del(&inode->i_list);
- INIT_LIST_HEAD(&inode->i_list);
- inode->i_state|=I_FREEING;
- spin_unlock(&inode_lock);
- clear_inode(inode);
- destroy = 1;
- spin_lock(&inode_lock);
+ list_add(&inode->i_list,
+ &inode_unused);
}
+ inodes_stat.nr_unused++;
+ spin_unlock(&inode_lock);
+ return;
+ } else {
+ /* magic nfs path */
+ list_del(&inode->i_list);
+ INIT_LIST_HEAD(&inode->i_list);
+ inode->i_state|=I_FREEING;
+ spin_unlock(&inode_lock);
+ clear_inode(inode);
}
-#ifdef INODE_PARANOIA
-if (inode->i_flock)
-printk(KERN_ERR "iput: inode %s/%ld still has locks!\n",
-kdevname(inode->i_dev), inode->i_ino);
-if (!list_empty(&inode->i_dentry))
-printk(KERN_ERR "iput: device %s inode %ld still has aliases!\n",
-kdevname(inode->i_dev), inode->i_ino);
-if (atomic_read(&inode->i_count))
-printk(KERN_ERR "iput: device %s inode %ld count changed, count=%d\n",
-kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_count));
-if (atomic_read(&inode->i_sem.count) != 1)
-printk(KERN_ERR "iput: Aieee, semaphore in use inode %s/%ld, count=%d\n",
-kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count));
-#endif
- }
- if ((unsigned)atomic_read(&inode->i_count) > (1U<<31)) {
- printk(KERN_ERR "iput: inode %s/%ld count wrapped\n",
- kdevname(inode->i_dev), inode->i_ino);
}
- spin_unlock(&inode_lock);
- if (destroy)
- destroy_inode(inode);
+ inodes_stat.nr_inodes--;
+ destroy_inode(inode);
}
}
diff --git a/fs/namei.c b/fs/namei.c
index cba4fb775..3ac2602dc 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -14,6 +14,7 @@
/* [Feb-Apr 2000, AV] Rewrite to the new namespace architecture.
*/
+#include <linux/init.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/smp_lock.h>
@@ -1951,3 +1952,20 @@ struct inode_operations page_symlink_inode_operations = {
readlink: page_readlink,
follow_link: page_follow_link,
};
+
+/* SLAB cache for name blocks */
+kmem_cache_t *names_cachep;
+
+static int __init namecache_init(void)
+{
+ names_cachep = kmem_cache_create("names_cache",
+ PAGE_SIZE,
+ 0,
+ SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (!names_cachep)
+ panic("Cannot create names cache");
+ return 0;
+}
+
+module_init(namecache_init)
diff --git a/fs/open.c b/fs/open.c
index 2968decf9..70a3d199d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -11,6 +11,7 @@
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <asm/uaccess.h>
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 9afe2d67c..5937878c9 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -508,18 +508,6 @@ static int swaps_read_proc(char *page, char **start, off_t off,
return len;
}
-static int slabinfo_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len = get_slabinfo(page);
- if (len <= off+count) *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
- return len;
-}
-
static int memory_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -671,4 +659,12 @@ void __init proc_misc_init(void)
entry->proc_fops = &ppc_htab_operations;
}
#endif
+ {
+ struct proc_dir_entry *res = create_proc_entry("slabinfo",
+ S_IWUSR | S_IRUGO, NULL);
+ if (res) {
+ res->read_proc = slabinfo_read_proc;
+ res->write_proc = slabinfo_write_proc;
+ }
+ }
}