* [PATCH 0/13] read-only remount race fix v7
@ 2011-10-12 14:48 Miklos Szeredi
2011-10-12 14:48 ` [PATCH 01/13] vfs: ignore error on forced remount Miklos Szeredi
` (14 more replies)
0 siblings, 15 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:48 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
Here's an update of the read-only remount race fixes.
It should now fix the races after unlink. I haven't been able to
trigger the bad behavior with the test scripts provided by Toshiyuki
Okajima.
Toshiyuki-san, could you please test these patches too?
Thanks,
Miklos
---
Miklos Szeredi (13):
vfs: ignore error on forced remount
vfs: keep list of mounts for each superblock
vfs: protect remounting superblock read-only
vfs: fs_may_remount_ro: turn unnecessary check into a WARN_ON
hypfs: remove unnecessary nlink setting
jfs: remove unnecessary nlink setting
ocfs2: remove unnecessary nlink setting
logfs: remove unnecessary nlink setting
filesystems: add missing nlink wrappers
filesystems: add set_nlink()
vfs: protect i_nlink
vfs: count unlinked inodes
vfs: prevent remount read-only if pending removes
---
arch/s390/hypfs/inode.c | 6 +--
drivers/mtd/mtdchar.c | 2 +-
drivers/staging/pohmelfs/inode.c | 2 +-
fs/9p/vfs_inode.c | 4 +-
fs/9p/vfs_inode_dotl.c | 4 +-
fs/adfs/inode.c | 2 +-
fs/affs/amigaffs.c | 4 +-
fs/affs/inode.c | 8 ++--
fs/affs/namei.c | 6 +-
fs/afs/fsclient.c | 2 +-
fs/afs/inode.c | 4 +-
fs/autofs4/inode.c | 2 +-
fs/befs/linuxvfs.c | 2 +-
fs/bfs/dir.c | 2 +-
fs/bfs/inode.c | 2 +-
fs/binfmt_misc.c | 2 +-
fs/btrfs/delayed-inode.c | 2 +-
fs/btrfs/disk-io.c | 2 +-
fs/btrfs/inode.c | 4 +-
fs/btrfs/tree-log.c | 2 +-
fs/ceph/caps.c | 2 +-
fs/ceph/inode.c | 2 +-
fs/cifs/inode.c | 6 +-
fs/cifs/link.c | 2 +-
fs/coda/coda_linux.c | 2 +-
fs/coda/dir.c | 2 +-
fs/devpts/inode.c | 4 +-
fs/ecryptfs/inode.c | 12 +++---
fs/efs/inode.c | 2 +-
fs/exofs/inode.c | 2 +-
fs/ext2/ialloc.c | 2 +-
fs/ext2/inode.c | 2 +-
fs/ext3/ialloc.c | 2 +-
fs/ext3/inode.c | 2 +-
fs/ext3/namei.c | 6 +-
fs/ext4/ialloc.c | 2 +-
fs/ext4/inode.c | 2 +-
fs/ext4/migrate.c | 2 +-
fs/ext4/namei.c | 8 ++--
fs/fat/inode.c | 4 +-
fs/fat/namei_msdos.c | 2 +-
fs/fat/namei_vfat.c | 2 +-
fs/file_table.c | 23 ----------
fs/freevxfs/vxfs_inode.c | 2 +-
fs/fuse/control.c | 2 +-
fs/fuse/inode.c | 2 +-
fs/gfs2/glops.c | 2 +-
fs/hfs/dir.c | 4 +-
fs/hfs/inode.c | 4 +-
fs/hfsplus/dir.c | 4 +-
fs/hfsplus/inode.c | 10 ++--
fs/hostfs/hostfs_kern.c | 2 +-
fs/hpfs/dir.c | 2 +-
fs/hpfs/inode.c | 10 ++--
fs/hpfs/namei.c | 8 ++--
fs/hppfs/hppfs.c | 2 +-
fs/hugetlbfs/inode.c | 2 +-
fs/inode.c | 83 +++++++++++++++++++++++++++++++++++++-
fs/internal.h | 1 +
fs/isofs/inode.c | 4 +-
fs/isofs/rock.c | 4 +-
fs/jffs2/dir.c | 6 +-
fs/jffs2/fs.c | 6 +-
fs/jfs/jfs_imap.c | 6 +-
fs/jfs/jfs_inode.c | 2 +-
fs/jfs/namei.c | 12 +++---
fs/jfs/super.c | 1 -
fs/libfs.c | 2 +-
fs/logfs/dir.c | 8 ++--
fs/logfs/inode.c | 3 +-
fs/logfs/readwrite.c | 2 +-
fs/minix/inode.c | 4 +-
fs/namespace.c | 57 +++++++++++++++++++++++++-
fs/ncpfs/inode.c | 2 +-
fs/nfs/inode.c | 6 +-
fs/nilfs2/inode.c | 4 +-
fs/nilfs2/namei.c | 2 +-
fs/ntfs/inode.c | 8 ++--
fs/ocfs2/dir.c | 4 +-
fs/ocfs2/dlmglue.c | 2 +-
fs/ocfs2/inode.c | 4 +-
fs/ocfs2/namei.c | 18 ++++-----
fs/openpromfs/inode.c | 4 +-
fs/proc/base.c | 12 +++---
fs/proc/generic.c | 2 +-
fs/proc/inode.c | 2 +-
fs/proc/proc_sysctl.c | 2 +-
fs/qnx4/inode.c | 2 +-
fs/reiserfs/inode.c | 10 ++--
fs/reiserfs/namei.c | 16 ++++----
fs/romfs/super.c | 2 +-
fs/squashfs/inode.c | 18 ++++----
fs/stack.c | 2 +-
fs/super.c | 27 ++++++++++--
fs/sysfs/inode.c | 2 +-
fs/sysv/inode.c | 2 +-
fs/ubifs/super.c | 2 +-
fs/ubifs/xattr.c | 4 +-
fs/udf/inode.c | 8 ++-
fs/udf/namei.c | 15 +++----
fs/ufs/ialloc.c | 2 +-
fs/ufs/inode.c | 4 +-
fs/xfs/xfs_iops.c | 2 +-
include/linux/fs.h | 66 ++++++++++--------------------
include/linux/mount.h | 1 +
mm/shmem.c | 2 +-
106 files changed, 389 insertions(+), 286 deletions(-)
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 01/13] vfs: ignore error on forced remount
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
@ 2011-10-12 14:48 ` Miklos Szeredi
2011-10-12 14:48 ` [PATCH 02/13] vfs: keep list of mounts for each superblock Miklos Szeredi
` (13 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:48 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
On emergency remount we want to force MS_RDONLY on the super block
even if ->remount_fs() failed for some reason.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/super.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/super.c b/fs/super.c
index 3f56a26..363fde2 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -727,8 +727,13 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
if (sb->s_op->remount_fs) {
retval = sb->s_op->remount_fs(sb, &flags, data);
- if (retval)
- return retval;
+ if (retval) {
+ if(!force)
+ return retval;
+ /* If forced remount, go ahead despite any errors */
+ WARN(1, "forced remount of a %s fs returned %i\n",
+ sb->s_type->name, retval);
+ }
}
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 02/13] vfs: keep list of mounts for each superblock
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
2011-10-12 14:48 ` [PATCH 01/13] vfs: ignore error on forced remount Miklos Szeredi
@ 2011-10-12 14:48 ` Miklos Szeredi
2011-10-12 14:48 ` [PATCH 03/13] vfs: protect remounting superblock read-only Miklos Szeredi
` (12 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:48 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
Keep track of vfsmounts belonging to a superblock. List is protected
by vfsmount_lock.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/namespace.c | 10 ++++++++++
fs/super.c | 2 ++
include/linux/fs.h | 1 +
include/linux/mount.h | 1 +
4 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/fs/namespace.c b/fs/namespace.c
index b4febb2..ccbec4e 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -696,6 +696,11 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
mnt->mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt_root;
mnt->mnt_parent = mnt;
+
+ br_write_lock(vfsmount_lock);
+ list_add_tail(&mnt->mnt_instance, &mnt->mnt_sb->s_mounts);
+ br_write_unlock(vfsmount_lock);
+
return mnt;
}
EXPORT_SYMBOL_GPL(vfs_kern_mount);
@@ -745,6 +750,10 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
if (!list_empty(&old->mnt_expire))
list_add(&mnt->mnt_expire, &old->mnt_expire);
}
+
+ br_write_lock(vfsmount_lock);
+ list_add_tail(&mnt->mnt_instance, &mnt->mnt_sb->s_mounts);
+ br_write_unlock(vfsmount_lock);
}
return mnt;
@@ -805,6 +814,7 @@ put_again:
acct_auto_close_mnt(mnt);
goto put_again;
}
+ list_del(&mnt->mnt_instance);
br_write_unlock(vfsmount_lock);
mntfree(mnt);
}
diff --git a/fs/super.c b/fs/super.c
index 363fde2..e8aad34 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -142,6 +142,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
INIT_LIST_HEAD(&s->s_dentry_lru);
INIT_LIST_HEAD(&s->s_inode_lru);
spin_lock_init(&s->s_inode_lru_lock);
+ INIT_LIST_HEAD(&s->s_mounts);
init_rwsem(&s->s_umount);
mutex_init(&s->s_lock);
lockdep_set_class(&s->s_umount, &type->s_umount_key);
@@ -200,6 +201,7 @@ static inline void destroy_super(struct super_block *s)
free_percpu(s->s_files);
#endif
security_sb_free(s);
+ WARN_ON(!list_empty(&s->s_mounts));
kfree(s->s_subtype);
kfree(s->s_options);
kfree(s);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 277f497..84e5df6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1408,6 +1408,7 @@ struct super_block {
#else
struct list_head s_files;
#endif
+ struct list_head s_mounts; /* list of mounts */
/* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
struct list_head s_dentry_lru; /* unused dentry lru */
int s_nr_dentry_unused; /* # of dentry on lru */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 33fe53d..f88c726 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -67,6 +67,7 @@ struct vfsmount {
#endif
struct list_head mnt_mounts; /* list of children, anchored here */
struct list_head mnt_child; /* and going through their mnt_child */
+ struct list_head mnt_instance; /* mount instance on sb->s_mounts */
int mnt_flags;
/* 4 bytes hole on 64bits arches without fsnotify */
#ifdef CONFIG_FSNOTIFY
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 03/13] vfs: protect remounting superblock read-only
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
2011-10-12 14:48 ` [PATCH 01/13] vfs: ignore error on forced remount Miklos Szeredi
2011-10-12 14:48 ` [PATCH 02/13] vfs: keep list of mounts for each superblock Miklos Szeredi
@ 2011-10-12 14:48 ` Miklos Szeredi
2011-10-12 14:48 ` [PATCH 04/13] vfs: fs_may_remount_ro: turn unnecessary check into a WARN_ON Miklos Szeredi
` (11 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:48 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
Currently remouting superblock read-only is racy in a major way.
With the per mount read-only infrastructure it is now possible to
prevent most races, which this patch attempts.
Before starting the remount read-only, iterate through all mounts
belonging to the superblock and if none of them have any pending
writes, set sb->s_readonly_remount. This indicates that remount is in
progress and no further write requests are allowed. If the remount
succeeds set MS_RDONLY and reset s_readonly_remount.
If the remounting is unsuccessful just reset s_readonly_remount.
This can result in transient EROFS errors, despite the fact the
remount failed. Unfortunately hodling off writes is difficult as
remount itself may touch the filesystem (e.g. through load_nls())
which would deadlock.
Small races still remain because delayed writes due to nlink going to
zero but inode still having a reference are not dealt with by this
patch.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/internal.h | 1 +
fs/namespace.c | 40 +++++++++++++++++++++++++++++++++++++++-
fs/super.c | 22 ++++++++++++++++++----
include/linux/fs.h | 3 +++
4 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/fs/internal.h b/fs/internal.h
index fe327c2..f925271 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -74,6 +74,7 @@ extern int finish_automount(struct vfsmount *, struct path *);
extern void mnt_make_longterm(struct vfsmount *);
extern void mnt_make_shortterm(struct vfsmount *);
+extern int sb_prepare_remount_readonly(struct super_block *);
extern void __init mnt_init(void);
diff --git a/fs/namespace.c b/fs/namespace.c
index ccbec4e..85838f5 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -311,6 +311,15 @@ static unsigned int mnt_get_writers(struct vfsmount *mnt)
#endif
}
+static int mnt_is_readonly(struct vfsmount *mnt)
+{
+ if (mnt->mnt_sb->s_readonly_remount)
+ return 1;
+ /* Order wrt setting s_flags/s_readonly_remount in do_remount() */
+ smp_rmb();
+ return __mnt_is_readonly(mnt);
+}
+
/*
* Most r/o checks on a fs are for operations that take
* discrete amounts of time, like a write() or unlink().
@@ -349,7 +358,7 @@ int mnt_want_write(struct vfsmount *mnt)
* MNT_WRITE_HOLD is cleared.
*/
smp_rmb();
- if (__mnt_is_readonly(mnt)) {
+ if (mnt_is_readonly(mnt)) {
mnt_dec_writers(mnt);
ret = -EROFS;
goto out;
@@ -466,6 +475,35 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt)
br_write_unlock(vfsmount_lock);
}
+int sb_prepare_remount_readonly(struct super_block *sb)
+{
+ struct vfsmount *mnt;
+ int err = 0;
+
+ br_write_lock(vfsmount_lock);
+ list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
+ if (!(mnt->mnt_flags & MNT_READONLY)) {
+ mnt->mnt_flags |= MNT_WRITE_HOLD;
+ smp_mb();
+ if (mnt_get_writers(mnt) > 0) {
+ err = -EBUSY;
+ break;
+ }
+ }
+ }
+ if (!err) {
+ sb->s_readonly_remount = 1;
+ smp_wmb();
+ }
+ list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
+ if (mnt->mnt_flags & MNT_WRITE_HOLD)
+ mnt->mnt_flags &= ~MNT_WRITE_HOLD;
+ }
+ br_write_unlock(vfsmount_lock);
+
+ return err;
+}
+
static void free_vfsmnt(struct vfsmount *mnt)
{
kfree(mnt->mnt_devname);
diff --git a/fs/super.c b/fs/super.c
index e8aad34..94c8ace 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -721,23 +721,33 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
/* If we are remounting RDONLY and current sb is read/write,
make sure there are no rw files opened */
if (remount_ro) {
- if (force)
+ if (force) {
mark_files_ro(sb);
- else if (!fs_may_remount_ro(sb))
- return -EBUSY;
+ } else {
+ retval = sb_prepare_remount_readonly(sb);
+ if (retval)
+ return retval;
+
+ retval = -EBUSY;
+ if (!fs_may_remount_ro(sb))
+ goto cancel_readonly;
+ }
}
if (sb->s_op->remount_fs) {
retval = sb->s_op->remount_fs(sb, &flags, data);
if (retval) {
if(!force)
- return retval;
+ goto cancel_readonly;
/* If forced remount, go ahead despite any errors */
WARN(1, "forced remount of a %s fs returned %i\n",
sb->s_type->name, retval);
}
}
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
+ /* Needs to be ordered wrt mnt_is_readonly() */
+ smp_wmb();
+ sb->s_readonly_remount = 0;
/*
* Some filesystems modify their metadata via some other path than the
@@ -750,6 +760,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
if (remount_ro && sb->s_bdev)
invalidate_bdev(sb->s_bdev);
return 0;
+
+cancel_readonly:
+ sb->s_readonly_remount = 0;
+ return retval;
}
static void do_emergency_remount(struct work_struct *work)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 84e5df6..0979638 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1462,6 +1462,9 @@ struct super_block {
int cleancache_poolid;
struct shrinker s_shrink; /* per-sb shrinker handle */
+
+ /* Being remounted read-only */
+ int s_readonly_remount;
};
/* superblock cache pruning functions */
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 04/13] vfs: fs_may_remount_ro: turn unnecessary check into a WARN_ON
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (2 preceding siblings ...)
2011-10-12 14:48 ` [PATCH 03/13] vfs: protect remounting superblock read-only Miklos Szeredi
@ 2011-10-12 14:48 ` Miklos Szeredi
2011-10-12 14:48 ` [PATCH 05/13] hypfs: remove unnecessary nlink setting Miklos Szeredi
` (10 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:48 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
Now a successful sb_prepare_remount_readonly() should ensure that no
writable files remain for this superblock. So turn this check into a
WARN_ON.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/file_table.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/file_table.c b/fs/file_table.c
index c322794..dc9f437 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -486,8 +486,11 @@ int fs_may_remount_ro(struct super_block *sb)
if (inode->i_nlink == 0)
goto too_bad;
- /* Writeable file? */
- if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
+ /*
+ * Writable file?
+ * Should be caught by sb_prepare_remount_readonly().
+ */
+ if (WARN_ON(S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)))
goto too_bad;
} while_file_list_for_each_entry;
lg_global_unlock(files_lglock);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 05/13] hypfs: remove unnecessary nlink setting
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (3 preceding siblings ...)
2011-10-12 14:48 ` [PATCH 04/13] vfs: fs_may_remount_ro: turn unnecessary check into a WARN_ON Miklos Szeredi
@ 2011-10-12 14:48 ` Miklos Szeredi
2011-10-12 14:48 ` [PATCH 06/13] jfs: " Miklos Szeredi
` (9 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:48 UTC (permalink / raw)
To: viro
Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi, Martin Schwidefsky
From: Miklos Szeredi <mszeredi@suse.cz>
alloc_inode() initializes i_nlink to 1. Remove unnecessary
re-initialization.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
CC: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
arch/s390/hypfs/inode.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 6fe874f..7ae0d0d 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -109,8 +109,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
if (mode & S_IFDIR)
ret->i_nlink = 2;
- else
- ret->i_nlink = 1;
}
return ret;
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 06/13] jfs: remove unnecessary nlink setting
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (4 preceding siblings ...)
2011-10-12 14:48 ` [PATCH 05/13] hypfs: remove unnecessary nlink setting Miklos Szeredi
@ 2011-10-12 14:48 ` Miklos Szeredi
2011-10-12 15:26 ` Dave Kleikamp
2011-10-12 14:49 ` [PATCH 07/13] ocfs2: " Miklos Szeredi
` (8 subsequent siblings)
14 siblings, 1 reply; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:48 UTC (permalink / raw)
To: viro
Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi, Dave Kleikamp
From: Miklos Szeredi <mszeredi@suse.cz>
alloc_inode() initializes i_nlink to 1. Remove unnecessary
re-initialization.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
CC: Dave Kleikamp <dave.kleikamp@oracle.com>
---
fs/jfs/super.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 06c8a67..a44eff0 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -485,7 +485,6 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
goto out_unload;
}
inode->i_ino = 0;
- inode->i_nlink = 1;
inode->i_size = sb->s_bdev->bd_inode->i_size;
inode->i_mapping->a_ops = &jfs_metapage_aops;
insert_inode_hash(inode);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 07/13] ocfs2: remove unnecessary nlink setting
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (5 preceding siblings ...)
2011-10-12 14:48 ` [PATCH 06/13] jfs: " Miklos Szeredi
@ 2011-10-12 14:49 ` Miklos Szeredi
2011-10-12 14:49 ` [PATCH 08/13] logfs: " Miklos Szeredi
` (7 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:49 UTC (permalink / raw)
To: viro
Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi, Joel Becker, Mark Fasheh
From: Miklos Szeredi <mszeredi@suse.cz>
alloc_inode() initializes i_nlink to 1. Remove unnecessary
re-initialization.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
CC: Joel Becker <jlbec@evilplan.org>
CC: Mark Fasheh <mfasheh@suse.com>
---
fs/ocfs2/namei.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 53aa41e..0181f63 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -200,8 +200,6 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
* callers. */
if (S_ISDIR(mode))
inode->i_nlink = 2;
- else
- inode->i_nlink = 1;
inode_init_owner(inode, dir, mode);
dquot_initialize(inode);
return inode;
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 08/13] logfs: remove unnecessary nlink setting
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (6 preceding siblings ...)
2011-10-12 14:49 ` [PATCH 07/13] ocfs2: " Miklos Szeredi
@ 2011-10-12 14:49 ` Miklos Szeredi
2011-10-12 14:49 ` [PATCH 09/13] filesystems: add missing nlink wrappers Miklos Szeredi
` (6 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:49 UTC (permalink / raw)
To: viro
Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi, Joern Engel, Prasad Joshi
From: Miklos Szeredi <mszeredi@suse.cz>
alloc_inode() initializes i_nlink to 1. Remove unnecessary
re-initialization.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
CC: Joern Engel <joern@logfs.org>
CC: Prasad Joshi <prasadjoshi.linux@gmail.com>
---
fs/logfs/inode.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index edfea7a..9abb048 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -199,7 +199,6 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode)
inode->i_blocks = 0;
inode->i_ctime = CURRENT_TIME;
inode->i_mtime = CURRENT_TIME;
- inode->i_nlink = 1;
li->li_refcount = 1;
INIT_LIST_HEAD(&li->li_freeing_list);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 09/13] filesystems: add missing nlink wrappers
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (7 preceding siblings ...)
2011-10-12 14:49 ` [PATCH 08/13] logfs: " Miklos Szeredi
@ 2011-10-12 14:49 ` Miklos Szeredi
2011-10-12 14:49 ` [PATCH 10/13] filesystems: add set_nlink() Miklos Szeredi
` (5 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:49 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
Replace direct i_nlink updates with the respective updater function
(inc_nlink, drop_nlink, clear_nlink, inode_dec_link_count).
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
arch/s390/hypfs/inode.c | 2 +-
drivers/mtd/mtdchar.c | 2 +-
fs/affs/amigaffs.c | 2 +-
fs/affs/namei.c | 6 +++---
fs/binfmt_misc.c | 2 +-
fs/cifs/link.c | 2 +-
fs/coda/dir.c | 2 +-
fs/devpts/inode.c | 2 +-
fs/ext2/ialloc.c | 2 +-
fs/ext3/ialloc.c | 2 +-
fs/ext3/namei.c | 2 +-
fs/ext4/ialloc.c | 2 +-
fs/ext4/migrate.c | 2 +-
fs/ext4/namei.c | 2 +-
fs/hfs/dir.c | 4 ++--
fs/hfsplus/dir.c | 4 ++--
fs/hpfs/inode.c | 2 +-
fs/hugetlbfs/inode.c | 2 +-
fs/jfs/jfs_inode.c | 2 +-
fs/jfs/namei.c | 10 +++++-----
fs/logfs/dir.c | 8 ++++----
fs/logfs/inode.c | 2 +-
fs/nfs/inode.c | 2 +-
fs/nilfs2/inode.c | 2 +-
fs/ocfs2/namei.c | 8 ++++----
fs/proc/proc_sysctl.c | 2 +-
fs/reiserfs/inode.c | 4 ++--
fs/reiserfs/namei.c | 12 ++++++------
fs/ubifs/xattr.c | 2 +-
fs/udf/namei.c | 11 ++++-------
fs/ufs/ialloc.c | 2 +-
mm/shmem.c | 2 +-
32 files changed, 55 insertions(+), 58 deletions(-)
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 7ae0d0d..baa82f8 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -359,7 +359,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
} else if (mode & S_IFDIR) {
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- parent->d_inode->i_nlink++;
+ inc_nlink(parent->d_inode);
} else
BUG();
inode->i_private = data;
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f1af222..61086ea 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1144,7 +1144,7 @@ static void mtdchar_notify_remove(struct mtd_info *mtd)
if (mtd_ino) {
/* Destroy the inode if it exists */
- mtd_ino->i_nlink = 0;
+ clear_nlink(mtd_ino);
iput(mtd_ino);
}
}
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index 3a4557e..8f12723 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -316,7 +316,7 @@ affs_remove_header(struct dentry *dentry)
if (inode->i_nlink > 1)
retval = affs_remove_link(dentry);
else
- inode->i_nlink = 0;
+ clear_nlink(inode);
affs_unlock_link(inode);
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index e3e9efc..780a11d 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -277,7 +277,7 @@ affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata
inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
error = affs_add_entry(dir, inode, dentry, ST_FILE);
if (error) {
- inode->i_nlink = 0;
+ clear_nlink(inode);
iput(inode);
return error;
}
@@ -305,7 +305,7 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
error = affs_add_entry(dir, inode, dentry, ST_USERDIR);
if (error) {
- inode->i_nlink = 0;
+ clear_nlink(inode);
mark_inode_dirty(inode);
iput(inode);
return error;
@@ -392,7 +392,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
return 0;
err:
- inode->i_nlink = 0;
+ clear_nlink(inode);
mark_inode_dirty(inode);
iput(inode);
return error;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index ba1a1ae..1e9edbd 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -521,7 +521,7 @@ static void kill_node(Node *e)
write_unlock(&entries_lock);
if (dentry) {
- dentry->d_inode->i_nlink--;
+ drop_nlink(dentry->d_inode);
d_drop(dentry);
dput(dentry);
simple_release_fs(&bm_mnt, &entry_count);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index db3f18c..d02e2ff 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -424,7 +424,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
if (old_file->d_inode) {
cifsInode = CIFS_I(old_file->d_inode);
if (rc == 0) {
- old_file->d_inode->i_nlink++;
+ inc_nlink(old_file->d_inode);
/* BB should we make this contingent on superblock flag NOATIME? */
/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
/* parent dir timestamps will update from srv
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 0239433..28e7e13 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -340,7 +340,7 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
if (!error) {
/* VFS may delete the child */
if (de->d_inode)
- de->d_inode->i_nlink = 0;
+ clear_nlink(de->d_inode);
/* fix the link count of the parent */
coda_dir_drop_nlink(dir);
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 2f27e57..c196e54 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -549,7 +549,7 @@ void devpts_pty_kill(struct tty_struct *tty)
dentry = d_find_alias(inode);
- inode->i_nlink--;
+ drop_nlink(inode);
d_delete(dentry);
dput(dentry); /* d_alloc_name() in devpts_pty_new() */
dput(dentry); /* d_find_alias above */
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index ee9ed31..c4e81df 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -601,7 +601,7 @@ fail_free_drop:
fail_drop:
dquot_drop(inode);
inode->i_flags |= S_NOQUOTA;
- inode->i_nlink = 0;
+ clear_nlink(inode);
unlock_new_inode(inode);
iput(inode);
return ERR_PTR(err);
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index bf09cbf..835d4ea 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -621,7 +621,7 @@ fail_free_drop:
fail_drop:
dquot_drop(inode);
inode->i_flags |= S_NOQUOTA;
- inode->i_nlink = 0;
+ clear_nlink(inode);
unlock_new_inode(inode);
iput(inode);
brelse(bitmap_bh);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 0629e09..8a60e33 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1833,7 +1833,7 @@ retry:
if (err) {
out_clear_inode:
- inode->i_nlink = 0;
+ clear_nlink(inode);
unlock_new_inode(inode);
ext3_mark_inode_dirty(handle, inode);
iput (inode);
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 9c63f27..ecc55bd 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1084,7 +1084,7 @@ fail_free_drop:
fail_drop:
dquot_drop(inode);
inode->i_flags |= S_NOQUOTA;
- inode->i_nlink = 0;
+ clear_nlink(inode);
unlock_new_inode(inode);
iput(inode);
brelse(inode_bitmap_bh);
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index b57b98f..667cc88 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -507,7 +507,7 @@ int ext4_ext_migrate(struct inode *inode)
* Set the i_nlink to zero so it will be deleted later
* when we drop inode reference.
*/
- tmp_inode->i_nlink = 0;
+ clear_nlink(tmp_inode);
ext4_ext_tree_init(handle, tmp_inode);
ext4_orphan_add(handle, tmp_inode);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 1c924fa..4623c08 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2539,7 +2539,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
if (new_inode) {
/* checked empty_dir above, can't have another parent,
* ext4_dec_count() won't work for many-linked dirs */
- new_inode->i_nlink = 0;
+ clear_nlink(new_inode);
} else {
ext4_inc_count(handle, new_dir);
ext4_update_dx_flag(new_dir);
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index b4d70b1..bce4eef 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -198,7 +198,7 @@ static int hfs_create(struct inode *dir, struct dentry *dentry, int mode,
res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
if (res) {
- inode->i_nlink = 0;
+ clear_nlink(inode);
hfs_delete_inode(inode);
iput(inode);
return res;
@@ -227,7 +227,7 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
if (res) {
- inode->i_nlink = 0;
+ clear_nlink(inode);
hfs_delete_inode(inode);
iput(inode);
return res;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 25b2443..4536cd3 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -415,7 +415,7 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
goto out;
out_err:
- inode->i_nlink = 0;
+ clear_nlink(inode);
hfsplus_delete_inode(inode);
iput(inode);
out:
@@ -440,7 +440,7 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
if (res) {
- inode->i_nlink = 0;
+ clear_nlink(inode);
hfsplus_delete_inode(inode);
iput(inode);
goto out;
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 338cd83..dfe800c 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -53,7 +53,7 @@ void hpfs_read_inode(struct inode *i)
i->i_mode &= ~0111;
i->i_op = &hpfs_file_iops;
i->i_fop = &hpfs_file_ops;
- i->i_nlink = 0;*/
+ clear_nlink(i);*/
make_bad_inode(i);
return;
}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index ec88953..0be5a78 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -970,7 +970,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
d_instantiate(path.dentry, inode);
inode->i_size = size;
- inode->i_nlink = 0;
+ clear_nlink(inode);
error = -ENFILE;
file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 2686531..c1a3e60 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -157,7 +157,7 @@ fail_drop:
dquot_drop(inode);
inode->i_flags |= S_NOQUOTA;
fail_unlock:
- inode->i_nlink = 0;
+ clear_nlink(inode);
unlock_new_inode(inode);
fail_put:
iput(inode);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index e17545e..94b0a62 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -172,7 +172,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
mutex_unlock(&JFS_IP(dip)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
- ip->i_nlink = 0;
+ clear_nlink(ip);
unlock_new_inode(ip);
iput(ip);
} else {
@@ -311,7 +311,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
mutex_unlock(&JFS_IP(dip)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
- ip->i_nlink = 0;
+ clear_nlink(ip);
unlock_new_inode(ip);
iput(ip);
} else {
@@ -844,7 +844,7 @@ static int jfs_link(struct dentry *old_dentry,
rc = txCommit(tid, 2, &iplist[0], 0);
if (rc) {
- ip->i_nlink--; /* never instantiated */
+ drop_nlink(ip); /* never instantiated */
iput(ip);
} else
d_instantiate(dentry, ip);
@@ -1048,7 +1048,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
mutex_unlock(&JFS_IP(dip)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
- ip->i_nlink = 0;
+ clear_nlink(ip);
unlock_new_inode(ip);
iput(ip);
} else {
@@ -1433,7 +1433,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
mutex_unlock(&JFS_IP(dir)->commit_mutex);
if (rc) {
free_ea_wmap(ip);
- ip->i_nlink = 0;
+ clear_nlink(ip);
unlock_new_inode(ip);
iput(ip);
} else {
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index b3ff3d8..b7d7f67 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -197,7 +197,7 @@ static int logfs_remove_inode(struct inode *inode)
{
int ret;
- inode->i_nlink--;
+ drop_nlink(inode);
ret = write_inode(inode);
LOGFS_BUG_ON(ret, inode->i_sb);
return ret;
@@ -433,7 +433,7 @@ static int __logfs_create(struct inode *dir, struct dentry *dentry,
ta = kzalloc(sizeof(*ta), GFP_KERNEL);
if (!ta) {
- inode->i_nlink--;
+ drop_nlink(inode);
iput(inode);
return -ENOMEM;
}
@@ -456,7 +456,7 @@ static int __logfs_create(struct inode *dir, struct dentry *dentry,
abort_transaction(inode, ta);
li->li_flags |= LOGFS_IF_STILLBORN;
/* FIXME: truncate symlink */
- inode->i_nlink--;
+ drop_nlink(inode);
iput(inode);
goto out;
}
@@ -563,7 +563,7 @@ static int logfs_link(struct dentry *old_dentry, struct inode *dir,
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
ihold(inode);
- inode->i_nlink++;
+ inc_nlink(inode);
mark_inode_dirty_sync(inode);
return __logfs_create(dir, dentry, inode, NULL, 0);
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index 9abb048..7e441ad 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -93,7 +93,7 @@ static struct inode *__logfs_iget(struct super_block *sb, ino_t ino)
/* inode->i_nlink == 0 can be true when called from
* block validator */
/* set i_nlink to 0 to prevent caching */
- inode->i_nlink = 0;
+ clear_nlink(inode);
logfs_inode(inode)->li_flags |= LOGFS_IF_ZOMBIE;
iget_failed(inode);
if (!err)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index fe12037..53e10ff 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -320,7 +320,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
memset(&inode->i_ctime, 0, sizeof(inode->i_ctime));
nfsi->change_attr = 0;
inode->i_size = 0;
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_uid = -2;
inode->i_gid = -2;
inode->i_blocks = 0;
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 666628b..08ac272 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -354,7 +354,7 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
failed_acl:
failed_bmap:
- inode->i_nlink = 0;
+ clear_nlink(inode);
iput(inode); /* raw_inode will be deleted through
generic_delete_inode() */
goto failed;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 0181f63..ea0ecbd 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1377,7 +1377,7 @@ static int ocfs2_rename(struct inode *old_dir,
}
if (new_inode) {
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
new_inode->i_ctime = CURRENT_TIME;
}
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
@@ -1385,9 +1385,9 @@ static int ocfs2_rename(struct inode *old_dir,
if (update_dot_dot) {
status = ocfs2_update_entry(old_inode, handle,
&old_inode_dot_dot_res, new_dir);
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
if (new_inode) {
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
} else {
inc_nlink(new_dir);
mark_inode_dirty(new_dir);
@@ -2280,7 +2280,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
goto leave;
}
- inode->i_nlink = 0;
+ clear_nlink(inode);
/* do the real work now. */
status = __ocfs2_mknod_locked(dir, inode,
0, &new_di_bh, parent_di_bh, handle,
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 1a77dbe..b441132 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -39,7 +39,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
inode->i_fop = &proc_sys_file_operations;
} else {
inode->i_mode |= S_IFDIR;
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_op = &proc_sys_dir_operations;
inode->i_fop = &proc_sys_dir_file_operations;
}
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 9b0d4b7..c425441 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1444,7 +1444,7 @@ void reiserfs_read_locked_inode(struct inode *inode,
/* a stale NFS handle can trigger this without it being an error */
pathrelse(&path_to_sd);
reiserfs_make_bad_inode(inode);
- inode->i_nlink = 0;
+ clear_nlink(inode);
return;
}
@@ -1987,7 +1987,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
make_bad_inode(inode);
out_inserted_sd:
- inode->i_nlink = 0;
+ clear_nlink(inode);
th->t_trans_id = 0; /* so the caller can't use this handle later */
unlock_new_inode(inode); /* OK to do even if we hadn't locked it */
iput(inode);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index ef39232..6ce3328 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -622,7 +622,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
dentry->d_name.len, inode, 1 /*visible */ );
if (retval) {
int err;
- inode->i_nlink--;
+ drop_nlink(inode);
reiserfs_update_sd(&th, inode);
err = journal_end(&th, dir->i_sb, jbegin_count);
if (err)
@@ -702,7 +702,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
dentry->d_name.len, inode, 1 /*visible */ );
if (retval) {
int err;
- inode->i_nlink--;
+ drop_nlink(inode);
reiserfs_update_sd(&th, inode);
err = journal_end(&th, dir->i_sb, jbegin_count);
if (err)
@@ -787,7 +787,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
dentry->d_name.len, inode, 1 /*visible */ );
if (retval) {
int err;
- inode->i_nlink = 0;
+ clear_nlink(inode);
DEC_DIR_INODE_NLINK(dir);
reiserfs_update_sd(&th, inode);
err = journal_end(&th, dir->i_sb, jbegin_count);
@@ -1086,7 +1086,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
dentry->d_name.len, inode, 1 /*visible */ );
if (retval) {
int err;
- inode->i_nlink--;
+ drop_nlink(inode);
reiserfs_update_sd(&th, inode);
err = journal_end(&th, parent_dir->i_sb, jbegin_count);
if (err)
@@ -1129,7 +1129,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
retval = journal_begin(&th, dir->i_sb, jbegin_count);
if (retval) {
- inode->i_nlink--;
+ drop_nlink(inode);
reiserfs_write_unlock(dir->i_sb);
return retval;
}
@@ -1144,7 +1144,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
if (retval) {
int err;
- inode->i_nlink--;
+ drop_nlink(inode);
err = journal_end(&th, dir->i_sb, jbegin_count);
reiserfs_write_unlock(dir->i_sb);
return err ? err : retval;
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 16f19f5..993adc8 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -558,7 +558,7 @@ int ubifs_removexattr(struct dentry *dentry, const char *name)
}
ubifs_assert(inode->i_nlink == 1);
- inode->i_nlink = 0;
+ clear_nlink(inode);
err = remove_xattr(c, host, inode, &nm);
if (err)
inode->i_nlink = 1;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index f1dce84..e8d61b1 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -577,8 +577,7 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (!fi) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
iput(inode);
return err;
}
@@ -618,8 +617,7 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
init_special_inode(inode, mode, rdev);
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (!fi) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
iput(inode);
return err;
}
@@ -665,8 +663,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
inode->i_fop = &udf_dir_operations;
fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
if (!fi) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
iput(inode);
goto out;
}
@@ -683,7 +680,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (!fi) {
- inode->i_nlink = 0;
+ clear_nlink(inode);
mark_inode_dirty(inode);
iput(inode);
goto out;
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 2eabf04..78a4c70 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -341,7 +341,7 @@ cg_found:
fail_remove_inode:
unlock_super(sb);
- inode->i_nlink = 0;
+ clear_nlink(inode);
iput(inode);
UFSD("EXIT (FAILED): err %d\n", err);
return ERR_PTR(err);
diff --git a/mm/shmem.c b/mm/shmem.c
index 32f6763..d06eb8c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2497,7 +2497,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
d_instantiate(path.dentry, inode);
inode->i_size = size;
- inode->i_nlink = 0; /* It is unlinked */
+ clear_nlink(inode); /* It is unlinked */
#ifndef CONFIG_MMU
error = ramfs_nommu_expand_for_mapping(inode, size);
if (error)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 10/13] filesystems: add set_nlink()
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (8 preceding siblings ...)
2011-10-12 14:49 ` [PATCH 09/13] filesystems: add missing nlink wrappers Miklos Szeredi
@ 2011-10-12 14:49 ` Miklos Szeredi
2011-10-13 16:33 ` Steven Whitehouse
2011-10-12 14:49 ` [PATCH 11/13] vfs: protect i_nlink Miklos Szeredi
` (4 subsequent siblings)
14 siblings, 1 reply; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:49 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
Replace remaining direct i_nlink updates with a new set_nlink()
updater function.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
arch/s390/hypfs/inode.c | 2 +-
drivers/staging/pohmelfs/inode.c | 2 +-
fs/9p/vfs_inode.c | 4 ++--
fs/9p/vfs_inode_dotl.c | 4 ++--
fs/adfs/inode.c | 2 +-
fs/affs/amigaffs.c | 2 +-
fs/affs/inode.c | 8 ++++----
fs/afs/fsclient.c | 2 +-
fs/afs/inode.c | 4 ++--
fs/autofs4/inode.c | 2 +-
fs/befs/linuxvfs.c | 2 +-
fs/bfs/dir.c | 2 +-
fs/bfs/inode.c | 2 +-
fs/btrfs/delayed-inode.c | 2 +-
fs/btrfs/disk-io.c | 2 +-
fs/btrfs/inode.c | 4 ++--
fs/btrfs/tree-log.c | 2 +-
fs/ceph/caps.c | 2 +-
fs/ceph/inode.c | 2 +-
fs/cifs/inode.c | 6 +++---
fs/coda/coda_linux.c | 2 +-
fs/devpts/inode.c | 2 +-
fs/ecryptfs/inode.c | 12 ++++++------
fs/efs/inode.c | 2 +-
fs/exofs/inode.c | 2 +-
fs/ext2/inode.c | 2 +-
fs/ext3/inode.c | 2 +-
fs/ext3/namei.c | 4 ++--
fs/ext4/inode.c | 2 +-
fs/ext4/namei.c | 6 +++---
fs/fat/inode.c | 4 ++--
fs/fat/namei_msdos.c | 2 +-
fs/fat/namei_vfat.c | 2 +-
fs/freevxfs/vxfs_inode.c | 2 +-
fs/fuse/control.c | 2 +-
fs/fuse/inode.c | 2 +-
fs/gfs2/glops.c | 2 +-
fs/hfs/inode.c | 4 ++--
fs/hfsplus/inode.c | 10 +++++-----
fs/hostfs/hostfs_kern.c | 2 +-
fs/hpfs/dir.c | 2 +-
fs/hpfs/inode.c | 8 ++++----
fs/hpfs/namei.c | 8 ++++----
fs/hppfs/hppfs.c | 2 +-
fs/isofs/inode.c | 4 ++--
fs/isofs/rock.c | 4 ++--
fs/jffs2/dir.c | 6 +++---
fs/jffs2/fs.c | 6 +++---
fs/jfs/jfs_imap.c | 6 +++---
fs/jfs/namei.c | 2 +-
fs/libfs.c | 2 +-
fs/logfs/readwrite.c | 2 +-
fs/minix/inode.c | 4 ++--
fs/ncpfs/inode.c | 2 +-
fs/nfs/inode.c | 4 ++--
fs/nilfs2/inode.c | 2 +-
fs/nilfs2/namei.c | 2 +-
fs/ntfs/inode.c | 8 ++++----
fs/ocfs2/dir.c | 4 ++--
fs/ocfs2/dlmglue.c | 2 +-
fs/ocfs2/inode.c | 4 ++--
fs/ocfs2/namei.c | 8 ++++----
fs/openpromfs/inode.c | 4 ++--
fs/proc/base.c | 12 ++++++------
fs/proc/generic.c | 2 +-
fs/proc/inode.c | 2 +-
fs/qnx4/inode.c | 2 +-
fs/reiserfs/inode.c | 6 +++---
fs/reiserfs/namei.c | 4 ++--
fs/romfs/super.c | 2 +-
fs/squashfs/inode.c | 18 +++++++++---------
fs/stack.c | 2 +-
fs/sysfs/inode.c | 2 +-
fs/sysv/inode.c | 2 +-
fs/ubifs/super.c | 2 +-
fs/ubifs/xattr.c | 2 +-
fs/udf/inode.c | 8 +++++---
fs/udf/namei.c | 4 ++--
fs/ufs/inode.c | 4 ++--
fs/xfs/xfs_iops.c | 2 +-
include/linux/fs.h | 13 +++++++++++++
81 files changed, 163 insertions(+), 148 deletions(-)
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index baa82f8..481f4f7 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -108,7 +108,7 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
ret->i_gid = hypfs_info->gid;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
if (mode & S_IFDIR)
- ret->i_nlink = 2;
+ set_nlink(ret, 2);
}
return ret;
}
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index f3c6060..7a19555 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -1197,7 +1197,7 @@ const struct inode_operations pohmelfs_file_inode_operations = {
void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
{
inode->i_mode = info->mode;
- inode->i_nlink = info->nlink;
+ set_nlink(inode, info->nlink);
inode->i_uid = info->uid;
inode->i_gid = info->gid;
inode->i_blocks = info->blocks;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index e3c03db..5aaaec7 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1140,7 +1140,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
struct v9fs_session_info *v9ses = sb->s_fs_info;
struct v9fs_inode *v9inode = V9FS_I(inode);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_atime.tv_sec = stat->atime;
inode->i_mtime.tv_sec = stat->mtime;
@@ -1166,7 +1166,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
/* HARDLINKCOUNT %u */
sscanf(ext, "%13s %u", tag_name, &i_nlink);
if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
- inode->i_nlink = i_nlink;
+ set_nlink(inode, i_nlink);
}
}
mode = stat->mode & S_IALLUGO;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index aded79f..0b5745e 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -606,7 +606,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
inode->i_uid = stat->st_uid;
inode->i_gid = stat->st_gid;
- inode->i_nlink = stat->st_nlink;
+ set_nlink(inode, stat->st_nlink);
mode = stat->st_mode & S_IALLUGO;
mode |= inode->i_mode & ~S_IALLUGO;
@@ -632,7 +632,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
if (stat->st_result_mask & P9_STATS_GID)
inode->i_gid = stat->st_gid;
if (stat->st_result_mask & P9_STATS_NLINK)
- inode->i_nlink = stat->st_nlink;
+ set_nlink(inode, stat->st_nlink);
if (stat->st_result_mask & P9_STATS_MODE) {
inode->i_mode = stat->st_mode;
if ((S_ISBLK(inode->i_mode)) ||
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index d5250c5..1dab6a1 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -247,7 +247,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
inode->i_gid = ADFS_SB(sb)->s_gid;
inode->i_ino = obj->file_id;
inode->i_size = obj->size;
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >>
sb->s_blocksize_bits;
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index 8f12723..de37ec8 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -215,7 +215,7 @@ affs_remove_link(struct dentry *dentry)
break;
default:
if (!AFFS_TAIL(sb, bh)->link_chain)
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
affs_free_block(sb, link_ino);
goto done;
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 5d82890..88a4b0b 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -54,7 +54,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
prot = be32_to_cpu(tail->protect);
inode->i_size = 0;
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_mode = 0;
AFFS_I(inode)->i_extcnt = 1;
AFFS_I(inode)->i_ext_last = ~1;
@@ -137,7 +137,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
sbi->s_hashsize + 1;
}
if (tail->link_chain)
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_mapping->a_ops = (sbi->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
inode->i_op = &affs_file_inode_operations;
inode->i_fop = &affs_file_operations;
@@ -304,7 +304,7 @@ affs_new_inode(struct inode *dir)
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
inode->i_ino = block;
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
atomic_set(&AFFS_I(inode)->i_opencnt, 0);
AFFS_I(inode)->i_blkcnt = 0;
@@ -387,7 +387,7 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3
AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
mark_buffer_dirty_inode(inode_bh, inode);
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
ihold(inode);
}
affs_fix_checksum(sb, bh);
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 346e328..2f213d1 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -90,7 +90,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
vnode->vfs_inode.i_uid = status->owner;
vnode->vfs_inode.i_gid = status->group;
vnode->vfs_inode.i_generation = vnode->fid.unique;
- vnode->vfs_inode.i_nlink = status->nlink;
+ set_nlink(&vnode->vfs_inode, status->nlink);
mode = vnode->vfs_inode.i_mode;
mode &= ~S_IALLUGO;
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 0fdab6e..d890ae3 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -67,7 +67,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
fscache_attr_changed(vnode->cache);
#endif
- inode->i_nlink = vnode->status.nlink;
+ set_nlink(inode, vnode->status.nlink);
inode->i_uid = vnode->status.owner;
inode->i_gid = 0;
inode->i_size = vnode->status.size;
@@ -174,7 +174,7 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name,
inode->i_size = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
inode->i_op = &afs_autocell_inode_operations;
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_uid = 0;
inode->i_gid = 0;
inode->i_ctime.tv_sec = get_seconds();
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 180fa24..8179f1a 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -342,7 +342,7 @@ struct inode *autofs4_get_inode(struct super_block *sb, mode_t mode)
inode->i_ino = get_next_ino();
if (S_ISDIR(mode)) {
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_op = &autofs4_dir_inode_operations;
inode->i_fop = &autofs4_dir_operations;
} else if (S_ISLNK(mode)) {
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 720d885..8342ca6 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -357,7 +357,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
inode->i_gid = befs_sb->mount_opts.use_gid ?
befs_sb->mount_opts.gid : (gid_t) fs32_to_cpu(sb, raw_inode->gid);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
/*
* BEFS's time is 64 bits, but current VFS is 32 bits...
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index b14cebf..9cc0740 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -199,7 +199,7 @@ static int bfs_unlink(struct inode *dir, struct dentry *dentry)
printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
inode->i_sb->s_id, inode->i_ino,
inode->i_nlink);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
de->ino = 0;
mark_buffer_dirty_inode(bh, dir);
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index a8e37f8..697af5b 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -78,7 +78,7 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino);
inode->i_uid = le32_to_cpu(di->i_uid);
inode->i_gid = le32_to_cpu(di->i_gid);
- inode->i_nlink = le32_to_cpu(di->i_nlink);
+ set_nlink(inode, le32_to_cpu(di->i_nlink));
inode->i_size = BFS_FILESIZE(di);
inode->i_blocks = BFS_FILEBLOCKS(di);
inode->i_atime.tv_sec = le32_to_cpu(di->i_atime);
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index b52c672..ae4d9cd 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1641,7 +1641,7 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev)
inode->i_gid = btrfs_stack_inode_gid(inode_item);
btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item));
inode->i_mode = btrfs_stack_inode_mode(inode_item);
- inode->i_nlink = btrfs_stack_inode_nlink(inode_item);
+ set_nlink(inode, btrfs_stack_inode_nlink(inode_item));
inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item));
BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item);
BTRFS_I(inode)->sequence = btrfs_stack_inode_sequence(inode_item);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 07b3ac6..07ea918 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1705,7 +1705,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
sb->s_bdi = &fs_info->bdi;
fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID;
- fs_info->btree_inode->i_nlink = 1;
+ set_nlink(fs_info->btree_inode, 1);
/*
* we set the i_size on the btree inode to the max possible int.
* the real end of the address space is determined by all of
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b2d004a..75686a6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2534,7 +2534,7 @@ static void btrfs_read_locked_inode(struct inode *inode)
inode_item = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_inode_item);
inode->i_mode = btrfs_inode_mode(leaf, inode_item);
- inode->i_nlink = btrfs_inode_nlink(leaf, inode_item);
+ set_nlink(inode, btrfs_inode_nlink(leaf, inode_item));
inode->i_uid = btrfs_inode_uid(leaf, inode_item);
inode->i_gid = btrfs_inode_gid(leaf, inode_item);
btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item));
@@ -6728,7 +6728,7 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
inode->i_op = &btrfs_dir_inode_operations;
inode->i_fop = &btrfs_dir_file_operations;
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
btrfs_i_size_write(inode, 0);
err = btrfs_update_inode(trans, new_root, inode);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 786639f..0618aa3 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1030,7 +1030,7 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
}
btrfs_release_path(path);
if (nlink != inode->i_nlink) {
- inode->i_nlink = nlink;
+ set_nlink(inode, nlink);
btrfs_update_inode(trans, root, inode);
}
BTRFS_I(inode)->index_cnt = (u64)-1;
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 8d74ad7..8c00ada 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2363,7 +2363,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
}
if ((issued & CEPH_CAP_LINK_EXCL) == 0)
- inode->i_nlink = le32_to_cpu(grant->nlink);
+ set_nlink(inode, le32_to_cpu(grant->nlink));
if ((issued & CEPH_CAP_XATTR_EXCL) == 0 && grant->xattr_len) {
int len = le32_to_cpu(grant->xattr_len);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 095799b..2dfbcee 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -619,7 +619,7 @@ static int fill_inode(struct inode *inode,
}
if ((issued & CEPH_CAP_LINK_EXCL) == 0)
- inode->i_nlink = le32_to_cpu(info->nlink);
+ set_nlink(inode, le32_to_cpu(info->nlink));
/* be careful with mtime, atime, size */
ceph_decode_timespec(&atime, &info->atime);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a7b2dcd..7989118 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -132,7 +132,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
inode->i_mtime = fattr->cf_mtime;
inode->i_ctime = fattr->cf_ctime;
inode->i_rdev = fattr->cf_rdev;
- inode->i_nlink = fattr->cf_nlink;
+ set_nlink(inode, fattr->cf_nlink);
inode->i_uid = fattr->cf_uid;
inode->i_gid = fattr->cf_gid;
@@ -900,7 +900,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
if (rc && tcon->ipc) {
cFYI(1, "ipc connection - fake read inode");
inode->i_mode |= S_IFDIR;
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_op = &cifs_ipc_inode_ops;
inode->i_fop = &simple_dir_operations;
inode->i_uid = cifs_sb->mnt_uid;
@@ -1362,7 +1362,7 @@ mkdir_get_info:
/* setting nlink not necessary except in cases where we
* failed to get it from the server or was set bogus */
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
- direntry->d_inode->i_nlink = 2;
+ set_nlink(direntry->d_inode, 2);
mode &= ~current_umask();
/* must turn on setgid bit if parent dir has it */
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index 2bdbcc1..854ace7 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -104,7 +104,7 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
if (attr->va_gid != -1)
inode->i_gid = (gid_t) attr->va_gid;
if (attr->va_nlink != -1)
- inode->i_nlink = attr->va_nlink;
+ set_nlink(inode, attr->va_nlink);
if (attr->va_size != -1)
inode->i_size = attr->va_size;
if (attr->va_size != -1)
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index c196e54..d5d5297 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -307,7 +307,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
s->s_root = d_alloc_root(inode);
if (s->s_root)
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 11f8582..a36d327 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -474,8 +474,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
goto out_lock;
fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
- old_dentry->d_inode->i_nlink =
- ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
+ set_nlink(old_dentry->d_inode,
+ ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink);
i_size_write(new_dentry->d_inode, file_size_save);
out_lock:
unlock_dir(lower_dir_dentry);
@@ -499,8 +499,8 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
goto out_unlock;
}
fsstack_copy_attr_times(dir, lower_dir_inode);
- dentry->d_inode->i_nlink =
- ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
+ set_nlink(dentry->d_inode,
+ ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink);
dentry->d_inode->i_ctime = dir->i_ctime;
d_drop(dentry);
out_unlock:
@@ -565,7 +565,7 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
goto out;
fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
- dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+ set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
out:
unlock_dir(lower_dir_dentry);
if (!dentry->d_inode)
@@ -588,7 +588,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
if (!rc && dentry->d_inode)
clear_nlink(dentry->d_inode);
fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
- dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+ set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
unlock_dir(lower_dir_dentry);
if (!rc)
d_drop(dentry);
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index 9c13412..bc84f36 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -96,7 +96,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino)
efs_inode = (struct efs_dinode *) (bh->b_data + offset);
inode->i_mode = be16_to_cpu(efs_inode->di_mode);
- inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
+ set_nlink(inode, be16_to_cpu(efs_inode->di_nlink));
inode->i_uid = (uid_t)be16_to_cpu(efs_inode->di_uid);
inode->i_gid = (gid_t)be16_to_cpu(efs_inode->di_gid);
inode->i_size = be32_to_cpu(efs_inode->di_size);
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index f39a38f..a81976f 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -1032,7 +1032,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
inode->i_mode = le16_to_cpu(fcb.i_mode);
inode->i_uid = le32_to_cpu(fcb.i_uid);
inode->i_gid = le32_to_cpu(fcb.i_gid);
- inode->i_nlink = le16_to_cpu(fcb.i_links_count);
+ set_nlink(inode, le16_to_cpu(fcb.i_links_count));
inode->i_ctime.tv_sec = (signed)le32_to_cpu(fcb.i_ctime);
inode->i_atime.tv_sec = (signed)le32_to_cpu(fcb.i_atime);
inode->i_mtime.tv_sec = (signed)le32_to_cpu(fcb.i_mtime);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a8a58f6..91a6945 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1321,7 +1321,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
}
- inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
inode->i_size = le32_to_cpu(raw_inode->i_size);
inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 12661e1..85fe655 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2899,7 +2899,7 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino)
inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
}
- inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
inode->i_size = le32_to_cpu(raw_inode->i_size);
inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 8a60e33..642dc6d 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1821,7 +1821,7 @@ retry:
de->name_len = 2;
strcpy (de->name, "..");
ext3_set_de_type(dir->i_sb, de, S_IFDIR);
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
err = ext3_journal_dirty_metadata(handle, dir_block);
if (err)
@@ -2170,7 +2170,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
ext3_warning (inode->i_sb, "ext3_unlink",
"Deleting nonexistent file (%lu), %d",
inode->i_ino, inode->i_nlink);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
retval = ext3_delete_entry(handle, dir, de, bh);
if (retval)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 986e238..989440e 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3414,7 +3414,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
}
- inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */
ei->i_dir_start_lookup = 0;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 4623c08..5f7fb46 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1694,7 +1694,7 @@ static void ext4_inc_count(handle_t *handle, struct inode *inode)
if (is_dx(inode) && inode->i_nlink > 1) {
/* limit is 16-bit i_links_count */
if (inode->i_nlink >= EXT4_LINK_MAX || inode->i_nlink == 2) {
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
EXT4_SET_RO_COMPAT_FEATURE(inode->i_sb,
EXT4_FEATURE_RO_COMPAT_DIR_NLINK);
}
@@ -1861,7 +1861,7 @@ retry:
de->name_len = 2;
strcpy(de->name, "..");
ext4_set_de_type(dir->i_sb, de, S_IFDIR);
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
err = ext4_handle_dirty_metadata(handle, dir, dir_block);
if (err)
@@ -2214,7 +2214,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
ext4_warning(inode->i_sb,
"Deleting nonexistent file (%lu), %d",
inode->i_ino, inode->i_nlink);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
retval = ext4_delete_entry(handle, dir, de, bh);
if (retval)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 1726d73..808cac7 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -379,7 +379,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
return error;
MSDOS_I(inode)->mmu_private = inode->i_size;
- inode->i_nlink = fat_subdirs(inode);
+ set_nlink(inode, fat_subdirs(inode));
} else { /* not a directory */
inode->i_generation |= 1;
inode->i_mode = fat_make_mode(sbi, de->attr,
@@ -1233,7 +1233,7 @@ static int fat_read_root(struct inode *inode)
fat_save_attrs(inode, ATTR_DIR);
inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
- inode->i_nlink = fat_subdirs(inode)+2;
+ set_nlink(inode, fat_subdirs(inode)+2);
return 0;
}
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 66e83b8..216b419 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -387,7 +387,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
/* the directory was completed, just return a error */
goto out;
}
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index bb3f29c..a87a656 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -900,7 +900,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
goto out;
}
inode->i_version++;
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 1a43114..7b2af5a 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -227,7 +227,7 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
ip->i_uid = (uid_t)vip->vii_uid;
ip->i_gid = (gid_t)vip->vii_gid;
- ip->i_nlink = vip->vii_nlink;
+ set_nlink(ip, vip->vii_nlink);
ip->i_size = vip->vii_size;
ip->i_atime.tv_sec = vip->vii_atime;
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 85542a7..42593c5 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -231,7 +231,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
if (iop)
inode->i_op = iop;
inode->i_fop = fop;
- inode->i_nlink = nlink;
+ set_nlink(inode, nlink);
inode->i_private = fc;
d_add(dentry, inode);
return dentry;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index add96f6..3e6d727 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -151,7 +151,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
inode->i_ino = attr->ino;
inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
- inode->i_nlink = attr->nlink;
+ set_nlink(inode, attr->nlink);
inode->i_uid = attr->uid;
inode->i_gid = attr->gid;
inode->i_blocks = attr->blocks;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index da21eca..102cf5e 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -277,7 +277,7 @@ static void gfs2_set_nlink(struct inode *inode, u32 nlink)
if (nlink == 0)
clear_nlink(inode);
else
- inode->i_nlink = nlink;
+ set_nlink(inode, nlink);
}
}
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 96a1b62..a1a9fdc 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -183,7 +183,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
inode->i_mode = mode;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
HFS_I(inode)->flags = 0;
HFS_I(inode)->rsrc_inode = NULL;
@@ -313,7 +313,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
/* Initialize the inode */
inode->i_uid = hsb->s_uid;
inode->i_gid = hsb->s_gid;
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
if (idata->key)
HFS_I(inode)->cat_key = *idata->key;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 4cc1e3a..40e1413 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -391,7 +391,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
inode->i_mode = mode;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
hip = HFSPLUS_I(inode);
@@ -512,7 +512,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
sizeof(struct hfsplus_cat_folder));
hfsplus_get_perms(inode, &folder->permissions, 1);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_size = 2 + be32_to_cpu(folder->valence);
inode->i_atime = hfsp_mt2ut(folder->access_date);
inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
@@ -532,11 +532,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
&file->rsrc_fork : &file->data_fork);
hfsplus_get_perms(inode, &file->permissions, 0);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
if (S_ISREG(inode->i_mode)) {
if (file->permissions.dev)
- inode->i_nlink =
- be32_to_cpu(file->permissions.dev);
+ set_nlink(inode,
+ be32_to_cpu(file->permissions.dev));
inode->i_op = &hfsplus_file_inode_operations;
inode->i_fop = &hfsplus_file_operations;
inode->i_mapping->a_ops = &hfsplus_aops;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 0d22afd..2f72da5 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -541,7 +541,7 @@ static int read_name(struct inode *ino, char *name)
ino->i_ino = st.ino;
ino->i_mode = st.mode;
- ino->i_nlink = st.nlink;
+ set_nlink(ino, st.nlink);
ino->i_uid = st.uid;
ino->i_gid = st.gid;
ino->i_atime = st.atime;
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 96a8ed9..2fa0089 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -247,7 +247,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
result->i_mode &= ~0111;
result->i_op = &hpfs_file_iops;
result->i_fop = &hpfs_file_ops;
- result->i_nlink = 1;
+ set_nlink(result, 1);
}
unlock_new_inode(result);
}
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index dfe800c..3b2cec2 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -77,7 +77,7 @@ void hpfs_read_inode(struct inode *i)
i->i_mode = S_IFLNK | 0777;
i->i_op = &page_symlink_inode_operations;
i->i_data.a_ops = &hpfs_symlink_aops;
- i->i_nlink = 1;
+ set_nlink(i, 1);
i->i_size = ea_size;
i->i_blocks = 1;
brelse(bh);
@@ -101,7 +101,7 @@ void hpfs_read_inode(struct inode *i)
}
if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
brelse(bh);
- i->i_nlink = 1;
+ set_nlink(i, 1);
i->i_size = 0;
i->i_blocks = 1;
init_special_inode(i, mode,
@@ -125,13 +125,13 @@ void hpfs_read_inode(struct inode *i)
hpfs_count_dnodes(i->i_sb, hpfs_inode->i_dno, &n_dnodes, &n_subdirs, NULL);
i->i_blocks = 4 * n_dnodes;
i->i_size = 2048 * n_dnodes;
- i->i_nlink = 2 + n_subdirs;
+ set_nlink(i, 2 + n_subdirs);
} else {
i->i_mode |= S_IFREG;
if (!hpfs_inode->i_ea_mode) i->i_mode &= ~0111;
i->i_op = &hpfs_file_iops;
i->i_fop = &hpfs_file_ops;
- i->i_nlink = 1;
+ set_nlink(i, 1);
i->i_size = le32_to_cpu(fnode->file_size);
i->i_blocks = ((i->i_size + 511) >> 9) + 1;
i->i_data.a_ops = &hpfs_aops;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 2df69e2..ea91fcb 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -56,7 +56,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
result->i_fop = &hpfs_dir_ops;
result->i_blocks = 4;
result->i_size = 2048;
- result->i_nlink = 2;
+ set_nlink(result, 2);
if (dee.read_only)
result->i_mode &= ~0222;
@@ -150,7 +150,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
result->i_mode &= ~0111;
result->i_op = &hpfs_file_iops;
result->i_fop = &hpfs_file_ops;
- result->i_nlink = 1;
+ set_nlink(result, 1);
hpfs_i(result)->i_parent_dir = dir->i_ino;
result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
result->i_ctime.tv_nsec = 0;
@@ -242,7 +242,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
hpfs_i(result)->i_ea_size = 0;
result->i_uid = current_fsuid();
result->i_gid = current_fsgid();
- result->i_nlink = 1;
+ set_nlink(result, 1);
result->i_size = 0;
result->i_blocks = 1;
init_special_inode(result, mode, rdev);
@@ -318,7 +318,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
result->i_uid = current_fsuid();
result->i_gid = current_fsgid();
result->i_blocks = 1;
- result->i_nlink = 1;
+ set_nlink(result, 1);
result->i_size = strlen(symlink);
result->i_op = &page_symlink_inode_operations;
result->i_data.a_ops = &hpfs_symlink_aops;
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 970ea98..f590b11 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -702,7 +702,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
inode->i_ctime = proc_ino->i_ctime;
inode->i_ino = proc_ino->i_ino;
inode->i_mode = proc_ino->i_mode;
- inode->i_nlink = proc_ino->i_nlink;
+ set_nlink(inode, proc_ino->i_nlink);
inode->i_size = proc_ino->i_size;
inode->i_blocks = proc_ino->i_blocks;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index a5d0367..562adab 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -1319,7 +1319,7 @@ static int isofs_read_inode(struct inode *inode)
inode->i_mode = S_IFDIR | sbi->s_dmode;
else
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
- inode->i_nlink = 1; /*
+ set_nlink(inode, 1); /*
* Set to 1. We know there are 2, but
* the find utility tries to optimize
* if it is 2, and it screws up. It is
@@ -1337,7 +1337,7 @@ static int isofs_read_inode(struct inode *inode)
*/
inode->i_mode = S_IFREG | S_IRUGO | S_IXUGO;
}
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
inode->i_uid = sbi->s_uid;
inode->i_gid = sbi->s_gid;
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 1fbc7de..70e79d0 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -363,7 +363,7 @@ repeat:
break;
case SIG('P', 'X'):
inode->i_mode = isonum_733(rr->u.PX.mode);
- inode->i_nlink = isonum_733(rr->u.PX.n_links);
+ set_nlink(inode, isonum_733(rr->u.PX.n_links));
inode->i_uid = isonum_733(rr->u.PX.uid);
inode->i_gid = isonum_733(rr->u.PX.gid);
break;
@@ -496,7 +496,7 @@ repeat:
goto out;
}
inode->i_mode = reloc->i_mode;
- inode->i_nlink = reloc->i_nlink;
+ set_nlink(inode, reloc->i_nlink);
inode->i_uid = reloc->i_uid;
inode->i_gid = reloc->i_gid;
inode->i_rdev = reloc->i_rdev;
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 9659b7c..be6169b 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -245,7 +245,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
dentry->d_name.len, dead_f, now);
if (dead_f->inocache)
- dentry->d_inode->i_nlink = dead_f->inocache->pino_nlink;
+ set_nlink(dentry->d_inode, dead_f->inocache->pino_nlink);
if (!ret)
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
return ret;
@@ -278,7 +278,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
if (!ret) {
mutex_lock(&f->sem);
- old_dentry->d_inode->i_nlink = ++f->inocache->pino_nlink;
+ set_nlink(old_dentry->d_inode, ++f->inocache->pino_nlink);
mutex_unlock(&f->sem);
d_instantiate(dentry, old_dentry->d_inode);
dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
@@ -497,7 +497,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
f = JFFS2_INODE_INFO(inode);
/* Directories get nlink 2 at start */
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
/* but ic->pino_nlink is the parent ino# */
f->inocache->pino_nlink = dir_i->i_ino;
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index bbcb975..7286e44 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -278,7 +278,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
- inode->i_nlink = f->inocache->pino_nlink;
+ set_nlink(inode, f->inocache->pino_nlink);
inode->i_blocks = (inode->i_size + 511) >> 9;
@@ -291,7 +291,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
case S_IFDIR:
{
struct jffs2_full_dirent *fd;
- inode->i_nlink = 2; /* parent and '.' */
+ set_nlink(inode, 2); /* parent and '.' */
for (fd=f->dents; fd; fd = fd->next) {
if (fd->type == DT_DIR && fd->ino)
@@ -453,7 +453,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r
iput(inode);
return ERR_PTR(ret);
}
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_ino = je32_to_cpu(ri->ino);
inode->i_mode = jemode_to_cpu(ri->mode);
inode->i_gid = je16_to_cpu(ri->gid);
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index b78b2f9..1b6f15f 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -457,7 +457,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
/* read the page of fixed disk inode (AIT) in raw mode */
mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1);
if (mp == NULL) {
- ip->i_nlink = 1; /* Don't want iput() deleting it */
+ set_nlink(ip, 1); /* Don't want iput() deleting it */
iput(ip);
return (NULL);
}
@@ -469,7 +469,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
/* copy on-disk inode to in-memory inode */
if ((copy_from_dinode(dp, ip)) != 0) {
/* handle bad return by returning NULL for ip */
- ip->i_nlink = 1; /* Don't want iput() deleting it */
+ set_nlink(ip, 1); /* Don't want iput() deleting it */
iput(ip);
/* release the page */
release_metapage(mp);
@@ -3076,7 +3076,7 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
ip->i_mode |= 0001;
}
}
- ip->i_nlink = le32_to_cpu(dip->di_nlink);
+ set_nlink(ip, le32_to_cpu(dip->di_nlink));
jfs_ip->saved_uid = le32_to_cpu(dip->di_uid);
if (sbi->uid == -1)
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 94b0a62..a112ad9 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -292,7 +292,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
goto out3;
}
- ip->i_nlink = 2; /* for '.' */
+ set_nlink(ip, 2); /* for '.' */
ip->i_op = &jfs_dir_inode_operations;
ip->i_fop = &jfs_dir_operations;
diff --git a/fs/libfs.c b/fs/libfs.c
index c18e9a1..fe3ec42 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -490,7 +490,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
root = d_alloc_root(inode);
if (!root) {
iput(inode);
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index d8d0938..2ac4217 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -126,7 +126,7 @@ static void logfs_disk_to_inode(struct logfs_disk_inode *di, struct inode*inode)
inode->i_atime = be64_to_timespec(di->di_atime);
inode->i_ctime = be64_to_timespec(di->di_ctime);
inode->i_mtime = be64_to_timespec(di->di_mtime);
- inode->i_nlink = be32_to_cpu(di->di_refcount);
+ set_nlink(inode, be32_to_cpu(di->di_refcount));
inode->i_generation = be32_to_cpu(di->di_generation);
switch (inode->i_mode & S_IFMT) {
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index e7d23e2..64cdcd6 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -446,7 +446,7 @@ static struct inode *V1_minix_iget(struct inode *inode)
inode->i_mode = raw_inode->i_mode;
inode->i_uid = (uid_t)raw_inode->i_uid;
inode->i_gid = (gid_t)raw_inode->i_gid;
- inode->i_nlink = raw_inode->i_nlinks;
+ set_nlink(inode, raw_inode->i_nlinks);
inode->i_size = raw_inode->i_size;
inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = raw_inode->i_time;
inode->i_mtime.tv_nsec = 0;
@@ -479,7 +479,7 @@ static struct inode *V2_minix_iget(struct inode *inode)
inode->i_mode = raw_inode->i_mode;
inode->i_uid = (uid_t)raw_inode->i_uid;
inode->i_gid = (gid_t)raw_inode->i_gid;
- inode->i_nlink = raw_inode->i_nlinks;
+ set_nlink(inode, raw_inode->i_nlinks);
inode->i_size = raw_inode->i_size;
inode->i_mtime.tv_sec = raw_inode->i_mtime;
inode->i_atime.tv_sec = raw_inode->i_atime;
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 202f370..5b5fa33 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -228,7 +228,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_uid = server->m.uid;
inode->i_gid = server->m.gid;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 53e10ff..109dbae 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -355,7 +355,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
| NFS_INO_INVALID_DATA
| NFS_INO_REVAL_PAGECACHE;
if (fattr->valid & NFS_ATTR_FATTR_NLINK)
- inode->i_nlink = fattr->nlink;
+ set_nlink(inode, fattr->nlink);
else if (nfs_server_capable(inode, NFS_CAP_NLINK))
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
if (fattr->valid & NFS_ATTR_FATTR_OWNER)
@@ -1361,7 +1361,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
invalid |= NFS_INO_INVALID_ATTR;
if (S_ISDIR(inode->i_mode))
invalid |= NFS_INO_INVALID_DATA;
- inode->i_nlink = fattr->nlink;
+ set_nlink(inode, fattr->nlink);
}
} else if (server->caps & NFS_CAP_NLINK)
invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 08ac272..b50ffb7 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -396,7 +396,7 @@ int nilfs_read_inode_common(struct inode *inode,
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_uid = (uid_t)le32_to_cpu(raw_inode->i_uid);
inode->i_gid = (gid_t)le32_to_cpu(raw_inode->i_gid);
- inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
inode->i_size = le64_to_cpu(raw_inode->i_size);
inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index a314199..768982d 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -289,7 +289,7 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
nilfs_warning(inode->i_sb, __func__,
"deleting nonexistent file (%lu), %d\n",
inode->i_ino, inode->i_nlink);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
err = nilfs_delete_entry(de, page);
if (err)
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 1371487..97e2dac 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -612,7 +612,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
* might be tricky due to vfs interactions. Need to think about this
* some more when implementing the unlink command.
*/
- vi->i_nlink = le16_to_cpu(m->link_count);
+ set_nlink(vi, le16_to_cpu(m->link_count));
/*
* FIXME: Reparse points can have the directory bit set even though
* they would be S_IFLNK. Need to deal with this further below when we
@@ -634,7 +634,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
vi->i_mode &= ~vol->dmask;
/* Things break without this kludge! */
if (vi->i_nlink > 1)
- vi->i_nlink = 1;
+ set_nlink(vi, 1);
} else {
vi->i_mode |= S_IFREG;
/* Apply the file permissions mask set in the mount options. */
@@ -1242,7 +1242,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
vi->i_version = base_vi->i_version;
vi->i_uid = base_vi->i_uid;
vi->i_gid = base_vi->i_gid;
- vi->i_nlink = base_vi->i_nlink;
+ set_nlink(vi, base_vi->i_nlink);
vi->i_mtime = base_vi->i_mtime;
vi->i_ctime = base_vi->i_ctime;
vi->i_atime = base_vi->i_atime;
@@ -1508,7 +1508,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
vi->i_version = base_vi->i_version;
vi->i_uid = base_vi->i_uid;
vi->i_gid = base_vi->i_gid;
- vi->i_nlink = base_vi->i_nlink;
+ set_nlink(vi, base_vi->i_nlink);
vi->i_mtime = base_vi->i_mtime;
vi->i_ctime = base_vi->i_ctime;
vi->i_atime = base_vi->i_atime;
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 8582e3f..e2878b5 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -2292,7 +2292,7 @@ static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
ocfs2_journal_dirty(handle, di_bh);
i_size_write(inode, size);
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_blocks = ocfs2_inode_sector_count(inode);
ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
@@ -2354,7 +2354,7 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
ocfs2_journal_dirty(handle, new_bh);
i_size_write(inode, inode->i_sb->s_blocksize);
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode->i_blocks = ocfs2_inode_sector_count(inode);
status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
if (status < 0) {
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 7642d7c..e1ed5e5 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2092,7 +2092,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
inode->i_uid = be32_to_cpu(lvb->lvb_iuid);
inode->i_gid = be32_to_cpu(lvb->lvb_igid);
inode->i_mode = be16_to_cpu(lvb->lvb_imode);
- inode->i_nlink = be16_to_cpu(lvb->lvb_inlink);
+ set_nlink(inode, be16_to_cpu(lvb->lvb_inlink));
ocfs2_unpack_timespec(&inode->i_atime,
be64_to_cpu(lvb->lvb_iatime_packed));
ocfs2_unpack_timespec(&inode->i_mtime,
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index b4c8bb6..a22d2c0 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -291,7 +291,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
(unsigned long long)OCFS2_I(inode)->ip_blkno,
(unsigned long long)le64_to_cpu(fe->i_blkno));
- inode->i_nlink = ocfs2_read_links_count(fe);
+ set_nlink(inode, ocfs2_read_links_count(fe));
trace_ocfs2_populate_inode(OCFS2_I(inode)->ip_blkno,
le32_to_cpu(fe->i_flags));
@@ -1290,7 +1290,7 @@ void ocfs2_refresh_inode(struct inode *inode,
OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
ocfs2_set_inode_flags(inode);
i_size_write(inode, le64_to_cpu(fe->i_size));
- inode->i_nlink = ocfs2_read_links_count(fe);
+ set_nlink(inode, ocfs2_read_links_count(fe));
inode->i_uid = le32_to_cpu(fe->i_uid);
inode->i_gid = le32_to_cpu(fe->i_gid);
inode->i_mode = le16_to_cpu(fe->i_mode);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index ea0ecbd..a8b2bfe 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -199,7 +199,7 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
* these are used by the support functions here and in
* callers. */
if (S_ISDIR(mode))
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
inode_init_owner(inode, dir, mode);
dquot_initialize(inode);
return inode;
@@ -2016,7 +2016,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
if (S_ISDIR(inode->i_mode))
ocfs2_add_links_count(orphan_fe, 1);
- orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
+ set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
ocfs2_journal_dirty(handle, orphan_dir_bh);
status = __ocfs2_add_entry(handle, orphan_dir_inode, name,
@@ -2114,7 +2114,7 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
if (S_ISDIR(inode->i_mode))
ocfs2_add_links_count(orphan_fe, -1);
- orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
+ set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
ocfs2_journal_dirty(handle, orphan_dir_bh);
leave:
@@ -2435,7 +2435,7 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
di = (struct ocfs2_dinode *)di_bh->b_data;
le32_add_cpu(&di->i_flags, -OCFS2_ORPHANED_FL);
di->i_orphaned_slot = 0;
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
ocfs2_set_links_count(di, inode->i_nlink);
ocfs2_journal_dirty(handle, di_bh);
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index a2a5bff..e4e0ff7 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -242,7 +242,7 @@ found:
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
inode->i_op = &openprom_inode_operations;
inode->i_fop = &openprom_operations;
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
break;
case op_inode_prop:
if (!strcmp(dp->name, "options") && (len == 17) &&
@@ -251,7 +251,7 @@ found:
else
inode->i_mode = S_IFREG | S_IRUGO;
inode->i_fop = &openpromfs_prop_ops;
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_size = ent_oi->u.prop->length;
break;
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 5eb0206..1f2ae7d 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2261,7 +2261,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
ei = PROC_I(inode);
inode->i_mode = p->mode;
if (S_ISDIR(inode->i_mode))
- inode->i_nlink = 2; /* Use getattr to fix if necessary */
+ set_nlink(inode, 2); /* Use getattr to fix if necessary */
if (p->iop)
inode->i_op = p->iop;
if (p->fop)
@@ -2655,7 +2655,7 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
inode->i_mode = p->mode;
if (S_ISDIR(inode->i_mode))
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
if (S_ISLNK(inode->i_mode))
inode->i_size = 64;
if (p->iop)
@@ -2994,8 +2994,8 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
inode->i_fop = &proc_tgid_base_operations;
inode->i_flags|=S_IMMUTABLE;
- inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff,
- ARRAY_SIZE(tgid_base_stuff));
+ set_nlink(inode, 2 + pid_entry_count_dirs(tgid_base_stuff,
+ ARRAY_SIZE(tgid_base_stuff)));
d_set_d_op(dentry, &pid_dentry_operations);
@@ -3246,8 +3246,8 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
inode->i_fop = &proc_tid_base_operations;
inode->i_flags|=S_IMMUTABLE;
- inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff,
- ARRAY_SIZE(tid_base_stuff));
+ set_nlink(inode, 2 + pid_entry_count_dirs(tid_base_stuff,
+ ARRAY_SIZE(tid_base_stuff)));
d_set_d_op(dentry, &pid_dentry_operations);
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 9d99131..10090d9 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -283,7 +283,7 @@ static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct inode *inode = dentry->d_inode;
struct proc_dir_entry *de = PROC_I(inode)->pde;
if (de && de->nlink)
- inode->i_nlink = de->nlink;
+ set_nlink(inode, de->nlink);
generic_fillattr(inode, stat);
return 0;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 7ed72d6..7737c54 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -445,7 +445,7 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
if (de->size)
inode->i_size = de->size;
if (de->nlink)
- inode->i_nlink = de->nlink;
+ set_nlink(inode, de->nlink);
if (de->proc_iops)
inode->i_op = de->proc_iops;
if (de->proc_fops) {
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 2b06466..3bdd214 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -379,7 +379,7 @@ struct inode *qnx4_iget(struct super_block *sb, unsigned long ino)
inode->i_mode = le16_to_cpu(raw_inode->di_mode);
inode->i_uid = (uid_t)le16_to_cpu(raw_inode->di_uid);
inode->i_gid = (gid_t)le16_to_cpu(raw_inode->di_gid);
- inode->i_nlink = le16_to_cpu(raw_inode->di_nlink);
+ set_nlink(inode, le16_to_cpu(raw_inode->di_nlink));
inode->i_size = le32_to_cpu(raw_inode->di_size);
inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->di_mtime);
inode->i_mtime.tv_nsec = 0;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index c425441..950f13a 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1154,7 +1154,7 @@ static void init_inode(struct inode *inode, struct treepath *path)
set_inode_item_key_version(inode, KEY_FORMAT_3_5);
set_inode_sd_version(inode, STAT_DATA_V1);
inode->i_mode = sd_v1_mode(sd);
- inode->i_nlink = sd_v1_nlink(sd);
+ set_nlink(inode, sd_v1_nlink(sd));
inode->i_uid = sd_v1_uid(sd);
inode->i_gid = sd_v1_gid(sd);
inode->i_size = sd_v1_size(sd);
@@ -1199,7 +1199,7 @@ static void init_inode(struct inode *inode, struct treepath *path)
struct stat_data *sd = (struct stat_data *)B_I_PITEM(bh, ih);
inode->i_mode = sd_v2_mode(sd);
- inode->i_nlink = sd_v2_nlink(sd);
+ set_nlink(inode, sd_v2_nlink(sd));
inode->i_uid = sd_v2_uid(sd);
inode->i_size = sd_v2_size(sd);
inode->i_gid = sd_v2_gid(sd);
@@ -1832,7 +1832,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
#endif
/* fill stat data */
- inode->i_nlink = (S_ISDIR(mode) ? 2 : 1);
+ set_nlink(inode, (S_ISDIR(mode) ? 2 : 1));
/* uid and gid must already be set by the caller for quota init */
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 6ce3328..80058e8 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -19,7 +19,7 @@
#include <linux/reiserfs_xattr.h>
#include <linux/quotaops.h>
-#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }
+#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) set_nlink(i, 1); }
#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
// directory item contains array of entry headers. This performs
@@ -964,7 +964,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
reiserfs_warning(inode->i_sb, "reiserfs-7042",
"deleting nonexistent file (%lu), %d",
inode->i_ino, inode->i_nlink);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
drop_nlink(inode);
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 2305e31..8b4089f 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -337,7 +337,7 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
inode->i_metasize = (ROMFH_SIZE + nlen + 1 + ROMFH_PAD) & ROMFH_MASK;
inode->i_dataoffset = pos + inode->i_metasize;
- i->i_nlink = 1; /* Hard to decide.. */
+ set_nlink(i, 1); /* Hard to decide.. */
i->i_size = be32_to_cpu(ri.size);
i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 04bebca..fd7b3b3 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -159,7 +159,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
frag_offset = 0;
}
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
inode->i_size = le32_to_cpu(sqsh_ino->file_size);
inode->i_fop = &generic_ro_fops;
inode->i_mode |= S_IFREG;
@@ -203,7 +203,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
}
xattr_id = le32_to_cpu(sqsh_ino->xattr);
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
inode->i_size = le64_to_cpu(sqsh_ino->file_size);
inode->i_op = &squashfs_inode_ops;
inode->i_fop = &generic_ro_fops;
@@ -232,7 +232,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
if (err < 0)
goto failed_read;
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
inode->i_size = le16_to_cpu(sqsh_ino->file_size);
inode->i_op = &squashfs_dir_inode_ops;
inode->i_fop = &squashfs_dir_ops;
@@ -257,7 +257,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
goto failed_read;
xattr_id = le32_to_cpu(sqsh_ino->xattr);
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
inode->i_size = le32_to_cpu(sqsh_ino->file_size);
inode->i_op = &squashfs_dir_inode_ops;
inode->i_fop = &squashfs_dir_ops;
@@ -284,7 +284,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
if (err < 0)
goto failed_read;
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
inode->i_op = &squashfs_symlink_inode_ops;
inode->i_data.a_ops = &squashfs_symlink_aops;
@@ -325,7 +325,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
inode->i_mode |= S_IFCHR;
else
inode->i_mode |= S_IFBLK;
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
rdev = le32_to_cpu(sqsh_ino->rdev);
init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
@@ -349,7 +349,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
inode->i_mode |= S_IFBLK;
xattr_id = le32_to_cpu(sqsh_ino->xattr);
inode->i_op = &squashfs_inode_ops;
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
rdev = le32_to_cpu(sqsh_ino->rdev);
init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
@@ -370,7 +370,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
inode->i_mode |= S_IFIFO;
else
inode->i_mode |= S_IFSOCK;
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
init_special_inode(inode, inode->i_mode, 0);
break;
}
@@ -389,7 +389,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
inode->i_mode |= S_IFSOCK;
xattr_id = le32_to_cpu(sqsh_ino->xattr);
inode->i_op = &squashfs_inode_ops;
- inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+ set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
init_special_inode(inode, inode->i_mode, 0);
break;
}
diff --git a/fs/stack.c b/fs/stack.c
index b4f2ab4..9c11519 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -71,6 +71,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
dest->i_ctime = src->i_ctime;
dest->i_blkbits = src->i_blkbits;
dest->i_flags = src->i_flags;
- dest->i_nlink = src->i_nlink;
+ set_nlink(dest, src->i_nlink);
}
EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index e3f091a..6b1afb9 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -230,7 +230,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
}
if (sysfs_type(sd) == SYSFS_DIR)
- inode->i_nlink = sysfs_count_nlink(sd);
+ set_nlink(inode, sysfs_count_nlink(sd));
}
int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 0630eb9..25ffb3e 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -219,7 +219,7 @@ struct inode *sysv_iget(struct super_block *sb, unsigned int ino)
inode->i_mode = fs16_to_cpu(sbi, raw_inode->i_mode);
inode->i_uid = (uid_t)fs16_to_cpu(sbi, raw_inode->i_uid);
inode->i_gid = (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid);
- inode->i_nlink = fs16_to_cpu(sbi, raw_inode->i_nlink);
+ set_nlink(inode, fs16_to_cpu(sbi, raw_inode->i_nlink));
inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size);
inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_atime);
inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_mtime);
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index b281212..20403dc 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -129,7 +129,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
goto out_ino;
inode->i_flags |= (S_NOCMTIME | S_NOATIME);
- inode->i_nlink = le32_to_cpu(ino->nlink);
+ set_nlink(inode, le32_to_cpu(ino->nlink));
inode->i_uid = le32_to_cpu(ino->uid);
inode->i_gid = le32_to_cpu(ino->gid);
inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec);
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 993adc8..bf18f7a 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -561,7 +561,7 @@ int ubifs_removexattr(struct dentry *dentry, const char *name)
clear_nlink(inode);
err = remove_xattr(c, host, inode, &nm);
if (err)
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
/* If @i_nlink is 0, 'iput()' will delete the inode */
iput(inode);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 1d1358e..6e73f1d 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1236,6 +1236,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
int offset;
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
struct udf_inode_info *iinfo = UDF_I(inode);
+ unsigned int link_count;
fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;
@@ -1318,9 +1319,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
inode->i_mode &= ~sbi->s_umask;
read_unlock(&sbi->s_cred_lock);
- inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
- if (!inode->i_nlink)
- inode->i_nlink = 1;
+ link_count = le16_to_cpu(fe->fileLinkCount);
+ if (!link_count)
+ link_count = 1;
+ set_nlink(inode, link_count);
inode->i_size = le64_to_cpu(fe->informationLength);
iinfo->i_lenExtents = inode->i_size;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index e8d61b1..f1c64c6 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -667,7 +667,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
iput(inode);
goto out;
}
- inode->i_nlink = 2;
+ set_nlink(inode, 2);
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
@@ -837,7 +837,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
if (!inode->i_nlink) {
udf_debug("Deleting nonexistent file (%lu), %d\n",
inode->i_ino, inode->i_nlink);
- inode->i_nlink = 1;
+ set_nlink(inode, 1);
}
retval = udf_delete_entry(dir, fi, &fibh, &cfi);
if (retval)
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index b4d791a..879b134 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -589,7 +589,7 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
* Copy data to the in-core inode.
*/
inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
- inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink);
+ set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink));
if (inode->i_nlink == 0) {
ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
return -1;
@@ -637,7 +637,7 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
* Copy data to the in-core inode.
*/
inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
- inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink);
+ set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink));
if (inode->i_nlink == 0) {
ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
return -1;
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 673704f..91fac2e 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1152,7 +1152,7 @@ xfs_setup_inode(
hlist_add_fake(&inode->i_hash);
inode->i_mode = ip->i_d.di_mode;
- inode->i_nlink = ip->i_d.di_nlink;
+ set_nlink(inode, ip->i_d.di_nlink);
inode->i_uid = ip->i_d.di_uid;
inode->i_gid = ip->i_d.di_gid;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0979638..28f4998 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1748,6 +1748,19 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
}
/**
+ * 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
*
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 11/13] vfs: protect i_nlink
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (9 preceding siblings ...)
2011-10-12 14:49 ` [PATCH 10/13] filesystems: add set_nlink() Miklos Szeredi
@ 2011-10-12 14:49 ` Miklos Szeredi
2011-10-12 14:49 ` [PATCH 12/13] vfs: count unlinked inodes Miklos Szeredi
` (3 subsequent siblings)
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:49 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
Prevent direct modification of i_nlink by making it const and adding a
non-const __i_nlink alias.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/inode.c | 2 +-
include/linux/fs.h | 20 +++++++++++++++-----
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/fs/inode.c b/fs/inode.c
index ec79246..e2d3633 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -142,7 +142,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
atomic_set(&inode->i_count, 1);
inode->i_op = &empty_iops;
inode->i_fop = &empty_fops;
- inode->i_nlink = 1;
+ inode->__i_nlink = 1;
inode->i_opflags = 0;
inode->i_uid = 0;
inode->i_gid = 0;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 28f4998..7813404 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -767,7 +767,17 @@ struct inode {
/* Stat data, not accessed from path walking */
unsigned long i_ino;
- unsigned int i_nlink;
+ /*
+ * Filesystems may only read i_nlink directly. They shall use the
+ * following functions for modification:
+ *
+ * (set|clear|inc|drop)_nlink
+ * inode_(inc|dec)_link_count
+ */
+ union {
+ const unsigned int i_nlink;
+ unsigned int __i_nlink;
+ };
dev_t i_rdev;
loff_t i_size;
struct timespec i_atime;
@@ -1757,7 +1767,7 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
*/
static inline void set_nlink(struct inode *inode, unsigned int nlink)
{
- inode->i_nlink = nlink;
+ inode->__i_nlink = nlink;
}
/**
@@ -1770,7 +1780,7 @@ static inline void set_nlink(struct inode *inode, unsigned int nlink)
*/
static inline void inc_nlink(struct inode *inode)
{
- inode->i_nlink++;
+ inode->__i_nlink++;
}
static inline void inode_inc_link_count(struct inode *inode)
@@ -1792,7 +1802,7 @@ static inline void inode_inc_link_count(struct inode *inode)
*/
static inline void drop_nlink(struct inode *inode)
{
- inode->i_nlink--;
+ inode->__i_nlink--;
}
/**
@@ -1805,7 +1815,7 @@ static inline void drop_nlink(struct inode *inode)
*/
static inline void clear_nlink(struct inode *inode)
{
- inode->i_nlink = 0;
+ inode->__i_nlink = 0;
}
static inline void inode_dec_link_count(struct inode *inode)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 12/13] vfs: count unlinked inodes
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (10 preceding siblings ...)
2011-10-12 14:49 ` [PATCH 11/13] vfs: protect i_nlink Miklos Szeredi
@ 2011-10-12 14:49 ` Miklos Szeredi
2011-10-28 6:08 ` Christoph Hellwig
2011-10-12 14:49 ` [PATCH 13/13] vfs: prevent remount read-only if pending removes Miklos Szeredi
` (2 subsequent siblings)
14 siblings, 1 reply; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:49 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
Add a new counter to the superblock that keeps track of unlinked but
not yet deleted inodes.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/inode.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 61 ++++----------------------------------
2 files changed, 88 insertions(+), 54 deletions(-)
diff --git a/fs/inode.c b/fs/inode.c
index e2d3633..ca27d4e 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -241,6 +241,11 @@ void __destroy_inode(struct inode *inode)
BUG_ON(inode_has_buffers(inode));
security_inode_free(inode);
fsnotify_inode_delete(inode);
+ if (!inode->i_nlink) {
+ WARN_ON(atomic_long_read(&inode->i_sb->s_remove_count) == 0);
+ atomic_long_dec(&inode->i_sb->s_remove_count);
+ }
+
#ifdef CONFIG_FS_POSIX_ACL
if (inode->i_acl && inode->i_acl != ACL_NOT_CACHED)
posix_acl_release(inode->i_acl);
@@ -268,6 +273,82 @@ static void destroy_inode(struct inode *inode)
call_rcu(&inode->i_rcu, i_callback);
}
+/**
+ * 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.
+ */
+void drop_nlink(struct inode *inode)
+{
+ WARN_ON(inode->i_nlink == 0);
+ inode->__i_nlink--;
+ if (!inode->i_nlink)
+ atomic_long_inc(&inode->i_sb->s_remove_count);
+}
+EXPORT_SYMBOL(drop_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.
+ */
+void clear_nlink(struct inode *inode)
+{
+ if (inode->i_nlink) {
+ inode->__i_nlink = 0;
+ atomic_long_inc(&inode->i_sb->s_remove_count);
+ }
+}
+EXPORT_SYMBOL(clear_nlink);
+
+/**
+ * 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.
+ */
+void set_nlink(struct inode *inode, unsigned int nlink)
+{
+ if (WARN_ON(!nlink)) {
+ clear_nlink(inode);
+ } else {
+ /* Yes, some filesystems do change nlink from zero to one */
+ if (inode->i_nlink == 0)
+ atomic_long_dec(&inode->i_sb->s_remove_count);
+
+ inode->__i_nlink = nlink;
+ }
+}
+EXPORT_SYMBOL(set_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().
+ */
+void inc_nlink(struct inode *inode)
+{
+ if (WARN_ON(inode->i_nlink == 0))
+ atomic_long_dec(&inode->i_sb->s_remove_count);
+
+ inode->__i_nlink++;
+}
+EXPORT_SYMBOL(inc_nlink);
+
void address_space_init_once(struct address_space *mapping)
{
memset(mapping, 0, sizeof(*mapping));
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7813404..71bacce 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1473,6 +1473,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;
};
@@ -1757,31 +1760,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)
{
@@ -1789,35 +1771,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);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 13/13] vfs: prevent remount read-only if pending removes
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (11 preceding siblings ...)
2011-10-12 14:49 ` [PATCH 12/13] vfs: count unlinked inodes Miklos Szeredi
@ 2011-10-12 14:49 ` Miklos Szeredi
2011-10-12 15:03 ` [PATCH 0/13] read-only remount race fix v7 Christoph Hellwig
2011-10-13 7:10 ` Toshiyuki Okajima
14 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 14:49 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
If there are any inodes on the super block that have been unlinked
(i_nlink == 0) but have not yet been deleted then prevent the
remounting the super block read-only.
Reported-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/file_table.c | 26 --------------------------
fs/namespace.c | 7 +++++++
fs/super.c | 4 ----
include/linux/fs.h | 2 --
4 files changed, 7 insertions(+), 32 deletions(-)
diff --git a/fs/file_table.c b/fs/file_table.c
index dc9f437..20002e3 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -474,32 +474,6 @@ void file_sb_list_del(struct file *file)
#endif
-int fs_may_remount_ro(struct super_block *sb)
-{
- struct file *file;
- /* Check that no files are currently opened for writing. */
- lg_global_lock(files_lglock);
- do_file_list_for_each_entry(sb, file) {
- struct inode *inode = file->f_path.dentry->d_inode;
-
- /* File with pending delete? */
- if (inode->i_nlink == 0)
- goto too_bad;
-
- /*
- * Writable file?
- * Should be caught by sb_prepare_remount_readonly().
- */
- if (WARN_ON(S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE)))
- goto too_bad;
- } while_file_list_for_each_entry;
- lg_global_unlock(files_lglock);
- return 1; /* Tis' cool bro. */
-too_bad:
- lg_global_unlock(files_lglock);
- return 0;
-}
-
/**
* mark_files_ro - mark all files read-only
* @sb: superblock in question
diff --git a/fs/namespace.c b/fs/namespace.c
index 85838f5..617705f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -480,6 +480,10 @@ int sb_prepare_remount_readonly(struct super_block *sb)
struct vfsmount *mnt;
int err = 0;
+ /* Racy optimization. Recheck the counter under MNT_WRITE_HOLD */
+ if (atomic_long_read(&sb->s_remove_count))
+ return -EBUSY;
+
br_write_lock(vfsmount_lock);
list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
if (!(mnt->mnt_flags & MNT_READONLY)) {
@@ -491,6 +495,9 @@ int sb_prepare_remount_readonly(struct super_block *sb)
}
}
}
+ if (!err && atomic_long_read(&sb->s_remove_count))
+ err = -EBUSY;
+
if (!err) {
sb->s_readonly_remount = 1;
smp_wmb();
diff --git a/fs/super.c b/fs/super.c
index 94c8ace..7b28dae 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -727,10 +727,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
retval = sb_prepare_remount_readonly(sb);
if (retval)
return retval;
-
- retval = -EBUSY;
- if (!fs_may_remount_ro(sb))
- goto cancel_readonly;
}
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 71bacce..c791aa8b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2135,8 +2135,6 @@ extern const struct file_operations read_pipefifo_fops;
extern const struct file_operations write_pipefifo_fops;
extern const struct file_operations rdwr_pipefifo_fops;
-extern int fs_may_remount_ro(struct super_block *);
-
#ifdef CONFIG_BLOCK
/*
* return READ, READA, or WRITE
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH 0/13] read-only remount race fix v7
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (12 preceding siblings ...)
2011-10-12 14:49 ` [PATCH 13/13] vfs: prevent remount read-only if pending removes Miklos Szeredi
@ 2011-10-12 15:03 ` Christoph Hellwig
2011-10-12 15:09 ` Miklos Szeredi
2011-10-13 7:10 ` Toshiyuki Okajima
14 siblings, 1 reply; 28+ messages in thread
From: Christoph Hellwig @ 2011-10-12 15:03 UTC (permalink / raw)
To: Miklos Szeredi
Cc: viro, linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
On Wed, Oct 12, 2011 at 04:48:53PM +0200, Miklos Szeredi wrote:
> Here's an update of the read-only remount race fixes.
>
> It should now fix the races after unlink. I haven't been able to
> trigger the bad behavior with the test scripts provided by Toshiyuki
> Okajima.
How does the test script look like? Could we integrate it into xfstests
so that we have a good regular run regression test for this?
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 0/13] read-only remount race fix v7
2011-10-12 15:03 ` [PATCH 0/13] read-only remount race fix v7 Christoph Hellwig
@ 2011-10-12 15:09 ` Miklos Szeredi
0 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-12 15:09 UTC (permalink / raw)
To: Christoph Hellwig
Cc: viro, linux-fsdevel, linux-kernel, jack, akpm, toshi.okajima
[-- Attachment #1: Type: text/plain, Size: 608 bytes --]
Christoph Hellwig <hch@infradead.org> writes:
> On Wed, Oct 12, 2011 at 04:48:53PM +0200, Miklos Szeredi wrote:
>> Here's an update of the read-only remount race fixes.
>>
>> It should now fix the races after unlink. I haven't been able to
>> trigger the bad behavior with the test scripts provided by Toshiyuki
>> Okajima.
>
> How does the test script look like? Could we integrate it into xfstests
> so that we have a good regular run regression test for this?
Attaching the scripts. It doesn't detect failure, currenly that needs
to be derived from the output of the run and dmesg.
Thanks,
Miklos
[-- Attachment #2: go.sh --]
[-- Type: application/x-shellscript, Size: 397 bytes --]
[-- Attachment #3: writer.sh --]
[-- Type: application/x-shellscript, Size: 502 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 06/13] jfs: remove unnecessary nlink setting
2011-10-12 14:48 ` [PATCH 06/13] jfs: " Miklos Szeredi
@ 2011-10-12 15:26 ` Dave Kleikamp
0 siblings, 0 replies; 28+ messages in thread
From: Dave Kleikamp @ 2011-10-12 15:26 UTC (permalink / raw)
To: Miklos Szeredi
Cc: viro, linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
On 10/12/2011 09:48 AM, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
>
> alloc_inode() initializes i_nlink to 1. Remove unnecessary
> re-initialization.
>
> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Acked-by: Dave Kleikamp <dave.kleikamp@oracle.com>
> ---
> fs/jfs/super.c | 1 -
> 1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/fs/jfs/super.c b/fs/jfs/super.c
> index 06c8a67..a44eff0 100644
> --- a/fs/jfs/super.c
> +++ b/fs/jfs/super.c
> @@ -485,7 +485,6 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
> goto out_unload;
> }
> inode->i_ino = 0;
> - inode->i_nlink = 1;
> inode->i_size = sb->s_bdev->bd_inode->i_size;
> inode->i_mapping->a_ops = &jfs_metapage_aops;
> insert_inode_hash(inode);
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 0/13] read-only remount race fix v7
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
` (13 preceding siblings ...)
2011-10-12 15:03 ` [PATCH 0/13] read-only remount race fix v7 Christoph Hellwig
@ 2011-10-13 7:10 ` Toshiyuki Okajima
2011-10-18 6:28 ` Toshiyuki Okajima
14 siblings, 1 reply; 28+ messages in thread
From: Toshiyuki Okajima @ 2011-10-13 7:10 UTC (permalink / raw)
To: Miklos Szeredi
Cc: toshi.okajima, viro, linux-fsdevel, linux-kernel, jack, hch, akpm,
mszeredi
Hi.
(2011/10/12 23:48), Miklos Szeredi wrote:
> Here's an update of the read-only remount race fixes.
>
> It should now fix the races after unlink. I haven't been able to
> trigger the bad behavior with the test scripts provided by Toshiyuki
> Okajima.
>
> Toshiyuki-san, could you please test these patches too?
OK. I will test them with ext4. Please wait.
Best Regards,
Toshiyuki Okajima
>
> Thanks,
> Miklos
> ---
>
> Miklos Szeredi (13):
> vfs: ignore error on forced remount
> vfs: keep list of mounts for each superblock
> vfs: protect remounting superblock read-only
> vfs: fs_may_remount_ro: turn unnecessary check into a WARN_ON
> hypfs: remove unnecessary nlink setting
> jfs: remove unnecessary nlink setting
> ocfs2: remove unnecessary nlink setting
> logfs: remove unnecessary nlink setting
> filesystems: add missing nlink wrappers
> filesystems: add set_nlink()
> vfs: protect i_nlink
> vfs: count unlinked inodes
> vfs: prevent remount read-only if pending removes
>
> ---
> arch/s390/hypfs/inode.c | 6 +--
> drivers/mtd/mtdchar.c | 2 +-
> drivers/staging/pohmelfs/inode.c | 2 +-
> fs/9p/vfs_inode.c | 4 +-
> fs/9p/vfs_inode_dotl.c | 4 +-
> fs/adfs/inode.c | 2 +-
> fs/affs/amigaffs.c | 4 +-
> fs/affs/inode.c | 8 ++--
> fs/affs/namei.c | 6 +-
> fs/afs/fsclient.c | 2 +-
> fs/afs/inode.c | 4 +-
> fs/autofs4/inode.c | 2 +-
> fs/befs/linuxvfs.c | 2 +-
> fs/bfs/dir.c | 2 +-
> fs/bfs/inode.c | 2 +-
> fs/binfmt_misc.c | 2 +-
> fs/btrfs/delayed-inode.c | 2 +-
> fs/btrfs/disk-io.c | 2 +-
> fs/btrfs/inode.c | 4 +-
> fs/btrfs/tree-log.c | 2 +-
> fs/ceph/caps.c | 2 +-
> fs/ceph/inode.c | 2 +-
> fs/cifs/inode.c | 6 +-
> fs/cifs/link.c | 2 +-
> fs/coda/coda_linux.c | 2 +-
> fs/coda/dir.c | 2 +-
> fs/devpts/inode.c | 4 +-
> fs/ecryptfs/inode.c | 12 +++---
> fs/efs/inode.c | 2 +-
> fs/exofs/inode.c | 2 +-
> fs/ext2/ialloc.c | 2 +-
> fs/ext2/inode.c | 2 +-
> fs/ext3/ialloc.c | 2 +-
> fs/ext3/inode.c | 2 +-
> fs/ext3/namei.c | 6 +-
> fs/ext4/ialloc.c | 2 +-
> fs/ext4/inode.c | 2 +-
> fs/ext4/migrate.c | 2 +-
> fs/ext4/namei.c | 8 ++--
> fs/fat/inode.c | 4 +-
> fs/fat/namei_msdos.c | 2 +-
> fs/fat/namei_vfat.c | 2 +-
> fs/file_table.c | 23 ----------
> fs/freevxfs/vxfs_inode.c | 2 +-
> fs/fuse/control.c | 2 +-
> fs/fuse/inode.c | 2 +-
> fs/gfs2/glops.c | 2 +-
> fs/hfs/dir.c | 4 +-
> fs/hfs/inode.c | 4 +-
> fs/hfsplus/dir.c | 4 +-
> fs/hfsplus/inode.c | 10 ++--
> fs/hostfs/hostfs_kern.c | 2 +-
> fs/hpfs/dir.c | 2 +-
> fs/hpfs/inode.c | 10 ++--
> fs/hpfs/namei.c | 8 ++--
> fs/hppfs/hppfs.c | 2 +-
> fs/hugetlbfs/inode.c | 2 +-
> fs/inode.c | 83 +++++++++++++++++++++++++++++++++++++-
> fs/internal.h | 1 +
> fs/isofs/inode.c | 4 +-
> fs/isofs/rock.c | 4 +-
> fs/jffs2/dir.c | 6 +-
> fs/jffs2/fs.c | 6 +-
> fs/jfs/jfs_imap.c | 6 +-
> fs/jfs/jfs_inode.c | 2 +-
> fs/jfs/namei.c | 12 +++---
> fs/jfs/super.c | 1 -
> fs/libfs.c | 2 +-
> fs/logfs/dir.c | 8 ++--
> fs/logfs/inode.c | 3 +-
> fs/logfs/readwrite.c | 2 +-
> fs/minix/inode.c | 4 +-
> fs/namespace.c | 57 +++++++++++++++++++++++++-
> fs/ncpfs/inode.c | 2 +-
> fs/nfs/inode.c | 6 +-
> fs/nilfs2/inode.c | 4 +-
> fs/nilfs2/namei.c | 2 +-
> fs/ntfs/inode.c | 8 ++--
> fs/ocfs2/dir.c | 4 +-
> fs/ocfs2/dlmglue.c | 2 +-
> fs/ocfs2/inode.c | 4 +-
> fs/ocfs2/namei.c | 18 ++++-----
> fs/openpromfs/inode.c | 4 +-
> fs/proc/base.c | 12 +++---
> fs/proc/generic.c | 2 +-
> fs/proc/inode.c | 2 +-
> fs/proc/proc_sysctl.c | 2 +-
> fs/qnx4/inode.c | 2 +-
> fs/reiserfs/inode.c | 10 ++--
> fs/reiserfs/namei.c | 16 ++++----
> fs/romfs/super.c | 2 +-
> fs/squashfs/inode.c | 18 ++++----
> fs/stack.c | 2 +-
> fs/super.c | 27 ++++++++++--
> fs/sysfs/inode.c | 2 +-
> fs/sysv/inode.c | 2 +-
> fs/ubifs/super.c | 2 +-
> fs/ubifs/xattr.c | 4 +-
> fs/udf/inode.c | 8 ++-
> fs/udf/namei.c | 15 +++----
> fs/ufs/ialloc.c | 2 +-
> fs/ufs/inode.c | 4 +-
> fs/xfs/xfs_iops.c | 2 +-
> include/linux/fs.h | 66 ++++++++++--------------------
> include/linux/mount.h | 1 +
> mm/shmem.c | 2 +-
> 106 files changed, 389 insertions(+), 286 deletions(-)
>
>
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 10/13] filesystems: add set_nlink()
2011-10-12 14:49 ` [PATCH 10/13] filesystems: add set_nlink() Miklos Szeredi
@ 2011-10-13 16:33 ` Steven Whitehouse
2011-10-14 15:04 ` Miklos Szeredi
0 siblings, 1 reply; 28+ messages in thread
From: Steven Whitehouse @ 2011-10-13 16:33 UTC (permalink / raw)
To: Miklos Szeredi
Cc: viro, linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
Hi,
On Wed, 2011-10-12 at 16:49 +0200, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
>
> Replace remaining direct i_nlink updates with a new set_nlink()
> updater function.
>
> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
> ---
[snip]
> diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
> index da21eca..102cf5e 100644
> --- a/fs/gfs2/glops.c
> +++ b/fs/gfs2/glops.c
> @@ -277,7 +277,7 @@ static void gfs2_set_nlink(struct inode *inode, u32 nlink)
> if (nlink == 0)
> clear_nlink(inode);
> else
> - inode->i_nlink = nlink;
> + set_nlink(inode, nlink);
> }
> }
So long as it is ok to call set_nlink() with nlink == 0, then the if
statement here can be removed and just replaced with set_nlink()
Steve.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 10/13] filesystems: add set_nlink()
2011-10-13 16:33 ` Steven Whitehouse
@ 2011-10-14 15:04 ` Miklos Szeredi
0 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-14 15:04 UTC (permalink / raw)
To: Steven Whitehouse
Cc: viro, linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima
Steven Whitehouse <swhiteho@redhat.com> writes:
> Hi,
>
> On Wed, 2011-10-12 at 16:49 +0200, Miklos Szeredi wrote:
>> From: Miklos Szeredi <mszeredi@suse.cz>
>>
>> Replace remaining direct i_nlink updates with a new set_nlink()
>> updater function.
>>
>> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
>> ---
> [snip]
>
>
>
>> diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
>> index da21eca..102cf5e 100644
>> --- a/fs/gfs2/glops.c
>> +++ b/fs/gfs2/glops.c
>> @@ -277,7 +277,7 @@ static void gfs2_set_nlink(struct inode *inode, u32 nlink)
>> if (nlink == 0)
>> clear_nlink(inode);
>> else
>> - inode->i_nlink = nlink;
>> + set_nlink(inode, nlink);
>> }
>> }
>
> So long as it is ok to call set_nlink() with nlink == 0, then the if
> statement here can be removed and just replaced with set_nlink()
Current patchset will WARN if set_nlink() is called with nlink == 0. I
think it's cleaner to keep the two cases separate.
Thanks,
Miklos
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 0/13] read-only remount race fix v7
2011-10-13 7:10 ` Toshiyuki Okajima
@ 2011-10-18 6:28 ` Toshiyuki Okajima
2011-10-18 9:02 ` Miklos Szeredi
0 siblings, 1 reply; 28+ messages in thread
From: Toshiyuki Okajima @ 2011-10-18 6:28 UTC (permalink / raw)
To: Miklos Szeredi
Cc: Toshiyuki Okajima, viro, linux-fsdevel, linux-kernel, jack, hch,
akpm, mszeredi
Miklos-san,
(2011/10/13 16:10), Toshiyuki Okajima wrote:
> Hi.
>
> (2011/10/12 23:48), Miklos Szeredi wrote:
>> Here's an update of the read-only remount race fixes.
>>
>> It should now fix the races after unlink. I haven't been able to
>> trigger the bad behavior with the test scripts provided by Toshiyuki
>> Okajima.
>>
>> Toshiyuki-san, could you please test these patches too?
> OK. I will test them with ext4. Please wait.
I have tested your latest patch set by my reproducer with ext4.
On my environment, this reproducer usually detects
"EXT4-fs (xxx): Couldn't remount RDWR because of unprocessed orphan inode list"
message within 20 minutes when I use your previous patch set.
However, when I use your latest patche set, this producer has not yet
detected the message for 2 days.
So, I think your latest patch set fixes the problem that delayed deletion
can start when we remount a superblock read-only.
Tested-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
Regards,
Toshiyuki Okajima
>
> Best Regards,
> Toshiyuki Okajima
>
>>
>> Thanks,
>> Miklos
>> ---
>>
>> Miklos Szeredi (13):
>> vfs: ignore error on forced remount
>> vfs: keep list of mounts for each superblock
>> vfs: protect remounting superblock read-only
>> vfs: fs_may_remount_ro: turn unnecessary check into a WARN_ON
>> hypfs: remove unnecessary nlink setting
>> jfs: remove unnecessary nlink setting
>> ocfs2: remove unnecessary nlink setting
>> logfs: remove unnecessary nlink setting
>> filesystems: add missing nlink wrappers
>> filesystems: add set_nlink()
>> vfs: protect i_nlink
>> vfs: count unlinked inodes
>> vfs: prevent remount read-only if pending removes
>>
>> ---
>> arch/s390/hypfs/inode.c | 6 +--
>> drivers/mtd/mtdchar.c | 2 +-
>> drivers/staging/pohmelfs/inode.c | 2 +-
>> fs/9p/vfs_inode.c | 4 +-
>> fs/9p/vfs_inode_dotl.c | 4 +-
>> fs/adfs/inode.c | 2 +-
>> fs/affs/amigaffs.c | 4 +-
>> fs/affs/inode.c | 8 ++--
>> fs/affs/namei.c | 6 +-
>> fs/afs/fsclient.c | 2 +-
>> fs/afs/inode.c | 4 +-
>> fs/autofs4/inode.c | 2 +-
>> fs/befs/linuxvfs.c | 2 +-
>> fs/bfs/dir.c | 2 +-
>> fs/bfs/inode.c | 2 +-
>> fs/binfmt_misc.c | 2 +-
>> fs/btrfs/delayed-inode.c | 2 +-
>> fs/btrfs/disk-io.c | 2 +-
>> fs/btrfs/inode.c | 4 +-
>> fs/btrfs/tree-log.c | 2 +-
>> fs/ceph/caps.c | 2 +-
>> fs/ceph/inode.c | 2 +-
>> fs/cifs/inode.c | 6 +-
>> fs/cifs/link.c | 2 +-
>> fs/coda/coda_linux.c | 2 +-
>> fs/coda/dir.c | 2 +-
>> fs/devpts/inode.c | 4 +-
>> fs/ecryptfs/inode.c | 12 +++---
>> fs/efs/inode.c | 2 +-
>> fs/exofs/inode.c | 2 +-
>> fs/ext2/ialloc.c | 2 +-
>> fs/ext2/inode.c | 2 +-
>> fs/ext3/ialloc.c | 2 +-
>> fs/ext3/inode.c | 2 +-
>> fs/ext3/namei.c | 6 +-
>> fs/ext4/ialloc.c | 2 +-
>> fs/ext4/inode.c | 2 +-
>> fs/ext4/migrate.c | 2 +-
>> fs/ext4/namei.c | 8 ++--
>> fs/fat/inode.c | 4 +-
>> fs/fat/namei_msdos.c | 2 +-
>> fs/fat/namei_vfat.c | 2 +-
>> fs/file_table.c | 23 ----------
>> fs/freevxfs/vxfs_inode.c | 2 +-
>> fs/fuse/control.c | 2 +-
>> fs/fuse/inode.c | 2 +-
>> fs/gfs2/glops.c | 2 +-
>> fs/hfs/dir.c | 4 +-
>> fs/hfs/inode.c | 4 +-
>> fs/hfsplus/dir.c | 4 +-
>> fs/hfsplus/inode.c | 10 ++--
>> fs/hostfs/hostfs_kern.c | 2 +-
>> fs/hpfs/dir.c | 2 +-
>> fs/hpfs/inode.c | 10 ++--
>> fs/hpfs/namei.c | 8 ++--
>> fs/hppfs/hppfs.c | 2 +-
>> fs/hugetlbfs/inode.c | 2 +-
>> fs/inode.c | 83 +++++++++++++++++++++++++++++++++++++-
>> fs/internal.h | 1 +
>> fs/isofs/inode.c | 4 +-
>> fs/isofs/rock.c | 4 +-
>> fs/jffs2/dir.c | 6 +-
>> fs/jffs2/fs.c | 6 +-
>> fs/jfs/jfs_imap.c | 6 +-
>> fs/jfs/jfs_inode.c | 2 +-
>> fs/jfs/namei.c | 12 +++---
>> fs/jfs/super.c | 1 -
>> fs/libfs.c | 2 +-
>> fs/logfs/dir.c | 8 ++--
>> fs/logfs/inode.c | 3 +-
>> fs/logfs/readwrite.c | 2 +-
>> fs/minix/inode.c | 4 +-
>> fs/namespace.c | 57 +++++++++++++++++++++++++-
>> fs/ncpfs/inode.c | 2 +-
>> fs/nfs/inode.c | 6 +-
>> fs/nilfs2/inode.c | 4 +-
>> fs/nilfs2/namei.c | 2 +-
>> fs/ntfs/inode.c | 8 ++--
>> fs/ocfs2/dir.c | 4 +-
>> fs/ocfs2/dlmglue.c | 2 +-
>> fs/ocfs2/inode.c | 4 +-
>> fs/ocfs2/namei.c | 18 ++++-----
>> fs/openpromfs/inode.c | 4 +-
>> fs/proc/base.c | 12 +++---
>> fs/proc/generic.c | 2 +-
>> fs/proc/inode.c | 2 +-
>> fs/proc/proc_sysctl.c | 2 +-
>> fs/qnx4/inode.c | 2 +-
>> fs/reiserfs/inode.c | 10 ++--
>> fs/reiserfs/namei.c | 16 ++++----
>> fs/romfs/super.c | 2 +-
>> fs/squashfs/inode.c | 18 ++++----
>> fs/stack.c | 2 +-
>> fs/super.c | 27 ++++++++++--
>> fs/sysfs/inode.c | 2 +-
>> fs/sysv/inode.c | 2 +-
>> fs/ubifs/super.c | 2 +-
>> fs/ubifs/xattr.c | 4 +-
>> fs/udf/inode.c | 8 ++-
>> fs/udf/namei.c | 15 +++----
>> fs/ufs/ialloc.c | 2 +-
>> fs/ufs/inode.c | 4 +-
>> fs/xfs/xfs_iops.c | 2 +-
>> include/linux/fs.h | 66 ++++++++++--------------------
>> include/linux/mount.h | 1 +
>> mm/shmem.c | 2 +-
>> 106 files changed, 389 insertions(+), 286 deletions(-)
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 0/13] read-only remount race fix v7
2011-10-18 6:28 ` Toshiyuki Okajima
@ 2011-10-18 9:02 ` Miklos Szeredi
0 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-18 9:02 UTC (permalink / raw)
To: toshi.okajima; +Cc: viro, linux-fsdevel, linux-kernel, jack, hch, akpm
Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com> writes:
> Miklos-san,
>
> (2011/10/13 16:10), Toshiyuki Okajima wrote:
>> Hi.
>>
>> (2011/10/12 23:48), Miklos Szeredi wrote:
>>> Here's an update of the read-only remount race fixes.
>>>
>>> It should now fix the races after unlink. I haven't been able to
>>> trigger the bad behavior with the test scripts provided by Toshiyuki
>>> Okajima.
>>>
>>> Toshiyuki-san, could you please test these patches too?
>> OK. I will test them with ext4. Please wait.
> I have tested your latest patch set by my reproducer with ext4.
>
> On my environment, this reproducer usually detects
> "EXT4-fs (xxx): Couldn't remount RDWR because of unprocessed orphan inode list"
> message within 20 minutes when I use your previous patch set.
> However, when I use your latest patche set, this producer has not yet
> detected the message for 2 days.
>
> So, I think your latest patch set fixes the problem that delayed deletion
> can start when we remount a superblock read-only.
>
> Tested-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
Thanks for testing.
Miklos
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 12/13] vfs: count unlinked inodes
2011-10-12 14:49 ` [PATCH 12/13] vfs: count unlinked inodes Miklos Szeredi
@ 2011-10-28 6:08 ` Christoph Hellwig
2011-10-28 7:53 ` Miklos Szeredi
0 siblings, 1 reply; 28+ messages in thread
From: Christoph Hellwig @ 2011-10-28 6:08 UTC (permalink / raw)
To: Miklos Szeredi
Cc: viro, linux-fsdevel, linux-kernel, jack, hch, akpm, toshi.okajima,
mszeredi
This one gets me a repeated spew of WARN_ONs during XFS log recover,
repeating the following pattern:
[ 1083.852789] ------------[ cut here ]------------
[ 1083.854471] WARNING: at /home/hch/work/linux-2.6/fs/inode.c:323
set_nlink+0x46/0x50()
[ 1083.857632] Hardware name: Bochs
[ 1083.858731] Modules linked in:
[ 1083.859932] Pid: 3111, comm: mount Not tainted 3.1.0+ #88
[ 1083.861735] Call Trace:
[ 1083.862694] [<ffffffff8108743a>] warn_slowpath_common+0x7a/0xb0
[ 1083.864995] [<ffffffff81087485>] warn_slowpath_null+0x15/0x20
[ 1083.867465] [<ffffffff81153b76>] set_nlink+0x46/0x50
[ 1083.868970] [<ffffffff813d70a9>] xfs_setup_inode+0x59/0x2b0
[ 1083.870817] [<ffffffff813d1b36>] xfs_iget+0x386/0x880
[ 1083.871809] [<ffffffff81427406>] xlog_recover_process_one_iunlink+0x46/0x1f0
[ 1083.872675] [<ffffffff813c914c>] ? xfs_buf_rele+0x8c/0x1e0
[ 1083.873523] [<ffffffff81427648>] xlog_recover_process_iunlinks+0x98/0x130
[ 1083.874378] [<ffffffff8142833e>] xlog_recover_finish+0x3e/0xd0
[ 1083.875130] [<ffffffff8142ebd4>] xfs_log_mount_finish+0x44/0x50
[ 1083.875933] [<ffffffff8142b91e>] xfs_mountfs+0x51e/0x7c0
[ 1083.876748] [<ffffffff813d8eda>] ? xfs_mru_cache_create+0x15a/0x180
[ 1083.877582] [<ffffffff813db42d>] xfs_fs_fill_super+0x1cd/0x280
[ 1083.878399] [<ffffffff8113e662>] mount_bdev+0x1a2/0x1e0
[ 1083.879090] [<ffffffff813db260>] ? xfs_finish_flags+0x120/0x120
[ 1083.879881] [<ffffffff813d92c0>] xfs_fs_mount+0x10/0x20
[ 1083.880716] [<ffffffff8113f12b>] mount_fs+0x1b/0xd0
[ 1083.881374] [<ffffffff81157e19>] vfs_kern_mount+0x69/0xf0
[ 1083.882117] [<ffffffff811582af>] do_kern_mount+0x4f/0x100
[ 1083.882831] [<ffffffff81159dd2>] do_mount+0x542/0x850
[ 1083.883642] [<ffffffff81116621>] ? memdup_user+0x41/0x80
[ 1083.884347] [<ffffffff811166b3>] ? strndup_user+0x53/0x70
[ 1083.885062] [<ffffffff81180c6f>] compat_sys_mount+0xdf/0x260
[ 1083.885798] [<ffffffff819e15c5>] sysenter_dispatch+0x7/0x2b
[ 1083.886518] ---[ end trace 4902e59f8848ff74 ]---
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 12/13] vfs: count unlinked inodes
2011-10-28 6:08 ` Christoph Hellwig
@ 2011-10-28 7:53 ` Miklos Szeredi
2011-10-28 8:04 ` Christoph Hellwig
0 siblings, 1 reply; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-28 7:53 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Miklos Szeredi, viro, linux-fsdevel, linux-kernel, jack, akpm,
toshi.okajima
On Fri, 2011-10-28 at 02:08 -0400, Christoph Hellwig wrote:
> This one gets me a repeated spew of WARN_ONs during XFS log recover,
> repeating the following pattern:
The assumption here is that set_nlink() is called with a non-zero count.
The point of introducing set_nlink() was to verify this assumption,
otherwise pending delete accounting will be screwed up.
If setting i_nlink to zero is not a bug in xfs we can do two things:
1) do a conditional clear_nlink() in xfs_setup_inode() to document that
nlink can indeed be zero
2) remove the warning from set_nlink(). That may hide some cases where
i_nlink was cleared without the intention of the filesystem but it will
work just fine wrt. the pending delete accounting.
Thanks,
Miklos
>
> [ 1083.852789] ------------[ cut here ]------------
> [ 1083.854471] WARNING: at /home/hch/work/linux-2.6/fs/inode.c:323
> set_nlink+0x46/0x50()
> [ 1083.857632] Hardware name: Bochs
> [ 1083.858731] Modules linked in:
> [ 1083.859932] Pid: 3111, comm: mount Not tainted 3.1.0+ #88
> [ 1083.861735] Call Trace:
> [ 1083.862694] [<ffffffff8108743a>] warn_slowpath_common+0x7a/0xb0
> [ 1083.864995] [<ffffffff81087485>] warn_slowpath_null+0x15/0x20
> [ 1083.867465] [<ffffffff81153b76>] set_nlink+0x46/0x50
> [ 1083.868970] [<ffffffff813d70a9>] xfs_setup_inode+0x59/0x2b0
> [ 1083.870817] [<ffffffff813d1b36>] xfs_iget+0x386/0x880
> [ 1083.871809] [<ffffffff81427406>] xlog_recover_process_one_iunlink+0x46/0x1f0
> [ 1083.872675] [<ffffffff813c914c>] ? xfs_buf_rele+0x8c/0x1e0
> [ 1083.873523] [<ffffffff81427648>] xlog_recover_process_iunlinks+0x98/0x130
> [ 1083.874378] [<ffffffff8142833e>] xlog_recover_finish+0x3e/0xd0
> [ 1083.875130] [<ffffffff8142ebd4>] xfs_log_mount_finish+0x44/0x50
> [ 1083.875933] [<ffffffff8142b91e>] xfs_mountfs+0x51e/0x7c0
> [ 1083.876748] [<ffffffff813d8eda>] ? xfs_mru_cache_create+0x15a/0x180
> [ 1083.877582] [<ffffffff813db42d>] xfs_fs_fill_super+0x1cd/0x280
> [ 1083.878399] [<ffffffff8113e662>] mount_bdev+0x1a2/0x1e0
> [ 1083.879090] [<ffffffff813db260>] ? xfs_finish_flags+0x120/0x120
> [ 1083.879881] [<ffffffff813d92c0>] xfs_fs_mount+0x10/0x20
> [ 1083.880716] [<ffffffff8113f12b>] mount_fs+0x1b/0xd0
> [ 1083.881374] [<ffffffff81157e19>] vfs_kern_mount+0x69/0xf0
> [ 1083.882117] [<ffffffff811582af>] do_kern_mount+0x4f/0x100
> [ 1083.882831] [<ffffffff81159dd2>] do_mount+0x542/0x850
> [ 1083.883642] [<ffffffff81116621>] ? memdup_user+0x41/0x80
> [ 1083.884347] [<ffffffff811166b3>] ? strndup_user+0x53/0x70
> [ 1083.885062] [<ffffffff81180c6f>] compat_sys_mount+0xdf/0x260
> [ 1083.885798] [<ffffffff819e15c5>] sysenter_dispatch+0x7/0x2b
> [ 1083.886518] ---[ end trace 4902e59f8848ff74 ]---
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 12/13] vfs: count unlinked inodes
2011-10-28 7:53 ` Miklos Szeredi
@ 2011-10-28 8:04 ` Christoph Hellwig
2011-10-28 8:20 ` Miklos Szeredi
0 siblings, 1 reply; 28+ messages in thread
From: Christoph Hellwig @ 2011-10-28 8:04 UTC (permalink / raw)
To: Miklos Szeredi
Cc: Christoph Hellwig, Miklos Szeredi, viro, linux-fsdevel,
linux-kernel, jack, akpm, toshi.okajima
On Fri, Oct 28, 2011 at 09:53:53AM +0200, Miklos Szeredi wrote:
> On Fri, 2011-10-28 at 02:08 -0400, Christoph Hellwig wrote:
> > This one gets me a repeated spew of WARN_ONs during XFS log recover,
> > repeating the following pattern:
>
> The assumption here is that set_nlink() is called with a non-zero count.
> The point of introducing set_nlink() was to verify this assumption,
> otherwise pending delete accounting will be screwed up.
>
> If setting i_nlink to zero is not a bug in xfs we can do two things:
>
> 1) do a conditional clear_nlink() in xfs_setup_inode() to document that
> nlink can indeed be zero
>
> 2) remove the warning from set_nlink(). That may hide some cases where
> i_nlink was cleared without the intention of the filesystem but it will
> work just fine wrt. the pending delete accounting.
I suspect 2 might be the better option. The pattern we see here in
XFS is pretty typical for transactional filesytems - when we mount a
filesystem after an unclean shutdown we need to drop all inodes that
were open but unlinked when the system crashed, and that typically
means reading inodes from disk that have a zero i_nlink. Maybe some
filesystems never instanciate a VFS inode for it, but I suspect many
do.
For XFS we will actually see it during regularly testing as we have
an ioctl that simulates a shutdown and can thus trigger log recovery
easily, while for others like ext4 you'd actually have to do a real
reset of your (physical or virtual) machine.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 12/13] vfs: count unlinked inodes
2011-10-28 8:04 ` Christoph Hellwig
@ 2011-10-28 8:20 ` Miklos Szeredi
2011-10-28 8:29 ` Christoph Hellwig
0 siblings, 1 reply; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-28 8:20 UTC (permalink / raw)
To: Christoph Hellwig
Cc: viro, linux-fsdevel, linux-kernel, jack, akpm, toshi.okajima
Christoph Hellwig <hch@infradead.org> writes:
> On Fri, Oct 28, 2011 at 09:53:53AM +0200, Miklos Szeredi wrote:
>> On Fri, 2011-10-28 at 02:08 -0400, Christoph Hellwig wrote:
>> > This one gets me a repeated spew of WARN_ONs during XFS log recover,
>> > repeating the following pattern:
>>
>> The assumption here is that set_nlink() is called with a non-zero count.
>> The point of introducing set_nlink() was to verify this assumption,
>> otherwise pending delete accounting will be screwed up.
>>
>> If setting i_nlink to zero is not a bug in xfs we can do two things:
>>
>> 1) do a conditional clear_nlink() in xfs_setup_inode() to document that
>> nlink can indeed be zero
>>
>> 2) remove the warning from set_nlink(). That may hide some cases where
>> i_nlink was cleared without the intention of the filesystem but it will
>> work just fine wrt. the pending delete accounting.
>
> I suspect 2 might be the better option. The pattern we see here in
> XFS is pretty typical for transactional filesytems - when we mount a
> filesystem after an unclean shutdown we need to drop all inodes that
> were open but unlinked when the system crashed, and that typically
> means reading inodes from disk that have a zero i_nlink. Maybe some
> filesystems never instanciate a VFS inode for it, but I suspect many
> do.
>
> For XFS we will actually see it during regularly testing as we have
> an ioctl that simulates a shutdown and can thus trigger log recovery
> easily, while for others like ext4 you'd actually have to do a real
> reset of your (physical or virtual) machine.
Okay, so a WARN_ON is not warranted. Perhaps a printk instead?
While initializing nlink with zero normally shouldn't be a problem it
might indicate something unexpected.
Thanks,
Miklos
---
fs/inode.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
Index: linux-2.6/fs/inode.c
===================================================================
--- linux-2.6.orig/fs/inode.c 2011-10-27 22:26:12.000000000 +0200
+++ linux-2.6/fs/inode.c 2011-10-28 10:14:18.000000000 +0200
@@ -320,7 +320,8 @@ EXPORT_SYMBOL(clear_nlink);
*/
void set_nlink(struct inode *inode, unsigned int nlink)
{
- if (WARN_ON(!nlink)) {
+ if (!nlink) {
+ printk(KERN_INFO "set_nlink() clearing i_nlink on %s inode %li\n", inode->i_sb->s_type->name, inode->i_ino);
clear_nlink(inode);
} else {
/* Yes, some filesystems do change nlink from zero to one */
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH 12/13] vfs: count unlinked inodes
2011-10-28 8:20 ` Miklos Szeredi
@ 2011-10-28 8:29 ` Christoph Hellwig
0 siblings, 0 replies; 28+ messages in thread
From: Christoph Hellwig @ 2011-10-28 8:29 UTC (permalink / raw)
To: Miklos Szeredi
Cc: Christoph Hellwig, viro, linux-fsdevel, linux-kernel, jack, akpm,
toshi.okajima
On Fri, Oct 28, 2011 at 10:20:06AM +0200, Miklos Szeredi wrote:
> Okay, so a WARN_ON is not warranted. Perhaps a printk instead?
>
> While initializing nlink with zero normally shouldn't be a problem it
> might indicate something unexpected.
Please do a ratelimited printk. If the log recovery case hits any fs
it will usually do it for tons of inodes in a short period.
Also please try to stick to 80 character lines if possible.
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 06/13] jfs: remove unnecessary nlink setting
2011-10-28 12:13 [PATCH 00/13] read-only remount race fix v9 Miklos Szeredi
@ 2011-10-28 12:13 ` Miklos Szeredi
0 siblings, 0 replies; 28+ messages in thread
From: Miklos Szeredi @ 2011-10-28 12:13 UTC (permalink / raw)
To: hch; +Cc: viro, linux-fsdevel, linux-kernel, jack, akpm, toshi.okajima,
mszeredi
From: Miklos Szeredi <mszeredi@suse.cz>
alloc_inode() initializes i_nlink to 1. Remove unnecessary
re-initialization.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Acked-by: Dave Kleikamp <dave.kleikamp@oracle.com>
---
fs/jfs/super.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 06c8a67..a44eff0 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -485,7 +485,6 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
goto out_unload;
}
inode->i_ino = 0;
- inode->i_nlink = 1;
inode->i_size = sb->s_bdev->bd_inode->i_size;
inode->i_mapping->a_ops = &jfs_metapage_aops;
insert_inode_hash(inode);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 28+ messages in thread
end of thread, other threads:[~2011-10-28 12:13 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-12 14:48 [PATCH 0/13] read-only remount race fix v7 Miklos Szeredi
2011-10-12 14:48 ` [PATCH 01/13] vfs: ignore error on forced remount Miklos Szeredi
2011-10-12 14:48 ` [PATCH 02/13] vfs: keep list of mounts for each superblock Miklos Szeredi
2011-10-12 14:48 ` [PATCH 03/13] vfs: protect remounting superblock read-only Miklos Szeredi
2011-10-12 14:48 ` [PATCH 04/13] vfs: fs_may_remount_ro: turn unnecessary check into a WARN_ON Miklos Szeredi
2011-10-12 14:48 ` [PATCH 05/13] hypfs: remove unnecessary nlink setting Miklos Szeredi
2011-10-12 14:48 ` [PATCH 06/13] jfs: " Miklos Szeredi
2011-10-12 15:26 ` Dave Kleikamp
2011-10-12 14:49 ` [PATCH 07/13] ocfs2: " Miklos Szeredi
2011-10-12 14:49 ` [PATCH 08/13] logfs: " Miklos Szeredi
2011-10-12 14:49 ` [PATCH 09/13] filesystems: add missing nlink wrappers Miklos Szeredi
2011-10-12 14:49 ` [PATCH 10/13] filesystems: add set_nlink() Miklos Szeredi
2011-10-13 16:33 ` Steven Whitehouse
2011-10-14 15:04 ` Miklos Szeredi
2011-10-12 14:49 ` [PATCH 11/13] vfs: protect i_nlink Miklos Szeredi
2011-10-12 14:49 ` [PATCH 12/13] vfs: count unlinked inodes Miklos Szeredi
2011-10-28 6:08 ` Christoph Hellwig
2011-10-28 7:53 ` Miklos Szeredi
2011-10-28 8:04 ` Christoph Hellwig
2011-10-28 8:20 ` Miklos Szeredi
2011-10-28 8:29 ` Christoph Hellwig
2011-10-12 14:49 ` [PATCH 13/13] vfs: prevent remount read-only if pending removes Miklos Szeredi
2011-10-12 15:03 ` [PATCH 0/13] read-only remount race fix v7 Christoph Hellwig
2011-10-12 15:09 ` Miklos Szeredi
2011-10-13 7:10 ` Toshiyuki Okajima
2011-10-18 6:28 ` Toshiyuki Okajima
2011-10-18 9:02 ` Miklos Szeredi
-- strict thread matches above, loose matches on Subject: below --
2011-10-28 12:13 [PATCH 00/13] read-only remount race fix v9 Miklos Szeredi
2011-10-28 12:13 ` [PATCH 06/13] jfs: remove unnecessary nlink setting Miklos Szeredi
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.