summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-06-07 13:43:19 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-08-09 16:48:35 -0400
commit45321ac54316eaeeebde0b5f728a1791e500974c (patch)
treec3989dd1a8b4a50168d696aa608941de88da9ade /fs
parent30140837f256558c943636245ab90897a9455a70 (diff)
downloadlwn-45321ac54316eaeeebde0b5f728a1791e500974c.tar.gz
lwn-45321ac54316eaeeebde0b5f728a1791e500974c.zip
Make ->drop_inode() just return whether inode needs to be dropped
... and let iput_final() do the actual eviction or retention Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/inode.c11
-rw-r--r--fs/cifs/cifsfs.c9
-rw-r--r--fs/gfs2/super.c4
-rw-r--r--fs/inode.c113
-rw-r--r--fs/logfs/inode.c4
-rw-r--r--fs/ocfs2/inode.c8
-rw-r--r--fs/ocfs2/inode.h2
8 files changed, 55 insertions, 98 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 394d5422ab6a..eaf286abad17 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2395,7 +2395,7 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
void btrfs_dirty_inode(struct inode *inode);
struct inode *btrfs_alloc_inode(struct super_block *sb);
void btrfs_destroy_inode(struct inode *inode);
-void btrfs_drop_inode(struct inode *inode);
+int btrfs_drop_inode(struct inode *inode);
int btrfs_init_cachep(void);
void btrfs_destroy_cachep(void);
long btrfs_ioctl_trans_end(struct file *file);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index ce02199ec4e5..2c54f04a0bf5 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3943,7 +3943,7 @@ again:
if (atomic_read(&inode->i_count) > 1)
d_prune_aliases(inode);
/*
- * btrfs_drop_inode will remove it from
+ * btrfs_drop_inode will have it removed from
* the inode cache when its usage count
* hits zero.
*/
@@ -6337,13 +6337,14 @@ free:
kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
}
-void btrfs_drop_inode(struct inode *inode)
+int btrfs_drop_inode(struct inode *inode)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
- if (inode->i_nlink > 0 && btrfs_root_refs(&root->root_item) == 0)
- generic_delete_inode(inode);
+
+ if (btrfs_root_refs(&root->root_item) == 0)
+ return 1;
else
- generic_drop_inode(inode);
+ return generic_drop_inode(inode);
}
static void init_once(void *foo)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 8a2cf129e535..20914f5627dd 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -480,14 +480,13 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-void cifs_drop_inode(struct inode *inode)
+static int cifs_drop_inode(struct inode *inode)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
- return generic_drop_inode(inode);
-
- return generic_delete_inode(inode);
+ /* no serverino => unconditional eviction */
+ return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
+ generic_drop_inode(inode);
}
static const struct super_operations cifs_super_ops = {
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 555f5a417c67..fa865ab37f12 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1191,7 +1191,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
* node for later deallocation.
*/
-static void gfs2_drop_inode(struct inode *inode)
+static int gfs2_drop_inode(struct inode *inode)
{
struct gfs2_inode *ip = GFS2_I(inode);
@@ -1200,7 +1200,7 @@ static void gfs2_drop_inode(struct inode *inode)
if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
clear_nlink(inode);
}
- generic_drop_inode(inode);
+ return generic_drop_inode(inode);
}
static int is_ancestor(const struct dentry *d1, const struct dentry *d2)
diff --git a/fs/inode.c b/fs/inode.c
index 82ca3562a688..0e077619cbf6 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1183,58 +1183,51 @@ void remove_inode_hash(struct inode *inode)
}
EXPORT_SYMBOL(remove_inode_hash);
+int generic_delete_inode(struct inode *inode)
+{
+ return 1;
+}
+EXPORT_SYMBOL(generic_delete_inode);
+
/*
- * Tell the filesystem that this inode is no longer of any interest and should
- * be completely destroyed.
- *
- * We leave the inode in the inode hash table until *after* the filesystem's
- * ->delete_inode completes. This ensures that an iget (such as nfsd might
- * instigate) will always find up-to-date information either in the hash or on
- * disk.
- *
- * I_FREEING is set so that no-one will take a new reference to the inode while
- * it is being deleted.
+ * Normal UNIX filesystem behaviour: delete the
+ * inode when the usage count drops to zero, and
+ * i_nlink is zero.
*/
-void generic_delete_inode(struct inode *inode)
+int generic_drop_inode(struct inode *inode)
{
- list_del_init(&inode->i_list);
- list_del_init(&inode->i_sb_list);
- WARN_ON(inode->i_state & I_NEW);
- inode->i_state |= I_FREEING;
- inodes_stat.nr_inodes--;
- spin_unlock(&inode_lock);
-
- evict(inode);
-
- spin_lock(&inode_lock);
- hlist_del_init(&inode->i_hash);
- spin_unlock(&inode_lock);
- wake_up_inode(inode);
- BUG_ON(inode->i_state != (I_FREEING | I_CLEAR));
- destroy_inode(inode);
+ return !inode->i_nlink || hlist_unhashed(&inode->i_hash);
}
-EXPORT_SYMBOL(generic_delete_inode);
+EXPORT_SYMBOL_GPL(generic_drop_inode);
-/**
- * generic_detach_inode - remove inode from inode lists
- * @inode: inode to remove
- *
- * Remove inode from inode lists, write it if it's dirty. This is just an
- * internal VFS helper exported for hugetlbfs. Do not use!
+/*
+ * Called when we're dropping the last reference
+ * to an inode.
*
- * Returns 1 if inode should be completely destroyed.
+ * Call the FS "drop_inode()" function, defaulting to
+ * the legacy UNIX filesystem behaviour. If it tells
+ * us to evict inode, do so. Otherwise, retain inode
+ * in cache if fs is alive, sync and evict if fs is
+ * shutting down.
*/
-static int generic_detach_inode(struct inode *inode)
+static void iput_final(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
+ const struct super_operations *op = inode->i_sb->s_op;
+ int drop;
+
+ if (op && op->drop_inode)
+ drop = op->drop_inode(inode);
+ else
+ drop = generic_drop_inode(inode);
- if (!hlist_unhashed(&inode->i_hash)) {
+ if (!drop) {
if (!(inode->i_state & (I_DIRTY|I_SYNC)))
list_move(&inode->i_list, &inode_unused);
inodes_stat.nr_unused++;
if (sb->s_flags & MS_ACTIVE) {
spin_unlock(&inode_lock);
- return 0;
+ return;
}
WARN_ON(inode->i_state & I_NEW);
inode->i_state |= I_WILL_FREE;
@@ -1252,53 +1245,15 @@ static int generic_detach_inode(struct inode *inode)
inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
- return 1;
-}
-
-static void generic_forget_inode(struct inode *inode)
-{
- if (!generic_detach_inode(inode))
- return;
evict(inode);
+ spin_lock(&inode_lock);
+ hlist_del_init(&inode->i_hash);
+ spin_unlock(&inode_lock);
wake_up_inode(inode);
+ BUG_ON(inode->i_state != (I_FREEING | I_CLEAR));
destroy_inode(inode);
}
-/*
- * Normal UNIX filesystem behaviour: delete the
- * inode when the usage count drops to zero, and
- * i_nlink is zero.
- */
-void generic_drop_inode(struct inode *inode)
-{
- if (!inode->i_nlink)
- generic_delete_inode(inode);
- else
- generic_forget_inode(inode);
-}
-EXPORT_SYMBOL_GPL(generic_drop_inode);
-
-/*
- * Called when we're dropping the last reference
- * to an inode.
- *
- * Call the FS "drop()" function, defaulting to
- * the legacy UNIX filesystem behaviour..
- *
- * NOTE! NOTE! NOTE! We're called with the inode lock
- * held, and the drop function is supposed to release
- * the lock!
- */
-static inline void iput_final(struct inode *inode)
-{
- const struct super_operations *op = inode->i_sb->s_op;
- void (*drop)(struct inode *) = generic_drop_inode;
-
- if (op && op->drop_inode)
- drop = op->drop_inode;
- drop(inode);
-}
-
/**
* iput - put an inode
* @inode: inode to put
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index 78be674d95c8..d8c71ece098f 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -287,7 +287,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
}
/* called with inode_lock held */
-static void logfs_drop_inode(struct inode *inode)
+static int logfs_drop_inode(struct inode *inode)
{
struct logfs_super *super = logfs_super(inode->i_sb);
struct logfs_inode *li = logfs_inode(inode);
@@ -295,7 +295,7 @@ static void logfs_drop_inode(struct inode *inode)
spin_lock(&logfs_inode_lock);
list_move(&li->li_freeing_list, &super->s_freeing_list);
spin_unlock(&logfs_inode_lock);
- generic_drop_inode(inode);
+ return generic_drop_inode(inode);
}
static void logfs_set_ino_generation(struct super_block *sb,
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index eb7fd07c90f2..0492464916b1 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -1194,9 +1194,10 @@ void ocfs2_evict_inode(struct inode *inode)
/* Called under inode_lock, with no more references on the
* struct inode, so it's safe here to check the flags field
* and to manipulate i_nlink without any other locks. */
-void ocfs2_drop_inode(struct inode *inode)
+int ocfs2_drop_inode(struct inode *inode)
{
struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ int res;
mlog_entry_void();
@@ -1204,11 +1205,12 @@ void ocfs2_drop_inode(struct inode *inode)
(unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags);
if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)
- generic_delete_inode(inode);
+ res = 1;
else
- generic_drop_inode(inode);
+ res = generic_drop_inode(inode);
mlog_exit_void();
+ return res;
}
/*
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 975eedd7b243..6de5a869db30 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -124,7 +124,7 @@ static inline struct ocfs2_caching_info *INODE_CACHE(struct inode *inode)
}
void ocfs2_evict_inode(struct inode *inode);
-void ocfs2_drop_inode(struct inode *inode);
+int ocfs2_drop_inode(struct inode *inode);
/* Flags for ocfs2_iget() */
#define OCFS2_FI_FLAG_SYSFILE 0x1