patch-2.3.47 linux/fs/inode.c
Next file: linux/fs/lockd/Makefile
Previous file: linux/fs/ext2/inode.c
Back to the patch index
Back to the overall index
- Lines: 144
- Date:
Sun Feb 20 20:51:56 2000
- Orig file:
v2.3.46/linux/fs/inode.c
- Orig date:
Sun Feb 13 19:29:04 2000
diff -u --recursive --new-file v2.3.46/linux/fs/inode.c linux/fs/inode.c
@@ -156,11 +156,26 @@
inode->i_sb->s_op->write_inode(inode);
}
+static inline void __iget(struct inode * inode)
+{
+ if (!inode->i_count++)
+ {
+ if (!(inode->i_state & I_DIRTY))
+ {
+ list_del(&inode->i_list);
+ list_add(&inode->i_list, &inode_in_use);
+ }
+ inodes_stat.nr_unused--;
+ }
+}
+
static inline void sync_one(struct inode *inode)
{
if (inode->i_state & I_LOCK) {
+ __iget(inode);
spin_unlock(&inode_lock);
__wait_on_inode(inode);
+ iput(inode);
spin_lock(&inode_lock);
} else {
list_del(&inode->i_list);
@@ -253,6 +268,8 @@
BUG();
if (!(inode->i_state & I_FREEING))
BUG();
+ if (inode->i_state & I_CLEAR)
+ BUG();
wait_on_inode(inode);
if (IS_QUOTAINIT(inode))
DQUOT_DROP(inode);
@@ -262,7 +279,7 @@
bdput(inode->i_bdev);
inode->i_bdev = NULL;
}
- inode->i_state = 0;
+ inode->i_state = I_CLEAR;
}
/*
@@ -377,6 +394,8 @@
entry = entry->prev;
inode = INODE(tmp);
+ if (inode->i_state & (I_FREEING|I_CLEAR))
+ BUG();
if (!CAN_UNUSE(inode))
continue;
if (inode->i_count)
@@ -413,19 +432,6 @@
return 0;
}
-static inline void __iget(struct inode * inode)
-{
- if (!inode->i_count++)
- {
- if (!(inode->i_state & I_DIRTY))
- {
- list_del(&inode->i_list);
- list_add(&inode->i_list, &inode_in_use);
- }
- inodes_stat.nr_unused--;
- }
-}
-
/*
* Called with the inode lock held.
* NOTE: we are not increasing the inode-refcount, you must call __iget()
@@ -603,6 +609,11 @@
if (!(inode->i_state & I_FREEING))
__iget(inode);
else
+ /*
+ * Handle the case where s_op->clear_inode is not been
+ * called yet, and somebody is calling igrab
+ * while the inode is getting freed.
+ */
inode = NULL;
spin_unlock(&inode_lock);
if (inode)
@@ -669,32 +680,39 @@
list_del(&inode->i_list);
INIT_LIST_HEAD(&inode->i_list);
inode->i_state|=I_FREEING;
+ spin_unlock(&inode_lock);
+
+ destroy = 1;
if (op && op->delete_inode) {
void (*delete)(struct inode *) = op->delete_inode;
- spin_unlock(&inode_lock);
if (inode->i_data.nrpages)
truncate_inode_pages(&inode->i_data, 0);
+ /* s_op->delete_inode internally recalls clear_inode() */
delete(inode);
- spin_lock(&inode_lock);
- }
- }
- 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);
- destroy = 1;
+ } else
+ clear_inode(inode);
+ if (inode->i_state != I_CLEAR)
+ BUG();
+
spin_lock(&inode_lock);
- }
- else
- {
- if (!(inode->i_state & I_DIRTY)) {
+ } 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 */
list_del(&inode->i_list);
- list_add(&inode->i_list,
- &inode_unused);
+ INIT_LIST_HEAD(&inode->i_list);
+ inode->i_state|=I_FREEING;
+ spin_unlock(&inode_lock);
+ clear_inode(inode);
+ destroy = 1;
+ spin_lock(&inode_lock);
}
- inodes_stat.nr_unused++;
}
#ifdef INODE_PARANOIA
if (inode->i_flock)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)