diff options
| -rw-r--r-- | fs/ext4/balloc.c | 1 | ||||
| -rw-r--r-- | fs/ext4/dir.c | 25 | ||||
| -rw-r--r-- | fs/ext4/ext4.h | 14 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 14 | ||||
| -rw-r--r-- | fs/ext4/file.c | 4 | ||||
| -rw-r--r-- | fs/ext4/indirect.c | 281 | ||||
| -rw-r--r-- | fs/ext4/inline.c | 18 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 130 | ||||
| -rw-r--r-- | fs/ext4/mballoc.c | 41 | ||||
| -rw-r--r-- | fs/ext4/migrate.c | 7 | ||||
| -rw-r--r-- | fs/ext4/move_extent.c | 3 | ||||
| -rw-r--r-- | fs/ext4/super.c | 88 |
12 files changed, 333 insertions, 293 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index fca382037ddd..581ef40fbe90 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -639,7 +639,6 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, | |||
| 639 | if (!(*errp) && | 639 | if (!(*errp) && |
| 640 | ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) { | 640 | ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) { |
| 641 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | 641 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); |
| 642 | EXT4_I(inode)->i_allocated_meta_blocks += ar.len; | ||
| 643 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 642 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
| 644 | dquot_alloc_block_nofail(inode, | 643 | dquot_alloc_block_nofail(inode, |
| 645 | EXT4_C2B(EXT4_SB(inode->i_sb), ar.len)); | 644 | EXT4_C2B(EXT4_SB(inode->i_sb), ar.len)); |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index ef1bed66c14f..0bb3f9ea0832 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
| @@ -571,6 +571,31 @@ static int ext4_release_dir(struct inode *inode, struct file *filp) | |||
| 571 | return 0; | 571 | return 0; |
| 572 | } | 572 | } |
| 573 | 573 | ||
| 574 | int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf, | ||
| 575 | int buf_size) | ||
| 576 | { | ||
| 577 | struct ext4_dir_entry_2 *de; | ||
| 578 | int nlen, rlen; | ||
| 579 | unsigned int offset = 0; | ||
| 580 | char *top; | ||
| 581 | |||
| 582 | de = (struct ext4_dir_entry_2 *)buf; | ||
| 583 | top = buf + buf_size; | ||
| 584 | while ((char *) de < top) { | ||
| 585 | if (ext4_check_dir_entry(dir, NULL, de, bh, | ||
| 586 | buf, buf_size, offset)) | ||
| 587 | return -EIO; | ||
| 588 | nlen = EXT4_DIR_REC_LEN(de->name_len); | ||
| 589 | rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); | ||
| 590 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); | ||
| 591 | offset += rlen; | ||
| 592 | } | ||
| 593 | if ((char *) de > top) | ||
| 594 | return -EIO; | ||
| 595 | |||
| 596 | return 0; | ||
| 597 | } | ||
| 598 | |||
| 574 | const struct file_operations ext4_dir_operations = { | 599 | const struct file_operations ext4_dir_operations = { |
| 575 | .llseek = ext4_dir_llseek, | 600 | .llseek = ext4_dir_llseek, |
| 576 | .read = generic_read_dir, | 601 | .read = generic_read_dir, |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 7cc5a0e23688..5b19760b1de5 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -591,7 +591,6 @@ enum { | |||
| 591 | #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008 | 591 | #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008 |
| 592 | #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010 | 592 | #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010 |
| 593 | #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020 | 593 | #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020 |
| 594 | #define EXT4_FREE_BLOCKS_RESERVE 0x0040 | ||
| 595 | 594 | ||
| 596 | /* | 595 | /* |
| 597 | * ioctl commands | 596 | * ioctl commands |
| @@ -2029,6 +2028,8 @@ static inline unsigned char get_dtype(struct super_block *sb, int filetype) | |||
| 2029 | 2028 | ||
| 2030 | return ext4_filetype_table[filetype]; | 2029 | return ext4_filetype_table[filetype]; |
| 2031 | } | 2030 | } |
| 2031 | extern int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, | ||
| 2032 | void *buf, int buf_size); | ||
| 2032 | 2033 | ||
| 2033 | /* fsync.c */ | 2034 | /* fsync.c */ |
| 2034 | extern int ext4_sync_file(struct file *, loff_t, loff_t, int); | 2035 | extern int ext4_sync_file(struct file *, loff_t, loff_t, int); |
| @@ -2144,8 +2145,8 @@ extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, | |||
| 2144 | extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock); | 2145 | extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock); |
| 2145 | extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks); | 2146 | extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks); |
| 2146 | extern void ext4_ind_truncate(handle_t *, struct inode *inode); | 2147 | extern void ext4_ind_truncate(handle_t *, struct inode *inode); |
| 2147 | extern int ext4_free_hole_blocks(handle_t *handle, struct inode *inode, | 2148 | extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode, |
| 2148 | ext4_lblk_t first, ext4_lblk_t stop); | 2149 | ext4_lblk_t start, ext4_lblk_t end); |
| 2149 | 2150 | ||
| 2150 | /* ioctl.c */ | 2151 | /* ioctl.c */ |
| 2151 | extern long ext4_ioctl(struct file *, unsigned int, unsigned long); | 2152 | extern long ext4_ioctl(struct file *, unsigned int, unsigned long); |
| @@ -2560,7 +2561,6 @@ extern const struct file_operations ext4_file_operations; | |||
| 2560 | extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); | 2561 | extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); |
| 2561 | 2562 | ||
| 2562 | /* inline.c */ | 2563 | /* inline.c */ |
| 2563 | extern int ext4_has_inline_data(struct inode *inode); | ||
| 2564 | extern int ext4_get_max_inline_size(struct inode *inode); | 2564 | extern int ext4_get_max_inline_size(struct inode *inode); |
| 2565 | extern int ext4_find_inline_data_nolock(struct inode *inode); | 2565 | extern int ext4_find_inline_data_nolock(struct inode *inode); |
| 2566 | extern int ext4_init_inline_data(handle_t *handle, struct inode *inode, | 2566 | extern int ext4_init_inline_data(handle_t *handle, struct inode *inode, |
| @@ -2626,6 +2626,12 @@ extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline); | |||
| 2626 | 2626 | ||
| 2627 | extern int ext4_convert_inline_data(struct inode *inode); | 2627 | extern int ext4_convert_inline_data(struct inode *inode); |
| 2628 | 2628 | ||
| 2629 | static inline int ext4_has_inline_data(struct inode *inode) | ||
| 2630 | { | ||
| 2631 | return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) && | ||
| 2632 | EXT4_I(inode)->i_inline_off; | ||
| 2633 | } | ||
| 2634 | |||
| 2629 | /* namei.c */ | 2635 | /* namei.c */ |
| 2630 | extern const struct inode_operations ext4_dir_inode_operations; | 2636 | extern const struct inode_operations ext4_dir_inode_operations; |
| 2631 | extern const struct inode_operations ext4_special_inode_operations; | 2637 | extern const struct inode_operations ext4_special_inode_operations; |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 4da228a0e6d0..76c2df382b7d 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -161,6 +161,8 @@ int __ext4_ext_dirty(const char *where, unsigned int line, handle_t *handle, | |||
| 161 | struct inode *inode, struct ext4_ext_path *path) | 161 | struct inode *inode, struct ext4_ext_path *path) |
| 162 | { | 162 | { |
| 163 | int err; | 163 | int err; |
| 164 | |||
| 165 | WARN_ON(!rwsem_is_locked(&EXT4_I(inode)->i_data_sem)); | ||
| 164 | if (path->p_bh) { | 166 | if (path->p_bh) { |
| 165 | ext4_extent_block_csum_set(inode, ext_block_hdr(path->p_bh)); | 167 | ext4_extent_block_csum_set(inode, ext_block_hdr(path->p_bh)); |
| 166 | /* path points to block */ | 168 | /* path points to block */ |
| @@ -1808,8 +1810,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle, | |||
| 1808 | 1810 | ||
| 1809 | brelse(path[1].p_bh); | 1811 | brelse(path[1].p_bh); |
| 1810 | ext4_free_blocks(handle, inode, NULL, blk, 1, | 1812 | ext4_free_blocks(handle, inode, NULL, blk, 1, |
| 1811 | EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET | | 1813 | EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); |
| 1812 | EXT4_FREE_BLOCKS_RESERVE); | ||
| 1813 | } | 1814 | } |
| 1814 | 1815 | ||
| 1815 | /* | 1816 | /* |
| @@ -3253,7 +3254,7 @@ out: | |||
| 3253 | 3254 | ||
| 3254 | fix_extent_len: | 3255 | fix_extent_len: |
| 3255 | ex->ee_len = orig_ex.ee_len; | 3256 | ex->ee_len = orig_ex.ee_len; |
| 3256 | ext4_ext_dirty(handle, inode, path + depth); | 3257 | ext4_ext_dirty(handle, inode, path + path->p_depth); |
| 3257 | return err; | 3258 | return err; |
| 3258 | } | 3259 | } |
| 3259 | 3260 | ||
| @@ -5403,16 +5404,13 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) | |||
| 5403 | int ret; | 5404 | int ret; |
| 5404 | 5405 | ||
| 5405 | /* Collapse range works only on fs block size aligned offsets. */ | 5406 | /* Collapse range works only on fs block size aligned offsets. */ |
| 5406 | if (offset & (EXT4_BLOCK_SIZE(sb) - 1) || | 5407 | if (offset & (EXT4_CLUSTER_SIZE(sb) - 1) || |
| 5407 | len & (EXT4_BLOCK_SIZE(sb) - 1)) | 5408 | len & (EXT4_CLUSTER_SIZE(sb) - 1)) |
| 5408 | return -EINVAL; | 5409 | return -EINVAL; |
| 5409 | 5410 | ||
| 5410 | if (!S_ISREG(inode->i_mode)) | 5411 | if (!S_ISREG(inode->i_mode)) |
| 5411 | return -EINVAL; | 5412 | return -EINVAL; |
| 5412 | 5413 | ||
| 5413 | if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1) | ||
| 5414 | return -EOPNOTSUPP; | ||
| 5415 | |||
| 5416 | trace_ext4_collapse_range(inode, offset, len); | 5414 | trace_ext4_collapse_range(inode, offset, len); |
| 5417 | 5415 | ||
| 5418 | punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb); | 5416 | punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb); |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 8695f70af1ef..aca7b24a4432 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
| @@ -200,10 +200,6 @@ static const struct vm_operations_struct ext4_file_vm_ops = { | |||
| 200 | 200 | ||
| 201 | static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) | 201 | static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) |
| 202 | { | 202 | { |
| 203 | struct address_space *mapping = file->f_mapping; | ||
| 204 | |||
| 205 | if (!mapping->a_ops->readpage) | ||
| 206 | return -ENOEXEC; | ||
| 207 | file_accessed(file); | 203 | file_accessed(file); |
| 208 | vma->vm_ops = &ext4_file_vm_ops; | 204 | vma->vm_ops = &ext4_file_vm_ops; |
| 209 | return 0; | 205 | return 0; |
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index fd69da194826..e75f840000a0 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c | |||
| @@ -1295,97 +1295,220 @@ do_indirects: | |||
| 1295 | } | 1295 | } |
| 1296 | } | 1296 | } |
| 1297 | 1297 | ||
| 1298 | static int free_hole_blocks(handle_t *handle, struct inode *inode, | 1298 | /** |
| 1299 | struct buffer_head *parent_bh, __le32 *i_data, | 1299 | * ext4_ind_remove_space - remove space from the range |
| 1300 | int level, ext4_lblk_t first, | 1300 | * @handle: JBD handle for this transaction |
| 1301 | ext4_lblk_t count, int max) | 1301 | * @inode: inode we are dealing with |
| 1302 | * @start: First block to remove | ||
| 1303 | * @end: One block after the last block to remove (exclusive) | ||
| 1304 | * | ||
| 1305 | * Free the blocks in the defined range (end is exclusive endpoint of | ||
| 1306 | * range). This is used by ext4_punch_hole(). | ||
| 1307 | */ | ||
| 1308 | int ext4_ind_remove_space(handle_t *handle, struct inode *inode, | ||
| 1309 | ext4_lblk_t start, ext4_lblk_t end) | ||
| 1302 | { | 1310 | { |
| 1303 | struct buffer_head *bh = NULL; | 1311 | struct ext4_inode_info *ei = EXT4_I(inode); |
| 1312 | __le32 *i_data = ei->i_data; | ||
| 1304 | int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); | 1313 | int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); |
| 1305 | int ret = 0; | 1314 | ext4_lblk_t offsets[4], offsets2[4]; |
| 1306 | int i, inc; | 1315 | Indirect chain[4], chain2[4]; |
| 1307 | ext4_lblk_t offset; | 1316 | Indirect *partial, *partial2; |
| 1308 | __le32 blk; | 1317 | ext4_lblk_t max_block; |
| 1309 | 1318 | __le32 nr = 0, nr2 = 0; | |
| 1310 | inc = 1 << ((EXT4_BLOCK_SIZE_BITS(inode->i_sb) - 2) * level); | 1319 | int n = 0, n2 = 0; |
| 1311 | for (i = 0, offset = 0; i < max; i++, i_data++, offset += inc) { | 1320 | unsigned blocksize = inode->i_sb->s_blocksize; |
| 1312 | if (offset >= count + first) | ||
| 1313 | break; | ||
| 1314 | if (*i_data == 0 || (offset + inc) <= first) | ||
| 1315 | continue; | ||
| 1316 | blk = *i_data; | ||
| 1317 | if (level > 0) { | ||
| 1318 | ext4_lblk_t first2; | ||
| 1319 | ext4_lblk_t count2; | ||
| 1320 | 1321 | ||
| 1321 | bh = sb_bread(inode->i_sb, le32_to_cpu(blk)); | 1322 | max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1) |
| 1322 | if (!bh) { | 1323 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); |
| 1323 | EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk), | 1324 | if (end >= max_block) |
| 1324 | "Read failure"); | 1325 | end = max_block; |
| 1325 | return -EIO; | 1326 | if ((start >= end) || (start > max_block)) |
| 1326 | } | 1327 | return 0; |
| 1327 | if (first > offset) { | 1328 | |
| 1328 | first2 = first - offset; | 1329 | n = ext4_block_to_path(inode, start, offsets, NULL); |
| 1329 | count2 = count; | 1330 | n2 = ext4_block_to_path(inode, end, offsets2, NULL); |
| 1331 | |||
| 1332 | BUG_ON(n > n2); | ||
| 1333 | |||
| 1334 | if ((n == 1) && (n == n2)) { | ||
| 1335 | /* We're punching only within direct block range */ | ||
| 1336 | ext4_free_data(handle, inode, NULL, i_data + offsets[0], | ||
| 1337 | i_data + offsets2[0]); | ||
| 1338 | return 0; | ||
| 1339 | } else if (n2 > n) { | ||
| 1340 | /* | ||
| 1341 | * Start and end are on a different levels so we're going to | ||
| 1342 | * free partial block at start, and partial block at end of | ||
| 1343 | * the range. If there are some levels in between then | ||
| 1344 | * do_indirects label will take care of that. | ||
| 1345 | */ | ||
| 1346 | |||
| 1347 | if (n == 1) { | ||
| 1348 | /* | ||
| 1349 | * Start is at the direct block level, free | ||
| 1350 | * everything to the end of the level. | ||
| 1351 | */ | ||
| 1352 | ext4_free_data(handle, inode, NULL, i_data + offsets[0], | ||
| 1353 | i_data + EXT4_NDIR_BLOCKS); | ||
| 1354 | goto end_range; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | |||
| 1358 | partial = ext4_find_shared(inode, n, offsets, chain, &nr); | ||
| 1359 | if (nr) { | ||
| 1360 | if (partial == chain) { | ||
| 1361 | /* Shared branch grows from the inode */ | ||
| 1362 | ext4_free_branches(handle, inode, NULL, | ||
| 1363 | &nr, &nr+1, (chain+n-1) - partial); | ||
| 1364 | *partial->p = 0; | ||
| 1330 | } else { | 1365 | } else { |
| 1331 | first2 = 0; | 1366 | /* Shared branch grows from an indirect block */ |
| 1332 | count2 = count - (offset - first); | 1367 | BUFFER_TRACE(partial->bh, "get_write_access"); |
| 1368 | ext4_free_branches(handle, inode, partial->bh, | ||
| 1369 | partial->p, | ||
| 1370 | partial->p+1, (chain+n-1) - partial); | ||
| 1333 | } | 1371 | } |
| 1334 | ret = free_hole_blocks(handle, inode, bh, | 1372 | } |
| 1335 | (__le32 *)bh->b_data, level - 1, | 1373 | |
| 1336 | first2, count2, | 1374 | /* |
| 1337 | inode->i_sb->s_blocksize >> 2); | 1375 | * Clear the ends of indirect blocks on the shared branch |
| 1338 | if (ret) { | 1376 | * at the start of the range |
| 1339 | brelse(bh); | 1377 | */ |
| 1340 | goto err; | 1378 | while (partial > chain) { |
| 1379 | ext4_free_branches(handle, inode, partial->bh, | ||
| 1380 | partial->p + 1, | ||
| 1381 | (__le32 *)partial->bh->b_data+addr_per_block, | ||
| 1382 | (chain+n-1) - partial); | ||
| 1383 | BUFFER_TRACE(partial->bh, "call brelse"); | ||
| 1384 | brelse(partial->bh); | ||
| 1385 | partial--; | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | end_range: | ||
| 1389 | partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); | ||
| 1390 | if (nr2) { | ||
| 1391 | if (partial2 == chain2) { | ||
| 1392 | /* | ||
| 1393 | * Remember, end is exclusive so here we're at | ||
| 1394 | * the start of the next level we're not going | ||
| 1395 | * to free. Everything was covered by the start | ||
| 1396 | * of the range. | ||
| 1397 | */ | ||
| 1398 | return 0; | ||
| 1399 | } else { | ||
| 1400 | /* Shared branch grows from an indirect block */ | ||
| 1401 | partial2--; | ||
| 1341 | } | 1402 | } |
| 1403 | } else { | ||
| 1404 | /* | ||
| 1405 | * ext4_find_shared returns Indirect structure which | ||
| 1406 | * points to the last element which should not be | ||
| 1407 | * removed by truncate. But this is end of the range | ||
| 1408 | * in punch_hole so we need to point to the next element | ||
| 1409 | */ | ||
| 1410 | partial2->p++; | ||
| 1342 | } | 1411 | } |
| 1343 | if (level == 0 || | 1412 | |
| 1344 | (bh && all_zeroes((__le32 *)bh->b_data, | 1413 | /* |
| 1345 | (__le32 *)bh->b_data + addr_per_block))) { | 1414 | * Clear the ends of indirect blocks on the shared branch |
| 1346 | ext4_free_data(handle, inode, parent_bh, | 1415 | * at the end of the range |
| 1347 | i_data, i_data + 1); | 1416 | */ |
| 1417 | while (partial2 > chain2) { | ||
| 1418 | ext4_free_branches(handle, inode, partial2->bh, | ||
| 1419 | (__le32 *)partial2->bh->b_data, | ||
| 1420 | partial2->p, | ||
| 1421 | (chain2+n2-1) - partial2); | ||
| 1422 | BUFFER_TRACE(partial2->bh, "call brelse"); | ||
| 1423 | brelse(partial2->bh); | ||
| 1424 | partial2--; | ||
| 1348 | } | 1425 | } |
| 1349 | brelse(bh); | 1426 | goto do_indirects; |
| 1350 | bh = NULL; | ||
| 1351 | } | 1427 | } |
| 1352 | 1428 | ||
| 1353 | err: | 1429 | /* Punch happened within the same level (n == n2) */ |
| 1354 | return ret; | 1430 | partial = ext4_find_shared(inode, n, offsets, chain, &nr); |
| 1355 | } | 1431 | partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); |
| 1356 | 1432 | /* | |
| 1357 | int ext4_free_hole_blocks(handle_t *handle, struct inode *inode, | 1433 | * ext4_find_shared returns Indirect structure which |
| 1358 | ext4_lblk_t first, ext4_lblk_t stop) | 1434 | * points to the last element which should not be |
| 1359 | { | 1435 | * removed by truncate. But this is end of the range |
| 1360 | int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); | 1436 | * in punch_hole so we need to point to the next element |
| 1361 | int level, ret = 0; | 1437 | */ |
| 1362 | int num = EXT4_NDIR_BLOCKS; | 1438 | partial2->p++; |
| 1363 | ext4_lblk_t count, max = EXT4_NDIR_BLOCKS; | 1439 | while ((partial > chain) || (partial2 > chain2)) { |
| 1364 | __le32 *i_data = EXT4_I(inode)->i_data; | 1440 | /* We're at the same block, so we're almost finished */ |
| 1365 | 1441 | if ((partial->bh && partial2->bh) && | |
| 1366 | count = stop - first; | 1442 | (partial->bh->b_blocknr == partial2->bh->b_blocknr)) { |
| 1367 | for (level = 0; level < 4; level++, max *= addr_per_block) { | 1443 | if ((partial > chain) && (partial2 > chain2)) { |
| 1368 | if (first < max) { | 1444 | ext4_free_branches(handle, inode, partial->bh, |
| 1369 | ret = free_hole_blocks(handle, inode, NULL, i_data, | 1445 | partial->p + 1, |
| 1370 | level, first, count, num); | 1446 | partial2->p, |
| 1371 | if (ret) | 1447 | (chain+n-1) - partial); |
| 1372 | goto err; | 1448 | BUFFER_TRACE(partial->bh, "call brelse"); |
| 1373 | if (count > max - first) | 1449 | brelse(partial->bh); |
| 1374 | count -= max - first; | 1450 | BUFFER_TRACE(partial2->bh, "call brelse"); |
| 1375 | else | 1451 | brelse(partial2->bh); |
| 1376 | break; | 1452 | } |
| 1377 | first = 0; | 1453 | return 0; |
| 1378 | } else { | ||
| 1379 | first -= max; | ||
| 1380 | } | 1454 | } |
| 1381 | i_data += num; | 1455 | /* |
| 1382 | if (level == 0) { | 1456 | * Clear the ends of indirect blocks on the shared branch |
| 1383 | num = 1; | 1457 | * at the start of the range |
| 1384 | max = 1; | 1458 | */ |
| 1459 | if (partial > chain) { | ||
| 1460 | ext4_free_branches(handle, inode, partial->bh, | ||
| 1461 | partial->p + 1, | ||
| 1462 | (__le32 *)partial->bh->b_data+addr_per_block, | ||
| 1463 | (chain+n-1) - partial); | ||
| 1464 | BUFFER_TRACE(partial->bh, "call brelse"); | ||
| 1465 | brelse(partial->bh); | ||
| 1466 | partial--; | ||
| 1467 | } | ||
| 1468 | /* | ||
| 1469 | * Clear the ends of indirect blocks on the shared branch | ||
| 1470 | * at the end of the range | ||
| 1471 | */ | ||
| 1472 | if (partial2 > chain2) { | ||
| 1473 | ext4_free_branches(handle, inode, partial2->bh, | ||
| 1474 | (__le32 *)partial2->bh->b_data, | ||
| 1475 | partial2->p, | ||
| 1476 | (chain2+n-1) - partial2); | ||
| 1477 | BUFFER_TRACE(partial2->bh, "call brelse"); | ||
| 1478 | brelse(partial2->bh); | ||
| 1479 | partial2--; | ||
| 1385 | } | 1480 | } |
| 1386 | } | 1481 | } |
| 1387 | 1482 | ||
| 1388 | err: | 1483 | do_indirects: |
| 1389 | return ret; | 1484 | /* Kill the remaining (whole) subtrees */ |
| 1485 | switch (offsets[0]) { | ||
| 1486 | default: | ||
| 1487 | if (++n >= n2) | ||
| 1488 | return 0; | ||
| 1489 | nr = i_data[EXT4_IND_BLOCK]; | ||
| 1490 | if (nr) { | ||
| 1491 | ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1); | ||
| 1492 | i_data[EXT4_IND_BLOCK] = 0; | ||
| 1493 | } | ||
| 1494 | case EXT4_IND_BLOCK: | ||
| 1495 | if (++n >= n2) | ||
| 1496 | return 0; | ||
| 1497 | nr = i_data[EXT4_DIND_BLOCK]; | ||
| 1498 | if (nr) { | ||
| 1499 | ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2); | ||
| 1500 | i_data[EXT4_DIND_BLOCK] = 0; | ||
| 1501 | } | ||
| 1502 | case EXT4_DIND_BLOCK: | ||
| 1503 | if (++n >= n2) | ||
| 1504 | return 0; | ||
| 1505 | nr = i_data[EXT4_TIND_BLOCK]; | ||
| 1506 | if (nr) { | ||
| 1507 | ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3); | ||
| 1508 | i_data[EXT4_TIND_BLOCK] = 0; | ||
| 1509 | } | ||
| 1510 | case EXT4_TIND_BLOCK: | ||
| 1511 | ; | ||
| 1512 | } | ||
| 1513 | return 0; | ||
| 1390 | } | 1514 | } |
| 1391 | |||
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 645205d8ada6..bea662bd0ca6 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
| @@ -120,12 +120,6 @@ int ext4_get_max_inline_size(struct inode *inode) | |||
| 120 | return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE; | 120 | return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | int ext4_has_inline_data(struct inode *inode) | ||
| 124 | { | ||
| 125 | return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) && | ||
| 126 | EXT4_I(inode)->i_inline_off; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | 123 | /* |
| 130 | * this function does not take xattr_sem, which is OK because it is | 124 | * this function does not take xattr_sem, which is OK because it is |
| 131 | * currently only used in a code path coming form ext4_iget, before | 125 | * currently only used in a code path coming form ext4_iget, before |
| @@ -1178,6 +1172,18 @@ static int ext4_convert_inline_data_nolock(handle_t *handle, | |||
| 1178 | if (error < 0) | 1172 | if (error < 0) |
| 1179 | goto out; | 1173 | goto out; |
| 1180 | 1174 | ||
| 1175 | /* | ||
| 1176 | * Make sure the inline directory entries pass checks before we try to | ||
| 1177 | * convert them, so that we avoid touching stuff that needs fsck. | ||
| 1178 | */ | ||
| 1179 | if (S_ISDIR(inode->i_mode)) { | ||
| 1180 | error = ext4_check_all_de(inode, iloc->bh, | ||
| 1181 | buf + EXT4_INLINE_DOTDOT_SIZE, | ||
| 1182 | inline_size - EXT4_INLINE_DOTDOT_SIZE); | ||
| 1183 | if (error) | ||
| 1184 | goto out; | ||
| 1185 | } | ||
| 1186 | |||
| 1181 | error = ext4_destroy_inline_data_nolock(handle, inode); | 1187 | error = ext4_destroy_inline_data_nolock(handle, inode); |
| 1182 | if (error) | 1188 | if (error) |
| 1183 | goto out; | 1189 | goto out; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8a064734e6eb..367a60c07cf0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -325,18 +325,6 @@ qsize_t *ext4_get_reserved_space(struct inode *inode) | |||
| 325 | #endif | 325 | #endif |
| 326 | 326 | ||
| 327 | /* | 327 | /* |
| 328 | * Calculate the number of metadata blocks need to reserve | ||
| 329 | * to allocate a block located at @lblock | ||
| 330 | */ | ||
| 331 | static int ext4_calc_metadata_amount(struct inode *inode, ext4_lblk_t lblock) | ||
| 332 | { | ||
| 333 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) | ||
| 334 | return ext4_ext_calc_metadata_amount(inode, lblock); | ||
| 335 | |||
| 336 | return ext4_ind_calc_metadata_amount(inode, lblock); | ||
| 337 | } | ||
| 338 | |||
| 339 | /* | ||
| 340 | * Called with i_data_sem down, which is important since we can call | 328 | * Called with i_data_sem down, which is important since we can call |
| 341 | * ext4_discard_preallocations() from here. | 329 | * ext4_discard_preallocations() from here. |
| 342 | */ | 330 | */ |
| @@ -357,35 +345,10 @@ void ext4_da_update_reserve_space(struct inode *inode, | |||
| 357 | used = ei->i_reserved_data_blocks; | 345 | used = ei->i_reserved_data_blocks; |
| 358 | } | 346 | } |
| 359 | 347 | ||
| 360 | if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) { | ||
| 361 | ext4_warning(inode->i_sb, "ino %lu, allocated %d " | ||
| 362 | "with only %d reserved metadata blocks " | ||
| 363 | "(releasing %d blocks with reserved %d data blocks)", | ||
| 364 | inode->i_ino, ei->i_allocated_meta_blocks, | ||
| 365 | ei->i_reserved_meta_blocks, used, | ||
| 366 | ei->i_reserved_data_blocks); | ||
| 367 | WARN_ON(1); | ||
| 368 | ei->i_allocated_meta_blocks = ei->i_reserved_meta_blocks; | ||
| 369 | } | ||
| 370 | |||
| 371 | /* Update per-inode reservations */ | 348 | /* Update per-inode reservations */ |
| 372 | ei->i_reserved_data_blocks -= used; | 349 | ei->i_reserved_data_blocks -= used; |
| 373 | ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks; | 350 | percpu_counter_sub(&sbi->s_dirtyclusters_counter, used); |
| 374 | percpu_counter_sub(&sbi->s_dirtyclusters_counter, | ||
| 375 | used + ei->i_allocated_meta_blocks); | ||
| 376 | ei->i_allocated_meta_blocks = 0; | ||
| 377 | 351 | ||
| 378 | if (ei->i_reserved_data_blocks == 0) { | ||
| 379 | /* | ||
| 380 | * We can release all of the reserved metadata blocks | ||
| 381 | * only when we have written all of the delayed | ||
| 382 | * allocation blocks. | ||
| 383 | */ | ||
| 384 | percpu_counter_sub(&sbi->s_dirtyclusters_counter, | ||
| 385 | ei->i_reserved_meta_blocks); | ||
| 386 | ei->i_reserved_meta_blocks = 0; | ||
| 387 | ei->i_da_metadata_calc_len = 0; | ||
| 388 | } | ||
| 389 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 352 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
| 390 | 353 | ||
| 391 | /* Update quota subsystem for data blocks */ | 354 | /* Update quota subsystem for data blocks */ |
| @@ -1222,49 +1185,6 @@ static int ext4_journalled_write_end(struct file *file, | |||
| 1222 | } | 1185 | } |
| 1223 | 1186 | ||
| 1224 | /* | 1187 | /* |
| 1225 | * Reserve a metadata for a single block located at lblock | ||
| 1226 | */ | ||
| 1227 | static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock) | ||
| 1228 | { | ||
| 1229 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
| 1230 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
| 1231 | unsigned int md_needed; | ||
| 1232 | ext4_lblk_t save_last_lblock; | ||
| 1233 | int save_len; | ||
| 1234 | |||
| 1235 | /* | ||
| 1236 | * recalculate the amount of metadata blocks to reserve | ||
| 1237 | * in order to allocate nrblocks | ||
| 1238 | * worse case is one extent per block | ||
| 1239 | */ | ||
| 1240 | spin_lock(&ei->i_block_reservation_lock); | ||
| 1241 | /* | ||
| 1242 | * ext4_calc_metadata_amount() has side effects, which we have | ||
| 1243 | * to be prepared undo if we fail to claim space. | ||
| 1244 | */ | ||
| 1245 | save_len = ei->i_da_metadata_calc_len; | ||
| 1246 | save_last_lblock = ei->i_da_metadata_calc_last_lblock; | ||
| 1247 | md_needed = EXT4_NUM_B2C(sbi, | ||
| 1248 | ext4_calc_metadata_amount(inode, lblock)); | ||
| 1249 | trace_ext4_da_reserve_space(inode, md_needed); | ||
| 1250 | |||
| 1251 | /* | ||
| 1252 | * We do still charge estimated metadata to the sb though; | ||
| 1253 | * we cannot afford to run out of free blocks. | ||
| 1254 | */ | ||
| 1255 | if (ext4_claim_free_clusters(sbi, md_needed, 0)) { | ||
| 1256 | ei->i_da_metadata_calc_len = save_len; | ||
| 1257 | ei->i_da_metadata_calc_last_lblock = save_last_lblock; | ||
| 1258 | spin_unlock(&ei->i_block_reservation_lock); | ||
| 1259 | return -ENOSPC; | ||
| 1260 | } | ||
| 1261 | ei->i_reserved_meta_blocks += md_needed; | ||
| 1262 | spin_unlock(&ei->i_block_reservation_lock); | ||
| 1263 | |||
| 1264 | return 0; /* success */ | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | /* | ||
| 1268 | * Reserve a single cluster located at lblock | 1188 | * Reserve a single cluster located at lblock |
| 1269 | */ | 1189 | */ |
| 1270 | static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) | 1190 | static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) |
| @@ -1273,8 +1193,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) | |||
| 1273 | struct ext4_inode_info *ei = EXT4_I(inode); | 1193 | struct ext4_inode_info *ei = EXT4_I(inode); |
| 1274 | unsigned int md_needed; | 1194 | unsigned int md_needed; |
| 1275 | int ret; | 1195 | int ret; |
| 1276 | ext4_lblk_t save_last_lblock; | ||
| 1277 | int save_len; | ||
| 1278 | 1196 | ||
| 1279 | /* | 1197 | /* |
| 1280 | * We will charge metadata quota at writeout time; this saves | 1198 | * We will charge metadata quota at writeout time; this saves |
| @@ -1295,25 +1213,15 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) | |||
| 1295 | * ext4_calc_metadata_amount() has side effects, which we have | 1213 | * ext4_calc_metadata_amount() has side effects, which we have |
| 1296 | * to be prepared undo if we fail to claim space. | 1214 | * to be prepared undo if we fail to claim space. |
| 1297 | */ | 1215 | */ |
| 1298 | save_len = ei->i_da_metadata_calc_len; | 1216 | md_needed = 0; |
| 1299 | save_last_lblock = ei->i_da_metadata_calc_last_lblock; | 1217 | trace_ext4_da_reserve_space(inode, 0); |
| 1300 | md_needed = EXT4_NUM_B2C(sbi, | ||
| 1301 | ext4_calc_metadata_amount(inode, lblock)); | ||
| 1302 | trace_ext4_da_reserve_space(inode, md_needed); | ||
| 1303 | 1218 | ||
| 1304 | /* | 1219 | if (ext4_claim_free_clusters(sbi, 1, 0)) { |
| 1305 | * We do still charge estimated metadata to the sb though; | ||
| 1306 | * we cannot afford to run out of free blocks. | ||
| 1307 | */ | ||
| 1308 | if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) { | ||
| 1309 | ei->i_da_metadata_calc_len = save_len; | ||
| 1310 | ei->i_da_metadata_calc_last_lblock = save_last_lblock; | ||
| 1311 | spin_unlock(&ei->i_block_reservation_lock); | 1220 | spin_unlock(&ei->i_block_reservation_lock); |
| 1312 | dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); | 1221 | dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); |
| 1313 | return -ENOSPC; | 1222 | return -ENOSPC; |
| 1314 | } | 1223 | } |
| 1315 | ei->i_reserved_data_blocks++; | 1224 | ei->i_reserved_data_blocks++; |
| 1316 | ei->i_reserved_meta_blocks += md_needed; | ||
| 1317 | spin_unlock(&ei->i_block_reservation_lock); | 1225 | spin_unlock(&ei->i_block_reservation_lock); |
| 1318 | 1226 | ||
| 1319 | return 0; /* success */ | 1227 | return 0; /* success */ |
| @@ -1346,20 +1254,6 @@ static void ext4_da_release_space(struct inode *inode, int to_free) | |||
| 1346 | } | 1254 | } |
| 1347 | ei->i_reserved_data_blocks -= to_free; | 1255 | ei->i_reserved_data_blocks -= to_free; |
| 1348 | 1256 | ||
| 1349 | if (ei->i_reserved_data_blocks == 0) { | ||
| 1350 | /* | ||
| 1351 | * We can release all of the reserved metadata blocks | ||
| 1352 | * only when we have written all of the delayed | ||
| 1353 | * allocation blocks. | ||
| 1354 | * Note that in case of bigalloc, i_reserved_meta_blocks, | ||
| 1355 | * i_reserved_data_blocks, etc. refer to number of clusters. | ||
| 1356 | */ | ||
| 1357 | percpu_counter_sub(&sbi->s_dirtyclusters_counter, | ||
| 1358 | ei->i_reserved_meta_blocks); | ||
| 1359 | ei->i_reserved_meta_blocks = 0; | ||
| 1360 | ei->i_da_metadata_calc_len = 0; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | /* update fs dirty data blocks counter */ | 1257 | /* update fs dirty data blocks counter */ |
| 1364 | percpu_counter_sub(&sbi->s_dirtyclusters_counter, to_free); | 1258 | percpu_counter_sub(&sbi->s_dirtyclusters_counter, to_free); |
| 1365 | 1259 | ||
| @@ -1500,10 +1394,6 @@ static void ext4_print_free_blocks(struct inode *inode) | |||
| 1500 | ext4_msg(sb, KERN_CRIT, "Block reservation details"); | 1394 | ext4_msg(sb, KERN_CRIT, "Block reservation details"); |
| 1501 | ext4_msg(sb, KERN_CRIT, "i_reserved_data_blocks=%u", | 1395 | ext4_msg(sb, KERN_CRIT, "i_reserved_data_blocks=%u", |
| 1502 | ei->i_reserved_data_blocks); | 1396 | ei->i_reserved_data_blocks); |
| 1503 | ext4_msg(sb, KERN_CRIT, "i_reserved_meta_blocks=%u", | ||
| 1504 | ei->i_reserved_meta_blocks); | ||
| 1505 | ext4_msg(sb, KERN_CRIT, "i_allocated_meta_blocks=%u", | ||
| 1506 | ei->i_allocated_meta_blocks); | ||
| 1507 | return; | 1397 | return; |
| 1508 | } | 1398 | } |
| 1509 | 1399 | ||
| @@ -1620,13 +1510,6 @@ add_delayed: | |||
| 1620 | retval = ret; | 1510 | retval = ret; |
| 1621 | goto out_unlock; | 1511 | goto out_unlock; |
| 1622 | } | 1512 | } |
| 1623 | } else { | ||
| 1624 | ret = ext4_da_reserve_metadata(inode, iblock); | ||
| 1625 | if (ret) { | ||
| 1626 | /* not enough space to reserve */ | ||
| 1627 | retval = ret; | ||
| 1628 | goto out_unlock; | ||
| 1629 | } | ||
| 1630 | } | 1513 | } |
| 1631 | 1514 | ||
| 1632 | ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, | 1515 | ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, |
| @@ -2843,8 +2726,7 @@ int ext4_alloc_da_blocks(struct inode *inode) | |||
| 2843 | { | 2726 | { |
| 2844 | trace_ext4_alloc_da_blocks(inode); | 2727 | trace_ext4_alloc_da_blocks(inode); |
| 2845 | 2728 | ||
| 2846 | if (!EXT4_I(inode)->i_reserved_data_blocks && | 2729 | if (!EXT4_I(inode)->i_reserved_data_blocks) |
| 2847 | !EXT4_I(inode)->i_reserved_meta_blocks) | ||
| 2848 | return 0; | 2730 | return 0; |
| 2849 | 2731 | ||
| 2850 | /* | 2732 | /* |
| @@ -3624,7 +3506,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) | |||
| 3624 | ret = ext4_ext_remove_space(inode, first_block, | 3506 | ret = ext4_ext_remove_space(inode, first_block, |
| 3625 | stop_block - 1); | 3507 | stop_block - 1); |
| 3626 | else | 3508 | else |
| 3627 | ret = ext4_free_hole_blocks(handle, inode, first_block, | 3509 | ret = ext4_ind_remove_space(handle, inode, first_block, |
| 3628 | stop_block); | 3510 | stop_block); |
| 3629 | 3511 | ||
| 3630 | up_write(&EXT4_I(inode)->i_data_sem); | 3512 | up_write(&EXT4_I(inode)->i_data_sem); |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 2dcb936be90e..956027711faf 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -3075,8 +3075,9 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
| 3075 | (23 - bsbits)) << 23; | 3075 | (23 - bsbits)) << 23; |
| 3076 | size = 8 * 1024 * 1024; | 3076 | size = 8 * 1024 * 1024; |
| 3077 | } else { | 3077 | } else { |
| 3078 | start_off = (loff_t)ac->ac_o_ex.fe_logical << bsbits; | 3078 | start_off = (loff_t) ac->ac_o_ex.fe_logical << bsbits; |
| 3079 | size = ac->ac_o_ex.fe_len << bsbits; | 3079 | size = (loff_t) EXT4_C2B(EXT4_SB(ac->ac_sb), |
| 3080 | ac->ac_o_ex.fe_len) << bsbits; | ||
| 3080 | } | 3081 | } |
| 3081 | size = size >> bsbits; | 3082 | size = size >> bsbits; |
| 3082 | start = start_off >> bsbits; | 3083 | start = start_off >> bsbits; |
| @@ -3216,8 +3217,27 @@ static void ext4_mb_collect_stats(struct ext4_allocation_context *ac) | |||
| 3216 | static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac) | 3217 | static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac) |
| 3217 | { | 3218 | { |
| 3218 | struct ext4_prealloc_space *pa = ac->ac_pa; | 3219 | struct ext4_prealloc_space *pa = ac->ac_pa; |
| 3220 | struct ext4_buddy e4b; | ||
| 3221 | int err; | ||
| 3219 | 3222 | ||
| 3220 | if (pa && pa->pa_type == MB_INODE_PA) | 3223 | if (pa == NULL) { |
| 3224 | err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b); | ||
| 3225 | if (err) { | ||
| 3226 | /* | ||
| 3227 | * This should never happen since we pin the | ||
| 3228 | * pages in the ext4_allocation_context so | ||
| 3229 | * ext4_mb_load_buddy() should never fail. | ||
| 3230 | */ | ||
| 3231 | WARN(1, "mb_load_buddy failed (%d)", err); | ||
| 3232 | return; | ||
| 3233 | } | ||
| 3234 | ext4_lock_group(ac->ac_sb, ac->ac_f_ex.fe_group); | ||
| 3235 | mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start, | ||
| 3236 | ac->ac_f_ex.fe_len); | ||
| 3237 | ext4_unlock_group(ac->ac_sb, ac->ac_f_ex.fe_group); | ||
| 3238 | return; | ||
| 3239 | } | ||
| 3240 | if (pa->pa_type == MB_INODE_PA) | ||
| 3221 | pa->pa_free += ac->ac_b_ex.fe_len; | 3241 | pa->pa_free += ac->ac_b_ex.fe_len; |
| 3222 | } | 3242 | } |
| 3223 | 3243 | ||
| @@ -4627,7 +4647,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
| 4627 | struct buffer_head *gd_bh; | 4647 | struct buffer_head *gd_bh; |
| 4628 | ext4_group_t block_group; | 4648 | ext4_group_t block_group; |
| 4629 | struct ext4_sb_info *sbi; | 4649 | struct ext4_sb_info *sbi; |
| 4630 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
| 4631 | struct ext4_buddy e4b; | 4650 | struct ext4_buddy e4b; |
| 4632 | unsigned int count_clusters; | 4651 | unsigned int count_clusters; |
| 4633 | int err = 0; | 4652 | int err = 0; |
| @@ -4838,19 +4857,7 @@ do_more: | |||
| 4838 | &sbi->s_flex_groups[flex_group].free_clusters); | 4857 | &sbi->s_flex_groups[flex_group].free_clusters); |
| 4839 | } | 4858 | } |
| 4840 | 4859 | ||
| 4841 | if (flags & EXT4_FREE_BLOCKS_RESERVE && ei->i_reserved_data_blocks) { | 4860 | if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE)) |
| 4842 | percpu_counter_add(&sbi->s_dirtyclusters_counter, | ||
| 4843 | count_clusters); | ||
| 4844 | spin_lock(&ei->i_block_reservation_lock); | ||
| 4845 | if (flags & EXT4_FREE_BLOCKS_METADATA) | ||
| 4846 | ei->i_reserved_meta_blocks += count_clusters; | ||
| 4847 | else | ||
| 4848 | ei->i_reserved_data_blocks += count_clusters; | ||
| 4849 | spin_unlock(&ei->i_block_reservation_lock); | ||
| 4850 | if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE)) | ||
| 4851 | dquot_reclaim_block(inode, | ||
| 4852 | EXT4_C2B(sbi, count_clusters)); | ||
| 4853 | } else if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE)) | ||
| 4854 | dquot_free_block(inode, EXT4_C2B(sbi, count_clusters)); | 4861 | dquot_free_block(inode, EXT4_C2B(sbi, count_clusters)); |
| 4855 | percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); | 4862 | percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); |
| 4856 | 4863 | ||
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index ec092437d3e0..d3567f27bae7 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c | |||
| @@ -39,6 +39,8 @@ static int finish_range(handle_t *handle, struct inode *inode, | |||
| 39 | newext.ee_block = cpu_to_le32(lb->first_block); | 39 | newext.ee_block = cpu_to_le32(lb->first_block); |
| 40 | newext.ee_len = cpu_to_le16(lb->last_block - lb->first_block + 1); | 40 | newext.ee_len = cpu_to_le16(lb->last_block - lb->first_block + 1); |
| 41 | ext4_ext_store_pblock(&newext, lb->first_pblock); | 41 | ext4_ext_store_pblock(&newext, lb->first_pblock); |
| 42 | /* Locking only for convinience since we are operating on temp inode */ | ||
| 43 | down_write(&EXT4_I(inode)->i_data_sem); | ||
| 42 | path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0); | 44 | path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0); |
| 43 | 45 | ||
| 44 | if (IS_ERR(path)) { | 46 | if (IS_ERR(path)) { |
| @@ -61,7 +63,9 @@ static int finish_range(handle_t *handle, struct inode *inode, | |||
| 61 | */ | 63 | */ |
| 62 | if (needed && ext4_handle_has_enough_credits(handle, | 64 | if (needed && ext4_handle_has_enough_credits(handle, |
| 63 | EXT4_RESERVE_TRANS_BLOCKS)) { | 65 | EXT4_RESERVE_TRANS_BLOCKS)) { |
| 66 | up_write((&EXT4_I(inode)->i_data_sem)); | ||
| 64 | retval = ext4_journal_restart(handle, needed); | 67 | retval = ext4_journal_restart(handle, needed); |
| 68 | down_write((&EXT4_I(inode)->i_data_sem)); | ||
| 65 | if (retval) | 69 | if (retval) |
| 66 | goto err_out; | 70 | goto err_out; |
| 67 | } else if (needed) { | 71 | } else if (needed) { |
| @@ -70,13 +74,16 @@ static int finish_range(handle_t *handle, struct inode *inode, | |||
| 70 | /* | 74 | /* |
| 71 | * IF not able to extend the journal restart the journal | 75 | * IF not able to extend the journal restart the journal |
| 72 | */ | 76 | */ |
| 77 | up_write((&EXT4_I(inode)->i_data_sem)); | ||
| 73 | retval = ext4_journal_restart(handle, needed); | 78 | retval = ext4_journal_restart(handle, needed); |
| 79 | down_write((&EXT4_I(inode)->i_data_sem)); | ||
| 74 | if (retval) | 80 | if (retval) |
| 75 | goto err_out; | 81 | goto err_out; |
| 76 | } | 82 | } |
| 77 | } | 83 | } |
| 78 | retval = ext4_ext_insert_extent(handle, inode, path, &newext, 0); | 84 | retval = ext4_ext_insert_extent(handle, inode, path, &newext, 0); |
| 79 | err_out: | 85 | err_out: |
| 86 | up_write((&EXT4_I(inode)->i_data_sem)); | ||
| 80 | if (path) { | 87 | if (path) { |
| 81 | ext4_ext_drop_refs(path); | 88 | ext4_ext_drop_refs(path); |
| 82 | kfree(path); | 89 | kfree(path); |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 2484c7ec6a72..671a74b14fd7 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
| @@ -1013,10 +1013,11 @@ data_copy: | |||
| 1013 | *err = -EBUSY; | 1013 | *err = -EBUSY; |
| 1014 | goto unlock_pages; | 1014 | goto unlock_pages; |
| 1015 | } | 1015 | } |
| 1016 | 1016 | ext4_double_down_write_data_sem(orig_inode, donor_inode); | |
| 1017 | replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, | 1017 | replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, |
| 1018 | orig_blk_offset, | 1018 | orig_blk_offset, |
| 1019 | block_len_in_page, err); | 1019 | block_len_in_page, err); |
| 1020 | ext4_double_up_write_data_sem(orig_inode, donor_inode); | ||
| 1020 | if (*err) { | 1021 | if (*err) { |
| 1021 | if (replaced_count) { | 1022 | if (replaced_count) { |
| 1022 | block_len_in_page = replaced_count; | 1023 | block_len_in_page = replaced_count; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 6df7bc611dbd..32b43ad154b9 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -2142,10 +2142,6 @@ static int ext4_check_descriptors(struct super_block *sb, | |||
| 2142 | } | 2142 | } |
| 2143 | if (NULL != first_not_zeroed) | 2143 | if (NULL != first_not_zeroed) |
| 2144 | *first_not_zeroed = grp; | 2144 | *first_not_zeroed = grp; |
| 2145 | |||
| 2146 | ext4_free_blocks_count_set(sbi->s_es, | ||
| 2147 | EXT4_C2B(sbi, ext4_count_free_clusters(sb))); | ||
| 2148 | sbi->s_es->s_free_inodes_count =cpu_to_le32(ext4_count_free_inodes(sb)); | ||
| 2149 | return 1; | 2145 | return 1; |
| 2150 | } | 2146 | } |
| 2151 | 2147 | ||
| @@ -3883,13 +3879,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3883 | ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); | 3879 | ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); |
| 3884 | goto failed_mount2; | 3880 | goto failed_mount2; |
| 3885 | } | 3881 | } |
| 3886 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | ||
| 3887 | if (!ext4_fill_flex_info(sb)) { | ||
| 3888 | ext4_msg(sb, KERN_ERR, | ||
| 3889 | "unable to initialize " | ||
| 3890 | "flex_bg meta info!"); | ||
| 3891 | goto failed_mount2; | ||
| 3892 | } | ||
| 3893 | 3882 | ||
| 3894 | sbi->s_gdb_count = db_count; | 3883 | sbi->s_gdb_count = db_count; |
| 3895 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 3884 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
| @@ -3902,23 +3891,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3902 | /* Register extent status tree shrinker */ | 3891 | /* Register extent status tree shrinker */ |
| 3903 | ext4_es_register_shrinker(sbi); | 3892 | ext4_es_register_shrinker(sbi); |
| 3904 | 3893 | ||
| 3905 | err = percpu_counter_init(&sbi->s_freeclusters_counter, | 3894 | if ((err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0)) != 0) { |
| 3906 | ext4_count_free_clusters(sb)); | ||
| 3907 | if (!err) { | ||
| 3908 | err = percpu_counter_init(&sbi->s_freeinodes_counter, | ||
| 3909 | ext4_count_free_inodes(sb)); | ||
| 3910 | } | ||
| 3911 | if (!err) { | ||
| 3912 | err = percpu_counter_init(&sbi->s_dirs_counter, | ||
| 3913 | ext4_count_dirs(sb)); | ||
| 3914 | } | ||
| 3915 | if (!err) { | ||
| 3916 | err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0); | ||
| 3917 | } | ||
| 3918 | if (!err) { | ||
| 3919 | err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0); | ||
| 3920 | } | ||
| 3921 | if (err) { | ||
| 3922 | ext4_msg(sb, KERN_ERR, "insufficient memory"); | 3895 | ext4_msg(sb, KERN_ERR, "insufficient memory"); |
| 3923 | goto failed_mount3; | 3896 | goto failed_mount3; |
| 3924 | } | 3897 | } |
| @@ -4022,18 +3995,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 4022 | 3995 | ||
| 4023 | sbi->s_journal->j_commit_callback = ext4_journal_commit_callback; | 3996 | sbi->s_journal->j_commit_callback = ext4_journal_commit_callback; |
| 4024 | 3997 | ||
| 4025 | /* | ||
| 4026 | * The journal may have updated the bg summary counts, so we | ||
| 4027 | * need to update the global counters. | ||
| 4028 | */ | ||
| 4029 | percpu_counter_set(&sbi->s_freeclusters_counter, | ||
| 4030 | ext4_count_free_clusters(sb)); | ||
| 4031 | percpu_counter_set(&sbi->s_freeinodes_counter, | ||
| 4032 | ext4_count_free_inodes(sb)); | ||
| 4033 | percpu_counter_set(&sbi->s_dirs_counter, | ||
| 4034 | ext4_count_dirs(sb)); | ||
| 4035 | percpu_counter_set(&sbi->s_dirtyclusters_counter, 0); | ||
| 4036 | |||
| 4037 | no_journal: | 3998 | no_journal: |
| 4038 | if (ext4_mballoc_ready) { | 3999 | if (ext4_mballoc_ready) { |
| 4039 | sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id); | 4000 | sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id); |
| @@ -4141,6 +4102,33 @@ no_journal: | |||
| 4141 | goto failed_mount5; | 4102 | goto failed_mount5; |
| 4142 | } | 4103 | } |
| 4143 | 4104 | ||
| 4105 | block = ext4_count_free_clusters(sb); | ||
| 4106 | ext4_free_blocks_count_set(sbi->s_es, | ||
| 4107 | EXT4_C2B(sbi, block)); | ||
| 4108 | err = percpu_counter_init(&sbi->s_freeclusters_counter, block); | ||
| 4109 | if (!err) { | ||
| 4110 | unsigned long freei = ext4_count_free_inodes(sb); | ||
| 4111 | sbi->s_es->s_free_inodes_count = cpu_to_le32(freei); | ||
| 4112 | err = percpu_counter_init(&sbi->s_freeinodes_counter, freei); | ||
| 4113 | } | ||
| 4114 | if (!err) | ||
| 4115 | err = percpu_counter_init(&sbi->s_dirs_counter, | ||
| 4116 | ext4_count_dirs(sb)); | ||
| 4117 | if (!err) | ||
| 4118 | err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0); | ||
| 4119 | if (err) { | ||
| 4120 | ext4_msg(sb, KERN_ERR, "insufficient memory"); | ||
| 4121 | goto failed_mount6; | ||
| 4122 | } | ||
| 4123 | |||
| 4124 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | ||
| 4125 | if (!ext4_fill_flex_info(sb)) { | ||
| 4126 | ext4_msg(sb, KERN_ERR, | ||
| 4127 | "unable to initialize " | ||
| 4128 | "flex_bg meta info!"); | ||
| 4129 | goto failed_mount6; | ||
| 4130 | } | ||
| 4131 | |||
| 4144 | err = ext4_register_li_request(sb, first_not_zeroed); | 4132 | err = ext4_register_li_request(sb, first_not_zeroed); |
| 4145 | if (err) | 4133 | if (err) |
| 4146 | goto failed_mount6; | 4134 | goto failed_mount6; |
| @@ -4215,6 +4203,12 @@ failed_mount7: | |||
| 4215 | ext4_unregister_li_request(sb); | 4203 | ext4_unregister_li_request(sb); |
| 4216 | failed_mount6: | 4204 | failed_mount6: |
| 4217 | ext4_mb_release(sb); | 4205 | ext4_mb_release(sb); |
| 4206 | if (sbi->s_flex_groups) | ||
| 4207 | ext4_kvfree(sbi->s_flex_groups); | ||
| 4208 | percpu_counter_destroy(&sbi->s_freeclusters_counter); | ||
| 4209 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
| 4210 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
| 4211 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); | ||
| 4218 | failed_mount5: | 4212 | failed_mount5: |
| 4219 | ext4_ext_release(sb); | 4213 | ext4_ext_release(sb); |
| 4220 | ext4_release_system_zone(sb); | 4214 | ext4_release_system_zone(sb); |
| @@ -4233,12 +4227,6 @@ failed_mount_wq: | |||
| 4233 | failed_mount3: | 4227 | failed_mount3: |
| 4234 | ext4_es_unregister_shrinker(sbi); | 4228 | ext4_es_unregister_shrinker(sbi); |
| 4235 | del_timer_sync(&sbi->s_err_report); | 4229 | del_timer_sync(&sbi->s_err_report); |
| 4236 | if (sbi->s_flex_groups) | ||
| 4237 | ext4_kvfree(sbi->s_flex_groups); | ||
| 4238 | percpu_counter_destroy(&sbi->s_freeclusters_counter); | ||
| 4239 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
| 4240 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
| 4241 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); | ||
| 4242 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); | 4230 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); |
| 4243 | if (sbi->s_mmp_tsk) | 4231 | if (sbi->s_mmp_tsk) |
| 4244 | kthread_stop(sbi->s_mmp_tsk); | 4232 | kthread_stop(sbi->s_mmp_tsk); |
| @@ -4556,11 +4544,13 @@ static int ext4_commit_super(struct super_block *sb, int sync) | |||
| 4556 | else | 4544 | else |
| 4557 | es->s_kbytes_written = | 4545 | es->s_kbytes_written = |
| 4558 | cpu_to_le64(EXT4_SB(sb)->s_kbytes_written); | 4546 | cpu_to_le64(EXT4_SB(sb)->s_kbytes_written); |
| 4559 | ext4_free_blocks_count_set(es, | 4547 | if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeclusters_counter)) |
| 4548 | ext4_free_blocks_count_set(es, | ||
| 4560 | EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive( | 4549 | EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive( |
| 4561 | &EXT4_SB(sb)->s_freeclusters_counter))); | 4550 | &EXT4_SB(sb)->s_freeclusters_counter))); |
| 4562 | es->s_free_inodes_count = | 4551 | if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter)) |
| 4563 | cpu_to_le32(percpu_counter_sum_positive( | 4552 | es->s_free_inodes_count = |
| 4553 | cpu_to_le32(percpu_counter_sum_positive( | ||
| 4564 | &EXT4_SB(sb)->s_freeinodes_counter)); | 4554 | &EXT4_SB(sb)->s_freeinodes_counter)); |
| 4565 | BUFFER_TRACE(sbh, "marking dirty"); | 4555 | BUFFER_TRACE(sbh, "marking dirty"); |
| 4566 | ext4_superblock_csum_set(sb); | 4556 | ext4_superblock_csum_set(sb); |
