1
0
Fork 0

[PATCH] r/o bind mounts: monitor zeroing of i_nlink

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>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
hifive-unleashed-5.1
Dave Hansen 2006-09-30 23:29:06 -07:00 committed by Linus Torvalds
parent 17ff785691
commit ce71ec3684
15 changed files with 26 additions and 21 deletions

View File

@ -638,7 +638,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
dput(ino->dentry); dput(ino->dentry);
dentry->d_inode->i_size = 0; dentry->d_inode->i_size = 0;
dentry->d_inode->i_nlink = 0; clear_nlink(dentry->d_inode);
dir->i_mtime = CURRENT_TIME; dir->i_mtime = CURRENT_TIME;
@ -673,7 +673,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
} }
dput(ino->dentry); dput(ino->dentry);
dentry->d_inode->i_size = 0; dentry->d_inode->i_size = 0;
dentry->d_inode->i_nlink = 0; clear_nlink(dentry->d_inode);
if (dir->i_nlink) if (dir->i_nlink)
drop_nlink(dir); drop_nlink(dir);

View File

@ -818,7 +818,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
if (!rc) { if (!rc) {
drop_nlink(inode); drop_nlink(inode);
i_size_write(direntry->d_inode,0); i_size_write(direntry->d_inode,0);
direntry->d_inode->i_nlink = 0; clear_nlink(direntry->d_inode);
} }
cifsInode = CIFS_I(direntry->d_inode); cifsInode = CIFS_I(direntry->d_inode);

View File

@ -2045,7 +2045,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
"empty directory has nlink!=2 (%d)", "empty directory has nlink!=2 (%d)",
inode->i_nlink); inode->i_nlink);
inode->i_version++; inode->i_version++;
inode->i_nlink = 0; clear_nlink(inode);
/* There's no need to set i_disksize: the fact that i_nlink is /* There's no need to set i_disksize: the fact that i_nlink is
* zero will ensure that the right thing happens during any * zero will ensure that the right thing happens during any
* recovery. */ * recovery. */

View File

@ -508,7 +508,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
/* Set nlink to zero so the inode can be cleared, if /* Set nlink to zero so the inode can be cleared, if
the inode does have more links this will be the inode does have more links this will be
discovered at the next lookup/getattr */ discovered at the next lookup/getattr */
inode->i_nlink = 0; clear_nlink(inode);
fuse_invalidate_attr(inode); fuse_invalidate_attr(inode);
fuse_invalidate_attr(dir); fuse_invalidate_attr(dir);
fuse_invalidate_entry_cache(entry); fuse_invalidate_entry_cache(entry);
@ -534,7 +534,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
err = req->out.h.error; err = req->out.h.error;
fuse_put_request(fc, req); fuse_put_request(fc, req);
if (!err) { if (!err) {
entry->d_inode->i_nlink = 0; clear_nlink(entry->d_inode);
fuse_invalidate_attr(dir); fuse_invalidate_attr(dir);
fuse_invalidate_entry_cache(entry); fuse_invalidate_entry_cache(entry);
} else if (err == -EINTR) } else if (err == -EINTR)

View File

@ -273,7 +273,7 @@ static int hfs_rmdir(struct inode *dir, struct dentry *dentry)
res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name);
if (res) if (res)
return res; return res;
inode->i_nlink = 0; clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
hfs_delete_inode(inode); hfs_delete_inode(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);

View File

@ -348,7 +348,7 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
} else } else
inode->i_flags |= S_DEAD; inode->i_flags |= S_DEAD;
} else } else
inode->i_nlink = 0; clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode); mark_inode_dirty(inode);
@ -387,7 +387,7 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
if (res) if (res)
return res; return res;
inode->i_nlink = 0; clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
hfsplus_delete_inode(inode); hfsplus_delete_inode(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);

View File

@ -495,7 +495,7 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
break; break;
default: default:
drop_nlink(dir); drop_nlink(dir);
inode->i_nlink = 0; clear_nlink(inode);
err = 0; err = 0;
} }
goto out; goto out;
@ -590,7 +590,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
int r; int r;
if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) { 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))) { 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); copy_de(nde, &de);
memcpy(nde->name, new_name, new_len); memcpy(nde->name, new_name, new_len);
hpfs_mark_4buffers_dirty(&qbh1); hpfs_mark_4buffers_dirty(&qbh1);

View File

@ -414,7 +414,7 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
JFS_IP(ip)->acl.flag = 0; JFS_IP(ip)->acl.flag = 0;
/* mark the target directory as deleted */ /* mark the target directory as deleted */
ip->i_nlink = 0; clear_nlink(ip);
mark_inode_dirty(ip); mark_inode_dirty(ip);
rc = txCommit(tid, 2, &iplist[0], 0); rc = txCommit(tid, 2, &iplist[0], 0);

View File

@ -345,7 +345,7 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
goto out; goto out;
drop_nlink(dir); drop_nlink(dir);
inode->i_nlink = 0; clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:
@ -430,7 +430,7 @@ static int msdos_unlink(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;
inode->i_nlink = 0; clear_nlink(inode);
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:

View File

@ -1286,7 +1286,7 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
/* Ensure the VFS deletes this inode */ /* Ensure the VFS deletes this inode */
if (error == 0 && dentry->d_inode != NULL) if (error == 0 && dentry->d_inode != NULL)
dentry->d_inode->i_nlink = 0; clear_nlink(dentry->d_inode);
nfs_end_data_update(dir); nfs_end_data_update(dir);
unlock_kernel(); unlock_kernel();

View File

@ -186,7 +186,7 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
memset(de->di_fname, 0, sizeof de->di_fname); memset(de->di_fname, 0, sizeof de->di_fname);
de->di_mode = 0; de->di_mode = 0;
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
inode->i_nlink = 0; clear_nlink(inode);
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;
inode_dec_link_count(dir); inode_dec_link_count(dir);

View File

@ -913,7 +913,7 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
reiserfs_warning(inode->i_sb, "%s: empty directory has nlink " reiserfs_warning(inode->i_sb, "%s: empty directory has nlink "
"!= 2 (%d)", __FUNCTION__, inode->i_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; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
reiserfs_update_sd(&th, inode); reiserfs_update_sd(&th, inode);
@ -1473,7 +1473,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (new_dentry_inode) { if (new_dentry_inode) {
// adjust link number of the victim // adjust link number of the victim
if (S_ISDIR(new_dentry_inode->i_mode)) { if (S_ISDIR(new_dentry_inode->i_mode)) {
new_dentry_inode->i_nlink = 0; clear_nlink(new_dentry_inode);
} else { } else {
drop_nlink(new_dentry_inode); drop_nlink(new_dentry_inode);
} }

View File

@ -876,7 +876,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
udf_warning(inode->i_sb, "udf_rmdir", udf_warning(inode->i_sb, "udf_rmdir",
"empty directory has nlink != 2 (%d)", "empty directory has nlink != 2 (%d)",
inode->i_nlink); inode->i_nlink);
inode->i_nlink = 0; clear_nlink(inode);
inode->i_size = 0; inode->i_size = 0;
inode_dec_link_count(inode); inode_dec_link_count(inode);
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);

View File

@ -784,7 +784,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
goto out; goto out;
drop_nlink(dir); drop_nlink(dir);
inode->i_nlink = 0; clear_nlink(inode);
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:
@ -808,7 +808,7 @@ static int vfat_unlink(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;
inode->i_nlink = 0; clear_nlink(inode);
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode); fat_detach(inode);
out: out:

View File

@ -1235,6 +1235,11 @@ static inline void drop_nlink(struct inode *inode)
inode->i_nlink--; 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) static inline void inode_dec_link_count(struct inode *inode)
{ {
drop_nlink(inode); drop_nlink(inode);