diff options
40 files changed, 57 insertions, 49 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 9e670d52764..ef5905f7c8a 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1789,9 +1789,10 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,  		kfree(st);  	} else {  		/* Caching disabled. No need to get upto date stat info. -		 * This dentry will be released immediately. So, just i_count++ +		 * This dentry will be released immediately. So, just hold the +		 * inode  		 */ -		atomic_inc(&old_dentry->d_inode->i_count); +		ihold(old_dentry->d_inode);  	}  	dentry->d_op = old_dentry->d_op; diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 3a0fdec175b..5d828903ac6 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -388,7 +388,7 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3  		affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));  		mark_buffer_dirty_inode(inode_bh, inode);  		inode->i_nlink = 2; -		atomic_inc(&inode->i_count); +		ihold(inode);  	}  	affs_fix_checksum(sb, bh);  	mark_buffer_dirty_inode(bh, inode); diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 0d38c09bd55..5439e1bc9a8 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -1045,7 +1045,7 @@ static int afs_link(struct dentry *from, struct inode *dir,  	if (ret < 0)  		goto link_error; -	atomic_inc(&vnode->vfs_inode.i_count); +	ihold(&vnode->vfs_inode);  	d_instantiate(dentry, &vnode->vfs_inode);  	key_put(key);  	_leave(" = 0"); @@ -1553,10 +1553,9 @@ static void aio_batch_add(struct address_space *mapping,  	 *  	 * When we're called, we always have a reference  	 * on the file, so we must always have a reference -	 * on the inode, so igrab must always just -	 * bump the count and move on. +	 * on the inode, so ihold() is safe here.  	 */ -	atomic_inc(&mapping->host->i_count); +	ihold(mapping->host);  	abe->mapping = mapping;  	hlist_add_head(&abe->list, &batch_hash[bucket]);  	return; diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index e4b75d6eda8..9c8e87b0361 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -111,10 +111,9 @@ struct file *anon_inode_getfile(const char *name,  	path.mnt = mntget(anon_inode_mnt);  	/*  	 * We know the anon_inode inode count is always greater than zero, -	 * so we can avoid doing an igrab() and we can use an open-coded -	 * atomic_inc(). +	 * so ihold() is safe.  	 */ -	atomic_inc(&anon_inode_inode->i_count); +	ihold(anon_inode_inode);  	path.dentry->d_op = &anon_inodefs_dentry_operations;  	d_instantiate(path.dentry, anon_inode_inode); diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index d967e052b77..685ecff3ab3 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -176,7 +176,7 @@ static int bfs_link(struct dentry *old, struct inode *dir,  	inc_nlink(inode);  	inode->i_ctime = CURRENT_TIME_SEC;  	mark_inode_dirty(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	d_instantiate(new, inode);  	mutex_unlock(&info->bfs_lock);  	return 0; diff --git a/fs/block_dev.c b/fs/block_dev.c index b737451e2e9..81972eb34b3 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -550,7 +550,7 @@ EXPORT_SYMBOL(bdget);   */  struct block_device *bdgrab(struct block_device *bdev)  { -	atomic_inc(&bdev->bd_inode->i_count); +	ihold(bdev->bd_inode);  	return bdev;  } @@ -580,7 +580,7 @@ static struct block_device *bd_acquire(struct inode *inode)  	spin_lock(&bdev_lock);  	bdev = inode->i_bdev;  	if (bdev) { -		atomic_inc(&bdev->bd_inode->i_count); +		ihold(bdev->bd_inode);  		spin_unlock(&bdev_lock);  		return bdev;  	} @@ -591,12 +591,12 @@ static struct block_device *bd_acquire(struct inode *inode)  		spin_lock(&bdev_lock);  		if (!inode->i_bdev) {  			/* -			 * We take an additional bd_inode->i_count for inode, +			 * We take an additional reference to bd_inode,  			 * and it's released in clear_inode() of inode.  			 * So, we can access it via ->i_mapping always  			 * without igrab().  			 */ -			atomic_inc(&bdev->bd_inode->i_count); +			ihold(bdev->bd_inode);  			inode->i_bdev = bdev;  			inode->i_mapping = bdev->bd_inode->i_mapping;  			list_add(&inode->i_devices, &bdev->bd_inodes); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f6f2a0da269..64f99cf69ce 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4758,7 +4758,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,  	}  	btrfs_set_trans_block_group(trans, dir); -	atomic_inc(&inode->i_count); +	ihold(inode);  	err = btrfs_add_nondir(trans, dentry, inode, 1, index); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 96fbeab77f2..5d8b3553960 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -276,7 +276,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,  	}  	coda_dir_update_mtime(dir_inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	d_instantiate(de, inode);  	inc_nlink(inode);  	return 0; diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c index b7dd0c23686..264e95d0283 100644 --- a/fs/exofs/namei.c +++ b/fs/exofs/namei.c @@ -153,7 +153,7 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir,  	inode->i_ctime = CURRENT_TIME;  	inode_inc_link_count(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	return exofs_add_nondir(dentry, inode);  } diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 71efb0e9a3f..f8aecd2e329 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -206,7 +206,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,  	inode->i_ctime = CURRENT_TIME_SEC;  	inode_inc_link_count(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	err = ext2_add_link(dentry, inode);  	if (!err) { diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 2b35ddb70d6..bce9dce639b 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -2260,7 +2260,7 @@ retry:  	inode->i_ctime = CURRENT_TIME_SEC;  	inc_nlink(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	err = ext3_add_entry(handle, dentry, inode);  	if (!err) { diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 314c0d3b3fa..bd39885b599 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2312,7 +2312,7 @@ retry:  	inode->i_ctime = ext4_current_time(inode);  	ext4_inc_count(handle, inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	err = ext4_add_entry(handle, dentry, inode);  	if (!err) { diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 48a274f1674..12cbea7502c 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -255,7 +255,7 @@ out_parent:  	gfs2_holder_uninit(ghs);  	gfs2_holder_uninit(ghs + 1);  	if (!error) { -		atomic_inc(&inode->i_count); +		ihold(inode);  		d_instantiate(dentry, inode);  		mark_inode_dirty(inode);  	} diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index d236d85ec9d..e318bbc0daf 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -286,7 +286,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,  	inc_nlink(inode);  	hfsplus_instantiate(dst_dentry, inode, cnid); -	atomic_inc(&inode->i_count); +	ihold(inode);  	inode->i_ctime = CURRENT_TIME_SEC;  	mark_inode_dirty(inode);  	sbi->file_count++; diff --git a/fs/inode.c b/fs/inode.c index 430d70f2abe..05ea293d5f3 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -320,6 +320,15 @@ void __iget(struct inode *inode)  	atomic_inc(&inode->i_count);  } +/* + * get additional reference to inode; caller must already hold one. + */ +void ihold(struct inode *inode) +{ +	WARN_ON(atomic_inc_return(&inode->i_count) < 2); +} +EXPORT_SYMBOL(ihold); +  static void inode_lru_list_add(struct inode *inode)  {  	if (list_empty(&inode->i_list)) { diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index ed78a3cf3cb..79121aa5858 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -289,7 +289,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de  		mutex_unlock(&f->sem);  		d_instantiate(dentry, old_dentry->d_inode);  		dir_i->i_mtime = dir_i->i_ctime = ITIME(now); -		atomic_inc(&old_dentry->d_inode->i_count); +		ihold(old_dentry->d_inode);  	}  	return ret;  } @@ -864,7 +864,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,  		printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);  		/* Might as well let the VFS know */  		d_instantiate(new_dentry, old_dentry->d_inode); -		atomic_inc(&old_dentry->d_inode->i_count); +		ihold(old_dentry->d_inode);  		new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);  		return ret;  	} diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index d945ea76b44..9466957ec84 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -1279,7 +1279,7 @@ int txCommit(tid_t tid,		/* transaction identifier */  	 * lazy commit thread finishes processing  	 */  	if (tblk->xflag & COMMIT_DELETE) { -		atomic_inc(&tblk->u.ip->i_count); +		ihold(tblk->u.ip);  		/*  		 * Avoid a rare deadlock  		 * diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index a9cf8e8675b..231ca4af9bc 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -839,7 +839,7 @@ static int jfs_link(struct dentry *old_dentry,  	ip->i_ctime = CURRENT_TIME;  	dir->i_ctime = dir->i_mtime = CURRENT_TIME;  	mark_inode_dirty(dir); -	atomic_inc(&ip->i_count); +	ihold(ip);  	iplist[0] = ip;  	iplist[1] = dir; diff --git a/fs/libfs.c b/fs/libfs.c index 2dbf4877d7e..304a5132ca2 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -255,7 +255,7 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den  	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;  	inc_nlink(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	dget(dentry);  	d_instantiate(dentry, inode);  	return 0; diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index 1eb4e89e045..409dfd65e9a 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c @@ -569,7 +569,7 @@ static int logfs_link(struct dentry *old_dentry, struct inode *dir,  		return -EMLINK;  	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; -	atomic_inc(&inode->i_count); +	ihold(inode);  	inode->i_nlink++;  	mark_inode_dirty_sync(inode); diff --git a/fs/minix/namei.c b/fs/minix/namei.c index f3f3578393a..c0d35a3acce 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -101,7 +101,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,  	inode->i_ctime = CURRENT_TIME_SEC;  	inode_inc_link_count(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	return add_nondir(dentry, inode);  } diff --git a/fs/namei.c b/fs/namei.c index f1ef97dbc6c..f7dbc06857a 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2285,7 +2285,7 @@ static long do_unlinkat(int dfd, const char __user *pathname)  			goto slashes;  		inode = dentry->d_inode;  		if (inode) -			atomic_inc(&inode->i_count); +			ihold(inode);  		error = mnt_want_write(nd.path.mnt);  		if (error)  			goto exit2; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e257172d438..0fac7fea18e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1580,7 +1580,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)  	d_drop(dentry);  	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);  	if (error == 0) { -		atomic_inc(&inode->i_count); +		ihold(inode);  		d_add(dentry, inode);  	}  	return error; diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index a70e446e160..ac7b814ce16 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -54,8 +54,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i  			iput(inode);  			return -ENOMEM;  		} -		/* Circumvent igrab(): we know the inode is not being freed */ -		atomic_inc(&inode->i_count); +		ihold(inode);  		/*  		 * Ensure that this dentry is invisible to d_find_alias().  		 * Otherwise, it may be spliced into the tree by diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 185d1607cb0..6e9557ecf16 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -207,7 +207,7 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,  	inode->i_ctime = CURRENT_TIME;  	inode_inc_link_count(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	err = nilfs_add_nondir(dentry, inode);  	if (!err) diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index d4dec2d3211..d3fbe5730bf 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2911,8 +2911,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)  		goto unl_upcase_iput_tmp_ino_err_out_now;  	}  	if ((sb->s_root = d_alloc_root(vol->root_ino))) { -		/* We increment i_count simulating an ntfs_iget(). */ -		atomic_inc(&vol->root_ino->i_count); +		/* We grab a reference, simulating an ntfs_iget(). */ +		ihold(vol->root_ino);  		ntfs_debug("Exiting, status successful.");  		/* Release the default upcase if it has no users. */  		mutex_lock(&ntfs_lock); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index e7bde21149a..ff5744e1e36 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -742,7 +742,7 @@ static int ocfs2_link(struct dentry *old_dentry,  		goto out_commit;  	} -	atomic_inc(&inode->i_count); +	ihold(inode);  	dentry->d_op = &ocfs2_dentry_ops;  	d_instantiate(dentry, inode); diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index ee78d4a0086..ba5f51ec345 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -1156,7 +1156,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,  	inode->i_ctime = CURRENT_TIME_SEC;  	reiserfs_update_sd(&th, inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	d_instantiate(dentry, inode);  	retval = journal_end(&th, dir->i_sb, jbegin_count);  	reiserfs_write_unlock(dir->i_sb); diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index 33e047b59b8..11e7f7d11cd 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -126,7 +126,7 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,  	inode->i_ctime = CURRENT_TIME_SEC;  	inode_inc_link_count(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	return add_nondir(dentry, inode);  } diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 87ebcce7221..14f64b689d7 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -550,7 +550,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,  	lock_2_inodes(dir, inode);  	inc_nlink(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	inode->i_ctime = ubifs_current_time(inode);  	dir->i_size += sz_change;  	dir_ui->ui_size = dir->i_size; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index bf5fc674193..6d8dc02baeb 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -1101,7 +1101,7 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,  	inc_nlink(inode);  	inode->i_ctime = current_fs_time(inode->i_sb);  	mark_inode_dirty(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	d_instantiate(dentry, inode);  	unlock_kernel(); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index b056f02b1fb..12f39b9e443 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -180,7 +180,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,  	inode->i_ctime = CURRENT_TIME_SEC;  	inode_inc_link_count(inode); -	atomic_inc(&inode->i_count); +	ihold(inode);  	error = ufs_add_nondir(dentry, inode);  	unlock_kernel(); diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 71d83c93621..96107efc0c6 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -317,7 +317,7 @@ xfs_vn_link(  	if (unlikely(error))  		return -error; -	atomic_inc(&inode->i_count); +	ihold(inode);  	d_instantiate(dentry, inode);  	return 0;  } diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index fac52290de9..fb2ca2e4cdc 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -500,7 +500,7 @@ void		xfs_mark_inode_dirty_sync(xfs_inode_t *);  #define IHOLD(ip) \  do { \  	ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \ -	atomic_inc(&(VFS_I(ip)->i_count)); \ +	ihold(VFS_I(ip)); \  	trace_xfs_ihold(ip, _THIS_IP_); \  } while (0) diff --git a/include/linux/fs.h b/include/linux/fs.h index d43e8b6685a..bd6ae6c71fc 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2171,6 +2171,7 @@ extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin);  extern int inode_init_always(struct super_block *, struct inode *);  extern void inode_init_once(struct inode *); +extern void ihold(struct inode * inode);  extern void iput(struct inode *);  extern struct inode * igrab(struct inode *);  extern ino_t iunique(struct super_block *, ino_t); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index e1e7b9635f5..80b35ffca25 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -769,7 +769,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)  	inode = dentry->d_inode;  	if (inode) -		atomic_inc(&inode->i_count); +		ihold(inode);  	err = mnt_want_write(ipc_ns->mq_mnt);  	if (err)  		goto out_err; diff --git a/kernel/futex.c b/kernel/futex.c index a118bf160e0..6c683b37f2c 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -169,7 +169,7 @@ static void get_futex_key_refs(union futex_key *key)  	switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {  	case FUT_OFF_INODE: -		atomic_inc(&key->shared.inode->i_count); +		ihold(key->shared.inode);  		break;  	case FUT_OFF_MMSHARED:  		atomic_inc(&key->private.mm->mm_count); diff --git a/mm/shmem.c b/mm/shmem.c index 27a58120dbd..d4e2852526e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1903,7 +1903,7 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr  	dir->i_size += BOGO_DIRENT_SIZE;  	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;  	inc_nlink(inode); -	atomic_inc(&inode->i_count);	/* New dentry reference */ +	ihold(inode);	/* New dentry reference */  	dget(dentry);		/* Extra pinning count for the created dentry */  	d_instantiate(dentry, inode);  out: diff --git a/net/socket.c b/net/socket.c index abf3e256152..d223725f99e 100644 --- a/net/socket.c +++ b/net/socket.c @@ -377,7 +377,7 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)  		  &socket_file_ops);  	if (unlikely(!file)) {  		/* drop dentry, keep inode */ -		atomic_inc(&path.dentry->d_inode->i_count); +		ihold(path.dentry->d_inode);  		path_put(&path);  		put_unused_fd(fd);  		return -ENFILE;  |