Commit 8dc207c0 authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: Save stack space by removing fake buffer heads

Struct mpage_da_data and mpage_add_bh_to_extent() use a fake struct
buffer_head which is 104 bytes on an x86_64 system, but only use 24
bytes of the structure.  On systems that use a spinlock for atomic_t,
the stack savings will be even greater.

It turns out that using a fake struct buffer_head doesn't even save
that much code, and it makes the code more confusing since it's not
used as a "real" buffer head.  So just store pass b_size and b_state
in mpage_add_bh_to_extent(), and store b_size, b_state, and b_block_nr
in the mpage_da_data structure.
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent ed5bde0b
...@@ -1703,7 +1703,9 @@ static void ext4_da_page_release_reservation(struct page *page, ...@@ -1703,7 +1703,9 @@ static void ext4_da_page_release_reservation(struct page *page,
struct mpage_da_data { struct mpage_da_data {
struct inode *inode; struct inode *inode;
struct buffer_head lbh; /* extent of blocks */ sector_t b_blocknr; /* start block number of extent */
size_t b_size; /* size of extent */
unsigned long b_state; /* state of the extent */
unsigned long first_page, next_page; /* extent of pages */ unsigned long first_page, next_page; /* extent of pages */
struct writeback_control *wbc; struct writeback_control *wbc;
int io_done; int io_done;
...@@ -1737,7 +1739,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) ...@@ -1737,7 +1739,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
/* /*
* We need to start from the first_page to the next_page - 1 * We need to start from the first_page to the next_page - 1
* to make sure we also write the mapped dirty buffer_heads. * to make sure we also write the mapped dirty buffer_heads.
* If we look at mpd->lbh.b_blocknr we would only be looking * If we look at mpd->b_blocknr we would only be looking
* at the currently mapped buffer_heads. * at the currently mapped buffer_heads.
*/ */
index = mpd->first_page; index = mpd->first_page;
...@@ -1975,7 +1977,7 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock, ...@@ -1975,7 +1977,7 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
/* /*
* mpage_da_map_blocks - go through given space * mpage_da_map_blocks - go through given space
* *
* @mpd->lbh - bh describing space * @mpd - bh describing space
* *
* The function skips space we know is already mapped to disk blocks. * The function skips space we know is already mapped to disk blocks.
* *
...@@ -1984,18 +1986,18 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) ...@@ -1984,18 +1986,18 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
{ {
int err = 0; int err = 0;
struct buffer_head new; struct buffer_head new;
struct buffer_head *lbh = &mpd->lbh;
sector_t next; sector_t next;
/* /*
* We consider only non-mapped and non-allocated blocks * We consider only non-mapped and non-allocated blocks
*/ */
if (buffer_mapped(lbh) && !buffer_delay(lbh)) if ((mpd->b_state & (1 << BH_Mapped)) &&
!(mpd->b_state & (1 << BH_Delay)))
return 0; return 0;
new.b_state = lbh->b_state; new.b_state = mpd->b_state;
new.b_blocknr = 0; new.b_blocknr = 0;
new.b_size = lbh->b_size; new.b_size = mpd->b_size;
next = lbh->b_blocknr; next = mpd->b_blocknr;
/* /*
* If we didn't accumulate anything * If we didn't accumulate anything
* to write simply return * to write simply return
...@@ -2031,7 +2033,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) ...@@ -2031,7 +2033,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
"%zd with error %d\n", "%zd with error %d\n",
__func__, mpd->inode->i_ino, __func__, mpd->inode->i_ino,
(unsigned long long)next, (unsigned long long)next,
lbh->b_size >> mpd->inode->i_blkbits, err); mpd->b_size >> mpd->inode->i_blkbits, err);
printk(KERN_EMERG "This should not happen.!! " printk(KERN_EMERG "This should not happen.!! "
"Data will be lost\n"); "Data will be lost\n");
if (err == -ENOSPC) { if (err == -ENOSPC) {
...@@ -2039,7 +2041,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) ...@@ -2039,7 +2041,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
} }
/* invlaidate all the pages */ /* invlaidate all the pages */
ext4_da_block_invalidatepages(mpd, next, ext4_da_block_invalidatepages(mpd, next,
lbh->b_size >> mpd->inode->i_blkbits); mpd->b_size >> mpd->inode->i_blkbits);
return err; return err;
} }
BUG_ON(new.b_size == 0); BUG_ON(new.b_size == 0);
...@@ -2051,7 +2053,8 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) ...@@ -2051,7 +2053,8 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
* If blocks are delayed marked, we need to * If blocks are delayed marked, we need to
* put actual blocknr and drop delayed bit * put actual blocknr and drop delayed bit
*/ */
if (buffer_delay(lbh) || buffer_unwritten(lbh)) if ((mpd->b_state & (1 << BH_Delay)) ||
(mpd->b_state & (1 << BH_Unwritten)))
mpage_put_bnr_to_bhs(mpd, next, &new); mpage_put_bnr_to_bhs(mpd, next, &new);
return 0; return 0;
...@@ -2070,12 +2073,11 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) ...@@ -2070,12 +2073,11 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
* the function is used to collect contig. blocks in same state * the function is used to collect contig. blocks in same state
*/ */
static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
sector_t logical, struct buffer_head *bh) sector_t logical, size_t b_size,
unsigned long b_state)
{ {
sector_t next; sector_t next;
size_t b_size = bh->b_size; int nrblocks = mpd->b_size >> mpd->inode->i_blkbits;
struct buffer_head *lbh = &mpd->lbh;
int nrblocks = lbh->b_size >> mpd->inode->i_blkbits;
/* check if thereserved journal credits might overflow */ /* check if thereserved journal credits might overflow */
if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) { if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) {
...@@ -2102,19 +2104,19 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, ...@@ -2102,19 +2104,19 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
/* /*
* First block in the extent * First block in the extent
*/ */
if (lbh->b_size == 0) { if (mpd->b_size == 0) {
lbh->b_blocknr = logical; mpd->b_blocknr = logical;
lbh->b_size = b_size; mpd->b_size = b_size;
lbh->b_state = bh->b_state & BH_FLAGS; mpd->b_state = b_state & BH_FLAGS;
return; return;
} }
next = lbh->b_blocknr + nrblocks; next = mpd->b_blocknr + nrblocks;
/* /*
* Can we merge the block to our big extent? * Can we merge the block to our big extent?
*/ */
if (logical == next && (bh->b_state & BH_FLAGS) == lbh->b_state) { if (logical == next && (b_state & BH_FLAGS) == mpd->b_state) {
lbh->b_size += b_size; mpd->b_size += b_size;
return; return;
} }
...@@ -2143,7 +2145,7 @@ static int __mpage_da_writepage(struct page *page, ...@@ -2143,7 +2145,7 @@ static int __mpage_da_writepage(struct page *page,
{ {
struct mpage_da_data *mpd = data; struct mpage_da_data *mpd = data;
struct inode *inode = mpd->inode; struct inode *inode = mpd->inode;
struct buffer_head *bh, *head, fake; struct buffer_head *bh, *head;
sector_t logical; sector_t logical;
if (mpd->io_done) { if (mpd->io_done) {
...@@ -2185,9 +2187,9 @@ static int __mpage_da_writepage(struct page *page, ...@@ -2185,9 +2187,9 @@ static int __mpage_da_writepage(struct page *page,
/* /*
* ... and blocks * ... and blocks
*/ */
mpd->lbh.b_size = 0; mpd->b_size = 0;
mpd->lbh.b_state = 0; mpd->b_state = 0;
mpd->lbh.b_blocknr = 0; mpd->b_blocknr = 0;
} }
mpd->next_page = page->index + 1; mpd->next_page = page->index + 1;
...@@ -2195,16 +2197,8 @@ static int __mpage_da_writepage(struct page *page, ...@@ -2195,16 +2197,8 @@ static int __mpage_da_writepage(struct page *page,
(PAGE_CACHE_SHIFT - inode->i_blkbits); (PAGE_CACHE_SHIFT - inode->i_blkbits);
if (!page_has_buffers(page)) { if (!page_has_buffers(page)) {
/* mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
* There is no attached buffer heads yet (mmap?) (1 << BH_Dirty) | (1 << BH_Uptodate));
* we treat the page asfull of dirty blocks
*/
bh = &fake;
bh->b_size = PAGE_CACHE_SIZE;
bh->b_state = 0;
set_buffer_dirty(bh);
set_buffer_uptodate(bh);
mpage_add_bh_to_extent(mpd, logical, bh);
if (mpd->io_done) if (mpd->io_done)
return MPAGE_DA_EXTENT_TAIL; return MPAGE_DA_EXTENT_TAIL;
} else { } else {
...@@ -2222,8 +2216,10 @@ static int __mpage_da_writepage(struct page *page, ...@@ -2222,8 +2216,10 @@ static int __mpage_da_writepage(struct page *page,
* with the page in ext4_da_writepage * with the page in ext4_da_writepage
*/ */
if (buffer_dirty(bh) && if (buffer_dirty(bh) &&
(!buffer_mapped(bh) || buffer_delay(bh))) { (!buffer_mapped(bh) || buffer_delay(bh))) {
mpage_add_bh_to_extent(mpd, logical, bh); mpage_add_bh_to_extent(mpd, logical,
bh->b_size,
bh->b_state);
if (mpd->io_done) if (mpd->io_done)
return MPAGE_DA_EXTENT_TAIL; return MPAGE_DA_EXTENT_TAIL;
} else if (buffer_dirty(bh) && (buffer_mapped(bh))) { } else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
...@@ -2235,9 +2231,8 @@ static int __mpage_da_writepage(struct page *page, ...@@ -2235,9 +2231,8 @@ static int __mpage_da_writepage(struct page *page,
* unmapped buffer_head later we need to * unmapped buffer_head later we need to
* use the b_state flag of that buffer_head. * use the b_state flag of that buffer_head.
*/ */
if (mpd->lbh.b_size == 0) if (mpd->b_size == 0)
mpd->lbh.b_state = mpd->b_state = bh->b_state & BH_FLAGS;
bh->b_state & BH_FLAGS;
} }
logical++; logical++;
} while ((bh = bh->b_this_page) != head); } while ((bh = bh->b_this_page) != head);
...@@ -2263,9 +2258,9 @@ static int mpage_da_writepages(struct address_space *mapping, ...@@ -2263,9 +2258,9 @@ static int mpage_da_writepages(struct address_space *mapping,
{ {
int ret; int ret;
mpd->lbh.b_size = 0; mpd->b_size = 0;
mpd->lbh.b_state = 0; mpd->b_state = 0;
mpd->lbh.b_blocknr = 0; mpd->b_blocknr = 0;
mpd->first_page = 0; mpd->first_page = 0;
mpd->next_page = 0; mpd->next_page = 0;
mpd->io_done = 0; mpd->io_done = 0;
......
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