From: Al Viro <viro@ZenIV.linux.org.uk>
To: linux-fsdevel@vger.kernel.org
Subject: [PATCH 55/58][v2] Make ->drop_inode() just return whether inode needs to be dropped
Date: Wed, 9 Jun 2010 02:47:32 +0100 [thread overview]
Message-ID: <20100609014732.GU31073@ZenIV.linux.org.uk> (raw)
In-Reply-To: <E1OM7DH-0004g8-Gp@ZenIV.linux.org.uk>
[v2:clean btrfs part of that a bit]
... and let iput_final() do the actual eviction or retention
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index e818f53..d32726d 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -1232,7 +1232,7 @@ static void pohmelfs_drop_inode(struct inode *inode)
list_del_init(&pi->inode_entry);
spin_unlock(&psb->ino_lock);
- generic_drop_inode(inode);
+ return generic_drop_inode(inode);
}
static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb,
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 394d542..eaf286a 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 21ea393..08c9299 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/gfs2/super.c b/fs/gfs2/super.c
index 555f5a4..fa865ab 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 0d8aa56..1b9504e 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 78be674..d8c71ec 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 eb7fd07..0492464 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 975eedd..6de5a86 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
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 801b0f2..183188b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1561,7 +1561,7 @@ struct super_operations {
void (*dirty_inode) (struct inode *);
int (*write_inode) (struct inode *, struct writeback_control *wbc);
- void (*drop_inode) (struct inode *);
+ int (*drop_inode) (struct inode *);
void (*evict_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
@@ -2150,8 +2150,8 @@ extern void iput(struct inode *);
extern struct inode * igrab(struct inode *);
extern ino_t iunique(struct super_block *, ino_t);
extern int inode_needs_sync(struct inode *inode);
-extern void generic_delete_inode(struct inode *inode);
-extern void generic_drop_inode(struct inode *inode);
+extern int generic_delete_inode(struct inode *inode);
+extern int generic_drop_inode(struct inode *inode);
extern struct inode *ilookup5_nowait(struct super_block *sb,
unsigned long hashval, int (*test)(struct inode *, void *),
next prev parent reply other threads:[~2010-06-09 1:47 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-08 22:24 [PATCH 55/58] Make ->drop_inode() just return whether inode needs to be dropped Al Viro
2010-06-09 0:24 ` Joel Becker
2010-06-09 1:47 ` Al Viro [this message]
2010-06-09 15:05 ` J. R. Okajima
2010-06-09 22:29 ` Al Viro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100609014732.GU31073@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.