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>
This commit is contained in:
committed by
Jan Kara
parent
d1668fe390
commit
4d0fb621d3
@ -27,7 +27,6 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include "udf_i.h"
|
||||
|
||||
@ -78,13 +77,16 @@ static int udf_symlink_filler(struct file *file, struct page *page)
|
||||
int err = -EIO;
|
||||
unsigned char *p = kmap(page);
|
||||
struct udf_inode_info *iinfo;
|
||||
uint32_t pos;
|
||||
|
||||
lock_kernel();
|
||||
iinfo = UDF_I(inode);
|
||||
pos = udf_block_map(inode, 0);
|
||||
|
||||
down_read(&iinfo->i_data_sem);
|
||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||
symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
|
||||
} else {
|
||||
bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
|
||||
bh = sb_bread(inode->i_sb, pos);
|
||||
|
||||
if (!bh)
|
||||
goto out;
|
||||
@ -95,14 +97,14 @@ static int udf_symlink_filler(struct file *file, struct page *page)
|
||||
udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
|
||||
brelse(bh);
|
||||
|
||||
unlock_kernel();
|
||||
up_read(&iinfo->i_data_sem);
|
||||
SetPageUptodate(page);
|
||||
kunmap(page);
|
||||
unlock_page(page);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
unlock_kernel();
|
||||
up_read(&iinfo->i_data_sem);
|
||||
SetPageError(page);
|
||||
kunmap(page);
|
||||
unlock_page(page);
|
||||
|
Reference in New Issue
Block a user