aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
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 /fs/inode.c
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>
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 961355d00e3..87535753ab0 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));