diff options
author | Theodore Ts'o <tytso@mit.edu> | 2010-05-16 20:00:00 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-05-16 20:00:00 -0400 |
commit | 2ed886852adfcb070bf350e66a0da0d98b2f3ab5 (patch) | |
tree | bcec0a1004f413b70087e2c43097892f87f21cc3 /fs/ext4 | |
parent | e35fd6609b2fee54484d520deccb8f18bf7d38f3 (diff) |
ext4: Convert callers of ext4_get_blocks() to use ext4_map_blocks()
This saves a huge amount of stack space by avoiding unnecesary struct
buffer_head's from being allocated on the stack.
In addition, to make the code easier to understand, collapse and
refactor ext4_get_block(), ext4_get_block_write(),
noalloc_get_block_write(), into a single function.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-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) |