Commit 2ed88685 authored by Theodore Ts'o's avatar Theodore Ts'o

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: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent e35fd660
...@@ -128,14 +128,14 @@ static int ext4_readdir(struct file *filp, ...@@ -128,14 +128,14 @@ static int ext4_readdir(struct file *filp,
offset = filp->f_pos & (sb->s_blocksize - 1); offset = filp->f_pos & (sb->s_blocksize - 1);
while (!error && !stored && filp->f_pos < inode->i_size) { while (!error && !stored && filp->f_pos < inode->i_size) {
ext4_lblk_t blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); struct ext4_map_blocks map;
struct buffer_head map_bh;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
map_bh.b_state = 0; map.m_lblk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb);
err = ext4_get_blocks(NULL, inode, blk, 1, &map_bh, 0); map.m_len = 1;
err = ext4_map_blocks(NULL, inode, &map, 0);
if (err > 0) { if (err > 0) {
pgoff_t index = map_bh.b_blocknr >> pgoff_t index = map.m_pblk >>
(PAGE_CACHE_SHIFT - inode->i_blkbits); (PAGE_CACHE_SHIFT - inode->i_blkbits);
if (!ra_has_index(&filp->f_ra, index)) if (!ra_has_index(&filp->f_ra, index))
page_cache_sync_readahead( page_cache_sync_readahead(
...@@ -143,7 +143,7 @@ static int ext4_readdir(struct file *filp, ...@@ -143,7 +143,7 @@ static int ext4_readdir(struct file *filp,
&filp->f_ra, filp, &filp->f_ra, filp,
index, 1); index, 1);
filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
bh = ext4_bread(NULL, inode, blk, 0, &err); bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err);
} }
/* /*
......
...@@ -3667,13 +3667,12 @@ static void ext4_falloc_update_inode(struct inode *inode, ...@@ -3667,13 +3667,12 @@ static void ext4_falloc_update_inode(struct inode *inode,
long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
{ {
handle_t *handle; handle_t *handle;
ext4_lblk_t block;
loff_t new_size; loff_t new_size;
unsigned int max_blocks; unsigned int max_blocks;
int ret = 0; int ret = 0;
int ret2 = 0; int ret2 = 0;
int retries = 0; int retries = 0;
struct buffer_head map_bh; struct ext4_map_blocks map;
unsigned int credits, blkbits = inode->i_blkbits; unsigned int credits, blkbits = inode->i_blkbits;
/* /*
...@@ -3687,13 +3686,13 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) ...@@ -3687,13 +3686,13 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
return -ENODEV; return -ENODEV;
block = offset >> blkbits; map.m_lblk = offset >> blkbits;
/* /*
* We can't just convert len to max_blocks because * We can't just convert len to max_blocks because
* If blocksize = 4096 offset = 3072 and len = 2048 * If blocksize = 4096 offset = 3072 and len = 2048
*/ */
max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
- block; - map.m_lblk;
/* /*
* credits to insert 1 extent into extent tree * credits to insert 1 extent into extent tree
*/ */
...@@ -3706,16 +3705,14 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) ...@@ -3706,16 +3705,14 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
} }
retry: retry:
while (ret >= 0 && ret < max_blocks) { while (ret >= 0 && ret < max_blocks) {
block = block + ret; map.m_lblk = map.m_lblk + ret;
max_blocks = max_blocks - ret; map.m_len = max_blocks = max_blocks - ret;
handle = ext4_journal_start(inode, credits); handle = ext4_journal_start(inode, credits);
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
ret = PTR_ERR(handle); ret = PTR_ERR(handle);
break; break;
} }
map_bh.b_state = 0; ret = ext4_map_blocks(handle, inode, &map,
ret = ext4_get_blocks(handle, inode, block,
max_blocks, &map_bh,
EXT4_GET_BLOCKS_CREATE_UNINIT_EXT); EXT4_GET_BLOCKS_CREATE_UNINIT_EXT);
if (ret <= 0) { if (ret <= 0) {
#ifdef EXT4FS_DEBUG #ifdef EXT4FS_DEBUG
...@@ -3729,14 +3726,14 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) ...@@ -3729,14 +3726,14 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
ret2 = ext4_journal_stop(handle); ret2 = ext4_journal_stop(handle);
break; break;
} }
if ((block + ret) >= (EXT4_BLOCK_ALIGN(offset + len, if ((map.m_lblk + ret) >= (EXT4_BLOCK_ALIGN(offset + len,
blkbits) >> blkbits)) blkbits) >> blkbits))
new_size = offset + len; new_size = offset + len;
else else
new_size = (block + ret) << blkbits; new_size = (map.m_lblk + ret) << blkbits;
ext4_falloc_update_inode(inode, mode, new_size, ext4_falloc_update_inode(inode, mode, new_size,
buffer_new(&map_bh)); (map.m_flags & EXT4_MAP_NEW));
ext4_mark_inode_dirty(handle, inode); ext4_mark_inode_dirty(handle, inode);
ret2 = ext4_journal_stop(handle); ret2 = ext4_journal_stop(handle);
if (ret2) if (ret2)
...@@ -3765,42 +3762,39 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, ...@@ -3765,42 +3762,39 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
ssize_t len) ssize_t len)
{ {
handle_t *handle; handle_t *handle;
ext4_lblk_t block;
unsigned int max_blocks; unsigned int max_blocks;
int ret = 0; int ret = 0;
int ret2 = 0; int ret2 = 0;
struct buffer_head map_bh; struct ext4_map_blocks map;
unsigned int credits, blkbits = inode->i_blkbits; unsigned int credits, blkbits = inode->i_blkbits;
block = offset >> blkbits; map.m_lblk = offset >> blkbits;
/* /*
* We can't just convert len to max_blocks because * We can't just convert len to max_blocks because
* If blocksize = 4096 offset = 3072 and len = 2048 * If blocksize = 4096 offset = 3072 and len = 2048
*/ */
max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) max_blocks = ((EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) -
- block; map.m_lblk);
/* /*
* credits to insert 1 extent into extent tree * credits to insert 1 extent into extent tree
*/ */
credits = ext4_chunk_trans_blocks(inode, max_blocks); credits = ext4_chunk_trans_blocks(inode, max_blocks);
while (ret >= 0 && ret < max_blocks) { while (ret >= 0 && ret < max_blocks) {
block = block + ret; map.m_lblk += ret;
max_blocks = max_blocks - ret; map.m_len = (max_blocks -= ret);
handle = ext4_journal_start(inode, credits); handle = ext4_journal_start(inode, credits);
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
ret = PTR_ERR(handle); ret = PTR_ERR(handle);
break; break;
} }
map_bh.b_state = 0; ret = ext4_map_blocks(handle, inode, &map,
ret = ext4_get_blocks(handle, inode, block,
max_blocks, &map_bh,
EXT4_GET_BLOCKS_IO_CONVERT_EXT); EXT4_GET_BLOCKS_IO_CONVERT_EXT);
if (ret <= 0) { if (ret <= 0) {
WARN_ON(ret <= 0); WARN_ON(ret <= 0);
printk(KERN_ERR "%s: ext4_ext_map_blocks " printk(KERN_ERR "%s: ext4_ext_map_blocks "
"returned error inode#%lu, block=%u, " "returned error inode#%lu, block=%u, "
"max_blocks=%u", __func__, "max_blocks=%u", __func__,
inode->i_ino, block, max_blocks); inode->i_ino, map.m_lblk, map.m_len);
} }
ext4_mark_inode_dirty(handle, inode); ext4_mark_inode_dirty(handle, inode);
ret2 = ext4_journal_stop(handle); ret2 = ext4_journal_stop(handle);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment