diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-02-23 06:46:01 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-02-23 06:46:01 -0500 |
commit | 8dc207c0e7a259e7122ddfaf56b8bbbc3c92d685 (patch) | |
tree | 68f3cfcf4d2f55c3e7fd8128b30c80b6d54679b1 /fs/ext4/inode.c | |
parent | ed5bde0bf8995d7d8c0b5a9c33e624a945f333ef (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/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 83 |
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 | ||
1704 | struct mpage_da_data { | 1704 | struct 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 | */ |
2072 | static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, | 2075 | static 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; |