From 493c987f7a352ca64fdb4dc03a21e24cbaf46f55 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 9 Jul 2000 02:54:55 +0000 Subject: Merge with Linux 2.4.0-pre3-test6. --- fs/binfmt_aout.c | 30 +++++++++++----- fs/dcache.c | 86 +++++++++++++++++++++++--------------------- fs/file.c | 18 +++------- fs/inode.c | 102 +++++++++++++++++++++------------------------------- fs/namei.c | 18 ++++++++++ fs/open.c | 1 + fs/proc/proc_misc.c | 20 +++++------ 7 files changed, 140 insertions(+), 135 deletions(-) (limited to 'fs') 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 */ -#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 #include #include #include @@ -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 #include #include +#include #include 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; + } + } } -- cgit v1.2.3