aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2011-11-21 06:11:32 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-06 23:20:12 -0500
commit7ada4db88634429f4da690ad1c4eb73c93085f0c (patch)
treeed1228f0bfa9d0050d746933595004d7c6e940f9
parent4ed5e82fe77f4147cf386327c9a63a2dd7eff518 (diff)
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>
-rw-r--r--fs/inode.c85
-rw-r--r--include/linux/fs.h61
2 files changed, 92 insertions, 54 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 961355d00e38..87535753ab04 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -26,6 +26,7 @@
26#include <linux/ima.h> 26#include <linux/ima.h>
27#include <linux/cred.h> 27#include <linux/cred.h>
28#include <linux/buffer_head.h> /* for inode_has_buffers */ 28#include <linux/buffer_head.h> /* for inode_has_buffers */
29#include <linux/ratelimit.h>
29#include "internal.h" 30#include "internal.h"
30 31
31/* 32/*
@@ -242,6 +243,11 @@ void __destroy_inode(struct inode *inode)
242 BUG_ON(inode_has_buffers(inode)); 243 BUG_ON(inode_has_buffers(inode));
243 security_inode_free(inode); 244 security_inode_free(inode);
244 fsnotify_inode_delete(inode); 245 fsnotify_inode_delete(inode);
246 if (!inode->i_nlink) {
247 WARN_ON(atomic_long_read(&inode->i_sb->s_remove_count) == 0);
248 atomic_long_dec(&inode->i_sb->s_remove_count);
249 }
250
245#ifdef CONFIG_FS_POSIX_ACL 251#ifdef CONFIG_FS_POSIX_ACL
246 if (inode->i_acl && inode->i_acl != ACL_NOT_CACHED) 252 if (inode->i_acl && inode->i_acl != ACL_NOT_CACHED)
247 posix_acl_release(inode->i_acl); 253 posix_acl_release(inode->i_acl);
@@ -268,6 +274,85 @@ static void destroy_inode(struct inode *inode)
268 call_rcu(&inode->i_rcu, i_callback); 274 call_rcu(&inode->i_rcu, i_callback);
269} 275}
270 276
277/**
278 * drop_nlink - directly drop an inode's link count
279 * @inode: inode
280 *
281 * This is a low-level filesystem helper to replace any
282 * direct filesystem manipulation of i_nlink. In cases
283 * where we are attempting to track writes to the
284 * filesystem, a decrement to zero means an imminent
285 * write when the file is truncated and actually unlinked
286 * on the filesystem.
287 */
288void drop_nlink(struct inode *inode)
289{
290 WARN_ON(inode->i_nlink == 0);
291 inode->__i_nlink--;
292 if (!inode->i_nlink)
293 atomic_long_inc(&inode->i_sb->s_remove_count);
294}
295EXPORT_SYMBOL(drop_nlink);
296
297/**
298 * clear_nlink - directly zero an inode's link count
299 * @inode: inode
300 *
301 * This is a low-level filesystem helper to replace any
302 * direct filesystem manipulation of i_nlink. See
303 * drop_nlink() for why we care about i_nlink hitting zero.
304 */
305void clear_nlink(struct inode *inode)
306{
307 if (inode->i_nlink) {
308 inode->__i_nlink = 0;
309 atomic_long_inc(&inode->i_sb->s_remove_count);
310 }
311}
312EXPORT_SYMBOL(clear_nlink);
313
314/**
315 * set_nlink - directly set an inode's link count
316 * @inode: inode
317 * @nlink: new nlink (should be non-zero)
318 *
319 * This is a low-level filesystem helper to replace any
320 * direct filesystem manipulation of i_nlink.
321 */
322void set_nlink(struct inode *inode, unsigned int nlink)
323{
324 if (!nlink) {
325 printk_ratelimited(KERN_INFO
326 "set_nlink() clearing i_nlink on %s inode %li\n",
327 inode->i_sb->s_type->name, inode->i_ino);
328 clear_nlink(inode);
329 } else {
330 /* Yes, some filesystems do change nlink from zero to one */
331 if (inode->i_nlink == 0)
332 atomic_long_dec(&inode->i_sb->s_remove_count);
333
334 inode->__i_nlink = nlink;
335 }
336}
337EXPORT_SYMBOL(set_nlink);
338
339/**
340 * inc_nlink - directly increment an inode's link count
341 * @inode: inode
342 *
343 * This is a low-level filesystem helper to replace any
344 * direct filesystem manipulation of i_nlink. Currently,
345 * it is only here for parity with dec_nlink().
346 */
347void inc_nlink(struct inode *inode)
348{
349 if (WARN_ON(inode->i_nlink == 0))
350 atomic_long_dec(&inode->i_sb->s_remove_count);
351
352 inode->__i_nlink++;
353}
354EXPORT_SYMBOL(inc_nlink);
355
271void address_space_init_once(struct address_space *mapping) 356void address_space_init_once(struct address_space *mapping)
272{ 357{
273 memset(mapping, 0, sizeof(*mapping)); 358 memset(mapping, 0, sizeof(*mapping));
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7b8a681b1ef4..8ac40921f5ac 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1483,6 +1483,9 @@ struct super_block {
1483 1483
1484 struct shrinker s_shrink; /* per-sb shrinker handle */ 1484 struct shrinker s_shrink; /* per-sb shrinker handle */
1485 1485
1486 /* Number of inodes with nlink == 0 but still referenced */
1487 atomic_long_t s_remove_count;
1488
1486 /* Being remounted read-only */ 1489 /* Being remounted read-only */
1487 int s_readonly_remount; 1490 int s_readonly_remount;
1488}; 1491};
@@ -1768,31 +1771,10 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
1768 __mark_inode_dirty(inode, I_DIRTY_SYNC); 1771 __mark_inode_dirty(inode, I_DIRTY_SYNC);
1769} 1772}
1770 1773
1771/** 1774extern void inc_nlink(struct inode *inode);
1772 * set_nlink - directly set an inode's link count 1775extern void drop_nlink(struct inode *inode);
1773 * @inode: inode 1776extern void clear_nlink(struct inode *inode);
1774 * @nlink: new nlink (should be non-zero) 1777extern void set_nlink(struct inode *inode, unsigned int nlink);
1775 *
1776 * This is a low-level filesystem helper to replace any
1777 * direct filesystem manipulation of i_nlink.
1778 */
1779static inline void set_nlink(struct inode *inode, unsigned int nlink)
1780{
1781 inode->__i_nlink = nlink;
1782}
1783
1784/**
1785 * inc_nlink - directly increment an inode's link count
1786 * @inode: inode
1787 *
1788 * This is a low-level filesystem helper to replace any
1789 * direct filesystem manipulation of i_nlink. Currently,
1790 * it is only here for parity with dec_nlink().
1791 */
1792static inline void inc_nlink(struct inode *inode)
1793{
1794 inode->__i_nlink++;
1795}
1796 1778
1797static inline void inode_inc_link_count(struct inode *inode) 1779static inline void inode_inc_link_count(struct inode *inode)
1798{ 1780{
@@ -1800,35 +1782,6 @@ static inline void inode_inc_link_count(struct inode *inode)
1800 mark_inode_dirty(inode); 1782 mark_inode_dirty(inode);
1801} 1783}
1802 1784
1803/**
1804 * drop_nlink - directly drop an inode's link count
1805 * @inode: inode
1806 *
1807 * This is a low-level filesystem helper to replace any
1808 * direct filesystem manipulation of i_nlink. In cases
1809 * where we are attempting to track writes to the
1810 * filesystem, a decrement to zero means an imminent
1811 * write when the file is truncated and actually unlinked
1812 * on the filesystem.
1813 */
1814static inline void drop_nlink(struct inode *inode)
1815{
1816 inode->__i_nlink--;
1817}
1818
1819/**
1820 * clear_nlink - directly zero an inode's link count
1821 * @inode: inode
1822 *
1823 * This is a low-level filesystem helper to replace any
1824 * direct filesystem manipulation of i_nlink. See
1825 * drop_nlink() for why we care about i_nlink hitting zero.
1826 */
1827static inline void clear_nlink(struct inode *inode)
1828{
1829 inode->__i_nlink = 0;
1830}
1831
1832static inline void inode_dec_link_count(struct inode *inode) 1785static inline void inode_dec_link_count(struct inode *inode)
1833{ 1786{
1834 drop_nlink(inode); 1787 drop_nlink(inode);