aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-02-23 06:46:01 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-02-23 06:46:01 -0500
commit8dc207c0e7a259e7122ddfaf56b8bbbc3c92d685 (patch)
tree68f3cfcf4d2f55c3e7fd8128b30c80b6d54679b1 /fs
parented5bde0bf8995d7d8c0b5a9c33e624a945f333ef (diff)
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: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/inode.c83
1 files changed, 39 insertions, 44 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 924ba8afc227..008b28a859d0 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1703,7 +1703,9 @@ static void ext4_da_page_release_reservation(struct page *page,
1703 1703
1704struct mpage_da_data { 1704struct mpage_da_data {
1705 struct inode *inode; 1705 struct inode *inode;
1706 struct buffer_head lbh; /* extent of blocks */ 1706 sector_t b_blocknr; /* start block number of extent */
1707 size_t b_size; /* size of extent */
1708 unsigned long b_state; /* state of the extent */
1707 unsigned long first_page, next_page; /* extent of pages */ 1709 unsigned long first_page, next_page; /* extent of pages */
1708 struct writeback_control *wbc; 1710 struct writeback_control *wbc;
1709 int io_done; 1711 int io_done;
@@ -1737,7 +1739,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
1737 /* 1739 /*
1738 * We need to start from the first_page to the next_page - 1 1740 * We need to start from the first_page to the next_page - 1
1739 * to make sure we also write the mapped dirty buffer_heads. 1741 * to make sure we also write the mapped dirty buffer_heads.
1740 * If we look at mpd->lbh.b_blocknr we would only be looking 1742 * If we look at mpd->b_blocknr we would only be looking
1741 * at the currently mapped buffer_heads. 1743 * at the currently mapped buffer_heads.
1742 */ 1744 */
1743 index = mpd->first_page; 1745 index = mpd->first_page;
@@ -1975,7 +1977,7 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock,
1975/* 1977/*
1976 * mpage_da_map_blocks - go through given space 1978 * mpage_da_map_blocks - go through given space
1977 * 1979 *
1978 * @mpd->lbh - bh describing space 1980 * @mpd - bh describing space
1979 * 1981 *
1980 * The function skips space we know is already mapped to disk blocks. 1982 * The function skips space we know is already mapped to disk blocks.
1981 * 1983 *
@@ -1984,18 +1986,18 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
1984{ 1986{
1985 int err = 0; 1987 int err = 0;
1986 struct buffer_head new; 1988 struct buffer_head new;
1987 struct buffer_head *lbh = &mpd->lbh;
1988 sector_t next; 1989 sector_t next;
1989 1990
1990 /* 1991 /*
1991 * We consider only non-mapped and non-allocated blocks 1992 * We consider only non-mapped and non-allocated blocks
1992 */ 1993 */
1993 if (buffer_mapped(lbh) && !buffer_delay(lbh)) 1994 if ((mpd->b_state & (1 << BH_Mapped)) &&
1995 !(mpd->b_state & (1 << BH_Delay)))
1994 return 0; 1996 return 0;
1995 new.b_state = lbh->b_state; 1997 new.b_state = mpd->b_state;
1996 new.b_blocknr = 0; 1998 new.b_blocknr = 0;
1997 new.b_size = lbh->b_size; 1999 new.b_size = mpd->b_size;
1998 next = lbh->b_blocknr; 2000 next = mpd->b_blocknr;
1999 /* 2001 /*
2000 * If we didn't accumulate anything 2002 * If we didn't accumulate anything
2001 * to write simply return 2003 * to write simply return
@@ -2031,7 +2033,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
2031 "%zd with error %d\n", 2033 "%zd with error %d\n",
2032 __func__, mpd->inode->i_ino, 2034 __func__, mpd->inode->i_ino,
2033 (unsigned long long)next, 2035 (unsigned long long)next,
2034 lbh->b_size >> mpd->inode->i_blkbits, err); 2036 mpd->b_size >> mpd->inode->i_blkbits, err);
2035 printk(KERN_EMERG "This should not happen.!! " 2037 printk(KERN_EMERG "This should not happen.!! "
2036 "Data will be lost\n"); 2038 "Data will be lost\n");
2037 if (err == -ENOSPC) { 2039 if (err == -ENOSPC) {
@@ -2039,7 +2041,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
2039 } 2041 }
2040 /* invlaidate all the pages */ 2042 /* invlaidate all the pages */
2041 ext4_da_block_invalidatepages(mpd, next, 2043 ext4_da_block_invalidatepages(mpd, next,
2042 lbh->b_size >> mpd->inode->i_blkbits); 2044 mpd->b_size >> mpd->inode->i_blkbits);
2043 return err; 2045 return err;
2044 } 2046 }
2045 BUG_ON(new.b_size == 0); 2047 BUG_ON(new.b_size == 0);
@@ -2051,7 +2053,8 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
2051 * If blocks are delayed marked, we need to 2053 * If blocks are delayed marked, we need to
2052 * put actual blocknr and drop delayed bit 2054 * put actual blocknr and drop delayed bit
2053 */ 2055 */
2054 if (buffer_delay(lbh) || buffer_unwritten(lbh)) 2056 if ((mpd->b_state & (1 << BH_Delay)) ||
2057 (mpd->b_state & (1 << BH_Unwritten)))
2055 mpage_put_bnr_to_bhs(mpd, next, &new); 2058 mpage_put_bnr_to_bhs(mpd, next, &new);
2056 2059
2057 return 0; 2060 return 0;
@@ -2070,12 +2073,11 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd)
2070 * the function is used to collect contig. blocks in same state 2073 * the function is used to collect contig. blocks in same state
2071 */ 2074 */
2072static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, 2075static void mpage_add_bh_to_extent(struct mpage_da_data *mpd,
2073 sector_t logical, struct buffer_head *bh) 2076 sector_t logical, size_t b_size,
2077 unsigned long b_state)
2074{ 2078{
2075 sector_t next; 2079 sector_t next;
2076 size_t b_size = bh->b_size; 2080 int nrblocks = mpd->b_size >> mpd->inode->i_blkbits;
2077 struct buffer_head *lbh = &mpd->lbh;
2078 int nrblocks = lbh->b_size >> mpd->inode->i_blkbits;
2079 2081
2080 /* check if thereserved journal credits might overflow */ 2082 /* check if thereserved journal credits might overflow */
2081 if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) { 2083 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 /* 2104 /*
2103 * First block in the extent 2105 * First block in the extent
2104 */ 2106 */
2105 if (lbh->b_size == 0) { 2107 if (mpd->b_size == 0) {
2106 lbh->b_blocknr = logical; 2108 mpd->b_blocknr = logical;
2107 lbh->b_size = b_size; 2109 mpd->b_size = b_size;
2108 lbh->b_state = bh->b_state & BH_FLAGS; 2110 mpd->b_state = b_state & BH_FLAGS;
2109 return; 2111 return;
2110 } 2112 }
2111 2113
2112 next = lbh->b_blocknr + nrblocks; 2114 next = mpd->b_blocknr + nrblocks;
2113 /* 2115 /*
2114 * Can we merge the block to our big extent? 2116 * Can we merge the block to our big extent?
2115 */ 2117 */
2116 if (logical == next && (bh->b_state & BH_FLAGS) == lbh->b_state) { 2118 if (logical == next && (b_state & BH_FLAGS) == mpd->b_state) {
2117 lbh->b_size += b_size; 2119 mpd->b_size += b_size;
2118 return; 2120 return;
2119 } 2121 }
2120 2122
@@ -2143,7 +2145,7 @@ static int __mpage_da_writepage(struct page *page,
2143{ 2145{
2144 struct mpage_da_data *mpd = data; 2146 struct mpage_da_data *mpd = data;
2145 struct inode *inode = mpd->inode; 2147 struct inode *inode = mpd->inode;
2146 struct buffer_head *bh, *head, fake; 2148 struct buffer_head *bh, *head;
2147 sector_t logical; 2149 sector_t logical;
2148 2150
2149 if (mpd->io_done) { 2151 if (mpd->io_done) {
@@ -2185,9 +2187,9 @@ static int __mpage_da_writepage(struct page *page,
2185 /* 2187 /*
2186 * ... and blocks 2188 * ... and blocks
2187 */ 2189 */
2188 mpd->lbh.b_size = 0; 2190 mpd->b_size = 0;
2189 mpd->lbh.b_state = 0; 2191 mpd->b_state = 0;
2190 mpd->lbh.b_blocknr = 0; 2192 mpd->b_blocknr = 0;
2191 } 2193 }
2192 2194
2193 mpd->next_page = page->index + 1; 2195 mpd->next_page = page->index + 1;
@@ -2195,16 +2197,8 @@ static int __mpage_da_writepage(struct page *page,
2195 (PAGE_CACHE_SHIFT - inode->i_blkbits); 2197 (PAGE_CACHE_SHIFT - inode->i_blkbits);
2196 2198
2197 if (!page_has_buffers(page)) { 2199 if (!page_has_buffers(page)) {
2198 /* 2200 mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
2199 * There is no attached buffer heads yet (mmap?) 2201 (1 << BH_Dirty) | (1 << BH_Uptodate));
2200 * we treat the page asfull of dirty blocks
2201 */
2202 bh = &fake;
2203 bh->b_size = PAGE_CACHE_SIZE;
2204 bh->b_state = 0;
2205 set_buffer_dirty(bh);
2206 set_buffer_uptodate(bh);
2207 mpage_add_bh_to_extent(mpd, logical, bh);
2208 if (mpd->io_done) 2202 if (mpd->io_done)
2209 return MPAGE_DA_EXTENT_TAIL; 2203 return MPAGE_DA_EXTENT_TAIL;
2210 } else { 2204 } else {
@@ -2222,8 +2216,10 @@ static int __mpage_da_writepage(struct page *page,
2222 * with the page in ext4_da_writepage 2216 * with the page in ext4_da_writepage
2223 */ 2217 */
2224 if (buffer_dirty(bh) && 2218 if (buffer_dirty(bh) &&
2225 (!buffer_mapped(bh) || buffer_delay(bh))) { 2219 (!buffer_mapped(bh) || buffer_delay(bh))) {
2226 mpage_add_bh_to_extent(mpd, logical, bh); 2220 mpage_add_bh_to_extent(mpd, logical,
2221 bh->b_size,
2222 bh->b_state);
2227 if (mpd->io_done) 2223 if (mpd->io_done)
2228 return MPAGE_DA_EXTENT_TAIL; 2224 return MPAGE_DA_EXTENT_TAIL;
2229 } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { 2225 } else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
@@ -2235,9 +2231,8 @@ static int __mpage_da_writepage(struct page *page,
2235 * unmapped buffer_head later we need to 2231 * unmapped buffer_head later we need to
2236 * use the b_state flag of that buffer_head. 2232 * use the b_state flag of that buffer_head.
2237 */ 2233 */
2238 if (mpd->lbh.b_size == 0) 2234 if (mpd->b_size == 0)
2239 mpd->lbh.b_state = 2235 mpd->b_state = bh->b_state & BH_FLAGS;
2240 bh->b_state & BH_FLAGS;
2241 } 2236 }
2242 logical++; 2237 logical++;
2243 } while ((bh = bh->b_this_page) != head); 2238 } while ((bh = bh->b_this_page) != head);
@@ -2263,9 +2258,9 @@ static int mpage_da_writepages(struct address_space *mapping,
2263{ 2258{
2264 int ret; 2259 int ret;
2265 2260
2266 mpd->lbh.b_size = 0; 2261 mpd->b_size = 0;
2267 mpd->lbh.b_state = 0; 2262 mpd->b_state = 0;
2268 mpd->lbh.b_blocknr = 0; 2263 mpd->b_blocknr = 0;
2269 mpd->first_page = 0; 2264 mpd->first_page = 0;
2270 mpd->next_page = 0; 2265 mpd->next_page = 0;
2271 mpd->io_done = 0; 2266 mpd->io_done = 0;