diff options
-rw-r--r-- | fs/ext4/inode.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 48fc023ab0a2..65bbc9339aca 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1305,6 +1305,55 @@ static int ext4_journalled_write_end(struct file *file, | |||
1305 | } | 1305 | } |
1306 | 1306 | ||
1307 | /* | 1307 | /* |
1308 | * Reserve a metadata for a single block located at lblock | ||
1309 | */ | ||
1310 | static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock) | ||
1311 | { | ||
1312 | int retries = 0; | ||
1313 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
1314 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
1315 | unsigned int md_needed; | ||
1316 | ext4_lblk_t save_last_lblock; | ||
1317 | int save_len; | ||
1318 | |||
1319 | /* | ||
1320 | * recalculate the amount of metadata blocks to reserve | ||
1321 | * in order to allocate nrblocks | ||
1322 | * worse case is one extent per block | ||
1323 | */ | ||
1324 | repeat: | ||
1325 | spin_lock(&ei->i_block_reservation_lock); | ||
1326 | /* | ||
1327 | * ext4_calc_metadata_amount() has side effects, which we have | ||
1328 | * to be prepared undo if we fail to claim space. | ||
1329 | */ | ||
1330 | save_len = ei->i_da_metadata_calc_len; | ||
1331 | save_last_lblock = ei->i_da_metadata_calc_last_lblock; | ||
1332 | md_needed = EXT4_NUM_B2C(sbi, | ||
1333 | ext4_calc_metadata_amount(inode, lblock)); | ||
1334 | trace_ext4_da_reserve_space(inode, md_needed); | ||
1335 | |||
1336 | /* | ||
1337 | * We do still charge estimated metadata to the sb though; | ||
1338 | * we cannot afford to run out of free blocks. | ||
1339 | */ | ||
1340 | if (ext4_claim_free_clusters(sbi, md_needed, 0)) { | ||
1341 | ei->i_da_metadata_calc_len = save_len; | ||
1342 | ei->i_da_metadata_calc_last_lblock = save_last_lblock; | ||
1343 | spin_unlock(&ei->i_block_reservation_lock); | ||
1344 | if (ext4_should_retry_alloc(inode->i_sb, &retries)) { | ||
1345 | cond_resched(); | ||
1346 | goto repeat; | ||
1347 | } | ||
1348 | return -ENOSPC; | ||
1349 | } | ||
1350 | ei->i_reserved_meta_blocks += md_needed; | ||
1351 | spin_unlock(&ei->i_block_reservation_lock); | ||
1352 | |||
1353 | return 0; /* success */ | ||
1354 | } | ||
1355 | |||
1356 | /* | ||
1308 | * Reserve a single cluster located at lblock | 1357 | * Reserve a single cluster located at lblock |
1309 | */ | 1358 | */ |
1310 | static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) | 1359 | static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) |
@@ -1940,8 +1989,11 @@ add_delayed: | |||
1940 | * XXX: __block_prepare_write() unmaps passed block, | 1989 | * XXX: __block_prepare_write() unmaps passed block, |
1941 | * is it OK? | 1990 | * is it OK? |
1942 | */ | 1991 | */ |
1943 | /* If the block was allocated from previously allocated cluster, | 1992 | /* |
1944 | * then we dont need to reserve it again. */ | 1993 | * If the block was allocated from previously allocated cluster, |
1994 | * then we don't need to reserve it again. However we still need | ||
1995 | * to reserve metadata for every block we're going to write. | ||
1996 | */ | ||
1945 | if (!(map->m_flags & EXT4_MAP_FROM_CLUSTER)) { | 1997 | if (!(map->m_flags & EXT4_MAP_FROM_CLUSTER)) { |
1946 | ret = ext4_da_reserve_space(inode, iblock); | 1998 | ret = ext4_da_reserve_space(inode, iblock); |
1947 | if (ret) { | 1999 | if (ret) { |
@@ -1949,6 +2001,13 @@ add_delayed: | |||
1949 | retval = ret; | 2001 | retval = ret; |
1950 | goto out_unlock; | 2002 | goto out_unlock; |
1951 | } | 2003 | } |
2004 | } else { | ||
2005 | ret = ext4_da_reserve_metadata(inode, iblock); | ||
2006 | if (ret) { | ||
2007 | /* not enough space to reserve */ | ||
2008 | retval = ret; | ||
2009 | goto out_unlock; | ||
2010 | } | ||
1952 | } | 2011 | } |
1953 | 2012 | ||
1954 | ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, | 2013 | ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, |