diff options
| -rw-r--r-- | fs/ext4/dir.c | 12 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 40 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 327 |
3 files changed, 150 insertions, 229 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 86cb6d86a048..e3f2700b8be7 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
| @@ -128,14 +128,14 @@ static int ext4_readdir(struct file *filp, | |||
| 128 | offset = filp->f_pos & (sb->s_blocksize - 1); | 128 | offset = filp->f_pos & (sb->s_blocksize - 1); |
| 129 | 129 | ||
| 130 | while (!error && !stored && filp->f_pos < inode->i_size) { | 130 | while (!error && !stored && filp->f_pos < inode->i_size) { |
| 131 | ext4_lblk_t blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); | 131 | struct ext4_map_blocks map; |
| 132 | struct buffer_head map_bh; | ||
| 133 | struct buffer_head *bh = NULL; | 132 | struct buffer_head *bh = NULL; |
| 134 | 133 | ||
| 135 | map_bh.b_state = 0; | 134 | map.m_lblk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); |
| 136 | err = ext4_get_blocks(NULL, inode, blk, 1, &map_bh, 0); | 135 | map.m_len = 1; |
| 136 | err = ext4_map_blocks(NULL, inode, &map, 0); | ||
| 137 | if (err > 0) { | 137 | if (err > 0) { |
| 138 | pgoff_t index = map_bh.b_blocknr >> | 138 | pgoff_t index = map.m_pblk >> |
| 139 | (PAGE_CACHE_SHIFT - inode->i_blkbits); | 139 | (PAGE_CACHE_SHIFT - inode->i_blkbits); |
| 140 | if (!ra_has_index(&filp->f_ra, index)) | 140 | if (!ra_has_index(&filp->f_ra, index)) |
| 141 | page_cache_sync_readahead( | 141 | page_cache_sync_readahead( |
| @@ -143,7 +143,7 @@ static int ext4_readdir(struct file *filp, | |||
| 143 | &filp->f_ra, filp, | 143 | &filp->f_ra, filp, |
| 144 | index, 1); | 144 | index, 1); |
| 145 | filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; | 145 | filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; |
| 146 | bh = ext4_bread(NULL, inode, blk, 0, &err); | 146 | bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err); |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | /* | 149 | /* |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 37f938789344..d6801eb7232b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -3667,13 +3667,12 @@ static void ext4_falloc_update_inode(struct inode *inode, | |||
| 3667 | long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | 3667 | long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) |
| 3668 | { | 3668 | { |
| 3669 | handle_t *handle; | 3669 | handle_t *handle; |
| 3670 | ext4_lblk_t block; | ||
| 3671 | loff_t new_size; | 3670 | loff_t new_size; |
| 3672 | unsigned int max_blocks; | 3671 | unsigned int max_blocks; |
| 3673 | int ret = 0; | 3672 | int ret = 0; |
| 3674 | int ret2 = 0; | 3673 | int ret2 = 0; |
| 3675 | int retries = 0; | 3674 | int retries = 0; |
| 3676 | struct buffer_head map_bh; | 3675 | struct ext4_map_blocks map; |
| 3677 | unsigned int credits, blkbits = inode->i_blkbits; | 3676 | unsigned int credits, blkbits = inode->i_blkbits; |
| 3678 | 3677 | ||
| 3679 | /* | 3678 | /* |
| @@ -3687,13 +3686,13 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | |||
| 3687 | if (S_ISDIR(inode->i_mode)) | 3686 | if (S_ISDIR(inode->i_mode)) |
| 3688 | return -ENODEV; | 3687 | return -ENODEV; |
| 3689 | 3688 | ||
| 3690 | block = offset >> blkbits; | 3689 | map.m_lblk = offset >> blkbits; |
| 3691 | /* | 3690 | /* |
| 3692 | * We can't just convert len to max_blocks because | 3691 | * We can't just convert len to max_blocks because |
| 3693 | * If blocksize = 4096 offset = 3072 and len = 2048 | 3692 | * If blocksize = 4096 offset = 3072 and len = 2048 |
| 3694 | */ | 3693 | */ |
| 3695 | max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) | 3694 | max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) |
| 3696 | - block; | 3695 | - map.m_lblk; |
| 3697 | /* | 3696 | /* |
| 3698 | * credits to insert 1 extent into extent tree | 3697 | * credits to insert 1 extent into extent tree |
| 3699 | */ | 3698 | */ |
| @@ -3706,16 +3705,14 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | |||
| 3706 | } | 3705 | } |
| 3707 | retry: | 3706 | retry: |
| 3708 | while (ret >= 0 && ret < max_blocks) { | 3707 | while (ret >= 0 && ret < max_blocks) { |
| 3709 | block = block + ret; | 3708 | map.m_lblk = map.m_lblk + ret; |
| 3710 | max_blocks = max_blocks - ret; | 3709 | map.m_len = max_blocks = max_blocks - ret; |
| 3711 | handle = ext4_journal_start(inode, credits); | 3710 | handle = ext4_journal_start(inode, credits); |
| 3712 | if (IS_ERR(handle)) { | 3711 | if (IS_ERR(handle)) { |
| 3713 | ret = PTR_ERR(handle); | 3712 | ret = PTR_ERR(handle); |
| 3714 | break; | 3713 | break; |
| 3715 | } | 3714 | } |
| 3716 | map_bh.b_state = 0; | 3715 | ret = ext4_map_blocks(handle, inode, &map, |
| 3717 | ret = ext4_get_blocks(handle, inode, block, | ||
| 3718 | max_blocks, &map_bh, | ||
| 3719 | EXT4_GET_BLOCKS_CREATE_UNINIT_EXT); | 3716 | EXT4_GET_BLOCKS_CREATE_UNINIT_EXT); |
| 3720 | if (ret <= 0) { | 3717 | if (ret <= 0) { |
| 3721 | #ifdef EXT4FS_DEBUG | 3718 | #ifdef EXT4FS_DEBUG |
| @@ -3729,14 +3726,14 @@ retry: | |||
| 3729 | ret2 = ext4_journal_stop(handle); | 3726 | ret2 = ext4_journal_stop(handle); |
| 3730 | break; | 3727 | break; |
| 3731 | } | 3728 | } |
| 3732 | if ((block + ret) >= (EXT4_BLOCK_ALIGN(offset + len, | 3729 | if ((map.m_lblk + ret) >= (EXT4_BLOCK_ALIGN(offset + len, |
| 3733 | blkbits) >> blkbits)) | 3730 | blkbits) >> blkbits)) |
| 3734 | new_size = offset + len; | 3731 | new_size = offset + len; |
| 3735 | else | 3732 | else |
| 3736 | new_size = (block + ret) << blkbits; | 3733 | new_size = (map.m_lblk + ret) << blkbits; |
| 3737 | 3734 | ||
| 3738 | ext4_falloc_update_inode(inode, mode, new_size, | 3735 | ext4_falloc_update_inode(inode, mode, new_size, |
| 3739 | buffer_new(&map_bh)); | 3736 | (map.m_flags & EXT4_MAP_NEW)); |
| 3740 | ext4_mark_inode_dirty(handle, inode); | 3737 | ext4_mark_inode_dirty(handle, inode); |
| 3741 | ret2 = ext4_journal_stop(handle); | 3738 | ret2 = ext4_journal_stop(handle); |
| 3742 | if (ret2) | 3739 | if (ret2) |
| @@ -3765,42 +3762,39 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, | |||
| 3765 | ssize_t len) | 3762 | ssize_t len) |
| 3766 | { | 3763 | { |
| 3767 | handle_t *handle; | 3764 | handle_t *handle; |
| 3768 | ext4_lblk_t block; | ||
| 3769 | unsigned int max_blocks; | 3765 | unsigned int max_blocks; |
| 3770 | int ret = 0; | 3766 | int ret = 0; |
| 3771 | int ret2 = 0; | 3767 | int ret2 = 0; |
| 3772 | struct buffer_head map_bh; | 3768 | struct ext4_map_blocks map; |
| 3773 | unsigned int credits, blkbits = inode->i_blkbits; | 3769 | unsigned int credits, blkbits = inode->i_blkbits; |
| 3774 | 3770 | ||
| 3775 | block = offset >> blkbits; | 3771 | map.m_lblk = offset >> blkbits; |
| 3776 | /* | 3772 | /* |
| 3777 | * We can't just convert len to max_blocks because | 3773 | * We can't just convert len to max_blocks because |
| 3778 | * If blocksize = 4096 offset = 3072 and len = 2048 | 3774 | * If blocksize = 4096 offset = 3072 and len = 2048 |
| 3779 | */ | 3775 | */ |
| 3780 | max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) | 3776 | max_blocks = ((EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) - |
| 3781 | - block; | 3777 | map.m_lblk); |
| 3782 | /* | 3778 | /* |
| 3783 | * credits to insert 1 extent into extent tree | 3779 | * credits to insert 1 extent into extent tree |
| 3784 | */ | 3780 | */ |
| 3785 | credits = ext4_chunk_trans_blocks(inode, max_blocks); | 3781 | credits = ext4_chunk_trans_blocks(inode, max_blocks); |
| 3786 | while (ret >= 0 && ret < max_blocks) { | 3782 | while (ret >= 0 && ret < max_blocks) { |
| 3787 | block = block + ret; | 3783 | map.m_lblk += ret; |
| 3788 | max_blocks = max_blocks - ret; | 3784 | map.m_len = (max_blocks -= ret); |
| 3789 | handle = ext4_journal_start(inode, credits); | 3785 | handle = ext4_journal_start(inode, credits); |
| 3790 | if (IS_ERR(handle)) { | 3786 | if (IS_ERR(handle)) { |
| 3791 | ret = PTR_ERR(handle); | 3787 | ret = PTR_ERR(handle); |
| 3792 | break; | 3788 | break; |
| 3793 | } | 3789 | } |
| 3794 | map_bh.b_state = 0; | 3790 | ret = ext4_map_blocks(handle, inode, &map, |
| 3795 | ret = ext4_get_blocks(handle, inode, block, | ||
| 3796 | max_blocks, &map_bh, | ||
| 3797 | EXT4_GET_BLOCKS_IO_CONVERT_EXT); | 3791 | EXT4_GET_BLOCKS_IO_CONVERT_EXT); |
| 3798 | if (ret <= 0) { | 3792 | if (ret <= 0) { |
| 3799 | WARN_ON(ret <= 0); | 3793 | WARN_ON(ret <= 0); |
| 3800 | printk(KERN_ERR "%s: ext4_ext_map_blocks " | 3794 | printk(KERN_ERR "%s: ext4_ext_map_blocks " |
| 3801 | "returned error inode#%lu, block=%u, " | 3795 | "returned error inode#%lu, block=%u, " |
| 3802 | "max_blocks=%u", __func__, | 3796 | "max_blocks=%u", __func__, |
| 3803 | inode->i_ino, block, max_blocks); | 3797 | inode->i_ino, map.m_lblk, map.m_len); |
| 3804 | } | 3798 | } |
| 3805 | ext4_mark_inode_dirty(handle, inode); | 3799 | ext4_mark_inode_dirty(handle, inode); |
| 3806 | ret2 = ext4_journal_stop(handle); | 3800 | ret2 = ext4_journal_stop(handle); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ff2f5fd681b5..0b1d7c89f93f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -1336,133 +1336,112 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
| 1336 | return retval; | 1336 | return retval; |
| 1337 | } | 1337 | } |
| 1338 | 1338 | ||
| 1339 | int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | ||
| 1340 | unsigned int max_blocks, struct buffer_head *bh, | ||
| 1341 | int flags) | ||
| 1342 | { | ||
| 1343 | struct ext4_map_blocks map; | ||
| 1344 | int ret; | ||
| 1345 | |||
| 1346 | map.m_lblk = block; | ||
| 1347 | map.m_len = max_blocks; | ||
| 1348 | |||
| 1349 | ret = ext4_map_blocks(handle, inode, &map, flags); | ||
| 1350 | if (ret < 0) | ||
| 1351 | return ret; | ||
| 1352 | |||
| 1353 | bh->b_blocknr = map.m_pblk; | ||
| 1354 | bh->b_size = inode->i_sb->s_blocksize * map.m_len; | ||
| 1355 | bh->b_bdev = inode->i_sb->s_bdev; | ||
| 1356 | bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; | ||
| 1357 | return ret; | ||
| 1358 | } | ||
| 1359 | |||
| 1360 | /* Maximum number of blocks we map for direct IO at once. */ | 1339 | /* Maximum number of blocks we map for direct IO at once. */ |
| 1361 | #define DIO_MAX_BLOCKS 4096 | 1340 | #define DIO_MAX_BLOCKS 4096 |
| 1362 | 1341 | ||
| 1363 | int ext4_get_block(struct inode *inode, sector_t iblock, | 1342 | static int _ext4_get_block(struct inode *inode, sector_t iblock, |
| 1364 | struct buffer_head *bh_result, int create) | 1343 | struct buffer_head *bh, int flags) |
| 1365 | { | 1344 | { |
| 1366 | handle_t *handle = ext4_journal_current_handle(); | 1345 | handle_t *handle = ext4_journal_current_handle(); |
| 1346 | struct ext4_map_blocks map; | ||
| 1367 | int ret = 0, started = 0; | 1347 | int ret = 0, started = 0; |
| 1368 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; | ||
| 1369 | int dio_credits; | 1348 | int dio_credits; |
| 1370 | 1349 | ||
| 1371 | if (create && !handle) { | 1350 | map.m_lblk = iblock; |
| 1351 | map.m_len = bh->b_size >> inode->i_blkbits; | ||
| 1352 | |||
| 1353 | if (flags && !handle) { | ||
| 1372 | /* Direct IO write... */ | 1354 | /* Direct IO write... */ |
| 1373 | if (max_blocks > DIO_MAX_BLOCKS) | 1355 | if (map.m_len > DIO_MAX_BLOCKS) |
| 1374 | max_blocks = DIO_MAX_BLOCKS; | 1356 | map.m_len = DIO_MAX_BLOCKS; |
| 1375 | dio_credits = ext4_chunk_trans_blocks(inode, max_blocks); | 1357 | dio_credits = ext4_chunk_trans_blocks(inode, map.m_len); |
| 1376 | handle = ext4_journal_start(inode, dio_credits); | 1358 | handle = ext4_journal_start(inode, dio_credits); |
| 1377 | if (IS_ERR(handle)) { | 1359 | if (IS_ERR(handle)) { |
| 1378 | ret = PTR_ERR(handle); | 1360 | ret = PTR_ERR(handle); |
| 1379 | goto out; | 1361 | return ret; |
| 1380 | } | 1362 | } |
| 1381 | started = 1; | 1363 | started = 1; |
| 1382 | } | 1364 | } |
| 1383 | 1365 | ||
| 1384 | ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result, | 1366 | ret = ext4_map_blocks(handle, inode, &map, flags); |
| 1385 | create ? EXT4_GET_BLOCKS_CREATE : 0); | ||
| 1386 | if (ret > 0) { | 1367 | if (ret > 0) { |
| 1387 | bh_result->b_size = (ret << inode->i_blkbits); | 1368 | map_bh(bh, inode->i_sb, map.m_pblk); |
| 1369 | bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; | ||
| 1370 | bh->b_size = inode->i_sb->s_blocksize * map.m_len; | ||
| 1388 | ret = 0; | 1371 | ret = 0; |
| 1389 | } | 1372 | } |
| 1390 | if (started) | 1373 | if (started) |
| 1391 | ext4_journal_stop(handle); | 1374 | ext4_journal_stop(handle); |
| 1392 | out: | ||
| 1393 | return ret; | 1375 | return ret; |
| 1394 | } | 1376 | } |
| 1395 | 1377 | ||
| 1378 | int ext4_get_block(struct inode *inode, sector_t iblock, | ||
| 1379 | struct buffer_head *bh, int create) | ||
| 1380 | { | ||
| 1381 | return _ext4_get_block(inode, iblock, bh, | ||
| 1382 | create ? EXT4_GET_BLOCKS_CREATE : 0); | ||
| 1383 | } | ||
| 1384 | |||
| 1396 | /* | 1385 | /* |
| 1397 | * `handle' can be NULL if create is zero | 1386 | * `handle' can be NULL if create is zero |
| 1398 | */ | 1387 | */ |
| 1399 | struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, | 1388 | struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, |
| 1400 | ext4_lblk_t block, int create, int *errp) | 1389 | ext4_lblk_t block, int create, int *errp) |
| 1401 | { | 1390 | { |
| 1402 | struct buffer_head dummy; | 1391 | struct ext4_map_blocks map; |
| 1392 | struct buffer_head *bh; | ||
| 1403 | int fatal = 0, err; | 1393 | int fatal = 0, err; |
| 1404 | int flags = 0; | ||
| 1405 | 1394 | ||
| 1406 | J_ASSERT(handle != NULL || create == 0); | 1395 | J_ASSERT(handle != NULL || create == 0); |
| 1407 | 1396 | ||
| 1408 | dummy.b_state = 0; | 1397 | map.m_lblk = block; |
| 1409 | dummy.b_blocknr = -1000; | 1398 | map.m_len = 1; |
| 1410 | buffer_trace_init(&dummy.b_history); | 1399 | err = ext4_map_blocks(handle, inode, &map, |
| 1411 | if (create) | 1400 | create ? EXT4_GET_BLOCKS_CREATE : 0); |
| 1412 | flags |= EXT4_GET_BLOCKS_CREATE; | 1401 | |
| 1413 | err = ext4_get_blocks(handle, inode, block, 1, &dummy, flags); | 1402 | if (err < 0) |
| 1414 | /* | 1403 | *errp = err; |
| 1415 | * ext4_get_blocks() returns number of blocks mapped. 0 in | 1404 | if (err <= 0) |
| 1416 | * case of a HOLE. | 1405 | return NULL; |
| 1417 | */ | 1406 | *errp = 0; |
| 1418 | if (err > 0) { | 1407 | |
| 1419 | if (err > 1) | 1408 | bh = sb_getblk(inode->i_sb, map.m_pblk); |
| 1420 | WARN_ON(1); | 1409 | if (!bh) { |
| 1421 | err = 0; | 1410 | *errp = -EIO; |
| 1411 | return NULL; | ||
| 1422 | } | 1412 | } |
| 1423 | *errp = err; | 1413 | if (map.m_flags & EXT4_MAP_NEW) { |
| 1424 | if (!err && buffer_mapped(&dummy)) { | 1414 | J_ASSERT(create != 0); |
| 1425 | struct buffer_head *bh; | 1415 | J_ASSERT(handle != NULL); |
| 1426 | bh = sb_getblk(inode->i_sb, dummy.b_blocknr); | ||
| 1427 | if (!bh) { | ||
| 1428 | *errp = -EIO; | ||
| 1429 | goto err; | ||
| 1430 | } | ||
| 1431 | if (buffer_new(&dummy)) { | ||
| 1432 | J_ASSERT(create != 0); | ||
| 1433 | J_ASSERT(handle != NULL); | ||
| 1434 | 1416 | ||
| 1435 | /* | 1417 | /* |
| 1436 | * Now that we do not always journal data, we should | 1418 | * Now that we do not always journal data, we should |
| 1437 | * keep in mind whether this should always journal the | 1419 | * keep in mind whether this should always journal the |
| 1438 | * new buffer as metadata. For now, regular file | 1420 | * new buffer as metadata. For now, regular file |
| 1439 | * writes use ext4_get_block instead, so it's not a | 1421 | * writes use ext4_get_block instead, so it's not a |
| 1440 | * problem. | 1422 | * problem. |
| 1441 | */ | 1423 | */ |
| 1442 | lock_buffer(bh); | 1424 | lock_buffer(bh); |
| 1443 | BUFFER_TRACE(bh, "call get_create_access"); | 1425 | BUFFER_TRACE(bh, "call get_create_access"); |
| 1444 | fatal = ext4_journal_get_create_access(handle, bh); | 1426 | fatal = ext4_journal_get_create_access(handle, bh); |
| 1445 | if (!fatal && !buffer_uptodate(bh)) { | 1427 | if (!fatal && !buffer_uptodate(bh)) { |
| 1446 | memset(bh->b_data, 0, inode->i_sb->s_blocksize); | 1428 | memset(bh->b_data, 0, inode->i_sb->s_blocksize); |
| 1447 | set_buffer_uptodate(bh); | 1429 | set_buffer_uptodate(bh); |
| 1448 | } | ||
| 1449 | unlock_buffer(bh); | ||
| 1450 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | ||
| 1451 | err = ext4_handle_dirty_metadata(handle, inode, bh); | ||
| 1452 | if (!fatal) | ||
| 1453 | fatal = err; | ||
| 1454 | } else { | ||
| 1455 | BUFFER_TRACE(bh, "not a new buffer"); | ||
| 1456 | } | ||
| 1457 | if (fatal) { | ||
| 1458 | *errp = fatal; | ||
| 1459 | brelse(bh); | ||
| 1460 | bh = NULL; | ||
| 1461 | } | 1430 | } |
| 1462 | return bh; | 1431 | unlock_buffer(bh); |
| 1432 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | ||
| 1433 | err = ext4_handle_dirty_metadata(handle, inode, bh); | ||
| 1434 | if (!fatal) | ||
| 1435 | fatal = err; | ||
| 1436 | } else { | ||
| 1437 | BUFFER_TRACE(bh, "not a new buffer"); | ||
| 1463 | } | 1438 | } |
| 1464 | err: | 1439 | if (fatal) { |
| 1465 | return NULL; | 1440 | *errp = fatal; |
| 1441 | brelse(bh); | ||
| 1442 | bh = NULL; | ||
| 1443 | } | ||
| 1444 | return bh; | ||
| 1466 | } | 1445 | } |
| 1467 | 1446 | ||
| 1468 | struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, | 1447 | struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, |
| @@ -2050,28 +2029,23 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) | |||
| 2050 | /* | 2029 | /* |
| 2051 | * mpage_put_bnr_to_bhs - walk blocks and assign them actual numbers | 2030 | * mpage_put_bnr_to_bhs - walk blocks and assign them actual numbers |
| 2052 | * | 2031 | * |
| 2053 | * @mpd->inode - inode to walk through | ||
| 2054 | * @exbh->b_blocknr - first block on a disk | ||
| 2055 | * @exbh->b_size - amount of space in bytes | ||
| 2056 | * @logical - first logical block to start assignment with | ||
| 2057 | * | ||
| 2058 | * the function goes through all passed space and put actual disk | 2032 | * the function goes through all passed space and put actual disk |
| 2059 | * block numbers into buffer heads, dropping BH_Delay and BH_Unwritten | 2033 | * block numbers into buffer heads, dropping BH_Delay and BH_Unwritten |
| 2060 | */ | 2034 | */ |
| 2061 | static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, | 2035 | static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, |
| 2062 | struct buffer_head *exbh) | 2036 | struct ext4_map_blocks *map) |
| 2063 | { | 2037 | { |
| 2064 | struct inode *inode = mpd->inode; | 2038 | struct inode *inode = mpd->inode; |
| 2065 | struct address_space *mapping = inode->i_mapping; | 2039 | struct address_space *mapping = inode->i_mapping; |
| 2066 | int blocks = exbh->b_size >> inode->i_blkbits; | 2040 | int blocks = map->m_len; |
| 2067 | sector_t pblock = exbh->b_blocknr, cur_logical; | 2041 | sector_t pblock = map->m_pblk, cur_logical; |
| 2068 | struct buffer_head *head, *bh; | 2042 | struct buffer_head *head, *bh; |
| 2069 | pgoff_t index, end; | 2043 | pgoff_t index, end; |
| 2070 | struct pagevec pvec; | 2044 | struct pagevec pvec; |
| 2071 | int nr_pages, i; | 2045 | int nr_pages, i; |
| 2072 | 2046 | ||
| 2073 | index = logical >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | 2047 | index = map->m_lblk >> (PAGE_CACHE_SHIFT - inode->i_blkbits); |
| 2074 | end = (logical + blocks - 1) >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | 2048 | end = (map->m_lblk + blocks - 1) >> (PAGE_CACHE_SHIFT - inode->i_blkbits); |
| 2075 | cur_logical = index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 2049 | cur_logical = index << (PAGE_CACHE_SHIFT - inode->i_blkbits); |
| 2076 | 2050 | ||
| 2077 | pagevec_init(&pvec, 0); | 2051 | pagevec_init(&pvec, 0); |
| @@ -2098,17 +2072,16 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, | |||
| 2098 | 2072 | ||
| 2099 | /* skip blocks out of the range */ | 2073 | /* skip blocks out of the range */ |
| 2100 | do { | 2074 | do { |
| 2101 | if (cur_logical >= logical) | 2075 | if (cur_logical >= map->m_lblk) |
| 2102 | break; | 2076 | break; |
| 2103 | cur_logical++; | 2077 | cur_logical++; |
| 2104 | } while ((bh = bh->b_this_page) != head); | 2078 | } while ((bh = bh->b_this_page) != head); |
| 2105 | 2079 | ||
| 2106 | do { | 2080 | do { |
| 2107 | if (cur_logical >= logical + blocks) | 2081 | if (cur_logical >= map->m_lblk + blocks) |
| 2108 | break; | 2082 | break; |
| 2109 | 2083 | ||
| 2110 | if (buffer_delay(bh) || | 2084 | if (buffer_delay(bh) || buffer_unwritten(bh)) { |
| 2111 | buffer_unwritten(bh)) { | ||
| 2112 | 2085 | ||
| 2113 | BUG_ON(bh->b_bdev != inode->i_sb->s_bdev); | 2086 | BUG_ON(bh->b_bdev != inode->i_sb->s_bdev); |
| 2114 | 2087 | ||
| @@ -2127,7 +2100,7 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, | |||
| 2127 | } else if (buffer_mapped(bh)) | 2100 | } else if (buffer_mapped(bh)) |
| 2128 | BUG_ON(bh->b_blocknr != pblock); | 2101 | BUG_ON(bh->b_blocknr != pblock); |
| 2129 | 2102 | ||
| 2130 | if (buffer_uninit(exbh)) | 2103 | if (map->m_flags & EXT4_MAP_UNINIT) |
| 2131 | set_buffer_uninit(bh); | 2104 | set_buffer_uninit(bh); |
| 2132 | cur_logical++; | 2105 | cur_logical++; |
| 2133 | pblock++; | 2106 | pblock++; |
| @@ -2138,21 +2111,6 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, | |||
| 2138 | } | 2111 | } |
| 2139 | 2112 | ||
| 2140 | 2113 | ||
| 2141 | /* | ||
| 2142 | * __unmap_underlying_blocks - just a helper function to unmap | ||
| 2143 | * set of blocks described by @bh | ||
| 2144 | */ | ||
| 2145 | static inline void __unmap_underlying_blocks(struct inode *inode, | ||
| 2146 | struct buffer_head *bh) | ||
| 2147 | { | ||
| 2148 | struct block_device *bdev = inode->i_sb->s_bdev; | ||
| 2149 | int blocks, i; | ||
| 2150 | |||
| 2151 | blocks = bh->b_size >> inode->i_blkbits; | ||
| 2152 | for (i = 0; i < blocks; i++) | ||
| 2153 | unmap_underlying_metadata(bdev, bh->b_blocknr + i); | ||
| 2154 | } | ||
| 2155 | |||
| 2156 | static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, | 2114 | static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, |
| 2157 | sector_t logical, long blk_cnt) | 2115 | sector_t logical, long blk_cnt) |
| 2158 | { | 2116 | { |
| @@ -2214,7 +2172,7 @@ static void ext4_print_free_blocks(struct inode *inode) | |||
| 2214 | static int mpage_da_map_blocks(struct mpage_da_data *mpd) | 2172 | static int mpage_da_map_blocks(struct mpage_da_data *mpd) |
| 2215 | { | 2173 | { |
| 2216 | int err, blks, get_blocks_flags; | 2174 | int err, blks, get_blocks_flags; |
| 2217 | struct buffer_head new; | 2175 | struct ext4_map_blocks map; |
| 2218 | sector_t next = mpd->b_blocknr; | 2176 | sector_t next = mpd->b_blocknr; |
| 2219 | unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits; | 2177 | unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits; |
| 2220 | loff_t disksize = EXT4_I(mpd->inode)->i_disksize; | 2178 | loff_t disksize = EXT4_I(mpd->inode)->i_disksize; |
| @@ -2255,15 +2213,15 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2255 | * EXT4_GET_BLOCKS_DELALLOC_RESERVE so the delalloc accounting | 2213 | * EXT4_GET_BLOCKS_DELALLOC_RESERVE so the delalloc accounting |
| 2256 | * variables are updated after the blocks have been allocated. | 2214 | * variables are updated after the blocks have been allocated. |
| 2257 | */ | 2215 | */ |
| 2258 | new.b_state = 0; | 2216 | map.m_lblk = next; |
| 2217 | map.m_len = max_blocks; | ||
| 2259 | get_blocks_flags = EXT4_GET_BLOCKS_CREATE; | 2218 | get_blocks_flags = EXT4_GET_BLOCKS_CREATE; |
| 2260 | if (ext4_should_dioread_nolock(mpd->inode)) | 2219 | if (ext4_should_dioread_nolock(mpd->inode)) |
| 2261 | get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT; | 2220 | get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT; |
| 2262 | if (mpd->b_state & (1 << BH_Delay)) | 2221 | if (mpd->b_state & (1 << BH_Delay)) |
| 2263 | get_blocks_flags |= EXT4_GET_BLOCKS_DELALLOC_RESERVE; | 2222 | get_blocks_flags |= EXT4_GET_BLOCKS_DELALLOC_RESERVE; |
| 2264 | 2223 | ||
| 2265 | blks = ext4_get_blocks(handle, mpd->inode, next, max_blocks, | 2224 | blks = ext4_map_blocks(handle, mpd->inode, &map, get_blocks_flags); |
| 2266 | &new, get_blocks_flags); | ||
| 2267 | if (blks < 0) { | 2225 | if (blks < 0) { |
| 2268 | err = blks; | 2226 | err = blks; |
| 2269 | /* | 2227 | /* |
| @@ -2305,10 +2263,13 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2305 | } | 2263 | } |
| 2306 | BUG_ON(blks == 0); | 2264 | BUG_ON(blks == 0); |
| 2307 | 2265 | ||
| 2308 | new.b_size = (blks << mpd->inode->i_blkbits); | 2266 | if (map.m_flags & EXT4_MAP_NEW) { |
| 2267 | struct block_device *bdev = mpd->inode->i_sb->s_bdev; | ||
| 2268 | int i; | ||
| 2309 | 2269 | ||
| 2310 | if (buffer_new(&new)) | 2270 | for (i = 0; i < map.m_len; i++) |
| 2311 | __unmap_underlying_blocks(mpd->inode, &new); | 2271 | unmap_underlying_metadata(bdev, map.m_pblk + i); |
| 2272 | } | ||
| 2312 | 2273 | ||
| 2313 | /* | 2274 | /* |
| 2314 | * If blocks are delayed marked, we need to | 2275 | * If blocks are delayed marked, we need to |
| @@ -2316,7 +2277,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2316 | */ | 2277 | */ |
| 2317 | if ((mpd->b_state & (1 << BH_Delay)) || | 2278 | if ((mpd->b_state & (1 << BH_Delay)) || |
| 2318 | (mpd->b_state & (1 << BH_Unwritten))) | 2279 | (mpd->b_state & (1 << BH_Unwritten))) |
| 2319 | mpage_put_bnr_to_bhs(mpd, next, &new); | 2280 | mpage_put_bnr_to_bhs(mpd, &map); |
| 2320 | 2281 | ||
| 2321 | if (ext4_should_order_data(mpd->inode)) { | 2282 | if (ext4_should_order_data(mpd->inode)) { |
| 2322 | err = ext4_jbd2_file_inode(handle, mpd->inode); | 2283 | err = ext4_jbd2_file_inode(handle, mpd->inode); |
| @@ -2534,8 +2495,9 @@ static int __mpage_da_writepage(struct page *page, | |||
| 2534 | * initialized properly. | 2495 | * initialized properly. |
| 2535 | */ | 2496 | */ |
| 2536 | static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | 2497 | static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, |
| 2537 | struct buffer_head *bh_result, int create) | 2498 | struct buffer_head *bh, int create) |
| 2538 | { | 2499 | { |
| 2500 | struct ext4_map_blocks map; | ||
| 2539 | int ret = 0; | 2501 | int ret = 0; |
| 2540 | sector_t invalid_block = ~((sector_t) 0xffff); | 2502 | sector_t invalid_block = ~((sector_t) 0xffff); |
| 2541 | 2503 | ||
| @@ -2543,16 +2505,22 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
| 2543 | invalid_block = ~0; | 2505 | invalid_block = ~0; |
| 2544 | 2506 | ||
| 2545 | BUG_ON(create == 0); | 2507 | BUG_ON(create == 0); |
| 2546 | BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); | 2508 | BUG_ON(bh->b_size != inode->i_sb->s_blocksize); |
| 2509 | |||
| 2510 | map.m_lblk = iblock; | ||
| 2511 | map.m_len = 1; | ||
| 2547 | 2512 | ||
| 2548 | /* | 2513 | /* |
| 2549 | * first, we need to know whether the block is allocated already | 2514 | * first, we need to know whether the block is allocated already |
| 2550 | * preallocated blocks are unmapped but should treated | 2515 | * preallocated blocks are unmapped but should treated |
| 2551 | * the same as allocated blocks. | 2516 | * the same as allocated blocks. |
| 2552 | */ | 2517 | */ |
| 2553 | ret = ext4_get_blocks(NULL, inode, iblock, 1, bh_result, 0); | 2518 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 2554 | if ((ret == 0) && !buffer_delay(bh_result)) { | 2519 | if (ret < 0) |
| 2555 | /* the block isn't (pre)allocated yet, let's reserve space */ | 2520 | return ret; |
| 2521 | if (ret == 0) { | ||
| 2522 | if (buffer_delay(bh)) | ||
| 2523 | return 0; /* Not sure this could or should happen */ | ||
| 2556 | /* | 2524 | /* |
| 2557 | * XXX: __block_prepare_write() unmaps passed block, | 2525 | * XXX: __block_prepare_write() unmaps passed block, |
| 2558 | * is it OK? | 2526 | * is it OK? |
| @@ -2562,26 +2530,26 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
| 2562 | /* not enough space to reserve */ | 2530 | /* not enough space to reserve */ |
| 2563 | return ret; | 2531 | return ret; |
| 2564 | 2532 | ||
| 2565 | map_bh(bh_result, inode->i_sb, invalid_block); | 2533 | map_bh(bh, inode->i_sb, invalid_block); |
| 2566 | set_buffer_new(bh_result); | 2534 | set_buffer_new(bh); |
| 2567 | set_buffer_delay(bh_result); | 2535 | set_buffer_delay(bh); |
| 2568 | } else if (ret > 0) { | 2536 | return 0; |
| 2569 | bh_result->b_size = (ret << inode->i_blkbits); | ||
| 2570 | if (buffer_unwritten(bh_result)) { | ||
| 2571 | /* A delayed write to unwritten bh should | ||
| 2572 | * be marked new and mapped. Mapped ensures | ||
| 2573 | * that we don't do get_block multiple times | ||
| 2574 | * when we write to the same offset and new | ||
| 2575 | * ensures that we do proper zero out for | ||
| 2576 | * partial write. | ||
| 2577 | */ | ||
| 2578 | set_buffer_new(bh_result); | ||
| 2579 | set_buffer_mapped(bh_result); | ||
| 2580 | } | ||
| 2581 | ret = 0; | ||
| 2582 | } | 2537 | } |
| 2583 | 2538 | ||
| 2584 | return ret; | 2539 | map_bh(bh, inode->i_sb, map.m_pblk); |
| 2540 | bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; | ||
| 2541 | |||
| 2542 | if (buffer_unwritten(bh)) { | ||
| 2543 | /* A delayed write to unwritten bh should be marked | ||
| 2544 | * new and mapped. Mapped ensures that we don't do | ||
| 2545 | * get_block multiple times when we write to the same | ||
| 2546 | * offset and new ensures that we do proper zero out | ||
| 2547 | * for partial write. | ||
| 2548 | */ | ||
| 2549 | set_buffer_new(bh); | ||
| 2550 | set_buffer_mapped(bh); | ||
| 2551 | } | ||
| 2552 | return 0; | ||
| 2585 | } | 2553 | } |
| 2586 | 2554 | ||
| 2587 | /* | 2555 | /* |
| @@ -2603,21 +2571,8 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
| 2603 | static int noalloc_get_block_write(struct inode *inode, sector_t iblock, | 2571 | static int noalloc_get_block_write(struct inode *inode, sector_t iblock, |
| 2604 | struct buffer_head *bh_result, int create) | 2572 | struct buffer_head *bh_result, int create) |
| 2605 | { | 2573 | { |
| 2606 | int ret = 0; | ||
| 2607 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; | ||
| 2608 | |||
| 2609 | BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); | 2574 | BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); |
| 2610 | 2575 | return _ext4_get_block(inode, iblock, bh_result, 0); | |
| 2611 | /* | ||
| 2612 | * we don't want to do block allocation in writepage | ||
| 2613 | * so call get_block_wrap with create = 0 | ||
| 2614 | */ | ||
| 2615 | ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0); | ||
| 2616 | if (ret > 0) { | ||
| 2617 | bh_result->b_size = (ret << inode->i_blkbits); | ||
| 2618 | ret = 0; | ||
| 2619 | } | ||
| 2620 | return ret; | ||
| 2621 | } | 2576 | } |
| 2622 | 2577 | ||
| 2623 | static int bget_one(handle_t *handle, struct buffer_head *bh) | 2578 | static int bget_one(handle_t *handle, struct buffer_head *bh) |
| @@ -3644,46 +3599,18 @@ out: | |||
| 3644 | return ret; | 3599 | return ret; |
| 3645 | } | 3600 | } |
| 3646 | 3601 | ||
| 3602 | /* | ||
| 3603 | * ext4_get_block used when preparing for a DIO write or buffer write. | ||
| 3604 | * We allocate an uinitialized extent if blocks haven't been allocated. | ||
| 3605 | * The extent will be converted to initialized after the IO is complete. | ||
| 3606 | */ | ||
| 3647 | static int ext4_get_block_write(struct inode *inode, sector_t iblock, | 3607 | static int ext4_get_block_write(struct inode *inode, sector_t iblock, |
| 3648 | struct buffer_head *bh_result, int create) | 3608 | struct buffer_head *bh_result, int create) |
| 3649 | { | 3609 | { |
| 3650 | handle_t *handle = ext4_journal_current_handle(); | ||
| 3651 | int ret = 0; | ||
| 3652 | unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; | ||
| 3653 | int dio_credits; | ||
| 3654 | int started = 0; | ||
| 3655 | |||
| 3656 | ext4_debug("ext4_get_block_write: inode %lu, create flag %d\n", | 3610 | ext4_debug("ext4_get_block_write: inode %lu, create flag %d\n", |
| 3657 | inode->i_ino, create); | 3611 | inode->i_ino, create); |
| 3658 | /* | 3612 | return _ext4_get_block(inode, iblock, bh_result, |
| 3659 | * ext4_get_block in prepare for a DIO write or buffer write. | 3613 | EXT4_GET_BLOCKS_IO_CREATE_EXT); |
| 3660 | * We allocate an uinitialized extent if blocks haven't been allocated. | ||
| 3661 | * The extent will be converted to initialized after IO complete. | ||
| 3662 | */ | ||
| 3663 | create = EXT4_GET_BLOCKS_IO_CREATE_EXT; | ||
| 3664 | |||
| 3665 | if (!handle) { | ||
| 3666 | if (max_blocks > DIO_MAX_BLOCKS) | ||
| 3667 | max_blocks = DIO_MAX_BLOCKS; | ||
| 3668 | dio_credits = ext4_chunk_trans_blocks(inode, max_blocks); | ||
| 3669 | handle = ext4_journal_start(inode, dio_credits); | ||
| 3670 | if (IS_ERR(handle)) { | ||
| 3671 | ret = PTR_ERR(handle); | ||
| 3672 | goto out; | ||
| 3673 | } | ||
| 3674 | started = 1; | ||
| 3675 | } | ||
| 3676 | |||
| 3677 | ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result, | ||
| 3678 | create); | ||
| 3679 | if (ret > 0) { | ||
| 3680 | bh_result->b_size = (ret << inode->i_blkbits); | ||
| 3681 | ret = 0; | ||
| 3682 | } | ||
| 3683 | if (started) | ||
| 3684 | ext4_journal_stop(handle); | ||
| 3685 | out: | ||
| 3686 | return ret; | ||
| 3687 | } | 3614 | } |
| 3688 | 3615 | ||
| 3689 | static void dump_completed_IO(struct inode * inode) | 3616 | static void dump_completed_IO(struct inode * inode) |
