Commit 9a53c3a7 authored by Dave Hansen's avatar Dave Hansen Committed by Linus Torvalds

[PATCH] r/o bind mounts: unlink: monitor i_nlink

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: default avatarDave Hansen <haveblue@us.ibm.com>
Acked-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent aab520e2
...@@ -332,7 +332,7 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry) ...@@ -332,7 +332,7 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
dentry->d_inode->i_nlink--; drop_nlink(dentry->d_inode);
dput(dentry); dput(dentry);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
d_delete(dentry); d_delete(dentry);
...@@ -347,10 +347,11 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -347,10 +347,11 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
dentry_unhash(dentry); dentry_unhash(dentry);
if (usbfs_empty(dentry)) { if (usbfs_empty(dentry)) {
dentry->d_inode->i_nlink -= 2; drop_nlink(dentry->d_inode);
drop_nlink(dentry->d_inode);
dput(dentry); dput(dentry);
inode->i_flags |= S_DEAD; inode->i_flags |= S_DEAD;
dir->i_nlink--; drop_nlink(dir);
error = 0; error = 0;
} }
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
......
...@@ -414,7 +414,7 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -414,7 +414,7 @@ static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
dentry->d_time = (unsigned long)(struct autofs_dir_ent *)NULL; dentry->d_time = (unsigned long)(struct autofs_dir_ent *)NULL;
autofs_hash_delete(ent); autofs_hash_delete(ent);
dir->i_nlink--; drop_nlink(dir);
d_drop(dentry); d_drop(dentry);
unlock_kernel(); unlock_kernel();
......
...@@ -676,7 +676,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -676,7 +676,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
dentry->d_inode->i_nlink = 0; dentry->d_inode->i_nlink = 0;
if (dir->i_nlink) if (dir->i_nlink)
dir->i_nlink--; drop_nlink(dir);
return 0; return 0;
} }
......
...@@ -117,8 +117,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, ...@@ -117,8 +117,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino); err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);
if (err) { if (err) {
inode->i_nlink--; inode_dec_link_count(inode);
mark_inode_dirty(inode);
iput(inode); iput(inode);
unlock_kernel(); unlock_kernel();
return err; return err;
...@@ -196,9 +195,8 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry) ...@@ -196,9 +195,8 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir); mark_inode_dirty(dir);
inode->i_nlink--;
inode->i_ctime = dir->i_ctime; inode->i_ctime = dir->i_ctime;
mark_inode_dirty(inode); inode_dec_link_count(inode);
error = 0; error = 0;
out_brelse: out_brelse:
...@@ -249,9 +247,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, ...@@ -249,9 +247,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(old_dir); mark_inode_dirty(old_dir);
if (new_inode) { if (new_inode) {
new_inode->i_nlink--;
new_inode->i_ctime = CURRENT_TIME_SEC; new_inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(new_inode); inode_dec_link_count(new_inode);
} }
mark_buffer_dirty(old_bh); mark_buffer_dirty(old_bh);
error = 0; error = 0;
......
...@@ -590,7 +590,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -590,7 +590,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
if (!rc) { if (!rc) {
if (direntry->d_inode) if (direntry->d_inode)
direntry->d_inode->i_nlink--; drop_nlink(direntry->d_inode);
} else if (rc == -ENOENT) { } else if (rc == -ENOENT) {
d_drop(direntry); d_drop(direntry);
} else if (rc == -ETXTBSY) { } else if (rc == -ETXTBSY) {
...@@ -609,7 +609,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -609,7 +609,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
if (direntry->d_inode) if (direntry->d_inode)
direntry->d_inode->i_nlink--; drop_nlink(direntry->d_inode);
} }
} else if (rc == -EACCES) { } else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */ /* try only if r/o attribute set in local lookup data? */
...@@ -663,7 +663,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -663,7 +663,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) { if (!rc) {
if (direntry->d_inode) if (direntry->d_inode)
direntry->d_inode->i_nlink--; drop_nlink(direntry->d_inode);
} else if (rc == -ETXTBSY) { } else if (rc == -ETXTBSY) {
int oplock = FALSE; int oplock = FALSE;
__u16 netfid; __u16 netfid;
...@@ -684,7 +684,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -684,7 +684,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
if (direntry->d_inode) if (direntry->d_inode)
direntry->d_inode->i_nlink--; drop_nlink(direntry->d_inode);
} }
/* BB if rc = -ETXTBUSY goto the rename logic BB */ /* BB if rc = -ETXTBUSY goto the rename logic BB */
} }
...@@ -816,7 +816,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -816,7 +816,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) { if (!rc) {
inode->i_nlink--; drop_nlink(inode);
i_size_write(direntry->d_inode,0); i_size_write(direntry->d_inode,0);
direntry->d_inode->i_nlink = 0; direntry->d_inode->i_nlink = 0;
} }
......
...@@ -367,7 +367,7 @@ int coda_unlink(struct inode *dir, struct dentry *de) ...@@ -367,7 +367,7 @@ int coda_unlink(struct inode *dir, struct dentry *de)
} }
coda_dir_changed(dir, 0); coda_dir_changed(dir, 0);
de->d_inode->i_nlink--; drop_nlink(de->d_inode);
unlock_kernel(); unlock_kernel();
return 0; return 0;
...@@ -394,7 +394,7 @@ int coda_rmdir(struct inode *dir, struct dentry *de) ...@@ -394,7 +394,7 @@ int coda_rmdir(struct inode *dir, struct dentry *de)
} }
coda_dir_changed(dir, -1); coda_dir_changed(dir, -1);
de->d_inode->i_nlink--; drop_nlink(de->d_inode);
d_delete(de); d_delete(de);
unlock_kernel(); unlock_kernel();
......
...@@ -326,7 +326,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, ...@@ -326,7 +326,7 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
ext2_set_link(new_dir, new_de, new_page, old_inode); ext2_set_link(new_dir, new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC; new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de) if (dir_de)
new_inode->i_nlink--; drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) { if (dir_de) {
......
...@@ -1621,7 +1621,7 @@ static inline void ext3_inc_count(handle_t *handle, struct inode *inode) ...@@ -1621,7 +1621,7 @@ static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
static inline void ext3_dec_count(handle_t *handle, struct inode *inode) 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, static int ext3_add_nondir(handle_t *handle,
...@@ -1743,7 +1743,7 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode) ...@@ -1743,7 +1743,7 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
dir_block = ext3_bread (handle, inode, 0, 1, &err); dir_block = ext3_bread (handle, inode, 0, 1, &err);
if (!dir_block) { if (!dir_block) {
inode->i_nlink--; /* is this nlink == 0? */ drop_nlink(inode); /* is this nlink == 0? */
ext3_mark_inode_dirty(handle, inode); ext3_mark_inode_dirty(handle, inode);
iput (inode); iput (inode);
goto out_stop; goto out_stop;
...@@ -2053,7 +2053,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) ...@@ -2053,7 +2053,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
ext3_orphan_add(handle, inode); ext3_orphan_add(handle, inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
ext3_mark_inode_dirty(handle, inode); ext3_mark_inode_dirty(handle, inode);
dir->i_nlink--; drop_nlink(dir);
ext3_update_dx_flag(dir); ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir); ext3_mark_inode_dirty(handle, dir);
...@@ -2104,7 +2104,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) ...@@ -2104,7 +2104,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
ext3_update_dx_flag(dir); ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir); ext3_mark_inode_dirty(handle, dir);
inode->i_nlink--; drop_nlink(inode);
if (!inode->i_nlink) if (!inode->i_nlink)
ext3_orphan_add(handle, inode); ext3_orphan_add(handle, inode);
inode->i_ctime = dir->i_ctime; inode->i_ctime = dir->i_ctime;
...@@ -2326,7 +2326,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, ...@@ -2326,7 +2326,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
} }
if (new_inode) { if (new_inode) {
new_inode->i_nlink--; drop_nlink(new_inode);
new_inode->i_ctime = CURRENT_TIME_SEC; new_inode->i_ctime = CURRENT_TIME_SEC;
} }
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
...@@ -2337,9 +2337,9 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, ...@@ -2337,9 +2337,9 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
ext3_journal_dirty_metadata(handle, dir_bh); ext3_journal_dirty_metadata(handle, dir_bh);
old_dir->i_nlink--; drop_nlink(old_dir);
if (new_inode) { if (new_inode) {
new_inode->i_nlink--; drop_nlink(new_inode);
} else { } else {
new_dir->i_nlink++; new_dir->i_nlink++;
ext3_update_dx_flag(new_dir); ext3_update_dx_flag(new_dir);
......
...@@ -246,7 +246,7 @@ static int hfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -246,7 +246,7 @@ static int hfs_unlink(struct inode *dir, struct dentry *dentry)
if (res) if (res)
return res; return res;
inode->i_nlink--; drop_nlink(inode);
hfs_delete_inode(inode); hfs_delete_inode(inode);
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode); mark_inode_dirty(inode);
......
...@@ -338,7 +338,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) ...@@ -338,7 +338,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
return res; return res;
if (inode->i_nlink > 0) if (inode->i_nlink > 0)
inode->i_nlink--; drop_nlink(inode);
hfsplus_delete_inode(inode); hfsplus_delete_inode(inode);
if (inode->i_ino != cnid && !inode->i_nlink) { if (inode->i_ino != cnid && !inode->i_nlink) {
if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
......
...@@ -434,7 +434,7 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -434,7 +434,7 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
unlock_kernel(); unlock_kernel();
return -ENOSPC; return -ENOSPC;
default: default:
inode->i_nlink--; drop_nlink(inode);
err = 0; err = 0;
} }
goto out; goto out;
...@@ -494,7 +494,7 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -494,7 +494,7 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
err = -ENOSPC; err = -ENOSPC;
break; break;
default: default:
dir->i_nlink--; drop_nlink(dir);
inode->i_nlink = 0; inode->i_nlink = 0;
err = 0; err = 0;
} }
...@@ -636,7 +636,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -636,7 +636,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
hpfs_i(i)->i_parent_dir = new_dir->i_ino; hpfs_i(i)->i_parent_dir = new_dir->i_ino;
if (S_ISDIR(i->i_mode)) { if (S_ISDIR(i->i_mode)) {
new_dir->i_nlink++; new_dir->i_nlink++;
old_dir->i_nlink--; drop_nlink(old_dir);
} }
if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) { if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
fnode->up = new_dir->i_ino; fnode->up = new_dir->i_ino;
......
...@@ -1052,9 +1052,8 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type) ...@@ -1052,9 +1052,8 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir); mark_inode_dirty(dir);
inode->i_nlink--;
inode->i_ctime = dir->i_ctime; inode->i_ctime = dir->i_ctime;
mark_inode_dirty(inode); inode_dec_link_count(inode);
d_delete(dentry); /* This also frees the inode */ d_delete(dentry); /* This also frees the inode */
......
...@@ -615,7 +615,7 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) ...@@ -615,7 +615,7 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
} }
ret = jffs2_unlink(dir_i, dentry); ret = jffs2_unlink(dir_i, dentry);
if (!ret) if (!ret)
dir_i->i_nlink--; drop_nlink(dir_i);
return ret; return ret;
} }
...@@ -823,7 +823,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ...@@ -823,7 +823,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
if (victim_f) { if (victim_f) {
/* There was a victim. Kill it off nicely */ /* 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 /* Don't oops if the victim was a dirent pointing to an
inode which didn't exist. */ inode which didn't exist. */
if (victim_f->inocache) { if (victim_f->inocache) {
...@@ -862,7 +862,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ...@@ -862,7 +862,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
} }
if (S_ISDIR(old_dentry->d_inode->i_mode)) 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); new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
......
...@@ -393,9 +393,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) ...@@ -393,9 +393,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
/* update parent directory's link count corresponding /* update parent directory's link count corresponding
* to ".." entry of the target directory deleted * to ".." entry of the target directory deleted
*/ */
dip->i_nlink--;
dip->i_ctime = dip->i_mtime = CURRENT_TIME; 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 * OS/2 could have created EA and/or ACL
...@@ -515,8 +514,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry) ...@@ -515,8 +514,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
mark_inode_dirty(dip); mark_inode_dirty(dip);
/* update target's inode */ /* update target's inode */
ip->i_nlink--; inode_dec_link_count(ip);
mark_inode_dirty(ip);
/* /*
* commit zero link count object * commit zero link count object
...@@ -835,7 +833,7 @@ static int jfs_link(struct dentry *old_dentry, ...@@ -835,7 +833,7 @@ static int jfs_link(struct dentry *old_dentry,
rc = txCommit(tid, 2, &iplist[0], 0); rc = txCommit(tid, 2, &iplist[0], 0);
if (rc) { if (rc) {
ip->i_nlink--; ip->i_nlink--; /* never instantiated */
iput(ip); iput(ip);
} else } else
d_instantiate(dentry, ip); d_instantiate(dentry, ip);
...@@ -1155,9 +1153,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1155,9 +1153,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
old_ip->i_ino, JFS_RENAME); old_ip->i_ino, JFS_RENAME);
if (rc) if (rc)
goto out4; goto out4;
new_ip->i_nlink--; drop_nlink(new_ip);
if (S_ISDIR(new_ip->i_mode)) { if (S_ISDIR(new_ip->i_mode)) {
new_ip->i_nlink--; drop_nlink(new_ip);
if (new_ip->i_nlink) { if (new_ip->i_nlink) {
mutex_unlock(&JFS_IP(new_ip)->commit_mutex); mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
if (old_dir != new_dir) if (old_dir != new_dir)
...@@ -1223,7 +1221,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1223,7 +1221,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto out4; goto out4;
} }
if (S_ISDIR(old_ip->i_mode)) { if (S_ISDIR(old_ip->i_mode)) {
old_dir->i_nlink--; drop_nlink(old_dir);
if (old_dir != new_dir) { if (old_dir != new_dir) {
/* /*
* Change inode number of parent for moved directory * Change inode number of parent for moved directory
......
...@@ -275,7 +275,7 @@ int simple_unlink(struct inode *dir, struct dentry *dentry) ...@@ -275,7 +275,7 @@ int simple_unlink(struct inode *dir, struct dentry *dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
inode->i_nlink--; drop_nlink(inode);
dput(dentry); dput(dentry);
return 0; return 0;
} }
...@@ -285,9 +285,9 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -285,9 +285,9 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
if (!simple_empty(dentry)) if (!simple_empty(dentry))
return -ENOTEMPTY; return -ENOTEMPTY;
dentry->d_inode->i_nlink--; drop_nlink(dentry->d_inode);
simple_unlink(dir, dentry); simple_unlink(dir, dentry);
dir->i_nlink--; drop_nlink(dir);
return 0; return 0;
} }
...@@ -303,9 +303,9 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -303,9 +303,9 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
if (new_dentry->d_inode) { if (new_dentry->d_inode) {
simple_unlink(new_dir, new_dentry); simple_unlink(new_dir, new_dentry);
if (they_are_dirs) if (they_are_dirs)
old_dir->i_nlink--; drop_nlink(old_dir);
} else if (they_are_dirs) { } else if (they_are_dirs) {
old_dir->i_nlink--; drop_nlink(old_dir);
new_dir->i_nlink++; new_dir->i_nlink++;
} }
......
...@@ -249,7 +249,7 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -249,7 +249,7 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
minix_set_link(new_de, new_page, old_inode); minix_set_link(new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC; new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de) if (dir_de)
new_inode->i_nlink--; drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) { if (dir_de) {
......
...@@ -343,7 +343,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -343,7 +343,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
err = fat_remove_entries(dir, &sinfo); /* and releases bh */ err = fat_remove_entries(dir, &sinfo); /* and releases bh */
if (err) if (err)
goto out; goto out;
dir->i_nlink--; drop_nlink(dir);
inode->i_nlink = 0; inode->i_nlink = 0;
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
...@@ -549,7 +549,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -549,7 +549,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
if (err) if (err)
goto error_dotdot; goto error_dotdot;
} }
old_dir->i_nlink--; drop_nlink(old_dir);
if (!new_inode) if (!new_inode)
new_dir->i_nlink++; new_dir->i_nlink++;
} }
...@@ -566,10 +566,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, ...@@ -566,10 +566,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
mark_inode_dirty(old_dir); mark_inode_dirty(old_dir);
if (new_inode) { if (new_inode) {
drop_nlink(new_inode);
if (is_dir) if (is_dir)
new_inode->i_nlink -= 2; drop_nlink(new_inode);
else
new_inode->i_nlink--;
new_inode->i_ctime = ts; new_inode->i_ctime = ts;
} }
out: out:
......
...@@ -843,7 +843,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) ...@@ -843,7 +843,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
nfs_inode_return_delegation(inode); nfs_inode_return_delegation(inode);
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
lock_kernel(); lock_kernel();
inode->i_nlink--; drop_nlink(inode);
nfs_complete_unlink(dentry); nfs_complete_unlink(dentry);
unlock_kernel(); unlock_kernel();
} }
...@@ -1401,7 +1401,7 @@ static int nfs_safe_remove(struct dentry *dentry) ...@@ -1401,7 +1401,7 @@ static int nfs_safe_remove(struct dentry *dentry)
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
/* The VFS may want to delete this inode */ /* The VFS may want to delete this inode */
if (error == 0) if (error == 0)
inode->i_nlink--; drop_nlink(inode);
nfs_mark_for_revalidate(inode); nfs_mark_for_revalidate(inode);
nfs_end_data_update(inode); nfs_end_data_update(inode);
} else } else
...@@ -1639,7 +1639,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1639,7 +1639,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto out; goto out;
} }
} else } else
new_inode->i_nlink--; drop_nlink(new_inode);
go_ahead: go_ahead:
/* /*
......
...@@ -739,7 +739,7 @@ static int ocfs2_link(struct dentry *old_dentry, ...@@ -739,7 +739,7 @@ static int ocfs2_link(struct dentry *old_dentry,
err = ocfs2_journal_dirty(handle, fe_bh); err = ocfs2_journal_dirty(handle, fe_bh);
if (err < 0) { if (err < 0) {
le16_add_cpu(&fe->i_links_count, -1); le16_add_cpu(&fe->i_links_count, -1);
inode->i_nlink--; drop_nlink(inode);
mlog_errno(err); mlog_errno(err);
goto bail; goto bail;
} }
...@@ -749,7 +749,7 @@ static int ocfs2_link(struct dentry *old_dentry, ...@@ -749,7 +749,7 @@ static int ocfs2_link(struct dentry *old_dentry,
parent_fe_bh, de_bh); parent_fe_bh, de_bh);
if (err) { if (err) {
le16_add_cpu(&fe->i_links_count, -1); le16_add_cpu(&fe->i_links_count, -1);
inode->i_nlink--; drop_nlink(inode);
mlog_errno(err); mlog_errno(err);
goto bail; goto bail;
} }
......
...@@ -189,8 +189,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -189,8 +189,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_nlink = 0; inode->i_nlink = 0;
mark_inode_dirty(inode); mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
dir->i_nlink--; inode_dec_link_count(dir);
mark_inode_dirty(dir);
retval = 0; retval = 0;
end_rmdir: end_rmdir:
...@@ -234,9 +233,8 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry) ...@@ -234,9 +233,8 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry)
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir); mark_inode_dirty(dir);
inode->i_nlink--;
inode->i_ctime = dir->i_ctime; inode->i_ctime = dir->i_ctime;
mark_inode_dirty(inode); inode_dec_link_count(inode);
retval = 0; retval = 0;
end_unlink: end_unlink:
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/quotaops.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) { 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 // directory item contains array of entry headers. This performs
// binary search through that array // binary search through that array
...@@ -994,7 +994,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -994,7 +994,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
inode->i_nlink = 1; inode->i_nlink = 1;
} }
inode->i_nlink--; drop_nlink(inode);
/* /*
* we schedule before doing the add_save_link call, save the link * we schedule before doing the add_save_link call, save the link
...@@ -1475,7 +1475,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1475,7 +1475,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (S_ISDIR(new_dentry_inode->i_mode)) { if (S_ISDIR(new_dentry_inode->i_mode)) {
new_dentry_inode->i_nlink = 0; new_dentry_inode->i_nlink = 0;
} else { } else {
new_dentry_inode->i_nlink--; drop_nlink(new_dentry_inode);
} }
new_dentry_inode->i_ctime = ctime; new_dentry_inode->i_ctime = ctime;
savelink = new_dentry_inode->i_nlink; savelink = new_dentry_inode->i_nlink;
......
...@@ -250,7 +250,7 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, ...@@ -250,7 +250,7 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
sysv_set_link(new_de, new_page, old_inode); sysv_set_link(new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC; new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de) if (dir_de)
new_inode->i_nlink--; drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) { if (dir_de) {
......
...@@ -878,8 +878,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry) ...@@ -878,8 +878,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
inode->i_nlink); inode->i_nlink);
inode->i_nlink = 0; inode->i_nlink = 0;
inode->i_size = 0; inode->i_size = 0;
mark_inode_dirty(inode); inode_dec_link_count(inode);
dir->i_nlink --;
inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
mark_inode_dirty(dir); mark_inode_dirty(dir);
...@@ -923,8 +922,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry) ...@@ -923,8 +922,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry)
goto end_unlink; goto end_unlink;
dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
mark_inode_dirty(dir); mark_inode_dirty(dir);
inode->i_nlink--; inode_dec_link_count(inode);
mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime; inode->i_ctime = dir->i_ctime;
retval = 0; retval = 0;
...@@ -1101,8 +1099,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char * ...@@ -1101,8 +1099,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
return err; return err;
out_no_entry: out_no_entry:
inode->i_nlink--; inode_dec_link_count(inode);
mark_inode_dirty(inode);
iput(inode); iput(inode);
goto out; goto out;
} }
...@@ -1261,9 +1258,8 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry, ...@@ -1261,9 +1258,8 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
if (new_inode) if (new_inode)
{ {
new_inode->i_nlink--;
new_inode->i_ctime = current_fs_time(new_inode->i_sb); 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); old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
mark_inode_dirty(old_dir); mark_inode_dirty(old_dir);
...@@ -1279,12 +1275,10 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry, ...@@ -1279,12 +1275,10 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
} }
else else
mark_buffer_dirty_inode(dir_bh, old_inode); mark_buffer_dirty_inode(dir_bh, old_inode);
old_dir->i_nlink --; inode_dec_link_count(old_dir);
mark_inode_dirty(old_dir);
if (new_inode) if (new_inode)
{ {
new_inode->i_nlink --; inode_dec_link_count(new_inode);
mark_inode_dirty(new_inode);
} }
else else
{ {
......
...@@ -308,7 +308,7 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -308,7 +308,7 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
ufs_set_link(new_dir, new_de, new_page, old_inode); ufs_set_link(new_dir, new_de, new_page, old_inode);
new_inode->i_ctime = CURRENT_TIME_SEC; new_inode->i_ctime = CURRENT_TIME_SEC;
if (dir_de) if (dir_de)
new_inode->i_nlink--; drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) { if (dir_de) {
......
...@@ -782,7 +782,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -782,7 +782,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
err = fat_remove_entries(dir, &sinfo); /* and releases bh */ err = fat_remove_entries(dir, &sinfo); /* and releases bh */
if (err) if (err)
goto out; goto out;
dir->i_nlink--; drop_nlink(dir);
inode->i_nlink = 0; inode->i_nlink = 0;
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
...@@ -930,7 +930,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -930,7 +930,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
if (err) if (err)
goto error_dotdot; goto error_dotdot;
} }
old_dir->i_nlink--; drop_nlink(old_dir);
if (!new_inode) if (!new_inode)
new_dir->i_nlink++; new_dir->i_nlink++;
} }
...@@ -947,10 +947,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -947,10 +947,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
mark_inode_dirty(old_dir); mark_inode_dirty(old_dir);
if (new_inode) { if (new_inode) {
drop_nlink(new_inode);
if (is_dir) if (is_dir)
new_inode->i_nlink -= 2; drop_nlink(new_inode);
else
new_inode->i_nlink--;
new_inode->i_ctime = ts; new_inode->i_ctime = ts;
} }
out: out:
......
...@@ -1225,9 +1225,14 @@ static inline void inode_inc_link_count(struct inode *inode) ...@@ -1225,9 +1225,14 @@ static inline void inode_inc_link_count(struct inode *inode)
mark_inode_dirty(inode); 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--; inode->i_nlink--;
}
static inline void inode_dec_link_count(struct inode *inode)
{
drop_nlink(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
......
...@@ -307,7 +307,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry) ...@@ -307,7 +307,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME; dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
dir->i_size -= DIRENT_SIZE; dir->i_size -= DIRENT_SIZE;
inode->i_nlink--; drop_nlink(inode);
dput(dentry); dput(dentry);
return 0; return 0;
} }
......
...@@ -1772,7 +1772,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1772,7 +1772,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
dir->i_size -= BOGO_DIRENT_SIZE; dir->i_size -= BOGO_DIRENT_SIZE;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; 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 */ dput(dentry); /* Undo the count from "create" - this does all the work */
return 0; return 0;
} }
...@@ -1782,8 +1782,8 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -1782,8 +1782,8 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
if (!simple_empty(dentry)) if (!simple_empty(dentry))
return -ENOTEMPTY; return -ENOTEMPTY;
dentry->d_inode->i_nlink--; drop_nlink(dentry->d_inode);
dir->i_nlink--; drop_nlink(dir);
return shmem_unlink(dir, dentry); return shmem_unlink(dir, dentry);
} }
...@@ -1804,9 +1804,9 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct ...@@ -1804,9 +1804,9 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct
if (new_dentry->d_inode) { if (new_dentry->d_inode) {
(void) shmem_unlink(new_dir, new_dentry); (void) shmem_unlink(new_dir, new_dentry);
if (they_are_dirs) if (they_are_dirs)
old_dir->i_nlink--; drop_nlink(old_dir);
} else if (they_are_dirs) { } else if (they_are_dirs) {
old_dir->i_nlink--; drop_nlink(old_dir);
new_dir->i_nlink++; new_dir->i_nlink++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment