diff --git a/fs/udf/file.c b/fs/udf/file.c index 6834509a7e5a..ccab8b78e363 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -120,36 +120,11 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ssize_t retval; struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); - int err, pos; size_t count = iov_iter_count(from); struct udf_inode_info *iinfo = UDF_I(inode); + int err; mutex_lock(&inode->i_mutex); - 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; - else - pos = iocb->ki_pos; - - if (inode->i_sb->s_blocksize < - (udf_file_entry_alloc_offset(inode) + - pos + count)) { - err = udf_expand_file_adinicb(inode); - if (err) { - mutex_unlock(&inode->i_mutex); - udf_debug("udf_expand_adinicb: err=%d\n", err); - return err; - } - } else { - if (pos + count > inode->i_size) - iinfo->i_lenAlloc = pos + count; - else - iinfo->i_lenAlloc = inode->i_size; - up_write(&iinfo->i_data_sem); - } - } else - up_write(&iinfo->i_data_sem); retval = generic_write_checks(file, &iocb->ki_pos, &count); if (retval) @@ -160,6 +135,25 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from) iov_iter_truncate(from, count); + down_write(&iinfo->i_data_sem); + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { + loff_t end = iocb->ki_pos + iov_iter_count(from); + + if (inode->i_sb->s_blocksize < + (udf_file_entry_alloc_offset(inode) + end)) { + err = udf_expand_file_adinicb(inode); + if (err) { + mutex_unlock(&inode->i_mutex); + udf_debug("udf_expand_adinicb: err=%d\n", err); + return err; + } + } else { + iinfo->i_lenAlloc = max(end, inode->i_size); + up_write(&iinfo->i_data_sem); + } + } else + up_write(&iinfo->i_data_sem); + retval = __generic_file_write_iter(iocb, from); out: mutex_unlock(&inode->i_mutex);