summary refs log tree commit diff
path: root/fs/udf/namei.c
diff options
context:
space:
mode:
authorAlessio Igor Bogani <abogani@texware.it>2010-11-16 18:40:47 +0100
committerJan Kara <jack@suse.cz>2011-01-06 17:03:56 +0100
commit4d0fb621d35007c19a396f2bb629e5aeaacef2d0 (patch)
tree92f6e0d3c38c15b0af507bd4b6d3353e34a337a9 /fs/udf/namei.c
parentd1668fe390c1e84580575965684a8fa7e4626dee (diff)
downloadlinux-4d0fb621d35007c19a396f2bb629e5aeaacef2d0.tar.gz
udf: Replace bkl with the UDF_I(inode)->i_data_sem for protect udf_inode_info struct
Replace bkl with the UDF_I(inode)->i_data_sem rw semaphore in
udf_release_file(), udf_symlink(), udf_symlink_filler(), udf_get_block(),
udf_block_map(), and udf_setattr(). The rule now is that any operation
on regular file's or symlink's extents (or generally allocation information
including goal block) needs to hold i_data_sem.

This work was supported by a hardware donation from the CE Linux Forum.

Signed-off-by: Alessio Igor Bogani <abogani@texware.it>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/namei.c')
-rw-r--r--fs/udf/namei.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 701fcda18415..d5eb000ddddd 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -893,18 +893,18 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
 	struct udf_inode_info *iinfo;
 	struct super_block *sb = dir->i_sb;
 
-	lock_kernel();
 	inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
 	if (!inode)
 		goto out;
 
+	iinfo = UDF_I(inode);
+	down_write(&iinfo->i_data_sem);
 	name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
 	if (!name) {
 		err = -ENOMEM;
 		goto out_no_entry;
 	}
 
-	iinfo = UDF_I(inode);
 	inode->i_data.a_ops = &udf_symlink_aops;
 	inode->i_op = &udf_symlink_inode_operations;
 
@@ -1024,6 +1024,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
 	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 	if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 		mark_inode_dirty(dir);
+	up_write(&iinfo->i_data_sem);
 	if (fibh.sbh != fibh.ebh)
 		brelse(fibh.ebh);
 	brelse(fibh.sbh);
@@ -1032,10 +1033,10 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
 
 out:
 	kfree(name);
-	unlock_kernel();
 	return err;
 
 out_no_entry:
+	up_write(&iinfo->i_data_sem);
 	inode_dec_link_count(inode);
 	iput(inode);
 	goto out;