Commit 201f4698 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.45pre3

parent 2730f0af
...@@ -29,19 +29,12 @@ ...@@ -29,19 +29,12 @@
#define D_HASHBITS 10 #define D_HASHBITS 10
#define D_HASHSIZE (1UL << D_HASHBITS) #define D_HASHSIZE (1UL << D_HASHBITS)
#define D_HASHMASK (D_HASHSIZE-1) #define D_HASHMASK (D_HASHSIZE-1)
struct list_head dentry_hashtable[D_HASHSIZE];
void d_free(struct dentry *dentry) static struct list_head dentry_hashtable[D_HASHSIZE];
{ static LIST_HEAD(dentry_unused);
if (dentry) {
kfree(dentry->d_name.name);
kfree(dentry);
}
}
void dput(struct dentry *dentry) void dput(struct dentry *dentry)
{ {
repeat:
if (dentry) { if (dentry) {
dentry->d_count--; dentry->d_count--;
if (dentry->d_count < 0) { if (dentry->d_count < 0) {
...@@ -49,67 +42,120 @@ void dput(struct dentry *dentry) ...@@ -49,67 +42,120 @@ void dput(struct dentry *dentry)
dentry->d_count, dentry->d_name.name); dentry->d_count, dentry->d_name.name);
return; return;
} }
/* if (!dentry->d_count) {
* This is broken right now: we should really put list_del(&dentry->d_lru);
* the dentry on a free list to be reclaimed later list_add(&dentry->d_lru, &dentry_unused);
* when we think we should throw it away. }
}
}
void d_free(struct dentry *dentry)
{
kfree(dentry->d_name.name);
kfree(dentry);
}
/*
* Note! This tries to free the last entry on the dentry
* LRU list. The dentries are put on the LRU list when
* they are free'd, but that doesn't actually mean that
* all LRU entries have d_count == 0 - it might have been
* re-allocated. If so we delete it from the LRU list
* here.
* *
* Instead we free it completely if the inode count * Rationale:
* indicates that we're the only ones holding onto * - keep "dget()" extremely simple
* the inode - if not we just fall back on the old * - if there have been a lot of lookups in the LRU list
* (broken) behaviour of not reclaiming it at all. * we want to make freeing more unlikely anyway, and
* keeping used dentries on the LRU list in that case
* will make the algorithm less likely to free an entry.
*/ */
if (!dentry->d_count && (!dentry->d_inode || atomic_read(&dentry->d_inode->i_count) == 1)) { static inline struct dentry * free_one_dentry(struct dentry * dentry)
struct dentry *parent = dentry->d_parent; {
struct dentry * parent;
list_del(&dentry->d_hash);
parent = dentry->d_parent;
if (parent != dentry)
dput(parent);
return dentry;
}
if (parent != dentry) { static inline struct dentry * try_free_one_dentry(struct dentry * dentry)
{
struct inode * inode = dentry->d_inode; struct inode * inode = dentry->d_inode;
if (inode) { if (inode) {
list_del(&dentry->d_list); if (atomic_read(&inode->i_count) != 1) {
list_add(&dentry->d_lru, &dentry_unused);
return NULL;
}
list_del(&dentry->d_alias);
iput(inode); iput(inode);
dentry->d_inode = NULL; dentry->d_inode = NULL;
} }
list_del(&dentry->d_hash); return free_one_dentry(dentry);
d_free(dentry); }
dentry = parent;
goto repeat; static struct dentry * try_free_dentries(void)
} {
} struct list_head * tmp = dentry_unused.next;
if (tmp != &dentry_unused) {
struct dentry * dentry;
list_del(tmp);
dentry = list_entry(tmp, struct dentry, d_lru);
if (dentry->d_count == 0)
return try_free_one_dentry(dentry);
} }
return NULL;
} }
#define NAME_ALLOC_LEN(len) ((len+16) & ~15) #define NAME_ALLOC_LEN(len) ((len+16) & ~15)
struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
{ {
char *str; int len;
struct dentry *res; char * str;
struct dentry *dentry;
res = kmalloc(sizeof(struct dentry), GFP_KERNEL); dentry = try_free_dentries();
if (!res) len = NAME_ALLOC_LEN(name->len);
if (dentry) {
str = (char *) dentry->d_name.name;
if (len == NAME_ALLOC_LEN(dentry->d_name.len))
goto right_size;
kfree(dentry->d_name.name);
} else {
dentry = kmalloc(sizeof(struct dentry), GFP_KERNEL);
if (!dentry)
return NULL; return NULL;
}
str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL); str = kmalloc(len, GFP_KERNEL);
if (!str) { if (!str) {
kfree(res); kfree(dentry);
return NULL; return NULL;
} }
right_size:
len = name->len;
memcpy(str, name->name, len);
str[len] = 0;
memcpy(str, name->name, name->len); dentry->d_count = 0;
str[name->len] = 0; dentry->d_flags = 0;
dentry->d_inode = NULL;
memset(res, 0, sizeof(struct dentry)); dentry->d_parent = parent;
dentry->d_mounts = dentry;
res->d_parent = parent; dentry->d_covers = dentry;
res->d_mounts = res; INIT_LIST_HEAD(&dentry->d_hash);
res->d_covers = res; INIT_LIST_HEAD(&dentry->d_alias);
res->d_flags = 0; INIT_LIST_HEAD(&dentry->d_lru);
res->d_name.name = str; dentry->d_name.name = str;
res->d_name.len = name->len; dentry->d_name.len = name->len;
res->d_name.hash = name->hash; dentry->d_name.hash = name->hash;
return res; return dentry;
} }
/* /*
...@@ -125,7 +171,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) ...@@ -125,7 +171,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
void d_instantiate(struct dentry *entry, struct inode * inode) void d_instantiate(struct dentry *entry, struct inode * inode)
{ {
if (inode) if (inode)
list_add(&entry->d_list, &inode->i_dentry); list_add(&entry->d_alias, &inode->i_dentry);
entry->d_inode = inode; entry->d_inode = inode;
} }
...@@ -137,6 +183,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root) ...@@ -137,6 +183,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root)
if (root_inode) { if (root_inode) {
res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 }); res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });
res->d_parent = res; res->d_parent = res;
res->d_count = 2;
d_instantiate(res, root_inode); d_instantiate(res, root_inode);
} }
return res; return res;
......
...@@ -38,10 +38,10 @@ ...@@ -38,10 +38,10 @@
* for low-overhead inode sync() operations. * for low-overhead inode sync() operations.
*/ */
LIST_HEAD(inode_in_use); static LIST_HEAD(inode_in_use);
LIST_HEAD(inode_dirty); static LIST_HEAD(inode_dirty);
LIST_HEAD(inode_unused); static LIST_HEAD(inode_unused);
struct list_head inode_hashtable[HASH_SIZE]; static struct list_head inode_hashtable[HASH_SIZE];
/* /*
* A simple spinlock to protect the list manipulations * A simple spinlock to protect the list manipulations
......
...@@ -588,8 +588,8 @@ static void d_mount(struct dentry *covers, struct dentry *dentry) ...@@ -588,8 +588,8 @@ static void d_mount(struct dentry *covers, struct dentry *dentry)
printk("VFS: mount - already mounted\n"); printk("VFS: mount - already mounted\n");
return; return;
} }
covers->d_mounts = dentry; covers->d_mounts = dget(dentry);
dentry->d_covers = covers; dentry->d_covers = dget(covers);
} }
static int do_umount(kdev_t dev,int unmount_root) static int do_umount(kdev_t dev,int unmount_root)
......
...@@ -45,8 +45,9 @@ struct dentry { ...@@ -45,8 +45,9 @@ struct dentry {
struct dentry * d_parent; /* parent directory */ struct dentry * d_parent; /* parent directory */
struct dentry * d_mounts; /* mount information */ struct dentry * d_mounts; /* mount information */
struct dentry * d_covers; struct dentry * d_covers;
struct list_head d_list; /* hardlink aliasname / empty list */ struct list_head d_hash; /* lookup hash list */
struct list_head d_hash; struct list_head d_alias; /* inode alias list */
struct list_head d_lru; /* d_count = 0 LRU list */
struct qstr d_name; struct qstr d_name;
}; };
...@@ -97,9 +98,9 @@ extern void dput(struct dentry *); ...@@ -97,9 +98,9 @@ extern void dput(struct dentry *);
/* /*
* This is ugly. The inode:dentry relationship is a 1:n * This is ugly. The inode:dentry relationship is a 1:n
* relationship, so we have to return one (random) dentry * relationship, so we have to return one (random) dentry
* from the list. We select the first one.. * from the alias list. We select the first one..
*/ */
#define i_dentry(inode) \ #define i_dentry(inode) \
list_entry((inode)->i_dentry.next, struct dentry, d_list) list_entry((inode)->i_dentry.next, struct dentry, d_alias)
#endif /* __LINUX_DCACHE_H */ #endif /* __LINUX_DCACHE_H */
...@@ -368,8 +368,11 @@ static inline void close_files(struct files_struct * files) ...@@ -368,8 +368,11 @@ static inline void close_files(struct files_struct * files)
break; break;
while (set) { while (set) {
if (set & 1) { if (set & 1) {
close_fp(files->fd[i]); struct file * file = files->fd[i];
if (file) {
files->fd[i] = NULL; files->fd[i] = NULL;
close_fp(file);
}
} }
i++; i++;
set >>= 1; set >>= 1;
......
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