* [PATCH 1/6] prepare for write access checks: collapse if()
2006-08-09 16:57 [PATCH 0/6] read-only bind mount prep work Dave Hansen
@ 2006-08-09 16:57 ` Dave Hansen
2006-08-09 17:09 ` Christoph Hellwig
2006-08-09 16:57 ` [PATCH 2/6] r/o bind mount prepwork: move open_namei()'s vfs_create() Dave Hansen
` (4 subsequent siblings)
5 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 16:57 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel, hch, Dave Hansen
We're shortly going to be adding a bunch more permission
checks in these functions. That requires adding either a
bunch of new if() conditions, or some gotos. This patch
collapses existing if()s and uses gotos instead to
prepare for the upcoming changes.
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---
lxc-dave/fs/namei.c | 93 +++++++++++++++++++++++++++-------------------------
lxc-dave/fs/open.c | 64 ++++++++++++++++++++---------------
2 files changed, 87 insertions(+), 70 deletions(-)
diff -puN fs/namei.c~B1-prepwork-collapse-ifs fs/namei.c
--- lxc/fs/namei.c~B1-prepwork-collapse-ifs 2006-08-06 03:21:02.000000000 -0700
+++ lxc-dave/fs/namei.c 2006-08-08 09:18:49.000000000 -0700
@@ -1926,30 +1926,32 @@ asmlinkage long sys_mkdirat(int dfd, con
{
int error = 0;
char * tmp;
+ struct dentry *dentry;
+ struct nameidata nd;
tmp = getname(pathname);
error = PTR_ERR(tmp);
- if (!IS_ERR(tmp)) {
- struct dentry *dentry;
- struct nameidata nd;
+ if (IS_ERR(tmp))
+ goto out_err;
- error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
- dentry = lookup_create(&nd, 1);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- if (!IS_POSIXACL(nd.dentry->d_inode))
- mode &= ~current->fs->umask;
- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
- dput(dentry);
- }
- mutex_unlock(&nd.dentry->d_inode->i_mutex);
- path_release(&nd);
-out:
- putname(tmp);
- }
+ error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+ if (error)
+ goto out;
+ dentry = lookup_create(&nd, 1);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto out_unlock;
+ if (!IS_POSIXACL(nd.dentry->d_inode))
+ mode &= ~current->fs->umask;
+ error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
+ dput(dentry);
+out_unlock:
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
+ path_release(&nd);
+out:
+ putname(tmp);
+out_err:
return error;
}
@@ -2048,10 +2050,11 @@ static long do_rmdir(int dfd, const char
mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
- dput(dentry);
- }
+ if (IS_ERR(dentry))
+ goto exit2;
+ error = vfs_rmdir(nd.dentry->d_inode, dentry);
+ dput(dentry);
+exit2:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
exit1:
path_release(&nd);
@@ -2191,30 +2194,33 @@ asmlinkage long sys_symlinkat(const char
int error = 0;
char * from;
char * to;
+ struct dentry *dentry;
+ struct nameidata nd;
from = getname(oldname);
if(IS_ERR(from))
return PTR_ERR(from);
to = getname(newname);
error = PTR_ERR(to);
- if (!IS_ERR(to)) {
- struct dentry *dentry;
- struct nameidata nd;
+ if (IS_ERR(to))
+ goto out_putname;
- error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
- dentry = lookup_create(&nd, 0);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
- dput(dentry);
- }
- mutex_unlock(&nd.dentry->d_inode->i_mutex);
- path_release(&nd);
+ error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+ if (error)
+ goto out;
+ dentry = lookup_create(&nd, 0);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto out_unlock;
+
+ error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
+ dput(dentry);
+out_unlock:
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
+ path_release(&nd);
out:
- putname(to);
- }
+ putname(to);
+out_putname:
putname(from);
return error;
}
@@ -2300,10 +2306,11 @@ asmlinkage long sys_linkat(int olddfd, c
goto out_release;
new_dentry = lookup_create(&nd, 0);
error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
- dput(new_dentry);
- }
+ if (IS_ERR(new_dentry))
+ goto out_unlock;
+ error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
+ dput(new_dentry);
+out_unlock:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
out_release:
path_release(&nd);
diff -puN fs/open.c~B1-prepwork-collapse-ifs fs/open.c
--- lxc/fs/open.c~B1-prepwork-collapse-ifs 2006-08-06 03:21:03.000000000 -0700
+++ lxc-dave/fs/open.c 2006-08-08 09:18:49.000000000 -0700
@@ -520,15 +520,21 @@ asmlinkage long sys_faccessat(int dfd, c
current->cap_effective = current->cap_permitted;
res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
- if (!res) {
- res = vfs_permission(&nd, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
- path_release(&nd);
- }
+ if (res)
+ goto out;
+
+ res = vfs_permission(&nd, mode);
+ /* SuS v2 requires we report a read only fs too */
+ if(res || !(mode & S_IWOTH) ||
+ special_file(nd.dentry->d_inode->i_mode))
+ goto out_path_release;
+
+ if(IS_RDONLY(nd.dentry->d_inode))
+ res = -EROFS;
+out_path_release:
+ path_release(&nd);
+out:
current->fsuid = old_fsuid;
current->fsgid = old_fsgid;
current->cap_effective = old_cap;
@@ -737,10 +743,11 @@ asmlinkage long sys_chown(const char __u
int error;
error = user_path_walk(filename, &nd);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
- path_release(&nd);
- }
+ if (error)
+ goto out;
+ error = chown_common(nd.dentry, user, group);
+ path_release(&nd);
+out:
return error;
}
@@ -756,10 +763,10 @@ asmlinkage long sys_fchownat(int dfd, co
follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
error = __user_walk_fd(dfd, filename, follow, &nd);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
- path_release(&nd);
- }
+ if (error)
+ goto out;
+ error = chown_common(nd.dentry, user, group);
+ path_release(&nd);
out:
return error;
}
@@ -770,10 +777,11 @@ asmlinkage long sys_lchown(const char __
int error;
error = user_path_walk_link(filename, &nd);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
- path_release(&nd);
- }
+ if (error)
+ goto out;
+ error = chown_common(nd.dentry, user, group);
+ path_release(&nd);
+out:
return error;
}
@@ -782,15 +790,17 @@ asmlinkage long sys_fchown(unsigned int
{
struct file * file;
int error = -EBADF;
+ struct dentry * dentry;
file = fget(fd);
- if (file) {
- struct dentry * dentry;
- dentry = file->f_dentry;
- audit_inode(NULL, dentry->d_inode);
- error = chown_common(dentry, user, group);
- fput(file);
- }
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ audit_inode(NULL, dentry->d_inode);
+ error = chown_common(dentry, user, group);
+ fput(file);
+out:
return error;
}
_
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 1/6] prepare for write access checks: collapse if()
2006-08-09 16:57 ` [PATCH 1/6] prepare for write access checks: collapse if() Dave Hansen
@ 2006-08-09 17:09 ` Christoph Hellwig
2006-08-09 17:18 ` Dave Hansen
0 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2006-08-09 17:09 UTC (permalink / raw)
To: Dave Hansen; +Cc: akpm, linux-kernel, hch
On Wed, Aug 09, 2006 at 09:57:30AM -0700, Dave Hansen wrote:
>
> We're shortly going to be adding a bunch more permission
> checks in these functions. That requires adding either a
> bunch of new if() conditions, or some gotos. This patch
> collapses existing if()s and uses gotos instead to
> prepare for the upcoming changes.
>
> Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Acked-by: Christoph Hellwig <hch@lst.de>
> + res = vfs_permission(&nd, mode);
> + /* SuS v2 requires we report a read only fs too */
> + if(res || !(mode & S_IWOTH) ||
except that there's a space missing after the if here :)
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/6] prepare for write access checks: collapse if()
2006-08-09 17:09 ` Christoph Hellwig
@ 2006-08-09 17:18 ` Dave Hansen
0 siblings, 0 replies; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 17:18 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: akpm, linux-kernel
On Wed, 2006-08-09 at 18:09 +0100, Christoph Hellwig wrote:
> On Wed, Aug 09, 2006 at 09:57:30AM -0700, Dave Hansen wrote:
> >
> > We're shortly going to be adding a bunch more permission
> > checks in these functions. That requires adding either a
> > bunch of new if() conditions, or some gotos. This patch
> > collapses existing if()s and uses gotos instead to
> > prepare for the upcoming changes.
> >
> > Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
>
>
> Acked-by: Christoph Hellwig <hch@lst.de>
>
> > + res = vfs_permission(&nd, mode);
> > + /* SuS v2 requires we report a read only fs too */
> > + if(res || !(mode & S_IWOTH) ||
>
> except that there's a space missing after the if here :)
In my defense, the code I moved sucked, too. ;)
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---
lxc-dave/fs/open.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff -puN fs/namei.c~B1-prepwork-collapse-ifs-spacefix fs/namei.c
diff -puN fs/open.c~B1-prepwork-collapse-ifs-spacefix fs/open.c
--- lxc/fs/open.c~B1-prepwork-collapse-ifs-spacefix 2006-08-09 10:13:18.000000000 -0700
+++ lxc-dave/fs/open.c 2006-08-09 10:14:12.000000000 -0700
@@ -525,11 +525,11 @@ asmlinkage long sys_faccessat(int dfd, c
res = vfs_permission(&nd, mode);
/* SuS v2 requires we report a read only fs too */
- if(res || !(mode & S_IWOTH) ||
+ if (res || !(mode & S_IWOTH) ||
special_file(nd.dentry->d_inode->i_mode))
goto out_path_release;
- if(IS_RDONLY(nd.dentry->d_inode))
+ if (IS_RDONLY(nd.dentry->d_inode))
res = -EROFS;
out_path_release:
_
-- Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 2/6] r/o bind mount prepwork: move open_namei()'s vfs_create()
2006-08-09 16:57 [PATCH 0/6] read-only bind mount prep work Dave Hansen
2006-08-09 16:57 ` [PATCH 1/6] prepare for write access checks: collapse if() Dave Hansen
@ 2006-08-09 16:57 ` Dave Hansen
2006-08-09 17:09 ` Christoph Hellwig
2006-08-09 16:57 ` [PATCH 4/6] r/o bind mount prepwork: inc_nlink() helper Dave Hansen
` (3 subsequent siblings)
5 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 16:57 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel, hch, Dave Hansen
The code around vfs_create() in open_namei() is getting a
bit too complex. Right now, there is at least the reference
count on the dentry, and the i_mutex to worry about. Soon,
we'll also have mnt_writecount.
So, break the vfs_create() call out of open_namei(), and
into a helper function. This duplicates the call to
may_open(), but that isn't such a bad thing since the
arguments (acc_mode and flag) were being heavily massaged
anyway.
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---
lxc-dave/fs/namei.c | 30 ++++++++++++++++++++----------
1 files changed, 20 insertions(+), 10 deletions(-)
diff -puN fs/namei.c~B2-prepwork-cleanup-open_namei fs/namei.c
--- lxc/fs/namei.c~B2-prepwork-cleanup-open_namei 2006-08-08 09:18:49.000000000 -0700
+++ lxc-dave/fs/namei.c 2006-08-08 09:18:50.000000000 -0700
@@ -1587,6 +1587,24 @@ int may_open(struct nameidata *nd, int a
return 0;
}
+static int open_namei_create(struct nameidata *nd, struct path *path,
+ int flag, int mode)
+{
+ int error;
+ struct dentry *dir = nd->dentry;
+
+ if (!IS_POSIXACL(dir->d_inode))
+ mode &= ~current->fs->umask;
+ error = vfs_create(dir->d_inode, path->dentry, mode, nd);
+ mutex_unlock(&dir->d_inode->i_mutex);
+ dput(nd->dentry);
+ nd->dentry = path->dentry;
+ if (error)
+ return error;
+ /* Don't check for write permission, don't truncate */
+ return may_open(nd, 0, flag & ~O_TRUNC);
+}
+
/*
* open_namei()
*
@@ -1668,18 +1686,10 @@ do_last:
/* Negative dentry, just create the file */
if (!path.dentry->d_inode) {
- if (!IS_POSIXACL(dir->d_inode))
- mode &= ~current->fs->umask;
- error = vfs_create(dir->d_inode, path.dentry, mode, nd);
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(nd->dentry);
- nd->dentry = path.dentry;
+ error = open_namei_create(nd, &path, flag, mode);
if (error)
goto exit;
- /* Don't check for write permission, don't truncate */
- acc_mode = 0;
- flag &= ~O_TRUNC;
- goto ok;
+ return 0;
}
/*
_
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 2/6] r/o bind mount prepwork: move open_namei()'s vfs_create()
2006-08-09 16:57 ` [PATCH 2/6] r/o bind mount prepwork: move open_namei()'s vfs_create() Dave Hansen
@ 2006-08-09 17:09 ` Christoph Hellwig
0 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2006-08-09 17:09 UTC (permalink / raw)
To: Dave Hansen; +Cc: akpm, linux-kernel, hch
On Wed, Aug 09, 2006 at 09:57:31AM -0700, Dave Hansen wrote:
>
> The code around vfs_create() in open_namei() is getting a
> bit too complex. Right now, there is at least the reference
> count on the dentry, and the i_mutex to worry about. Soon,
> we'll also have mnt_writecount.
>
> So, break the vfs_create() call out of open_namei(), and
> into a helper function. This duplicates the call to
> may_open(), but that isn't such a bad thing since the
> arguments (acc_mode and flag) were being heavily massaged
> anyway.
>
> Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Acked-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 4/6] r/o bind mount prepwork: inc_nlink() helper
2006-08-09 16:57 [PATCH 0/6] read-only bind mount prep work Dave Hansen
2006-08-09 16:57 ` [PATCH 1/6] prepare for write access checks: collapse if() Dave Hansen
2006-08-09 16:57 ` [PATCH 2/6] r/o bind mount prepwork: move open_namei()'s vfs_create() Dave Hansen
@ 2006-08-09 16:57 ` Dave Hansen
2006-08-09 17:11 ` Christoph Hellwig
2006-08-09 16:57 ` [PATCH 3/6] unlink: monitor i_nlink Dave Hansen
` (2 subsequent siblings)
5 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 16:57 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel, hch, Dave Hansen
This is mostly included for parity with dec_nlink(), where
we will have some more hooks. This one should stay pretty
darn straightforward for now.
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---
lxc-dave/drivers/infiniband/hw/ipath/ipath_fs.c | 4 ++--
lxc-dave/drivers/usb/core/inode.c | 4 ++--
lxc-dave/fs/9p/vfs_inode.c | 2 +-
lxc-dave/fs/autofs/root.c | 2 +-
lxc-dave/fs/autofs4/root.c | 2 +-
lxc-dave/fs/bfs/dir.c | 2 +-
lxc-dave/fs/cifs/inode.c | 2 +-
lxc-dave/fs/coda/dir.c | 2 +-
lxc-dave/fs/configfs/dir.c | 4 ++--
lxc-dave/fs/configfs/mount.c | 2 +-
lxc-dave/fs/debugfs/inode.c | 4 ++--
lxc-dave/fs/ext3/namei.c | 6 +++---
lxc-dave/fs/fuse/control.c | 2 +-
lxc-dave/fs/hfsplus/dir.c | 2 +-
lxc-dave/fs/hpfs/namei.c | 4 ++--
lxc-dave/fs/hugetlbfs/inode.c | 4 ++--
lxc-dave/fs/jffs2/dir.c | 6 +++---
lxc-dave/fs/jffs2/fs.c | 6 +++---
lxc-dave/fs/jfs/namei.c | 6 +++---
lxc-dave/fs/libfs.c | 4 ++--
lxc-dave/fs/msdos/namei.c | 4 ++--
lxc-dave/fs/ocfs2/dlm/dlmfs.c | 6 +++---
lxc-dave/fs/ocfs2/namei.c | 8 ++++----
lxc-dave/fs/ramfs/inode.c | 4 ++--
lxc-dave/fs/reiserfs/namei.c | 6 +++---
lxc-dave/fs/sysfs/dir.c | 4 ++--
lxc-dave/fs/sysfs/mount.c | 2 +-
lxc-dave/fs/udf/inode.c | 2 +-
lxc-dave/fs/udf/namei.c | 6 +++---
lxc-dave/fs/vfat/namei.c | 4 ++--
lxc-dave/include/linux/fs.h | 7 ++++++-
lxc-dave/ipc/mqueue.c | 2 +-
lxc-dave/kernel/cpuset.c | 8 ++++----
lxc-dave/mm/shmem.c | 8 ++++----
lxc-dave/net/sunrpc/rpc_pipe.c | 6 +++---
lxc-dave/security/inode.c | 4 ++--
lxc-dave/security/selinux/selinuxfs.c | 4 ++--
37 files changed, 80 insertions(+), 75 deletions(-)
diff -puN include/linux/fs.h~B4-monitor_inc_nlink include/linux/fs.h
--- lxc/include/linux/fs.h~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/include/linux/fs.h 2006-08-08 10:57:59.000000000 -0700
@@ -1256,9 +1256,14 @@ static inline void mark_inode_dirty_sync
__mark_inode_dirty(inode, I_DIRTY_SYNC);
}
-static inline void inode_inc_link_count(struct inode *inode)
+static inline void inc_nlink(struct inode *inode)
{
inode->i_nlink++;
+}
+
+static inline void inode_inc_link_count(struct inode *inode)
+{
+ inc_nlink(inode);
mark_inode_dirty(inode);
}
diff -puN fs/libfs.c~B4-monitor_inc_nlink fs/libfs.c
--- lxc/fs/libfs.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/libfs.c 2006-08-08 10:57:59.000000000 -0700
@@ -243,7 +243,7 @@ int simple_link(struct dentry *old_dentr
struct inode *inode = old_dentry->d_inode;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- inode->i_nlink++;
+ inc_nlink(inode);
atomic_inc(&inode->i_count);
dget(dentry);
d_instantiate(dentry, inode);
@@ -306,7 +306,7 @@ int simple_rename(struct inode *old_dir,
drop_nlink(old_dir);
} else if (they_are_dirs) {
drop_nlink(old_dir);
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
}
old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
diff -puN mm/shmem.c~B4-monitor_inc_nlink mm/shmem.c
--- lxc/mm/shmem.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/mm/shmem.c 2006-08-08 10:57:59.000000000 -0700
@@ -1371,7 +1371,7 @@ shmem_get_inode(struct super_block *sb,
&sbinfo->policy_nodes);
break;
case S_IFDIR:
- inode->i_nlink++;
+ inc_nlink(inode);
/* Some things misbehave if size == 0 on a directory */
inode->i_size = 2 * BOGO_DIRENT_SIZE;
inode->i_op = &shmem_dir_inode_operations;
@@ -1703,7 +1703,7 @@ static int shmem_mkdir(struct inode *dir
if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
return error;
- dir->i_nlink++;
+ inc_nlink(dir);
return 0;
}
@@ -1738,7 +1738,7 @@ static int shmem_link(struct dentry *old
dir->i_size += BOGO_DIRENT_SIZE;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- inode->i_nlink++;
+ inc_nlink(inode);
atomic_inc(&inode->i_count); /* New dentry reference */
dget(dentry); /* Extra pinning count for the created dentry */
d_instantiate(dentry, inode);
@@ -1795,7 +1795,7 @@ static int shmem_rename(struct inode *ol
drop_nlink(old_dir);
} else if (they_are_dirs) {
drop_nlink(old_dir);
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
}
old_dir->i_size -= BOGO_DIRENT_SIZE;
diff -puN drivers/infiniband/hw/ipath/ipath_fs.c~B4-monitor_inc_nlink drivers/infiniband/hw/ipath/ipath_fs.c
--- lxc/drivers/infiniband/hw/ipath/ipath_fs.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/drivers/infiniband/hw/ipath/ipath_fs.c 2006-08-08 10:57:59.000000000 -0700
@@ -66,8 +66,8 @@ static int ipathfs_mknod(struct inode *d
inode->i_private = data;
if ((mode & S_IFMT) == S_IFDIR) {
inode->i_op = &simple_dir_inode_operations;
- inode->i_nlink++;
- dir->i_nlink++;
+ inc_nlink(inode);
+ inc_nlink(dir);
}
inode->i_fop = fops;
diff -puN drivers/usb/core/inode.c~B4-monitor_inc_nlink drivers/usb/core/inode.c
--- lxc/drivers/usb/core/inode.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/drivers/usb/core/inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -263,7 +263,7 @@ static struct inode *usbfs_get_inode (st
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
break;
}
}
@@ -295,7 +295,7 @@ static int usbfs_mkdir (struct inode *di
mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
res = usbfs_mknod (dir, dentry, mode, 0);
if (!res)
- dir->i_nlink++;
+ inc_nlink(dir);
return res;
}
diff -puN fs/9p/vfs_inode.c~B4-monitor_inc_nlink fs/9p/vfs_inode.c
--- lxc/fs/9p/vfs_inode.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/9p/vfs_inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -233,7 +233,7 @@ struct inode *v9fs_get_inode(struct supe
inode->i_op = &v9fs_symlink_inode_operations;
break;
case S_IFDIR:
- inode->i_nlink++;
+ inc_nlink(inode);
if(v9ses->extended)
inode->i_op = &v9fs_dir_inode_operations_ext;
else
diff -puN fs/autofs/root.c~B4-monitor_inc_nlink fs/autofs/root.c
--- lxc/fs/autofs/root.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/autofs/root.c 2006-08-08 10:57:59.000000000 -0700
@@ -466,7 +466,7 @@ static int autofs_root_mkdir(struct inod
ent->dentry = dentry;
autofs_hash_insert(dh,ent);
- dir->i_nlink++;
+ inc_nlink(dir);
d_instantiate(dentry, iget(dir->i_sb,ino));
unlock_kernel();
diff -puN fs/autofs4/root.c~B4-monitor_inc_nlink fs/autofs4/root.c
--- lxc/fs/autofs4/root.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/autofs4/root.c 2006-08-08 10:57:59.000000000 -0700
@@ -713,7 +713,7 @@ static int autofs4_dir_mkdir(struct inod
if (p_ino && dentry->d_parent != dentry)
atomic_inc(&p_ino->count);
ino->inode = inode;
- dir->i_nlink++;
+ inc_nlink(dir);
dir->i_mtime = CURRENT_TIME;
return 0;
diff -puN fs/bfs/dir.c~B4-monitor_inc_nlink fs/bfs/dir.c
--- lxc/fs/bfs/dir.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/bfs/dir.c 2006-08-08 10:57:59.000000000 -0700
@@ -163,7 +163,7 @@ static int bfs_link(struct dentry * old,
unlock_kernel();
return err;
}
- inode->i_nlink++;
+ inc_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
atomic_inc(&inode->i_count);
diff -puN fs/cifs/inode.c~B4-monitor_inc_nlink fs/cifs/inode.c
--- lxc/fs/cifs/inode.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/cifs/inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -736,7 +736,7 @@ int cifs_mkdir(struct inode *inode, stru
cFYI(1, ("cifs_mkdir returned 0x%x", rc));
d_drop(direntry);
} else {
- inode->i_nlink++;
+ inc_nlink(inode);
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid);
diff -puN fs/coda/dir.c~B4-monitor_inc_nlink fs/coda/dir.c
--- lxc/fs/coda/dir.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/coda/dir.c 2006-08-08 10:57:59.000000000 -0700
@@ -304,7 +304,7 @@ static int coda_link(struct dentry *sour
coda_dir_changed(dir_inode, 0);
atomic_inc(&inode->i_count);
d_instantiate(de, inode);
- inode->i_nlink++;
+ inc_nlink(inode);
out:
unlock_kernel();
diff -puN fs/configfs/dir.c~B4-monitor_inc_nlink fs/configfs/dir.c
--- lxc/fs/configfs/dir.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/configfs/dir.c 2006-08-08 10:57:59.000000000 -0700
@@ -113,7 +113,7 @@ static int init_dir(struct inode * inode
inode->i_fop = &configfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
return 0;
}
@@ -141,7 +141,7 @@ static int create_dir(struct config_item
if (!error) {
error = configfs_create(d, mode, init_dir);
if (!error) {
- p->d_inode->i_nlink++;
+ inc_nlink(p->d_inode);
(d)->d_op = &configfs_dentry_ops;
} else {
struct configfs_dirent *sd = d->d_fsdata;
diff -puN fs/configfs/mount.c~B4-monitor_inc_nlink fs/configfs/mount.c
--- lxc/fs/configfs/mount.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/configfs/mount.c 2006-08-08 10:57:59.000000000 -0700
@@ -84,7 +84,7 @@ static int configfs_fill_super(struct su
inode->i_op = &configfs_dir_inode_operations;
inode->i_fop = &configfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
} else {
pr_debug("configfs: could not get root inode\n");
return -ENOMEM;
diff -puN fs/debugfs/inode.c~B4-monitor_inc_nlink fs/debugfs/inode.c
--- lxc/fs/debugfs/inode.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/debugfs/inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -54,7 +54,7 @@ static struct inode *debugfs_get_inode(s
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
break;
}
}
@@ -87,7 +87,7 @@ static int debugfs_mkdir(struct inode *d
mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
res = debugfs_mknod(dir, dentry, mode, 0);
if (!res)
- dir->i_nlink++;
+ inc_nlink(dir);
return res;
}
diff -puN fs/ext3/namei.c~B4-monitor_inc_nlink fs/ext3/namei.c
--- lxc/fs/ext3/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/ext3/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -1616,7 +1616,7 @@ static int ext3_delete_entry (handle_t *
*/
static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
{
- inode->i_nlink++;
+ inc_nlink(inode);
}
static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
@@ -1775,7 +1775,7 @@ retry:
iput (inode);
goto out_stop;
}
- dir->i_nlink++;
+ inc_nlink(dir);
ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir);
d_instantiate(dentry, inode);
@@ -2341,7 +2341,7 @@ static int ext3_rename (struct inode * o
if (new_inode) {
drop_nlink(new_inode);
} else {
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
ext3_update_dx_flag(new_dir);
ext3_mark_inode_dirty(handle, new_dir);
}
diff -puN fs/fuse/control.c~B4-monitor_inc_nlink fs/fuse/control.c
--- lxc/fs/fuse/control.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/fuse/control.c 2006-08-08 10:57:59.000000000 -0700
@@ -116,7 +116,7 @@ int fuse_ctl_add_conn(struct fuse_conn *
return 0;
parent = fuse_control_sb->s_root;
- parent->d_inode->i_nlink++;
+ inc_nlink(parent->d_inode);
sprintf(name, "%llu", (unsigned long long) fc->id);
parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
&simple_dir_inode_operations,
diff -puN fs/hfsplus/dir.c~B4-monitor_inc_nlink fs/hfsplus/dir.c
--- lxc/fs/hfsplus/dir.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/hfsplus/dir.c 2006-08-08 10:57:59.000000000 -0700
@@ -298,7 +298,7 @@ static int hfsplus_link(struct dentry *s
if (res)
return res;
- inode->i_nlink++;
+ inc_nlink(inode);
hfsplus_instantiate(dst_dentry, inode, cnid);
atomic_inc(&inode->i_count);
inode->i_ctime = CURRENT_TIME_SEC;
diff -puN fs/hpfs/namei.c~B4-monitor_inc_nlink fs/hpfs/namei.c
--- lxc/fs/hpfs/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/hpfs/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -89,7 +89,7 @@ static int hpfs_mkdir(struct inode *dir,
brelse(bh);
hpfs_mark_4buffers_dirty(&qbh0);
hpfs_brelse4(&qbh0);
- dir->i_nlink++;
+ inc_nlink(dir);
insert_inode_hash(result);
if (result->i_uid != current->fsuid ||
@@ -635,7 +635,7 @@ static int hpfs_rename(struct inode *old
end:
hpfs_i(i)->i_parent_dir = new_dir->i_ino;
if (S_ISDIR(i->i_mode)) {
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
drop_nlink(old_dir);
}
if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
diff -puN fs/hugetlbfs/inode.c~B4-monitor_inc_nlink fs/hugetlbfs/inode.c
--- lxc/fs/hugetlbfs/inode.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/hugetlbfs/inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -377,7 +377,7 @@ static struct inode *hugetlbfs_get_inode
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
break;
case S_IFLNK:
inode->i_op = &page_symlink_inode_operations;
@@ -418,7 +418,7 @@ static int hugetlbfs_mkdir(struct inode
{
int retval = hugetlbfs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!retval)
- dir->i_nlink++;
+ inc_nlink(dir);
return retval;
}
diff -puN fs/jffs2/dir.c~B4-monitor_inc_nlink fs/jffs2/dir.c
--- lxc/fs/jffs2/dir.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/jffs2/dir.c 2006-08-08 10:57:59.000000000 -0700
@@ -588,7 +588,7 @@ static int jffs2_mkdir (struct inode *di
}
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
- dir_i->i_nlink++;
+ inc_nlink(dir_i);
jffs2_free_raw_dirent(rd);
@@ -836,7 +836,7 @@ static int jffs2_rename (struct inode *o
/* If it was a directory we moved, and there was no victim,
increase i_nlink on its new parent */
if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f)
- new_dir_i->i_nlink++;
+ inc_nlink(new_dir_i);
/* Unlink the original */
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
@@ -848,7 +848,7 @@ static int jffs2_rename (struct inode *o
/* Oh shit. We really ought to make a single node which can do both atomically */
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
down(&f->sem);
- old_dentry->d_inode->i_nlink++;
+ inc_nlink(old_dentry->d_inode);
if (f->inocache)
f->inocache->nlink++;
up(&f->sem);
diff -puN fs/jffs2/fs.c~B4-monitor_inc_nlink fs/jffs2/fs.c
--- lxc/fs/jffs2/fs.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/jffs2/fs.c 2006-08-08 10:57:59.000000000 -0700
@@ -277,13 +277,13 @@ void jffs2_read_inode (struct inode *ino
for (fd=f->dents; fd; fd = fd->next) {
if (fd->type == DT_DIR && fd->ino)
- inode->i_nlink++;
+ inc_nlink(inode);
}
/* and '..' */
- inode->i_nlink++;
+ inc_nlink(inode);
/* Root dir gets i_nlink 3 for some reason */
if (inode->i_ino == 1)
- inode->i_nlink++;
+ inc_nlink(inode);
inode->i_op = &jffs2_dir_inode_operations;
inode->i_fop = &jffs2_dir_operations;
diff -puN fs/jfs/namei.c~B4-monitor_inc_nlink fs/jfs/namei.c
--- lxc/fs/jfs/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/jfs/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -292,7 +292,7 @@ static int jfs_mkdir(struct inode *dip,
mark_inode_dirty(ip);
/* update parent directory inode */
- dip->i_nlink++; /* for '..' from child directory */
+ inc_nlink(dip); /* for '..' from child directory */
dip->i_ctime = dip->i_mtime = CURRENT_TIME;
mark_inode_dirty(dip);
@@ -822,7 +822,7 @@ static int jfs_link(struct dentry *old_d
goto free_dname;
/* update object inode */
- ip->i_nlink++; /* for new link */
+ inc_nlink(ip); /* for new link */
ip->i_ctime = CURRENT_TIME;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(dir);
@@ -1206,7 +1206,7 @@ static int jfs_rename(struct inode *old_
goto out4;
}
if (S_ISDIR(old_ip->i_mode))
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
}
/*
* Remove old directory entry
diff -puN fs/msdos/namei.c~B4-monitor_inc_nlink fs/msdos/namei.c
--- lxc/fs/msdos/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/msdos/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -385,7 +385,7 @@ static int msdos_mkdir(struct inode *dir
err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
if (err)
goto out_free;
- dir->i_nlink++;
+ inc_nlink(dir);
inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
brelse(sinfo.bh);
@@ -544,7 +544,7 @@ static int do_msdos_rename(struct inode
}
drop_nlink(old_dir);
if (!new_inode)
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
}
err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */
diff -puN fs/ocfs2/dlm/dlmfs.c~B4-monitor_inc_nlink fs/ocfs2/dlm/dlmfs.c
--- lxc/fs/ocfs2/dlm/dlmfs.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/ocfs2/dlm/dlmfs.c 2006-08-08 10:57:59.000000000 -0700
@@ -338,7 +338,7 @@ static struct inode *dlmfs_get_root_inod
inode->i_blocks = 0;
inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_nlink++;
+ inc_nlink(inode);
inode->i_fop = &simple_dir_operations;
inode->i_op = &dlmfs_root_inode_operations;
@@ -395,7 +395,7 @@ static struct inode *dlmfs_get_inode(str
/* directory inodes start off with i_nlink ==
* 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
break;
}
@@ -449,7 +449,7 @@ static int dlmfs_mkdir(struct inode * di
}
ip->ip_dlm = dlm;
- dir->i_nlink++;
+ inc_nlink(dir);
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
diff -puN fs/ocfs2/namei.c~B4-monitor_inc_nlink fs/ocfs2/namei.c
--- lxc/fs/ocfs2/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/ocfs2/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -408,7 +408,7 @@ static int ocfs2_mknod(struct inode *dir
mlog_errno(status);
goto leave;
}
- dir->i_nlink++;
+ inc_nlink(dir);
}
status = ocfs2_add_entry(handle, dentry, inode,
@@ -702,7 +702,7 @@ static int ocfs2_link(struct dentry *old
goto bail;
}
- inode->i_nlink++;
+ inc_nlink(inode);
inode->i_ctime = CURRENT_TIME;
fe->i_links_count = cpu_to_le16(inode->i_nlink);
fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
@@ -902,7 +902,7 @@ static int ocfs2_unlink(struct inode *di
parent_node_bh);
if (status < 0) {
mlog_errno(status);
- dir->i_nlink++;
+ inc_nlink(dir);
}
}
@@ -1344,7 +1344,7 @@ static int ocfs2_rename(struct inode *ol
if (new_inode) {
new_inode->i_nlink--;
} else {
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
mark_inode_dirty(new_dir);
}
}
diff -puN fs/ramfs/inode.c~B4-monitor_inc_nlink fs/ramfs/inode.c
--- lxc/fs/ramfs/inode.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/ramfs/inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -75,7 +75,7 @@ struct inode *ramfs_get_inode(struct sup
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
break;
case S_IFLNK:
inode->i_op = &page_symlink_inode_operations;
@@ -113,7 +113,7 @@ static int ramfs_mkdir(struct inode * di
{
int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!retval)
- dir->i_nlink++;
+ inc_nlink(dir);
return retval;
}
diff -puN fs/reiserfs/namei.c~B4-monitor_inc_nlink fs/reiserfs/namei.c
--- lxc/fs/reiserfs/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/reiserfs/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -19,7 +19,7 @@
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
-#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { i->i_nlink++; 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) i->i_nlink=1; }
#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
// directory item contains array of entry headers. This performs
@@ -1006,7 +1006,7 @@ static int reiserfs_unlink(struct inode
reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL,
0);
if (retval < 0) {
- inode->i_nlink++;
+ inc_nlink(inode);
goto end_unlink;
}
inode->i_ctime = CURRENT_TIME_SEC;
@@ -1143,7 +1143,7 @@ static int reiserfs_link(struct dentry *
}
/* inc before scheduling so reiserfs_unlink knows we are here */
- inode->i_nlink++;
+ inc_nlink(inode);
retval = journal_begin(&th, dir->i_sb, jbegin_count);
if (retval) {
diff -puN fs/sysfs/dir.c~B4-monitor_inc_nlink fs/sysfs/dir.c
--- lxc/fs/sysfs/dir.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/sysfs/dir.c 2006-08-08 10:57:59.000000000 -0700
@@ -103,7 +103,7 @@ static int init_dir(struct inode * inode
inode->i_fop = &sysfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
return 0;
}
@@ -137,7 +137,7 @@ static int create_dir(struct kobject * k
if (!error) {
error = sysfs_create(*d, mode, init_dir);
if (!error) {
- p->d_inode->i_nlink++;
+ inc_nlink(p->d_inode);
(*d)->d_op = &sysfs_dentry_ops;
d_rehash(*d);
}
diff -puN fs/sysfs/mount.c~B4-monitor_inc_nlink fs/sysfs/mount.c
--- lxc/fs/sysfs/mount.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/sysfs/mount.c 2006-08-08 10:57:59.000000000 -0700
@@ -49,7 +49,7 @@ static int sysfs_fill_super(struct super
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
} else {
pr_debug("sysfs: could not get root inode\n");
return -ENOMEM;
diff -puN fs/udf/inode.c~B4-monitor_inc_nlink fs/udf/inode.c
--- lxc/fs/udf/inode.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/udf/inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -1165,7 +1165,7 @@ static void udf_fill_inode(struct inode
inode->i_op = &udf_dir_inode_operations;
inode->i_fop = &udf_dir_operations;
inode->i_mode |= S_IFDIR;
- inode->i_nlink ++;
+ inc_nlink(inode);
break;
}
case ICBTAG_FILE_TYPE_REALTIME:
diff -puN fs/udf/namei.c~B4-monitor_inc_nlink fs/udf/namei.c
--- lxc/fs/udf/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/udf/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -762,7 +762,7 @@ static int udf_mkdir(struct inode * dir,
cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
- dir->i_nlink++;
+ inc_nlink(dir);
mark_inode_dirty(dir);
d_instantiate(dentry, inode);
if (fibh.sbh != fibh.ebh)
@@ -1147,7 +1147,7 @@ static int udf_link(struct dentry * old_
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
- inode->i_nlink ++;
+ inc_nlink(inode);
inode->i_ctime = current_fs_time(inode->i_sb);
mark_inode_dirty(inode);
atomic_inc(&inode->i_count);
@@ -1282,7 +1282,7 @@ static int udf_rename (struct inode * ol
}
else
{
- new_dir->i_nlink ++;
+ inc_nlink(new_dir);
mark_inode_dirty(new_dir);
}
}
diff -puN fs/vfat/namei.c~B4-monitor_inc_nlink fs/vfat/namei.c
--- lxc/fs/vfat/namei.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/fs/vfat/namei.c 2006-08-08 10:57:59.000000000 -0700
@@ -837,7 +837,7 @@ static int vfat_mkdir(struct inode *dir,
if (err)
goto out_free;
dir->i_version++;
- dir->i_nlink++;
+ inc_nlink(dir);
inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
brelse(sinfo.bh);
@@ -932,7 +932,7 @@ static int vfat_rename(struct inode *old
}
drop_nlink(old_dir);
if (!new_inode)
- new_dir->i_nlink++;
+ inc_nlink(new_dir);
}
err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */
diff -puN ipc/mqueue.c~B4-monitor_inc_nlink ipc/mqueue.c
--- lxc/ipc/mqueue.c~B4-monitor_inc_nlink 2006-08-08 10:57:11.000000000 -0700
+++ lxc-dave/ipc/mqueue.c 2006-08-08 10:57:59.000000000 -0700
@@ -168,7 +168,7 @@ static struct inode *mqueue_get_inode(st
/* all is ok */
info->user = get_uid(u);
} else if (S_ISDIR(mode)) {
- inode->i_nlink++;
+ inc_nlink(inode);
/* Some things misbehave if size == 0 on a directory */
inode->i_size = 2 * DIRENT_SIZE;
inode->i_op = &mqueue_dir_inode_operations;
diff -puN kernel/cpuset.c~B4-monitor_inc_nlink kernel/cpuset.c
--- lxc/kernel/cpuset.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/kernel/cpuset.c 2006-08-08 10:57:59.000000000 -0700
@@ -377,7 +377,7 @@ static int cpuset_fill_super(struct supe
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
/* directories start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
} else {
return -ENOMEM;
}
@@ -1552,7 +1552,7 @@ static int cpuset_create_file(struct den
inode->i_fop = &simple_dir_operations;
/* start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
} else if (S_ISREG(mode)) {
inode->i_size = 0;
inode->i_fop = &cpuset_file_operations;
@@ -1585,7 +1585,7 @@ static int cpuset_create_dir(struct cpus
error = cpuset_create_file(dentry, S_IFDIR | mode);
if (!error) {
dentry->d_fsdata = cs;
- parent->d_inode->i_nlink++;
+ inc_nlink(parent->d_inode);
cs->dentry = dentry;
}
dput(dentry);
@@ -2020,7 +2020,7 @@ int __init cpuset_init(void)
}
root = cpuset_mount->mnt_sb->s_root;
root->d_fsdata = &top_cpuset;
- root->d_inode->i_nlink++;
+ inc_nlink(root->d_inode);
top_cpuset.dentry = root;
root->d_inode->i_op = &cpuset_dir_inode_operations;
number_of_cpusets = 1;
diff -puN net/sunrpc/rpc_pipe.c~B4-monitor_inc_nlink net/sunrpc/rpc_pipe.c
--- lxc/net/sunrpc/rpc_pipe.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/net/sunrpc/rpc_pipe.c 2006-08-08 10:57:59.000000000 -0700
@@ -496,7 +496,7 @@ rpc_get_inode(struct super_block *sb, in
case S_IFDIR:
inode->i_fop = &simple_dir_operations;
inode->i_op = &simple_dir_inode_operations;
- inode->i_nlink++;
+ inc_nlink(inode);
default:
break;
}
@@ -572,7 +572,7 @@ rpc_populate(struct dentry *parent,
if (private)
rpc_inode_setowner(inode, private);
if (S_ISDIR(mode))
- dir->i_nlink++;
+ inc_nlink(dir);
d_add(dentry, inode);
}
mutex_unlock(&dir->i_mutex);
@@ -594,7 +594,7 @@ __rpc_mkdir(struct inode *dir, struct de
goto out_err;
inode->i_ino = iunique(dir->i_sb, 100);
d_instantiate(dentry, inode);
- dir->i_nlink++;
+ inc_nlink(dir);
inode_dir_notify(dir, DN_CREATE);
return 0;
out_err:
diff -puN security/inode.c~B4-monitor_inc_nlink security/inode.c
--- lxc/security/inode.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/security/inode.c 2006-08-08 10:57:59.000000000 -0700
@@ -78,7 +78,7 @@ static struct inode *get_inode(struct su
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
break;
}
}
@@ -111,7 +111,7 @@ static int mkdir(struct inode *dir, stru
mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
res = mknod(dir, dentry, mode, 0);
if (!res)
- dir->i_nlink++;
+ inc_nlink(dir);
return res;
}
diff -puN security/selinux/selinuxfs.c~B4-monitor_inc_nlink security/selinux/selinuxfs.c
--- lxc/security/selinux/selinuxfs.c~B4-monitor_inc_nlink 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/security/selinux/selinuxfs.c 2006-08-08 10:57:59.000000000 -0700
@@ -1253,10 +1253,10 @@ static int sel_make_dir(struct inode *di
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
+ inc_nlink(inode);
d_add(dentry, inode);
/* bump link count on parent directory, too */
- dir->i_nlink++;
+ inc_nlink(dir);
out:
return ret;
}
_
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 3/6] unlink: monitor i_nlink
2006-08-09 16:57 [PATCH 0/6] read-only bind mount prep work Dave Hansen
` (2 preceding siblings ...)
2006-08-09 16:57 ` [PATCH 4/6] r/o bind mount prepwork: inc_nlink() helper Dave Hansen
@ 2006-08-09 16:57 ` Dave Hansen
2006-08-09 17:11 ` Christoph Hellwig
2006-08-09 16:57 ` [PATCH 5/6] clean up OCFS2 nlink handling Dave Hansen
2006-08-09 16:57 ` [PATCH 6/6] monitor zeroing of i_nlink Dave Hansen
5 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 16:57 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel, hch, Dave Hansen
When a filesystem decrements i_nlink to zero, it means that a
write must be performed in order to drop the inode from the
filesystem.
We're shortly going to have keep filesystems from being remounted
r/o between the time that this i_nlink decrement and that write
occurs.
So, add a little helper function to do the decrements. We'll
tie into it in a bit to note when i_nlink hits zero.
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---
lxc-dave/drivers/usb/core/inode.c | 7 ++++---
lxc-dave/fs/autofs/root.c | 2 +-
lxc-dave/fs/autofs4/root.c | 2 +-
lxc-dave/fs/bfs/dir.c | 9 +++------
lxc-dave/fs/cifs/inode.c | 10 +++++-----
lxc-dave/fs/coda/dir.c | 4 ++--
lxc-dave/fs/ext2/namei.c | 2 +-
lxc-dave/fs/ext3/namei.c | 14 +++++++-------
lxc-dave/fs/hfs/dir.c | 2 +-
lxc-dave/fs/hfsplus/dir.c | 2 +-
lxc-dave/fs/hpfs/namei.c | 6 +++---
lxc-dave/fs/jffs/inode-v23.c | 3 +--
lxc-dave/fs/jffs2/dir.c | 6 +++---
lxc-dave/fs/jfs/namei.c | 14 ++++++--------
lxc-dave/fs/libfs.c | 10 +++++-----
lxc-dave/fs/minix/namei.c | 2 +-
lxc-dave/fs/msdos/namei.c | 9 ++++-----
lxc-dave/fs/nfs/dir.c | 6 +++---
lxc-dave/fs/ocfs2/namei.c | 4 ++--
lxc-dave/fs/qnx4/namei.c | 6 ++----
lxc-dave/fs/reiserfs/namei.c | 6 +++---
lxc-dave/fs/sysv/namei.c | 2 +-
lxc-dave/fs/udf/namei.c | 18 ++++++------------
lxc-dave/fs/ufs/namei.c | 2 +-
lxc-dave/fs/vfat/namei.c | 9 ++++-----
lxc-dave/include/linux/fs.h | 7 ++++++-
lxc-dave/ipc/mqueue.c | 2 +-
lxc-dave/mm/shmem.c | 10 +++++-----
28 files changed, 83 insertions(+), 93 deletions(-)
diff -puN include/linux/fs.h~B3-unlink-monitor-i_nlink-0 include/linux/fs.h
--- lxc/include/linux/fs.h~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/include/linux/fs.h 2006-08-08 10:57:11.000000000 -0700
@@ -1262,9 +1262,14 @@ static inline void inode_inc_link_count(
mark_inode_dirty(inode);
}
-static inline void inode_dec_link_count(struct inode *inode)
+static inline void drop_nlink(struct inode *inode)
{
inode->i_nlink--;
+}
+
+static inline void inode_dec_link_count(struct inode *inode)
+{
+ drop_nlink(inode);
mark_inode_dirty(inode);
}
diff -puN drivers/usb/core/inode.c~B3-unlink-monitor-i_nlink-0 drivers/usb/core/inode.c
--- lxc/drivers/usb/core/inode.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/drivers/usb/core/inode.c 2006-08-08 10:57:11.000000000 -0700
@@ -332,7 +332,7 @@ static int usbfs_unlink (struct inode *d
{
struct inode *inode = dentry->d_inode;
mutex_lock(&inode->i_mutex);
- dentry->d_inode->i_nlink--;
+ drop_nlink(dentry->d_inode);
dput(dentry);
mutex_unlock(&inode->i_mutex);
d_delete(dentry);
@@ -347,10 +347,11 @@ static int usbfs_rmdir(struct inode *dir
mutex_lock(&inode->i_mutex);
dentry_unhash(dentry);
if (usbfs_empty(dentry)) {
- dentry->d_inode->i_nlink -= 2;
+ drop_nlink(dentry->d_inode);
+ drop_nlink(dentry->d_inode);
dput(dentry);
inode->i_flags |= S_DEAD;
- dir->i_nlink--;
+ drop_nlink(dir);
error = 0;
}
mutex_unlock(&inode->i_mutex);
diff -puN fs/autofs/root.c~B3-unlink-monitor-i_nlink-0 fs/autofs/root.c
--- lxc/fs/autofs/root.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/autofs/root.c 2006-08-08 10:57:11.000000000 -0700
@@ -414,7 +414,7 @@ static int autofs_root_rmdir(struct inod
dentry->d_time = (unsigned long)(struct autofs_dir_ent *)NULL;
autofs_hash_delete(ent);
- dir->i_nlink--;
+ drop_nlink(dir);
d_drop(dentry);
unlock_kernel();
diff -puN fs/autofs4/root.c~B3-unlink-monitor-i_nlink-0 fs/autofs4/root.c
--- lxc/fs/autofs4/root.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/autofs4/root.c 2006-08-08 10:57:11.000000000 -0700
@@ -676,7 +676,7 @@ static int autofs4_dir_rmdir(struct inod
dentry->d_inode->i_nlink = 0;
if (dir->i_nlink)
- dir->i_nlink--;
+ drop_nlink(dir);
return 0;
}
diff -puN fs/bfs/dir.c~B3-unlink-monitor-i_nlink-0 fs/bfs/dir.c
--- lxc/fs/bfs/dir.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/bfs/dir.c 2006-08-08 10:57:11.000000000 -0700
@@ -117,8 +117,7 @@ static int bfs_create(struct inode * dir
err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);
if (err) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
iput(inode);
unlock_kernel();
return err;
@@ -196,9 +195,8 @@ static int bfs_unlink(struct inode * dir
mark_buffer_dirty(bh);
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
- inode->i_nlink--;
inode->i_ctime = dir->i_ctime;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
error = 0;
out_brelse:
@@ -249,9 +247,8 @@ static int bfs_rename(struct inode * old
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(old_dir);
if (new_inode) {
- new_inode->i_nlink--;
new_inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(new_inode);
+ inode_dec_link_count(new_inode);
}
mark_buffer_dirty(old_bh);
error = 0;
diff -puN fs/cifs/inode.c~B3-unlink-monitor-i_nlink-0 fs/cifs/inode.c
--- lxc/fs/cifs/inode.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/cifs/inode.c 2006-08-08 10:57:11.000000000 -0700
@@ -591,7 +591,7 @@ int cifs_unlink(struct inode *inode, str
if (!rc) {
if (direntry->d_inode)
- direntry->d_inode->i_nlink--;
+ drop_nlink(direntry->d_inode);
} else if (rc == -ENOENT) {
d_drop(direntry);
} else if (rc == -ETXTBSY) {
@@ -610,7 +610,7 @@ int cifs_unlink(struct inode *inode, str
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
if (direntry->d_inode)
- direntry->d_inode->i_nlink--;
+ drop_nlink(direntry->d_inode);
}
} else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */
@@ -664,7 +664,7 @@ int cifs_unlink(struct inode *inode, str
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
if (direntry->d_inode)
- direntry->d_inode->i_nlink--;
+ drop_nlink(direntry->d_inode);
} else if (rc == -ETXTBSY) {
int oplock = FALSE;
__u16 netfid;
@@ -685,7 +685,7 @@ int cifs_unlink(struct inode *inode, str
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
if (direntry->d_inode)
- direntry->d_inode->i_nlink--;
+ drop_nlink(direntry->d_inode);
}
/* BB if rc = -ETXTBUSY goto the rename logic BB */
}
@@ -817,7 +817,7 @@ int cifs_rmdir(struct inode *inode, stru
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
- inode->i_nlink--;
+ drop_nlink(inode);
i_size_write(direntry->d_inode,0);
direntry->d_inode->i_nlink = 0;
}
diff -puN fs/coda/dir.c~B3-unlink-monitor-i_nlink-0 fs/coda/dir.c
--- lxc/fs/coda/dir.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/coda/dir.c 2006-08-08 10:57:11.000000000 -0700
@@ -367,7 +367,7 @@ int coda_unlink(struct inode *dir, struc
}
coda_dir_changed(dir, 0);
- de->d_inode->i_nlink--;
+ drop_nlink(de->d_inode);
unlock_kernel();
return 0;
@@ -394,7 +394,7 @@ int coda_rmdir(struct inode *dir, struct
}
coda_dir_changed(dir, -1);
- de->d_inode->i_nlink--;
+ drop_nlink(de->d_inode);
d_delete(de);
unlock_kernel();
diff -puN fs/ext2/namei.c~B3-unlink-monitor-i_nlink-0 fs/ext2/namei.c
--- lxc/fs/ext2/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/ext2/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -326,7 +326,7 @@ static int ext2_rename (struct inode * o
ext2_set_link(new_dir, new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de)
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
inode_dec_link_count(new_inode);
} else {
if (dir_de) {
diff -puN fs/ext3/namei.c~B3-unlink-monitor-i_nlink-0 fs/ext3/namei.c
--- lxc/fs/ext3/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/ext3/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -1621,7 +1621,7 @@ static inline void ext3_inc_count(handle
static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
{
- inode->i_nlink--;
+ drop_nlink(inode);
}
static int ext3_add_nondir(handle_t *handle,
@@ -1743,7 +1743,7 @@ retry:
inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
dir_block = ext3_bread (handle, inode, 0, 1, &err);
if (!dir_block) {
- inode->i_nlink--; /* is this nlink == 0? */
+ drop_nlink(inode); /* is this nlink == 0? */
ext3_mark_inode_dirty(handle, inode);
iput (inode);
goto out_stop;
@@ -2053,7 +2053,7 @@ static int ext3_rmdir (struct inode * di
ext3_orphan_add(handle, inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
ext3_mark_inode_dirty(handle, inode);
- dir->i_nlink--;
+ drop_nlink(dir);
ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir);
@@ -2104,7 +2104,7 @@ static int ext3_unlink(struct inode * di
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir);
- inode->i_nlink--;
+ drop_nlink(inode);
if (!inode->i_nlink)
ext3_orphan_add(handle, inode);
inode->i_ctime = dir->i_ctime;
@@ -2326,7 +2326,7 @@ static int ext3_rename (struct inode * o
}
if (new_inode) {
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
new_inode->i_ctime = CURRENT_TIME_SEC;
}
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
@@ -2337,9 +2337,9 @@ static int ext3_rename (struct inode * o
PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
ext3_journal_dirty_metadata(handle, dir_bh);
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
if (new_inode) {
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
} else {
new_dir->i_nlink++;
ext3_update_dx_flag(new_dir);
diff -puN fs/hfs/dir.c~B3-unlink-monitor-i_nlink-0 fs/hfs/dir.c
--- lxc/fs/hfs/dir.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/hfs/dir.c 2006-08-08 10:57:11.000000000 -0700
@@ -246,7 +246,7 @@ static int hfs_unlink(struct inode *dir,
if (res)
return res;
- inode->i_nlink--;
+ drop_nlink(inode);
hfs_delete_inode(inode);
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
diff -puN fs/hfsplus/dir.c~B3-unlink-monitor-i_nlink-0 fs/hfsplus/dir.c
--- lxc/fs/hfsplus/dir.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/hfsplus/dir.c 2006-08-08 10:57:11.000000000 -0700
@@ -338,7 +338,7 @@ static int hfsplus_unlink(struct inode *
return res;
if (inode->i_nlink > 0)
- inode->i_nlink--;
+ drop_nlink(inode);
hfsplus_delete_inode(inode);
if (inode->i_ino != cnid && !inode->i_nlink) {
if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
diff -puN fs/hpfs/namei.c~B3-unlink-monitor-i_nlink-0 fs/hpfs/namei.c
--- lxc/fs/hpfs/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/hpfs/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -434,7 +434,7 @@ again:
unlock_kernel();
return -ENOSPC;
default:
- inode->i_nlink--;
+ drop_nlink(inode);
err = 0;
}
goto out;
@@ -494,7 +494,7 @@ static int hpfs_rmdir(struct inode *dir,
err = -ENOSPC;
break;
default:
- dir->i_nlink--;
+ drop_nlink(dir);
inode->i_nlink = 0;
err = 0;
}
@@ -636,7 +636,7 @@ static int hpfs_rename(struct inode *old
hpfs_i(i)->i_parent_dir = new_dir->i_ino;
if (S_ISDIR(i->i_mode)) {
new_dir->i_nlink++;
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
}
if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
fnode->up = new_dir->i_ino;
diff -puN fs/jffs2/dir.c~B3-unlink-monitor-i_nlink-0 fs/jffs2/dir.c
--- lxc/fs/jffs2/dir.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/jffs2/dir.c 2006-08-08 10:57:11.000000000 -0700
@@ -615,7 +615,7 @@ static int jffs2_rmdir (struct inode *di
}
ret = jffs2_unlink(dir_i, dentry);
if (!ret)
- dir_i->i_nlink--;
+ drop_nlink(dir_i);
return ret;
}
@@ -823,7 +823,7 @@ static int jffs2_rename (struct inode *o
if (victim_f) {
/* There was a victim. Kill it off nicely */
- new_dentry->d_inode->i_nlink--;
+ drop_nlink(new_dentry->d_inode);
/* Don't oops if the victim was a dirent pointing to an
inode which didn't exist. */
if (victim_f->inocache) {
@@ -862,7 +862,7 @@ static int jffs2_rename (struct inode *o
}
if (S_ISDIR(old_dentry->d_inode->i_mode))
- old_dir_i->i_nlink--;
+ drop_nlink(old_dir_i);
new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
diff -puN fs/jfs/namei.c~B3-unlink-monitor-i_nlink-0 fs/jfs/namei.c
--- lxc/fs/jfs/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/jfs/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -393,9 +393,8 @@ static int jfs_rmdir(struct inode *dip,
/* update parent directory's link count corresponding
* to ".." entry of the target directory deleted
*/
- dip->i_nlink--;
dip->i_ctime = dip->i_mtime = CURRENT_TIME;
- mark_inode_dirty(dip);
+ inode_dec_link_count(dip);
/*
* OS/2 could have created EA and/or ACL
@@ -515,8 +514,7 @@ static int jfs_unlink(struct inode *dip,
mark_inode_dirty(dip);
/* update target's inode */
- ip->i_nlink--;
- mark_inode_dirty(ip);
+ inode_dec_link_count(ip);
/*
* commit zero link count object
@@ -835,7 +833,7 @@ static int jfs_link(struct dentry *old_d
rc = txCommit(tid, 2, &iplist[0], 0);
if (rc) {
- ip->i_nlink--;
+ ip->i_nlink--; /* never instantiated */
iput(ip);
} else
d_instantiate(dentry, ip);
@@ -1155,9 +1153,9 @@ static int jfs_rename(struct inode *old_
old_ip->i_ino, JFS_RENAME);
if (rc)
goto out4;
- new_ip->i_nlink--;
+ drop_nlink(new_ip);
if (S_ISDIR(new_ip->i_mode)) {
- new_ip->i_nlink--;
+ drop_nlink(new_ip);
if (new_ip->i_nlink) {
mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
if (old_dir != new_dir)
@@ -1223,7 +1221,7 @@ static int jfs_rename(struct inode *old_
goto out4;
}
if (S_ISDIR(old_ip->i_mode)) {
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
if (old_dir != new_dir) {
/*
* Change inode number of parent for moved directory
diff -puN fs/libfs.c~B3-unlink-monitor-i_nlink-0 fs/libfs.c
--- lxc/fs/libfs.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/libfs.c 2006-08-08 10:57:11.000000000 -0700
@@ -275,7 +275,7 @@ int simple_unlink(struct inode *dir, str
struct inode *inode = dentry->d_inode;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- inode->i_nlink--;
+ drop_nlink(inode);
dput(dentry);
return 0;
}
@@ -285,9 +285,9 @@ int simple_rmdir(struct inode *dir, stru
if (!simple_empty(dentry))
return -ENOTEMPTY;
- dentry->d_inode->i_nlink--;
+ drop_nlink(dentry->d_inode);
simple_unlink(dir, dentry);
- dir->i_nlink--;
+ drop_nlink(dir);
return 0;
}
@@ -303,9 +303,9 @@ int simple_rename(struct inode *old_dir,
if (new_dentry->d_inode) {
simple_unlink(new_dir, new_dentry);
if (they_are_dirs)
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
} else if (they_are_dirs) {
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
new_dir->i_nlink++;
}
diff -puN fs/nfs/dir.c~B3-unlink-monitor-i_nlink-0 fs/nfs/dir.c
--- lxc/fs/nfs/dir.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/nfs/dir.c 2006-08-08 10:57:11.000000000 -0700
@@ -842,7 +842,7 @@ static void nfs_dentry_iput(struct dentr
nfs_inode_return_delegation(inode);
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
lock_kernel();
- inode->i_nlink--;
+ drop_nlink(inode);
nfs_complete_unlink(dentry);
unlock_kernel();
}
@@ -1395,7 +1395,7 @@ static int nfs_safe_remove(struct dentry
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
/* The VFS may want to delete this inode */
if (error == 0)
- inode->i_nlink--;
+ drop_nlink(inode);
nfs_mark_for_revalidate(inode);
nfs_end_data_update(inode);
} else
@@ -1599,7 +1599,7 @@ static int nfs_rename(struct inode *old_
goto out;
}
} else
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
go_ahead:
/*
diff -puN fs/ocfs2/namei.c~B3-unlink-monitor-i_nlink-0 fs/ocfs2/namei.c
--- lxc/fs/ocfs2/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/ocfs2/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -711,7 +711,7 @@ static int ocfs2_link(struct dentry *old
err = ocfs2_journal_dirty(handle, fe_bh);
if (err < 0) {
le16_add_cpu(&fe->i_links_count, -1);
- inode->i_nlink--;
+ drop_nlink(inode);
mlog_errno(err);
goto bail;
}
@@ -721,7 +721,7 @@ static int ocfs2_link(struct dentry *old
parent_fe_bh, de_bh);
if (err) {
le16_add_cpu(&fe->i_links_count, -1);
- inode->i_nlink--;
+ drop_nlink(inode);
mlog_errno(err);
goto bail;
}
diff -puN fs/qnx4/namei.c~B3-unlink-monitor-i_nlink-0 fs/qnx4/namei.c
--- lxc/fs/qnx4/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/qnx4/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -189,8 +189,7 @@ int qnx4_rmdir(struct inode *dir, struct
inode->i_nlink = 0;
mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
- dir->i_nlink--;
- mark_inode_dirty(dir);
+ inode_dec_link_count(dir);
retval = 0;
end_rmdir:
@@ -234,9 +233,8 @@ int qnx4_unlink(struct inode *dir, struc
mark_buffer_dirty(bh);
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
- inode->i_nlink--;
inode->i_ctime = dir->i_ctime;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
retval = 0;
end_unlink:
diff -puN fs/reiserfs/namei.c~B3-unlink-monitor-i_nlink-0 fs/reiserfs/namei.c
--- lxc/fs/reiserfs/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/reiserfs/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -20,7 +20,7 @@
#include <linux/quotaops.h>
#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { i->i_nlink++; if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }
-#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) i->i_nlink--;
+#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
// directory item contains array of entry headers. This performs
// binary search through that array
@@ -994,7 +994,7 @@ static int reiserfs_unlink(struct inode
inode->i_nlink = 1;
}
- inode->i_nlink--;
+ drop_nlink(inode);
/*
* we schedule before doing the add_save_link call, save the link
@@ -1475,7 +1475,7 @@ static int reiserfs_rename(struct inode
if (S_ISDIR(new_dentry_inode->i_mode)) {
new_dentry_inode->i_nlink = 0;
} else {
- new_dentry_inode->i_nlink--;
+ drop_nlink(new_dentry_inode);
}
new_dentry_inode->i_ctime = ctime;
savelink = new_dentry_inode->i_nlink;
diff -puN fs/sysv/namei.c~B3-unlink-monitor-i_nlink-0 fs/sysv/namei.c
--- lxc/fs/sysv/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/sysv/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -250,7 +250,7 @@ static int sysv_rename(struct inode * ol
sysv_set_link(new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de)
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
inode_dec_link_count(new_inode);
} else {
if (dir_de) {
diff -puN fs/udf/namei.c~B3-unlink-monitor-i_nlink-0 fs/udf/namei.c
--- lxc/fs/udf/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/udf/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -878,8 +878,7 @@ static int udf_rmdir(struct inode * dir,
inode->i_nlink);
inode->i_nlink = 0;
inode->i_size = 0;
- mark_inode_dirty(inode);
- dir->i_nlink --;
+ inode_dec_link_count(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
mark_inode_dirty(dir);
@@ -923,8 +922,7 @@ static int udf_unlink(struct inode * dir
goto end_unlink;
dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
mark_inode_dirty(dir);
- inode->i_nlink--;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
inode->i_ctime = dir->i_ctime;
retval = 0;
@@ -1101,8 +1099,7 @@ out:
return err;
out_no_entry:
- inode->i_nlink--;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
iput(inode);
goto out;
}
@@ -1261,9 +1258,8 @@ static int udf_rename (struct inode * ol
if (new_inode)
{
- new_inode->i_nlink--;
new_inode->i_ctime = current_fs_time(new_inode->i_sb);
- mark_inode_dirty(new_inode);
+ inode_dec_link_count(new_inode);
}
old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
mark_inode_dirty(old_dir);
@@ -1279,12 +1275,10 @@ static int udf_rename (struct inode * ol
}
else
mark_buffer_dirty_inode(dir_bh, old_inode);
- old_dir->i_nlink --;
- mark_inode_dirty(old_dir);
+ inode_dec_link_count(old_dir);
if (new_inode)
{
- new_inode->i_nlink --;
- mark_inode_dirty(new_inode);
+ inode_dec_link_count(new_inode);
}
else
{
diff -puN fs/ufs/namei.c~B3-unlink-monitor-i_nlink-0 fs/ufs/namei.c
--- lxc/fs/ufs/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/ufs/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -308,7 +308,7 @@ static int ufs_rename(struct inode *old_
ufs_set_link(new_dir, new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de)
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
inode_dec_link_count(new_inode);
} else {
if (dir_de) {
diff -puN fs/vfat/namei.c~B3-unlink-monitor-i_nlink-0 fs/vfat/namei.c
--- lxc/fs/vfat/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/vfat/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -782,7 +782,7 @@ static int vfat_rmdir(struct inode *dir,
err = fat_remove_entries(dir, &sinfo); /* and releases bh */
if (err)
goto out;
- dir->i_nlink--;
+ drop_nlink(dir);
inode->i_nlink = 0;
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
@@ -930,7 +930,7 @@ static int vfat_rename(struct inode *old
if (err)
goto error_dotdot;
}
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
if (!new_inode)
new_dir->i_nlink++;
}
@@ -947,10 +947,9 @@ static int vfat_rename(struct inode *old
mark_inode_dirty(old_dir);
if (new_inode) {
+ drop_nlink(new_inode);
if (is_dir)
- new_inode->i_nlink -= 2;
- else
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
new_inode->i_ctime = ts;
}
out:
diff -puN ipc/mqueue.c~B3-unlink-monitor-i_nlink-0 ipc/mqueue.c
--- lxc/ipc/mqueue.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/ipc/mqueue.c 2006-08-08 10:57:11.000000000 -0700
@@ -307,7 +307,7 @@ static int mqueue_unlink(struct inode *d
dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
dir->i_size -= DIRENT_SIZE;
- inode->i_nlink--;
+ drop_nlink(inode);
dput(dentry);
return 0;
}
diff -puN mm/shmem.c~B3-unlink-monitor-i_nlink-0 mm/shmem.c
--- lxc/mm/shmem.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/mm/shmem.c 2006-08-08 10:57:11.000000000 -0700
@@ -1760,7 +1760,7 @@ static int shmem_unlink(struct inode *di
dir->i_size -= BOGO_DIRENT_SIZE;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- inode->i_nlink--;
+ drop_nlink(inode);
dput(dentry); /* Undo the count from "create" - this does all the work */
return 0;
}
@@ -1770,8 +1770,8 @@ static int shmem_rmdir(struct inode *dir
if (!simple_empty(dentry))
return -ENOTEMPTY;
- dentry->d_inode->i_nlink--;
- dir->i_nlink--;
+ drop_nlink(dentry->d_inode);
+ drop_nlink(dir);
return shmem_unlink(dir, dentry);
}
@@ -1792,9 +1792,9 @@ static int shmem_rename(struct inode *ol
if (new_dentry->d_inode) {
(void) shmem_unlink(new_dir, new_dentry);
if (they_are_dirs)
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
} else if (they_are_dirs) {
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
new_dir->i_nlink++;
}
diff -puN fs/binfmt_misc.c~B3-unlink-monitor-i_nlink-0 fs/binfmt_misc.c
diff -puN fs/jffs/inode-v23.c~B3-unlink-monitor-i_nlink-0 fs/jffs/inode-v23.c
--- lxc/fs/jffs/inode-v23.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/jffs/inode-v23.c 2006-08-08 10:57:11.000000000 -0700
@@ -1052,9 +1052,8 @@ jffs_remove(struct inode *dir, struct de
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
- inode->i_nlink--;
inode->i_ctime = dir->i_ctime;
- mark_inode_dirty(inode);
+ inode_dec_link_count(inode);
d_delete(dentry); /* This also frees the inode */
diff -puN fs/minix/namei.c~B3-unlink-monitor-i_nlink-0 fs/minix/namei.c
--- lxc/fs/minix/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/minix/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -249,7 +249,7 @@ static int minix_rename(struct inode * o
minix_set_link(new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de)
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
inode_dec_link_count(new_inode);
} else {
if (dir_de) {
diff -puN fs/msdos/namei.c~B3-unlink-monitor-i_nlink-0 fs/msdos/namei.c
--- lxc/fs/msdos/namei.c~B3-unlink-monitor-i_nlink-0 2006-08-08 09:30:58.000000000 -0700
+++ lxc-dave/fs/msdos/namei.c 2006-08-08 10:57:11.000000000 -0700
@@ -341,7 +341,7 @@ static int msdos_rmdir(struct inode *dir
err = fat_remove_entries(dir, &sinfo); /* and releases bh */
if (err)
goto out;
- dir->i_nlink--;
+ drop_nlink(dir);
inode->i_nlink = 0;
inode->i_ctime = CURRENT_TIME_SEC;
@@ -542,7 +542,7 @@ static int do_msdos_rename(struct inode
if (err)
goto error_dotdot;
}
- old_dir->i_nlink--;
+ drop_nlink(old_dir);
if (!new_inode)
new_dir->i_nlink++;
}
@@ -559,10 +559,9 @@ static int do_msdos_rename(struct inode
mark_inode_dirty(old_dir);
if (new_inode) {
+ drop_nlink(new_inode);
if (is_dir)
- new_inode->i_nlink -= 2;
- else
- new_inode->i_nlink--;
+ drop_nlink(new_inode);
new_inode->i_ctime = ts;
}
out:
_
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 3/6] unlink: monitor i_nlink
2006-08-09 16:57 ` [PATCH 3/6] unlink: monitor i_nlink Dave Hansen
@ 2006-08-09 17:11 ` Christoph Hellwig
2006-08-09 17:17 ` Dave Hansen
0 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2006-08-09 17:11 UTC (permalink / raw)
To: Dave Hansen; +Cc: akpm, linux-kernel, hch
On Wed, Aug 09, 2006 at 09:57:32AM -0700, Dave Hansen wrote:
>
> When a filesystem decrements i_nlink to zero, it means that a
> write must be performed in order to drop the inode from the
> filesystem.
>
> We're shortly going to have keep filesystems from being remounted
> r/o between the time that this i_nlink decrement and that write
> occurs.
>
> So, add a little helper function to do the decrements. We'll
> tie into it in a bit to note when i_nlink hits zero.
>
> Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Acked-by: Christoph Hellwig <hch@lst.de>
Note that we all (and especially Andrew :)) need to be carefull not to
introduce unguarded i_nlink decrements again. Dave, you'll probably need
to do another audit when you introduce the real functionality.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/6] unlink: monitor i_nlink
2006-08-09 17:11 ` Christoph Hellwig
@ 2006-08-09 17:17 ` Dave Hansen
2006-08-09 18:27 ` Andrew Morton
0 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 17:17 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: akpm, linux-kernel
On Wed, 2006-08-09 at 18:11 +0100, Christoph Hellwig wrote:
> On Wed, Aug 09, 2006 at 09:57:32AM -0700, Dave Hansen wrote:
> >
> > When a filesystem decrements i_nlink to zero, it means that a
> > write must be performed in order to drop the inode from the
> > filesystem.
> >
> > We're shortly going to have keep filesystems from being remounted
> > r/o between the time that this i_nlink decrement and that write
> > occurs.
> >
> > So, add a little helper function to do the decrements. We'll
> > tie into it in a bit to note when i_nlink hits zero.
> >
> > Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
>
> Acked-by: Christoph Hellwig <hch@lst.de>
> Note that we all (and especially Andrew :)) need to be carefull not to
> introduce unguarded i_nlink decrements again. Dave, you'll probably need
> to do another audit when you introduce the real functionality.
Yup, I have my eyes on it. git and mm commits should help as well.
-- Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/6] unlink: monitor i_nlink
2006-08-09 17:17 ` Dave Hansen
@ 2006-08-09 18:27 ` Andrew Morton
2006-08-12 14:15 ` Arnd Bergmann
0 siblings, 1 reply; 21+ messages in thread
From: Andrew Morton @ 2006-08-09 18:27 UTC (permalink / raw)
To: Dave Hansen; +Cc: Christoph Hellwig, linux-kernel
On Wed, 09 Aug 2006 10:17:19 -0700
Dave Hansen <haveblue@us.ibm.com> wrote:
> On Wed, 2006-08-09 at 18:11 +0100, Christoph Hellwig wrote:
> > On Wed, Aug 09, 2006 at 09:57:32AM -0700, Dave Hansen wrote:
> > >
> > > When a filesystem decrements i_nlink to zero, it means that a
> > > write must be performed in order to drop the inode from the
> > > filesystem.
> > >
> > > We're shortly going to have keep filesystems from being remounted
> > > r/o between the time that this i_nlink decrement and that write
> > > occurs.
> > >
> > > So, add a little helper function to do the decrements. We'll
> > > tie into it in a bit to note when i_nlink hits zero.
> > >
> > > Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
> >
> > Acked-by: Christoph Hellwig <hch@lst.de>
>
> > Note that we all (and especially Andrew :)) need to be carefull not to
> > introduce unguarded i_nlink decrements again. Dave, you'll probably need
> > to do another audit when you introduce the real functionality.
>
> Yup, I have my eyes on it. git and mm commits should help as well.
>
A comprehensive way to do this sort of thing is to rename the field. We
have >500 references, so one would do:
struct inode {
...
union {
unsigned int i_nlink;
unsigned int i_nlink_use_the_accessors_please;
}
...
};
then, when everything in-tree is migrated, remove `i_nlink'.
It's a bit of a hassle, but it will give the most reliable result for both
in-tree and out-of-tree filesystems.
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 3/6] unlink: monitor i_nlink
2006-08-09 18:27 ` Andrew Morton
@ 2006-08-12 14:15 ` Arnd Bergmann
0 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2006-08-12 14:15 UTC (permalink / raw)
To: Andrew Morton; +Cc: Dave Hansen, Christoph Hellwig, linux-kernel
On Wednesday 09 August 2006 20:27, Andrew Morton wrote:
> struct inode {
> ...
> union {
> unsigned int i_nlink;
> unsigned int i_nlink_use_the_accessors_please;
> }
> ...
> };
>
> then, when everything in-tree is migrated, remove `i_nlink'.
You can also mark a union member deprecated:
struct inode {
...
union {
unsigned int __deprecated i_nlink;
unsigned int i_nlink_use_the_accessors_please;
}
...
};
So gcc will warn about any newly introduced users.
Arnd <><
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 5/6] clean up OCFS2 nlink handling
2006-08-09 16:57 [PATCH 0/6] read-only bind mount prep work Dave Hansen
` (3 preceding siblings ...)
2006-08-09 16:57 ` [PATCH 3/6] unlink: monitor i_nlink Dave Hansen
@ 2006-08-09 16:57 ` Dave Hansen
2006-08-09 17:12 ` Christoph Hellwig
2006-08-09 16:57 ` [PATCH 6/6] monitor zeroing of i_nlink Dave Hansen
5 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 16:57 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel, hch, Dave Hansen
OCFS2 does some operations on i_nlink, then reverts them if some
of its operations fail to complete. This does not fit in well
with the drop_nlink() logic where we expect i_nlink to stay at
zero once it gets there.
So, delay all of the nlink operations until we're sure that the
operations have completed. Also, introduce a small helper to
check whether an inode has proper "unlinkable" i_nlink counts
no matter whether it is a directory or regular inode.
This patch is broken out from the others because it does contain
some logical changes.
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
---
arch/i386/kernel/setup.c | 0
lxc-dave/fs/ocfs2/namei.c | 45 ++++++++++++++++++++++++---------------------
2 files changed, 24 insertions(+), 21 deletions(-)
diff -puN fs/ocfs2/namei.c~B5-clean_up_OCFS2_nlink_handling fs/ocfs2/namei.c
--- lxc/fs/ocfs2/namei.c~B5-clean_up_OCFS2_nlink_handling 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/ocfs2/namei.c 2006-08-08 09:18:56.000000000 -0700
@@ -744,11 +744,23 @@ bail:
return err;
}
+static inline int inode_is_unlinkable(struct inode *inode)
+{
+ if (S_ISDIR(inode->i_mode)) {
+ if (inode->i_nlink == 2)
+ return 1;
+ return 0;
+ }
+
+ if (inode->i_nlink == 1)
+ return 1;
+ return 0;
+}
+
static int ocfs2_unlink(struct inode *dir,
struct dentry *dentry)
{
int status;
- unsigned int saved_nlink = 0;
struct inode *inode = dentry->d_inode;
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
u64 blkno;
@@ -760,6 +772,7 @@ static int ocfs2_unlink(struct inode *di
struct buffer_head *dirent_bh = NULL;
char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
struct buffer_head *orphan_entry_bh = NULL;
+ unsigned int future_nlink;
mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
dentry->d_name.len, dentry->d_name.name);
@@ -823,18 +836,11 @@ static int ocfs2_unlink(struct inode *di
}
}
- /* There are still a few steps left until we can consider the
- * unlink to have succeeded. Save off nlink here before
- * modification so we can set it back in case we hit an issue
- * before commit. */
- saved_nlink = inode->i_nlink;
- if (S_ISDIR(inode->i_mode))
- inode->i_nlink = 0;
+ if (S_ISDIR(inode->i_mode) && (inode->i_nlink == 2))
+ future_nlink = 0;
else
- inode->i_nlink--;
-
- status = ocfs2_request_unlink_vote(inode, dentry,
- (unsigned int) inode->i_nlink);
+ future_nlink = inode->i_nlink - 1;
+ status = ocfs2_request_unlink_vote(inode, dentry, future_nlink);
if (status < 0) {
/* This vote should succeed under all normal
* circumstances. */
@@ -842,7 +848,7 @@ static int ocfs2_unlink(struct inode *di
goto leave;
}
- if (!inode->i_nlink) {
+ if (inode_is_unlinkable(inode)) {
status = ocfs2_prepare_orphan_dir(osb, handle, inode,
orphan_name,
&orphan_entry_bh);
@@ -869,7 +875,7 @@ static int ocfs2_unlink(struct inode *di
fe = (struct ocfs2_dinode *) fe_bh->b_data;
- if (!inode->i_nlink) {
+ if (inode_is_unlinkable(inode)) {
status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name,
orphan_entry_bh);
if (status < 0) {
@@ -885,10 +891,10 @@ static int ocfs2_unlink(struct inode *di
goto leave;
}
- /* We can set nlink on the dinode now. clear the saved version
- * so that it doesn't get set later. */
+ if (S_ISDIR(inode->i_mode))
+ drop_nlink(inode);
+ drop_nlink(inode);
fe->i_links_count = cpu_to_le16(inode->i_nlink);
- saved_nlink = 0;
status = ocfs2_journal_dirty(handle, fe_bh);
if (status < 0) {
@@ -897,7 +903,7 @@ static int ocfs2_unlink(struct inode *di
}
if (S_ISDIR(inode->i_mode)) {
- dir->i_nlink--;
+ drop_nlink(dir);
status = ocfs2_mark_inode_dirty(handle, dir,
parent_node_bh);
if (status < 0) {
@@ -907,9 +913,6 @@ static int ocfs2_unlink(struct inode *di
}
leave:
- if (status < 0 && saved_nlink)
- inode->i_nlink = saved_nlink;
-
if (handle)
ocfs2_commit_trans(handle);
diff -puN arch/i386/kernel/setup.c~B5-clean_up_OCFS2_nlink_handling arch/i386/kernel/setup.c
_
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 5/6] clean up OCFS2 nlink handling
2006-08-09 16:57 ` [PATCH 5/6] clean up OCFS2 nlink handling Dave Hansen
@ 2006-08-09 17:12 ` Christoph Hellwig
2006-08-09 19:15 ` Dave Hansen
0 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2006-08-09 17:12 UTC (permalink / raw)
To: Dave Hansen; +Cc: akpm, linux-kernel, hch
On Wed, Aug 09, 2006 at 09:57:33AM -0700, Dave Hansen wrote:
>
> OCFS2 does some operations on i_nlink, then reverts them if some
> of its operations fail to complete. This does not fit in well
> with the drop_nlink() logic where we expect i_nlink to stay at
> zero once it gets there.
>
> So, delay all of the nlink operations until we're sure that the
> operations have completed. Also, introduce a small helper to
> check whether an inode has proper "unlinkable" i_nlink counts
> no matter whether it is a directory or regular inode.
>
> This patch is broken out from the others because it does contain
> some logical changes.
looks good to me, although I probably can't ACK ocfs2 patches. did you
look whether gfs2 in -mm needs something similar?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/6] clean up OCFS2 nlink handling
2006-08-09 17:12 ` Christoph Hellwig
@ 2006-08-09 19:15 ` Dave Hansen
2006-08-10 8:07 ` Steven Whitehouse
0 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 19:15 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: akpm, linux-kernel
On Wed, 2006-08-09 at 18:12 +0100, Christoph Hellwig wrote:
> On Wed, Aug 09, 2006 at 09:57:33AM -0700, Dave Hansen wrote:
> > OCFS2 does some operations on i_nlink, then reverts them if some
> > of its operations fail to complete. This does not fit in well
> > with the drop_nlink() logic where we expect i_nlink to stay at
> > zero once it gets there.
> >
> > So, delay all of the nlink operations until we're sure that the
> > operations have completed. Also, introduce a small helper to
> > check whether an inode has proper "unlinkable" i_nlink counts
> > no matter whether it is a directory or regular inode.
> >
> > This patch is broken out from the others because it does contain
> > some logical changes.
>
> looks good to me, although I probably can't ACK ocfs2 patches.
That's probably OK. One of the Oracle guys was nice enough to help me
beat it into shape and sign off on it.
> did you look whether gfs2 in -mm needs something similar?
It doesn't appear to. It doesn't manipulate i_nlink in the same, direct
manner.
-- Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/6] clean up OCFS2 nlink handling
2006-08-09 19:15 ` Dave Hansen
@ 2006-08-10 8:07 ` Steven Whitehouse
2006-08-10 19:06 ` Dave Hansen
0 siblings, 1 reply; 21+ messages in thread
From: Steven Whitehouse @ 2006-08-10 8:07 UTC (permalink / raw)
To: Dave Hansen; +Cc: linux-kernel, akpm, Christoph Hellwig
Hi,
On Wed, 2006-08-09 at 12:15 -0700, Dave Hansen wrote:
> On Wed, 2006-08-09 at 18:12 +0100, Christoph Hellwig wrote:
[snip]
> > did you look whether gfs2 in -mm needs something similar?
>
> It doesn't appear to. It doesn't manipulate i_nlink in the same, direct
> manner.
>
> -- Dave
I think it will need something similar. I suspect the required changes
will all be confined to routines in inode.c. If the link count is
changed by (a) remote node(s), then gfs2_inode_attr_in() might change
the link count. Also gfs2_change_nlink() is the other place to look. I
think everywhere else is ok,
Steve.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/6] clean up OCFS2 nlink handling
2006-08-10 8:07 ` Steven Whitehouse
@ 2006-08-10 19:06 ` Dave Hansen
2006-08-11 9:38 ` Steven Whitehouse
0 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-10 19:06 UTC (permalink / raw)
To: Steven Whitehouse; +Cc: linux-kernel, akpm, Christoph Hellwig
On Thu, 2006-08-10 at 09:07 +0100, Steven Whitehouse wrote:
> On Wed, 2006-08-09 at 12:15 -0700, Dave Hansen wrote:
> > On Wed, 2006-08-09 at 18:12 +0100, Christoph Hellwig wrote:
> [snip]
> > > did you look whether gfs2 in -mm needs something similar?
> >
> > It doesn't appear to. It doesn't manipulate i_nlink in the same, direct
> > manner.
>
> I think it will need something similar. I suspect the required changes
> will all be confined to routines in inode.c. If the link count is
> changed by (a) remote node(s), then gfs2_inode_attr_in() might change
> the link count. Also gfs2_change_nlink() is the other place to look. I
> think everywhere else is ok,
Well, I think this is all that it needs. I'm trying to decide if we
need a set_nlink() function for users like this, but I'm not sure there
are enough of them.
---
lxc-dave/fs/gfs2/inode.c | 3 +++
2 files changed, 3 insertions(+)
diff -puN fs/gfs2/inode.c~gfs fs/gfs2/inode.c
--- lxc/fs/gfs2/inode.c~gfs 2006-08-10 09:52:33.000000000 -0700
+++ lxc-dave/fs/gfs2/inode.c 2006-08-10 12:05:06.000000000 -0700
@@ -332,6 +332,9 @@ int gfs2_change_nlink(struct gfs2_inode
ip->i_di.di_ctime = get_seconds();
ip->i_inode.i_nlink = nlink;
+ if (!nlink)
+ ip->i_inode.i_state |= I_AWAITING_FINAL_IPUT;
+
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(&ip->i_di, dibh->b_data);
brelse(dibh);
-- Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/6] clean up OCFS2 nlink handling
2006-08-10 19:06 ` Dave Hansen
@ 2006-08-11 9:38 ` Steven Whitehouse
0 siblings, 0 replies; 21+ messages in thread
From: Steven Whitehouse @ 2006-08-11 9:38 UTC (permalink / raw)
To: Dave Hansen; +Cc: linux-kernel, akpm, Christoph Hellwig
Hi,
On Thu, 2006-08-10 at 12:06 -0700, Dave Hansen wrote:
> On Thu, 2006-08-10 at 09:07 +0100, Steven Whitehouse wrote:
> > On Wed, 2006-08-09 at 12:15 -0700, Dave Hansen wrote:
> > > On Wed, 2006-08-09 at 18:12 +0100, Christoph Hellwig wrote:
> > [snip]
> > > > did you look whether gfs2 in -mm needs something similar?
> > >
> > > It doesn't appear to. It doesn't manipulate i_nlink in the same, direct
> > > manner.
> >
> > I think it will need something similar. I suspect the required changes
> > will all be confined to routines in inode.c. If the link count is
> > changed by (a) remote node(s), then gfs2_inode_attr_in() might change
> > the link count. Also gfs2_change_nlink() is the other place to look. I
> > think everywhere else is ok,
>
> Well, I think this is all that it needs. I'm trying to decide if we
> need a set_nlink() function for users like this, but I'm not sure there
> are enough of them.
>
I suspect that something is required for gfs2_inode_attr_in() as well.
Here is the scenario... suppose there are two nodes A and B. On node A a
file is opened, on node B the same file is then unlinked such that its
link count hits zero. If node A then does something to the file (read or
write, it doesn't matter) then it will reread the attributes off disk
via gfs2_inode_attr_in() and discover that the link count is then zero.
We don't play any games in that once the link count has hit zero, thats
it, it will never increment above zero again. The node which actually
deals with the deallocation and clean up is the one that performs the
final close (iput). This is dealt with using the iopen lock to ensure
that we are certain of which node is the last to close the file. The
iopen lock is held in a shared state by all nodes having the file open.
On gfs2_delete_inode we attempt to upgrade the iopen lock to exclusive,
if this succeeds we then presume that no other node has the file open
and proceed with deallocation, as per a normal local filesystem.
So if I've understood what you are doing correctly, the adjustment
you've made below needs to be copied into gfs2_inode_attr_in() as well,
Steve.
> ---
>
> lxc-dave/fs/gfs2/inode.c | 3 +++
> 2 files changed, 3 insertions(+)
>
> diff -puN fs/gfs2/inode.c~gfs fs/gfs2/inode.c
> --- lxc/fs/gfs2/inode.c~gfs 2006-08-10 09:52:33.000000000 -0700
> +++ lxc-dave/fs/gfs2/inode.c 2006-08-10 12:05:06.000000000 -0700
> @@ -332,6 +332,9 @@ int gfs2_change_nlink(struct gfs2_inode
> ip->i_di.di_ctime = get_seconds();
> ip->i_inode.i_nlink = nlink;
>
> + if (!nlink)
> + ip->i_inode.i_state |= I_AWAITING_FINAL_IPUT;
> +
> gfs2_trans_add_bh(ip->i_gl, dibh, 1);
> gfs2_dinode_out(&ip->i_di, dibh->b_data);
> brelse(dibh);
>
>
> -- Dave
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 6/6] monitor zeroing of i_nlink
2006-08-09 16:57 [PATCH 0/6] read-only bind mount prep work Dave Hansen
` (4 preceding siblings ...)
2006-08-09 16:57 ` [PATCH 5/6] clean up OCFS2 nlink handling Dave Hansen
@ 2006-08-09 16:57 ` Dave Hansen
2006-08-09 17:14 ` Christoph Hellwig
5 siblings, 1 reply; 21+ messages in thread
From: Dave Hansen @ 2006-08-09 16:57 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel, hch, Dave Hansen
Some filesystems, instead of simply decrementing i_nlink, simply zero
it during an unlink operation. We need to catch these in addition
to the decrement operations.
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---
kernel/fork.c | 0
lxc-dave/fs/autofs4/root.c | 4 ++--
lxc-dave/fs/cifs/inode.c | 2 +-
lxc-dave/fs/ext3/namei.c | 2 +-
lxc-dave/fs/fuse/dir.c | 4 ++--
lxc-dave/fs/hfs/dir.c | 2 +-
lxc-dave/fs/hfsplus/dir.c | 4 ++--
lxc-dave/fs/hpfs/namei.c | 4 ++--
lxc-dave/fs/jfs/namei.c | 2 +-
lxc-dave/fs/msdos/namei.c | 4 ++--
lxc-dave/fs/nfs/dir.c | 2 +-
lxc-dave/fs/qnx4/namei.c | 2 +-
lxc-dave/fs/reiserfs/namei.c | 4 ++--
lxc-dave/fs/udf/namei.c | 2 +-
lxc-dave/fs/vfat/namei.c | 4 ++--
lxc-dave/include/linux/fs.h | 5 +++++
16 files changed, 26 insertions(+), 21 deletions(-)
diff -puN fs/libfs.c~B6-monitor-clear-i_nlink fs/libfs.c
diff -puN fs/cifs/inode.c~B6-monitor-clear-i_nlink fs/cifs/inode.c
--- lxc/fs/cifs/inode.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/cifs/inode.c 2006-08-08 09:18:57.000000000 -0700
@@ -819,7 +819,7 @@ int cifs_rmdir(struct inode *inode, stru
if (!rc) {
drop_nlink(inode);
i_size_write(direntry->d_inode,0);
- direntry->d_inode->i_nlink = 0;
+ clear_nlink(direntry->d_inode);
}
cifsInode = CIFS_I(direntry->d_inode);
diff -puN fs/ext3/namei.c~B6-monitor-clear-i_nlink fs/ext3/namei.c
--- lxc/fs/ext3/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/ext3/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -2045,7 +2045,7 @@ static int ext3_rmdir (struct inode * di
"empty directory has nlink!=2 (%d)",
inode->i_nlink);
inode->i_version++;
- inode->i_nlink = 0;
+ clear_nlink(inode);
/* There's no need to set i_disksize: the fact that i_nlink is
* zero will ensure that the right thing happens during any
* recovery. */
diff -puN fs/autofs4/root.c~B6-monitor-clear-i_nlink fs/autofs4/root.c
--- lxc/fs/autofs4/root.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/autofs4/root.c 2006-08-08 09:18:57.000000000 -0700
@@ -638,7 +638,7 @@ static int autofs4_dir_unlink(struct ino
dput(ino->dentry);
dentry->d_inode->i_size = 0;
- dentry->d_inode->i_nlink = 0;
+ clear_nlink(dentry->d_inode);
dir->i_mtime = CURRENT_TIME;
@@ -673,7 +673,7 @@ static int autofs4_dir_rmdir(struct inod
}
dput(ino->dentry);
dentry->d_inode->i_size = 0;
- dentry->d_inode->i_nlink = 0;
+ clear_nlink(dentry->d_inode);
if (dir->i_nlink)
drop_nlink(dir);
diff -puN fs/fuse/dir.c~B6-monitor-clear-i_nlink fs/fuse/dir.c
--- lxc/fs/fuse/dir.c~B6-monitor-clear-i_nlink 2006-08-06 03:21:02.000000000 -0700
+++ lxc-dave/fs/fuse/dir.c 2006-08-08 09:18:57.000000000 -0700
@@ -508,7 +508,7 @@ static int fuse_unlink(struct inode *dir
/* Set nlink to zero so the inode can be cleared, if
the inode does have more links this will be
discovered at the next lookup/getattr */
- inode->i_nlink = 0;
+ clear_nlink(inode);
fuse_invalidate_attr(inode);
fuse_invalidate_attr(dir);
fuse_invalidate_entry_cache(entry);
@@ -534,7 +534,7 @@ static int fuse_rmdir(struct inode *dir,
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err) {
- entry->d_inode->i_nlink = 0;
+ clear_nlink(entry->d_inode);
fuse_invalidate_attr(dir);
fuse_invalidate_entry_cache(entry);
} else if (err == -EINTR)
diff -puN fs/hfs/dir.c~B6-monitor-clear-i_nlink fs/hfs/dir.c
--- lxc/fs/hfs/dir.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:52.000000000 -0700
+++ lxc-dave/fs/hfs/dir.c 2006-08-08 09:18:57.000000000 -0700
@@ -273,7 +273,7 @@ static int hfs_rmdir(struct inode *dir,
res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
if (res)
return res;
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC;
hfs_delete_inode(inode);
mark_inode_dirty(inode);
diff -puN fs/hfsplus/dir.c~B6-monitor-clear-i_nlink fs/hfsplus/dir.c
--- lxc/fs/hfsplus/dir.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/hfsplus/dir.c 2006-08-08 09:18:57.000000000 -0700
@@ -348,7 +348,7 @@ static int hfsplus_unlink(struct inode *
} else
inode->i_flags |= S_DEAD;
} else
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
@@ -387,7 +387,7 @@ static int hfsplus_rmdir(struct inode *d
res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
if (res)
return res;
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC;
hfsplus_delete_inode(inode);
mark_inode_dirty(inode);
diff -puN fs/hpfs/namei.c~B6-monitor-clear-i_nlink fs/hpfs/namei.c
--- lxc/fs/hpfs/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/hpfs/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -495,7 +495,7 @@ static int hpfs_rmdir(struct inode *dir,
break;
default:
drop_nlink(dir);
- inode->i_nlink = 0;
+ clear_nlink(inode);
err = 0;
}
goto out;
@@ -590,7 +590,7 @@ static int hpfs_rename(struct inode *old
int r;
if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, (char *)new_name, new_len, NULL, &qbh1))) {
- new_inode->i_nlink = 0;
+ clear_nlink(new_inode);
copy_de(nde, &de);
memcpy(nde->name, new_name, new_len);
hpfs_mark_4buffers_dirty(&qbh1);
diff -puN fs/jfs/namei.c~B6-monitor-clear-i_nlink fs/jfs/namei.c
--- lxc/fs/jfs/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/jfs/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -414,7 +414,7 @@ static int jfs_rmdir(struct inode *dip,
JFS_IP(ip)->acl.flag = 0;
/* mark the target directory as deleted */
- ip->i_nlink = 0;
+ clear_nlink(ip);
mark_inode_dirty(ip);
rc = txCommit(tid, 2, &iplist[0], 0);
diff -puN fs/msdos/namei.c~B6-monitor-clear-i_nlink fs/msdos/namei.c
--- lxc/fs/msdos/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/msdos/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -343,7 +343,7 @@ static int msdos_rmdir(struct inode *dir
goto out;
drop_nlink(dir);
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode);
out:
@@ -425,7 +425,7 @@ static int msdos_unlink(struct inode *di
err = fat_remove_entries(dir, &sinfo); /* and releases bh */
if (err)
goto out;
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode);
out:
diff -puN fs/nfs/dir.c~B6-monitor-clear-i_nlink fs/nfs/dir.c
--- lxc/fs/nfs/dir.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:52.000000000 -0700
+++ lxc-dave/fs/nfs/dir.c 2006-08-08 09:18:57.000000000 -0700
@@ -1280,7 +1280,7 @@ static int nfs_rmdir(struct inode *dir,
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
/* Ensure the VFS deletes this inode */
if (error == 0 && dentry->d_inode != NULL)
- dentry->d_inode->i_nlink = 0;
+ clear_nlink(dentry->d_inode);
nfs_end_data_update(dir);
unlock_kernel();
diff -puN fs/ocfs2/namei.c~B6-monitor-clear-i_nlink fs/ocfs2/namei.c
diff -puN fs/qnx4/namei.c~B6-monitor-clear-i_nlink fs/qnx4/namei.c
--- lxc/fs/qnx4/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:52.000000000 -0700
+++ lxc-dave/fs/qnx4/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -186,7 +186,7 @@ int qnx4_rmdir(struct inode *dir, struct
memset(de->di_fname, 0, sizeof de->di_fname);
de->di_mode = 0;
mark_buffer_dirty(bh);
- inode->i_nlink = 0;
+ clear_nlink(inode);
mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
inode_dec_link_count(dir);
diff -puN fs/reiserfs/namei.c~B6-monitor-clear-i_nlink fs/reiserfs/namei.c
--- lxc/fs/reiserfs/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/reiserfs/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -913,7 +913,7 @@ static int reiserfs_rmdir(struct inode *
reiserfs_warning(inode->i_sb, "%s: empty directory has nlink "
"!= 2 (%d)", __FUNCTION__, inode->i_nlink);
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
reiserfs_update_sd(&th, inode);
@@ -1473,7 +1473,7 @@ static int reiserfs_rename(struct inode
if (new_dentry_inode) {
// adjust link number of the victim
if (S_ISDIR(new_dentry_inode->i_mode)) {
- new_dentry_inode->i_nlink = 0;
+ clear_nlink(new_dentry_inode);
} else {
drop_nlink(new_dentry_inode);
}
diff -puN fs/udf/namei.c~B6-monitor-clear-i_nlink fs/udf/namei.c
--- lxc/fs/udf/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/udf/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -876,7 +876,7 @@ static int udf_rmdir(struct inode * dir,
udf_warning(inode->i_sb, "udf_rmdir",
"empty directory has nlink != 2 (%d)",
inode->i_nlink);
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_size = 0;
inode_dec_link_count(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
diff -puN fs/vfat/namei.c~B6-monitor-clear-i_nlink fs/vfat/namei.c
--- lxc/fs/vfat/namei.c~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/fs/vfat/namei.c 2006-08-08 09:18:57.000000000 -0700
@@ -784,7 +784,7 @@ static int vfat_rmdir(struct inode *dir,
goto out;
drop_nlink(dir);
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode);
out:
@@ -808,7 +808,7 @@ static int vfat_unlink(struct inode *dir
err = fat_remove_entries(dir, &sinfo); /* and releases bh */
if (err)
goto out;
- inode->i_nlink = 0;
+ clear_nlink(inode);
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode);
out:
diff -puN include/linux/fs.h~B6-monitor-clear-i_nlink include/linux/fs.h
--- lxc/include/linux/fs.h~B6-monitor-clear-i_nlink 2006-08-08 09:18:54.000000000 -0700
+++ lxc-dave/include/linux/fs.h 2006-08-08 09:18:57.000000000 -0700
@@ -1272,6 +1272,11 @@ static inline void drop_nlink(struct ino
inode->i_nlink--;
}
+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);
diff -puN kernel/fork.c~B6-monitor-clear-i_nlink kernel/fork.c
_
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 6/6] monitor zeroing of i_nlink
2006-08-09 16:57 ` [PATCH 6/6] monitor zeroing of i_nlink Dave Hansen
@ 2006-08-09 17:14 ` Christoph Hellwig
0 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2006-08-09 17:14 UTC (permalink / raw)
To: Dave Hansen; +Cc: akpm, linux-kernel, hch
On Wed, Aug 09, 2006 at 09:57:34AM -0700, Dave Hansen wrote:
>
> Some filesystems, instead of simply decrementing i_nlink, simply zero
> it during an unlink operation. We need to catch these in addition
> to the decrement operations.
>
> Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Acked-by: Christoph Hellwig <hch@lst.de>
btw, what about adding some nice kerneldoc for all the *_nlink helpers
you added?
> ---
>
> kernel/fork.c | 0
something is screwed up in your diffstats :)
^ permalink raw reply [flat|nested] 21+ messages in thread