Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -332,7 +332,7 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
{
	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, struct dentry *dentry)
	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);
+1 −1
Original line number Diff line number Diff line
@@ -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;
	autofs_hash_delete(ent);
	dir->i_nlink--;
	drop_nlink(dir);
	d_drop(dentry);
	unlock_kernel();

+1 −1
Original line number Diff line number Diff line
@@ -676,7 +676,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
	dentry->d_inode->i_nlink = 0;

	if (dir->i_nlink)
		dir->i_nlink--;
		drop_nlink(dir);

	return 0;
}
+3 −6
Original line number Diff line number Diff line
@@ -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);
	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, struct dentry * dentry)
	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_dir, struct dentry * old_dentry,
	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;
+5 −5
Original line number Diff line number Diff line
@@ -590,7 +590,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)

	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) {
@@ -609,7 +609,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
						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? */
@@ -663,7 +663,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
						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;
@@ -684,7 +684,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
						    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 */
			}
@@ -816,7 +816,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
			  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;
	}
Loading