patch-2.4.3 linux/fs/dcache.c
Next file: linux/fs/efs/super.c
Previous file: linux/fs/cramfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 148
- Date:
Wed Mar 7 16:53:48 2001
- Orig file:
v2.4.2/linux/fs/dcache.c
- Orig date:
Wed Feb 21 18:20:38 2001
diff -u --recursive --new-file v2.4.2/linux/fs/dcache.c linux/fs/dcache.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/cache.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
@@ -223,8 +224,7 @@
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 */
+ list_del_init(&dentry->d_lru);
}
return dentry;
}
@@ -413,8 +413,7 @@
if (atomic_read(&dentry->d_count))
continue;
dentry_stat.nr_unused--;
- list_del(tmp);
- INIT_LIST_HEAD(tmp);
+ list_del_init(tmp);
prune_one_dentry(dentry);
goto repeat;
}
@@ -656,6 +655,7 @@
void d_instantiate(struct dentry *entry, struct inode * inode)
{
+ if (!list_empty(&entry->d_alias)) BUG();
spin_lock(&dcache_lock);
if (inode)
list_add(&entry->d_alias, &inode->i_dentry);
@@ -744,58 +744,48 @@
/**
* d_validate - verify dentry provided from insecure source
- * @dentry: The dentry alleged to be valid
- * @dparent: The parent dentry
+ * @dentry: The dentry alleged to be valid child of @dparent
+ * @dparent: The parent dentry (known to be valid)
* @hash: Hash of the dentry
* @len: Length of the name
*
* An insecure source has sent us a dentry, here we verify it and dget() it.
* This is used by ncpfs in its readdir implementation.
* Zero is returned in the dentry is invalid.
- *
- * NOTE: This function does _not_ dereference the pointers before we have
- * validated them. We can test the pointer values, but we
- * must not actually use them until we have found a valid
- * copy of the pointer in kernel space..
*/
-int d_validate(struct dentry *dentry, struct dentry *dparent,
- unsigned int hash, unsigned int len)
+int d_validate(struct dentry *dentry, struct dentry *dparent)
{
+ unsigned long dent_addr = (unsigned long) dentry;
+ unsigned long min_addr = PAGE_OFFSET;
+ unsigned long align_mask = 0x0F;
struct list_head *base, *lhp;
- int valid = 1;
- spin_lock(&dcache_lock);
- if (dentry != dparent) {
- base = d_hash(dparent, hash);
- lhp = base;
- while ((lhp = lhp->next) != base) {
- if (dentry == list_entry(lhp, struct dentry, d_hash)) {
- __dget_locked(dentry);
- goto out;
- }
- }
- } else {
- /*
- * Special case: local mount points don't live in
- * the hashes, so we search the super blocks.
- */
- struct super_block *sb = sb_entry(super_blocks.next);
+ if (dent_addr < min_addr)
+ goto out;
+ if (dent_addr > (unsigned long)high_memory - sizeof(struct dentry))
+ goto out;
+ if (dent_addr & align_mask)
+ goto out;
+ if ((!kern_addr_valid(dent_addr)) || (!kern_addr_valid(dent_addr -1 +
+ sizeof(struct dentry))))
+ goto out;
- for (; sb != sb_entry(&super_blocks);
- sb = sb_entry(sb->s_list.next)) {
- if (!sb->s_dev)
- continue;
- if (sb->s_root == dentry) {
- __dget_locked(dentry);
- goto out;
- }
+ if (dentry->d_parent != dparent)
+ goto out;
+
+ spin_lock(&dcache_lock);
+ lhp = base = d_hash(dparent, dentry->d_name.hash);
+ while ((lhp = lhp->next) != base) {
+ if (dentry == list_entry(lhp, struct dentry, d_hash)) {
+ __dget_locked(dentry);
+ spin_unlock(&dcache_lock);
+ return 1;
}
}
- valid = 0;
-out:
spin_unlock(&dcache_lock);
- return valid;
+out:
+ return 0;
}
/*
@@ -848,6 +838,7 @@
void d_rehash(struct dentry * entry)
{
struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
+ if (!list_empty(&entry->d_hash)) BUG();
spin_lock(&dcache_lock);
list_add(&entry->d_hash, list);
spin_unlock(&dcache_lock);
@@ -922,8 +913,7 @@
list_add(&dentry->d_hash, &target->d_hash);
/* Unhash the target: dput() will then get rid of it */
- list_del(&target->d_hash);
- INIT_LIST_HEAD(&target->d_hash);
+ list_del_init(&target->d_hash);
list_del(&dentry->d_child);
list_del(&target->d_child);
@@ -1250,6 +1240,7 @@
/* SLAB cache for buffer_head structures */
kmem_cache_t *bh_cachep;
+EXPORT_SYMBOL(bh_cachep);
void __init vfs_caches_init(unsigned long mempages)
{
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)