@@ -1134,6 +1134,7 @@ struct ext4_inode_info {
atomic_t i_unwritten; /* Nr. of inflight conversions pending */
spinlock_t i_block_reservation_lock;
+ struct rw_semaphore i_rsv_unwritten_sem;
/*
* Transactions that contain inode's metadata needed to complete
@@ -4807,6 +4807,7 @@ int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
break;
}
}
+ down_write(&EXT4_I(inode)->i_rsv_unwritten_sem);
ret = ext4_map_blocks(handle, inode, &map,
EXT4_GET_BLOCKS_IO_CONVERT_EXT);
if (ret <= 0)
@@ -4815,6 +4816,7 @@ int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
"ext4_ext_map_blocks returned %d",
inode->i_ino, map.m_lblk,
map.m_len, ret);
+ up_write(&EXT4_I(inode)->i_rsv_unwritten_sem);
ret2 = ext4_mark_inode_dirty(handle, inode);
if (credits) {
ret3 = ext4_journal_stop(handle);
@@ -1466,6 +1466,7 @@ static void init_once(void *foo)
INIT_LIST_HEAD(&ei->i_orphan);
init_rwsem(&ei->xattr_sem);
init_rwsem(&ei->i_data_sem);
+ init_rwsem(&ei->i_rsv_unwritten_sem);
inode_init_once(&ei->vfs_inode);
ext4_fc_init_inode(&ei->vfs_inode);
}
@@ -5452,7 +5453,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
* concurrency isn't really necessary. Limit it to 1.
*/
EXT4_SB(sb)->rsv_conversion_wq =
- alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
if (!EXT4_SB(sb)->rsv_conversion_wq) {
printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
err = -ENOMEM;