summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-11-16 16:33:48 +0300
committerJan Kara <jack@suse.cz>2011-01-06 19:03:57 +0300
commit8754a3f718f08dc21b3c5eccd044f612d4bc1ab1 (patch)
tree40d2b8af8e64f9041f19e8d93df0ab81e6b8054e /fs
parent9db9f9e31d7661dff35a75ed01ff9fc0d6acdaf8 (diff)
downloadlinux-8754a3f718f08dc21b3c5eccd044f612d4bc1ab1.tar.xz
udf: Protect udf_file_aio_write from possible races
Code doing conversion from INICB file to a normal file in udf_file_aio_write() is not protected by any lock from other code modifying the inode. Use i_alloc_sem for that. Reported-by: Alessio Igor Bogani <abogani@texware.it> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/udf/file.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 4e3bbd81b57b..89c78486cbbe 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -113,6 +113,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
size_t count = iocb->ki_left;
struct udf_inode_info *iinfo = UDF_I(inode);
+ down_write(&iinfo->i_data_sem);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
if (file->f_flags & O_APPEND)
pos = inode->i_size;
@@ -125,6 +126,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
udf_expand_file_adinicb(inode, pos + count, &err);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
udf_debug("udf_expand_adinicb: err=%d\n", err);
+ up_write(&iinfo->i_data_sem);
return err;
}
} else {
@@ -134,6 +136,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
iinfo->i_lenAlloc = inode->i_size;
}
}
+ up_write(&iinfo->i_data_sem);
retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
if (retval > 0)