differently than data written to linked files. If that is not the case
I'd appreciate any pointers to the code showing where/how they are
handled differently. All I could find in ext3/4 was the orphan inode list.
Signed-off-by: Matt Helsley <matthltc@us.ibm.com>
Cc: Eric Sandeen <sandeen@redhat.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: linux-ext4@vger.kernel.org
Cc: Jan Kara <jack@suse.cz>
Cc: containers@lists.linux-foundation.org
Cc: Oren Laadan <orenl@cs.columbia.edu>
Cc: Amir Goldstein <amir73il@users.sf.net>
Cc: linux-fsdevel@vger.kernel.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Jamie Lokier <jamie@shareable.org>
---
fs/ext3/namei.c | 16 ++++++++--------
fs/ext4/namei.c | 14 +++++++-------
2 files changed, 15 insertions(+), 15 deletions(-)
@@ -1985,7 +1985,7 @@ out_unlock:
/*
* ext3_orphan_del() removes an unlinked or truncated inode from the list
- * of such inodes stored on disk, because it is finally being cleaned up.
+ * of such inodes stored on disk.
*/
int ext3_orphan_del(handle_t *handle, struct inode *inode)
{
@@ -2243,13 +2243,6 @@ static int ext3_link (struct dentry * old_dentry,
dquot_initialize(dir);
- /*
- * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing
- * otherwise has the potential to corrupt the orphan inode list.
- */
- if (inode->i_nlink == 0)
- return -ENOENT;
-
retry:
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS);
@@ -2267,6 +2260,12 @@ retry:
if (!err) {
ext3_mark_inode_dirty(handle, inode);
d_instantiate(dentry, inode);
+ if (inode->i_nlink == 1)
+ /*
+ * i_nlink went from 0 to 1 thus the inode is no
+ * longer an orphan.
+ */
+ ext3_orphan_del(handle, inode);
} else {
drop_nlink(inode);
iput(inode);
@@ -2451,6 +2450,7 @@ end_rename:
const struct inode_operations ext3_dir_inode_operations = {
.create = ext3_create,
.lookup = ext3_lookup,
+ .relink = ext3_link,
.link = ext3_link,
.unlink = ext3_unlink,
.symlink = ext3_symlink,
@@ -2323,13 +2323,6 @@ static int ext4_link(struct dentry *old_dentry,
dquot_initialize(dir);
- /*
- * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing
- * otherwise has the potential to corrupt the orphan inode list.
- */
- if (inode->i_nlink == 0)
- return -ENOENT;
-
retry:
handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT4_INDEX_EXTRA_TRANS_BLOCKS);
@@ -2347,6 +2340,12 @@ retry:
if (!err) {
ext4_mark_inode_dirty(handle, inode);
d_instantiate(dentry, inode);
+ if (inode->i_nlink == 1)
+ /*
+ * i_nlink went from 0 to 1 thus the inode is no
+ * longer an orphan.
+ */
+ ext4_orphan_del(handle, inode);
} else {
drop_nlink(inode);
iput(inode);
@@ -2535,6 +2534,7 @@ end_rename:
const struct inode_operations ext4_dir_inode_operations = {
.create = ext4_create,
.lookup = ext4_lookup,
+ .relink = ext4_link,
.link = ext4_link,
.unlink = ext4_unlink,
.symlink = ext4_symlink,