forked from Minki/linux
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>
This commit is contained in:
parent
30140837f2
commit
45321ac543
@ -1223,7 +1223,7 @@ void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pohmelfs_drop_inode(struct inode *inode)
|
static int pohmelfs_drop_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
|
struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
|
||||||
struct pohmelfs_inode *pi = POHMELFS_I(inode);
|
struct pohmelfs_inode *pi = POHMELFS_I(inode);
|
||||||
@ -1232,7 +1232,7 @@ static void pohmelfs_drop_inode(struct inode *inode)
|
|||||||
list_del_init(&pi->inode_entry);
|
list_del_init(&pi->inode_entry);
|
||||||
spin_unlock(&psb->ino_lock);
|
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,
|
static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb,
|
||||||
|
@ -2395,7 +2395,7 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
|
|||||||
void btrfs_dirty_inode(struct inode *inode);
|
void btrfs_dirty_inode(struct inode *inode);
|
||||||
struct inode *btrfs_alloc_inode(struct super_block *sb);
|
struct inode *btrfs_alloc_inode(struct super_block *sb);
|
||||||
void btrfs_destroy_inode(struct inode *inode);
|
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);
|
int btrfs_init_cachep(void);
|
||||||
void btrfs_destroy_cachep(void);
|
void btrfs_destroy_cachep(void);
|
||||||
long btrfs_ioctl_trans_end(struct file *file);
|
long btrfs_ioctl_trans_end(struct file *file);
|
||||||
|
@ -3943,7 +3943,7 @@ again:
|
|||||||
if (atomic_read(&inode->i_count) > 1)
|
if (atomic_read(&inode->i_count) > 1)
|
||||||
d_prune_aliases(inode);
|
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
|
* the inode cache when its usage count
|
||||||
* hits zero.
|
* hits zero.
|
||||||
*/
|
*/
|
||||||
@ -6337,13 +6337,14 @@ free:
|
|||||||
kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
|
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;
|
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
|
else
|
||||||
generic_drop_inode(inode);
|
return generic_drop_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_once(void *foo)
|
static void init_once(void *foo)
|
||||||
|
@ -480,14 +480,13 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data)
|
|||||||
return 0;
|
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);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
/* no serverino => unconditional eviction */
|
||||||
return generic_drop_inode(inode);
|
return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
|
||||||
|
generic_drop_inode(inode);
|
||||||
return generic_delete_inode(inode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct super_operations cifs_super_ops = {
|
static const struct super_operations cifs_super_ops = {
|
||||||
|
@ -1191,7 +1191,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
|
|||||||
* node for later deallocation.
|
* 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);
|
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))
|
if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
|
||||||
clear_nlink(inode);
|
clear_nlink(inode);
|
||||||
}
|
}
|
||||||
generic_drop_inode(inode);
|
return generic_drop_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_ancestor(const struct dentry *d1, const struct dentry *d2)
|
static int is_ancestor(const struct dentry *d1, const struct dentry *d2)
|
||||||
|
117
fs/inode.c
117
fs/inode.c
@ -1183,58 +1183,51 @@ void remove_inode_hash(struct inode *inode)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(remove_inode_hash);
|
EXPORT_SYMBOL(remove_inode_hash);
|
||||||
|
|
||||||
/*
|
int generic_delete_inode(struct inode *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.
|
|
||||||
*/
|
|
||||||
void generic_delete_inode(struct inode *inode)
|
|
||||||
{
|
{
|
||||||
list_del_init(&inode->i_list);
|
return 1;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(generic_delete_inode);
|
EXPORT_SYMBOL(generic_delete_inode);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* generic_detach_inode - remove inode from inode lists
|
* Normal UNIX filesystem behaviour: delete the
|
||||||
* @inode: inode to remove
|
* inode when the usage count drops to zero, and
|
||||||
*
|
* i_nlink is zero.
|
||||||
* Remove inode from inode lists, write it if it's dirty. This is just an
|
|
||||||
* internal VFS helper exported for hugetlbfs. Do not use!
|
|
||||||
*
|
|
||||||
* Returns 1 if inode should be completely destroyed.
|
|
||||||
*/
|
*/
|
||||||
static int generic_detach_inode(struct inode *inode)
|
int generic_drop_inode(struct inode *inode)
|
||||||
|
{
|
||||||
|
return !inode->i_nlink || hlist_unhashed(&inode->i_hash);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(generic_drop_inode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when we're dropping the last reference
|
||||||
|
* to an inode.
|
||||||
|
*
|
||||||
|
* 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 void iput_final(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
|
const struct super_operations *op = inode->i_sb->s_op;
|
||||||
|
int drop;
|
||||||
|
|
||||||
if (!hlist_unhashed(&inode->i_hash)) {
|
if (op && op->drop_inode)
|
||||||
|
drop = op->drop_inode(inode);
|
||||||
|
else
|
||||||
|
drop = generic_drop_inode(inode);
|
||||||
|
|
||||||
|
if (!drop) {
|
||||||
if (!(inode->i_state & (I_DIRTY|I_SYNC)))
|
if (!(inode->i_state & (I_DIRTY|I_SYNC)))
|
||||||
list_move(&inode->i_list, &inode_unused);
|
list_move(&inode->i_list, &inode_unused);
|
||||||
inodes_stat.nr_unused++;
|
inodes_stat.nr_unused++;
|
||||||
if (sb->s_flags & MS_ACTIVE) {
|
if (sb->s_flags & MS_ACTIVE) {
|
||||||
spin_unlock(&inode_lock);
|
spin_unlock(&inode_lock);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
WARN_ON(inode->i_state & I_NEW);
|
WARN_ON(inode->i_state & I_NEW);
|
||||||
inode->i_state |= I_WILL_FREE;
|
inode->i_state |= I_WILL_FREE;
|
||||||
@ -1252,53 +1245,15 @@ static int generic_detach_inode(struct inode *inode)
|
|||||||
inode->i_state |= I_FREEING;
|
inode->i_state |= I_FREEING;
|
||||||
inodes_stat.nr_inodes--;
|
inodes_stat.nr_inodes--;
|
||||||
spin_unlock(&inode_lock);
|
spin_unlock(&inode_lock);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void generic_forget_inode(struct inode *inode)
|
|
||||||
{
|
|
||||||
if (!generic_detach_inode(inode))
|
|
||||||
return;
|
|
||||||
evict(inode);
|
evict(inode);
|
||||||
|
spin_lock(&inode_lock);
|
||||||
|
hlist_del_init(&inode->i_hash);
|
||||||
|
spin_unlock(&inode_lock);
|
||||||
wake_up_inode(inode);
|
wake_up_inode(inode);
|
||||||
|
BUG_ON(inode->i_state != (I_FREEING | I_CLEAR));
|
||||||
destroy_inode(inode);
|
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
|
* iput - put an inode
|
||||||
* @inode: inode to put
|
* @inode: inode to put
|
||||||
|
@ -287,7 +287,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* called with inode_lock held */
|
/* 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_super *super = logfs_super(inode->i_sb);
|
||||||
struct logfs_inode *li = logfs_inode(inode);
|
struct logfs_inode *li = logfs_inode(inode);
|
||||||
@ -295,7 +295,7 @@ static void logfs_drop_inode(struct inode *inode)
|
|||||||
spin_lock(&logfs_inode_lock);
|
spin_lock(&logfs_inode_lock);
|
||||||
list_move(&li->li_freeing_list, &super->s_freeing_list);
|
list_move(&li->li_freeing_list, &super->s_freeing_list);
|
||||||
spin_unlock(&logfs_inode_lock);
|
spin_unlock(&logfs_inode_lock);
|
||||||
generic_drop_inode(inode);
|
return generic_drop_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void logfs_set_ino_generation(struct super_block *sb,
|
static void logfs_set_ino_generation(struct super_block *sb,
|
||||||
|
@ -1194,9 +1194,10 @@ void ocfs2_evict_inode(struct inode *inode)
|
|||||||
/* Called under inode_lock, with no more references on the
|
/* Called under inode_lock, with no more references on the
|
||||||
* struct inode, so it's safe here to check the flags field
|
* struct inode, so it's safe here to check the flags field
|
||||||
* and to manipulate i_nlink without any other locks. */
|
* 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);
|
struct ocfs2_inode_info *oi = OCFS2_I(inode);
|
||||||
|
int res;
|
||||||
|
|
||||||
mlog_entry_void();
|
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);
|
(unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags);
|
||||||
|
|
||||||
if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)
|
if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)
|
||||||
generic_delete_inode(inode);
|
res = 1;
|
||||||
else
|
else
|
||||||
generic_drop_inode(inode);
|
res = generic_drop_inode(inode);
|
||||||
|
|
||||||
mlog_exit_void();
|
mlog_exit_void();
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -124,7 +124,7 @@ static inline struct ocfs2_caching_info *INODE_CACHE(struct inode *inode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ocfs2_evict_inode(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() */
|
/* Flags for ocfs2_iget() */
|
||||||
#define OCFS2_FI_FLAG_SYSFILE 0x1
|
#define OCFS2_FI_FLAG_SYSFILE 0x1
|
||||||
|
@ -1562,7 +1562,7 @@ struct super_operations {
|
|||||||
|
|
||||||
void (*dirty_inode) (struct inode *);
|
void (*dirty_inode) (struct inode *);
|
||||||
int (*write_inode) (struct inode *, struct writeback_control *wbc);
|
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 (*evict_inode) (struct inode *);
|
||||||
void (*put_super) (struct super_block *);
|
void (*put_super) (struct super_block *);
|
||||||
void (*write_super) (struct super_block *);
|
void (*write_super) (struct super_block *);
|
||||||
@ -2164,8 +2164,8 @@ extern void iput(struct inode *);
|
|||||||
extern struct inode * igrab(struct inode *);
|
extern struct inode * igrab(struct inode *);
|
||||||
extern ino_t iunique(struct super_block *, ino_t);
|
extern ino_t iunique(struct super_block *, ino_t);
|
||||||
extern int inode_needs_sync(struct inode *inode);
|
extern int inode_needs_sync(struct inode *inode);
|
||||||
extern void generic_delete_inode(struct inode *inode);
|
extern int generic_delete_inode(struct inode *inode);
|
||||||
extern void generic_drop_inode(struct inode *inode);
|
extern int generic_drop_inode(struct inode *inode);
|
||||||
|
|
||||||
extern struct inode *ilookup5_nowait(struct super_block *sb,
|
extern struct inode *ilookup5_nowait(struct super_block *sb,
|
||||||
unsigned long hashval, int (*test)(struct inode *, void *),
|
unsigned long hashval, int (*test)(struct inode *, void *),
|
||||||
|
Loading…
Reference in New Issue
Block a user