vfs: count unlinked inodes
Add a new counter to the superblock that keeps track of unlinked but not yet deleted inodes. Do not WARN_ON if set_nlink is called with zero count, just do a ratelimited printk. This happens on xfs and probably other filesystems after an unclean shutdown when the filesystem reads inodes which already have zero i_nlink. Reported by Christoph Hellwig. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Tested-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
4ed5e82fe7
commit
7ada4db886
2 changed files with 92 additions and 54 deletions
|
@ -1483,6 +1483,9 @@ struct super_block {
|
|||
|
||||
struct shrinker s_shrink; /* per-sb shrinker handle */
|
||||
|
||||
/* Number of inodes with nlink == 0 but still referenced */
|
||||
atomic_long_t s_remove_count;
|
||||
|
||||
/* Being remounted read-only */
|
||||
int s_readonly_remount;
|
||||
};
|
||||
|
@ -1768,31 +1771,10 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
|
|||
__mark_inode_dirty(inode, I_DIRTY_SYNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_nlink - directly set an inode's link count
|
||||
* @inode: inode
|
||||
* @nlink: new nlink (should be non-zero)
|
||||
*
|
||||
* This is a low-level filesystem helper to replace any
|
||||
* direct filesystem manipulation of i_nlink.
|
||||
*/
|
||||
static inline void set_nlink(struct inode *inode, unsigned int nlink)
|
||||
{
|
||||
inode->__i_nlink = nlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* inc_nlink - directly increment an inode's link count
|
||||
* @inode: inode
|
||||
*
|
||||
* This is a low-level filesystem helper to replace any
|
||||
* direct filesystem manipulation of i_nlink. Currently,
|
||||
* it is only here for parity with dec_nlink().
|
||||
*/
|
||||
static inline void inc_nlink(struct inode *inode)
|
||||
{
|
||||
inode->__i_nlink++;
|
||||
}
|
||||
extern void inc_nlink(struct inode *inode);
|
||||
extern void drop_nlink(struct inode *inode);
|
||||
extern void clear_nlink(struct inode *inode);
|
||||
extern void set_nlink(struct inode *inode, unsigned int nlink);
|
||||
|
||||
static inline void inode_inc_link_count(struct inode *inode)
|
||||
{
|
||||
|
@ -1800,35 +1782,6 @@ static inline void inode_inc_link_count(struct inode *inode)
|
|||
mark_inode_dirty(inode);
|
||||
}
|
||||
|
||||
/**
|
||||
* drop_nlink - directly drop an inode's link count
|
||||
* @inode: inode
|
||||
*
|
||||
* This is a low-level filesystem helper to replace any
|
||||
* direct filesystem manipulation of i_nlink. In cases
|
||||
* where we are attempting to track writes to the
|
||||
* filesystem, a decrement to zero means an imminent
|
||||
* write when the file is truncated and actually unlinked
|
||||
* on the filesystem.
|
||||
*/
|
||||
static inline void drop_nlink(struct inode *inode)
|
||||
{
|
||||
inode->__i_nlink--;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_nlink - directly zero an inode's link count
|
||||
* @inode: inode
|
||||
*
|
||||
* This is a low-level filesystem helper to replace any
|
||||
* direct filesystem manipulation of i_nlink. See
|
||||
* drop_nlink() for why we care about i_nlink hitting zero.
|
||||
*/
|
||||
static inline void clear_nlink(struct inode *inode)
|
||||
{
|
||||
inode->__i_nlink = 0;
|
||||
}
|
||||
|
||||
static inline void inode_dec_link_count(struct inode *inode)
|
||||
{
|
||||
drop_nlink(inode);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue