summaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
commit59223edaa18759982db0a8aced0e77457d10c68e (patch)
tree89354903b01fa0a447bffeefe00df3044495db2e /fs/inode.c
parentdb7d4daea91e105e3859cf461d7e53b9b77454b2 (diff)
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/fs/inode.c b/fs/inode.c
index ac1ef535d..88805efe6 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -99,7 +99,7 @@ void __mark_inode_dirty(struct inode *inode)
static void __wait_on_inode(struct inode * inode)
{
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&inode->i_wait, &wait);
repeat:
@@ -126,7 +126,7 @@ static inline void wait_on_inode(struct inode *inode)
static inline void init_once(struct inode * inode)
{
memset(inode, 0, sizeof(*inode));
- init_waitqueue(&inode->i_wait);
+ init_waitqueue_head(&inode->i_wait);
INIT_LIST_HEAD(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_dentry);
sema_init(&inode->i_sem, 1);
@@ -296,6 +296,7 @@ static int invalidate_list(struct list_head *head, struct super_block * sb, stru
INIT_LIST_HEAD(&inode->i_hash);
list_del(&inode->i_list);
list_add(&inode->i_list, dispose);
+ inode->i_state |= I_FREEING;
continue;
}
busy = 1;
@@ -356,6 +357,7 @@ static int free_inodes(void)
list_del(&INODE(tmp)->i_hash);
INIT_LIST_HEAD(&INODE(tmp)->i_hash);
list_add(tmp, freeable);
+ list_entry(tmp, struct inode, i_list)->i_state = I_FREEING;
found = 1;
}
@@ -639,6 +641,43 @@ static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
return tmp & HASH_MASK;
}
+/* Yeah, I know about quadratic hash. Maybe, later. */
+ino_t iunique(struct super_block *sb, ino_t max_reserved)
+{
+ static ino_t counter = 0;
+ struct inode *inode;
+ struct list_head * head;
+ ino_t res;
+ spin_lock(&inode_lock);
+retry:
+ if (counter > max_reserved) {
+ head = inode_hashtable + hash(sb,counter);
+ inode = find_inode(sb, res = counter++, head);
+ if (!inode) {
+ spin_unlock(&inode_lock);
+ return res;
+ }
+ inode->i_count--; /* compensate find_inode() */
+ } else {
+ counter = max_reserved + 1;
+ }
+ goto retry;
+
+}
+
+struct inode *igrab(struct inode *inode)
+{
+ spin_lock(&inode_lock);
+ if (inode->i_state & I_FREEING)
+ inode = NULL;
+ else
+ inode->i_count++;
+ spin_unlock(&inode_lock);
+ if (inode)
+ wait_on_inode(inode);
+ return inode;
+}
+
struct inode *iget(struct super_block *sb, unsigned long ino)
{
struct list_head * head = inode_hashtable + hash(sb,ino);
@@ -692,6 +731,7 @@ void iput(struct inode *inode)
INIT_LIST_HEAD(&inode->i_hash);
list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list);
+ inode->i_state|=I_FREEING;
if (op && op->delete_inode) {
void (*delete)(struct inode *) = op->delete_inode;
spin_unlock(&inode_lock);
@@ -702,6 +742,7 @@ void iput(struct inode *inode)
if (list_empty(&inode->i_hash)) {
list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list);
+ inode->i_state|=I_FREEING;
spin_unlock(&inode_lock);
clear_inode(inode);
spin_lock(&inode_lock);