diff options
-rw-r--r-- | fs/ocfs2/suballoc.c | 159 | ||||
-rw-r--r-- | fs/ocfs2/suballoc.h | 21 |
2 files changed, 180 insertions, 0 deletions
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index e7edda8c6a11..8a286f54dca1 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
@@ -57,6 +57,12 @@ struct ocfs2_suballoc_result { | |||
57 | u64 sr_bg_blkno; /* The bg we allocated from. Set | 57 | u64 sr_bg_blkno; /* The bg we allocated from. Set |
58 | to 0 when a block group is | 58 | to 0 when a block group is |
59 | contiguous. */ | 59 | contiguous. */ |
60 | u64 sr_bg_stable_blkno; /* | ||
61 | * Doesn't change, always | ||
62 | * set to target block | ||
63 | * group descriptor | ||
64 | * block. | ||
65 | */ | ||
60 | u64 sr_blkno; /* The first allocated block */ | 66 | u64 sr_blkno; /* The first allocated block */ |
61 | unsigned int sr_bit_offset; /* The bit in the bg */ | 67 | unsigned int sr_bit_offset; /* The bit in the bg */ |
62 | unsigned int sr_bits; /* How many bits we claimed */ | 68 | unsigned int sr_bits; /* How many bits we claimed */ |
@@ -149,6 +155,10 @@ void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac) | |||
149 | brelse(ac->ac_bh); | 155 | brelse(ac->ac_bh); |
150 | ac->ac_bh = NULL; | 156 | ac->ac_bh = NULL; |
151 | ac->ac_resv = NULL; | 157 | ac->ac_resv = NULL; |
158 | if (ac->ac_find_loc_priv) { | ||
159 | kfree(ac->ac_find_loc_priv); | ||
160 | ac->ac_find_loc_priv = NULL; | ||
161 | } | ||
152 | } | 162 | } |
153 | 163 | ||
154 | void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac) | 164 | void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac) |
@@ -1689,6 +1699,15 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, | |||
1689 | if (!ret) | 1699 | if (!ret) |
1690 | ocfs2_bg_discontig_fix_result(ac, gd, res); | 1700 | ocfs2_bg_discontig_fix_result(ac, gd, res); |
1691 | 1701 | ||
1702 | /* | ||
1703 | * sr_bg_blkno might have been changed by | ||
1704 | * ocfs2_bg_discontig_fix_result | ||
1705 | */ | ||
1706 | res->sr_bg_stable_blkno = group_bh->b_blocknr; | ||
1707 | |||
1708 | if (ac->ac_find_loc_only) | ||
1709 | goto out_loc_only; | ||
1710 | |||
1692 | ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, | 1711 | ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, |
1693 | res->sr_bits, | 1712 | res->sr_bits, |
1694 | le16_to_cpu(gd->bg_chain)); | 1713 | le16_to_cpu(gd->bg_chain)); |
@@ -1702,6 +1721,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, | |||
1702 | if (ret < 0) | 1721 | if (ret < 0) |
1703 | mlog_errno(ret); | 1722 | mlog_errno(ret); |
1704 | 1723 | ||
1724 | out_loc_only: | ||
1705 | *bits_left = le16_to_cpu(gd->bg_free_bits_count); | 1725 | *bits_left = le16_to_cpu(gd->bg_free_bits_count); |
1706 | 1726 | ||
1707 | out: | 1727 | out: |
@@ -1780,6 +1800,11 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, | |||
1780 | if (!status) | 1800 | if (!status) |
1781 | ocfs2_bg_discontig_fix_result(ac, bg, res); | 1801 | ocfs2_bg_discontig_fix_result(ac, bg, res); |
1782 | 1802 | ||
1803 | /* | ||
1804 | * sr_bg_blkno might have been changed by | ||
1805 | * ocfs2_bg_discontig_fix_result | ||
1806 | */ | ||
1807 | res->sr_bg_stable_blkno = group_bh->b_blocknr; | ||
1783 | 1808 | ||
1784 | /* | 1809 | /* |
1785 | * Keep track of previous block descriptor read. When | 1810 | * Keep track of previous block descriptor read. When |
@@ -1806,6 +1831,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, | |||
1806 | } | 1831 | } |
1807 | } | 1832 | } |
1808 | 1833 | ||
1834 | if (ac->ac_find_loc_only) | ||
1835 | goto out_loc_only; | ||
1836 | |||
1809 | status = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, | 1837 | status = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, |
1810 | ac->ac_bh, res->sr_bits, | 1838 | ac->ac_bh, res->sr_bits, |
1811 | chain); | 1839 | chain); |
@@ -1828,6 +1856,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, | |||
1828 | mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, | 1856 | mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, |
1829 | (unsigned long long)le64_to_cpu(fe->i_blkno)); | 1857 | (unsigned long long)le64_to_cpu(fe->i_blkno)); |
1830 | 1858 | ||
1859 | out_loc_only: | ||
1831 | *bits_left = le16_to_cpu(bg->bg_free_bits_count); | 1860 | *bits_left = le16_to_cpu(bg->bg_free_bits_count); |
1832 | bail: | 1861 | bail: |
1833 | brelse(group_bh); | 1862 | brelse(group_bh); |
@@ -2023,6 +2052,136 @@ static inline void ocfs2_save_inode_ac_group(struct inode *dir, | |||
2023 | OCFS2_I(dir)->ip_last_used_slot = ac->ac_alloc_slot; | 2052 | OCFS2_I(dir)->ip_last_used_slot = ac->ac_alloc_slot; |
2024 | } | 2053 | } |
2025 | 2054 | ||
2055 | int ocfs2_find_new_inode_loc(struct inode *dir, | ||
2056 | struct buffer_head *parent_fe_bh, | ||
2057 | struct ocfs2_alloc_context *ac, | ||
2058 | u64 *fe_blkno) | ||
2059 | { | ||
2060 | int ret; | ||
2061 | handle_t *handle = NULL; | ||
2062 | struct ocfs2_suballoc_result *res; | ||
2063 | |||
2064 | BUG_ON(!ac); | ||
2065 | BUG_ON(ac->ac_bits_given != 0); | ||
2066 | BUG_ON(ac->ac_bits_wanted != 1); | ||
2067 | BUG_ON(ac->ac_which != OCFS2_AC_USE_INODE); | ||
2068 | |||
2069 | res = kzalloc(sizeof(*res), GFP_NOFS); | ||
2070 | if (res == NULL) { | ||
2071 | ret = -ENOMEM; | ||
2072 | mlog_errno(ret); | ||
2073 | goto out; | ||
2074 | } | ||
2075 | |||
2076 | ocfs2_init_inode_ac_group(dir, parent_fe_bh, ac); | ||
2077 | |||
2078 | /* | ||
2079 | * The handle started here is for chain relink. Alternatively, | ||
2080 | * we could just disable relink for these calls. | ||
2081 | */ | ||
2082 | handle = ocfs2_start_trans(OCFS2_SB(dir->i_sb), OCFS2_SUBALLOC_ALLOC); | ||
2083 | if (IS_ERR(handle)) { | ||
2084 | ret = PTR_ERR(handle); | ||
2085 | handle = NULL; | ||
2086 | mlog_errno(ret); | ||
2087 | goto out; | ||
2088 | } | ||
2089 | |||
2090 | /* | ||
2091 | * This will instruct ocfs2_claim_suballoc_bits and | ||
2092 | * ocfs2_search_one_group to search but save actual allocation | ||
2093 | * for later. | ||
2094 | */ | ||
2095 | ac->ac_find_loc_only = 1; | ||
2096 | |||
2097 | ret = ocfs2_claim_suballoc_bits(ac, handle, 1, 1, res); | ||
2098 | if (ret < 0) { | ||
2099 | mlog_errno(ret); | ||
2100 | goto out; | ||
2101 | } | ||
2102 | |||
2103 | ac->ac_find_loc_priv = res; | ||
2104 | *fe_blkno = res->sr_blkno; | ||
2105 | |||
2106 | out: | ||
2107 | if (handle) | ||
2108 | ocfs2_commit_trans(OCFS2_SB(dir->i_sb), handle); | ||
2109 | |||
2110 | if (ret) | ||
2111 | kfree(res); | ||
2112 | |||
2113 | return ret; | ||
2114 | } | ||
2115 | |||
2116 | int ocfs2_claim_new_inode_at_loc(handle_t *handle, | ||
2117 | struct inode *dir, | ||
2118 | struct ocfs2_alloc_context *ac, | ||
2119 | u64 *suballoc_loc, | ||
2120 | u16 *suballoc_bit, | ||
2121 | u64 di_blkno) | ||
2122 | { | ||
2123 | int ret; | ||
2124 | u16 chain; | ||
2125 | struct ocfs2_suballoc_result *res = ac->ac_find_loc_priv; | ||
2126 | struct buffer_head *bg_bh = NULL; | ||
2127 | struct ocfs2_group_desc *bg; | ||
2128 | struct ocfs2_dinode *di = (struct ocfs2_dinode *) ac->ac_bh->b_data; | ||
2129 | |||
2130 | /* | ||
2131 | * Since di_blkno is being passed back in, we check for any | ||
2132 | * inconsistencies which may have happened between | ||
2133 | * calls. These are code bugs as di_blkno is not expected to | ||
2134 | * change once returned from ocfs2_find_new_inode_loc() | ||
2135 | */ | ||
2136 | BUG_ON(res->sr_blkno != di_blkno); | ||
2137 | |||
2138 | ret = ocfs2_read_group_descriptor(ac->ac_inode, di, | ||
2139 | res->sr_bg_stable_blkno, &bg_bh); | ||
2140 | if (ret) { | ||
2141 | mlog_errno(ret); | ||
2142 | goto out; | ||
2143 | } | ||
2144 | |||
2145 | bg = (struct ocfs2_group_desc *) bg_bh->b_data; | ||
2146 | chain = le16_to_cpu(bg->bg_chain); | ||
2147 | |||
2148 | ret = ocfs2_alloc_dinode_update_counts(ac->ac_inode, handle, | ||
2149 | ac->ac_bh, res->sr_bits, | ||
2150 | chain); | ||
2151 | if (ret) { | ||
2152 | mlog_errno(ret); | ||
2153 | goto out; | ||
2154 | } | ||
2155 | |||
2156 | ret = ocfs2_block_group_set_bits(handle, | ||
2157 | ac->ac_inode, | ||
2158 | bg, | ||
2159 | bg_bh, | ||
2160 | res->sr_bit_offset, | ||
2161 | res->sr_bits); | ||
2162 | if (ret < 0) { | ||
2163 | mlog_errno(ret); | ||
2164 | goto out; | ||
2165 | } | ||
2166 | |||
2167 | mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, | ||
2168 | (unsigned long long)di_blkno); | ||
2169 | |||
2170 | atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs); | ||
2171 | |||
2172 | BUG_ON(res->sr_bits != 1); | ||
2173 | |||
2174 | *suballoc_loc = res->sr_bg_blkno; | ||
2175 | *suballoc_bit = res->sr_bit_offset; | ||
2176 | ac->ac_bits_given++; | ||
2177 | ocfs2_save_inode_ac_group(dir, ac); | ||
2178 | |||
2179 | out: | ||
2180 | brelse(bg_bh); | ||
2181 | |||
2182 | return ret; | ||
2183 | } | ||
2184 | |||
2026 | int ocfs2_claim_new_inode(handle_t *handle, | 2185 | int ocfs2_claim_new_inode(handle_t *handle, |
2027 | struct inode *dir, | 2186 | struct inode *dir, |
2028 | struct buffer_head *parent_fe_bh, | 2187 | struct buffer_head *parent_fe_bh, |
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h index a017dd3ee7d9..b8afabfeede4 100644 --- a/fs/ocfs2/suballoc.h +++ b/fs/ocfs2/suballoc.h | |||
@@ -56,6 +56,9 @@ struct ocfs2_alloc_context { | |||
56 | u64 ac_max_block; /* Highest block number to allocate. 0 is | 56 | u64 ac_max_block; /* Highest block number to allocate. 0 is |
57 | is the same as ~0 - unlimited */ | 57 | is the same as ~0 - unlimited */ |
58 | 58 | ||
59 | int ac_find_loc_only; /* hack for reflink operation ordering */ | ||
60 | struct ocfs2_suballoc_result *ac_find_loc_priv; /* */ | ||
61 | |||
59 | struct ocfs2_alloc_reservation *ac_resv; | 62 | struct ocfs2_alloc_reservation *ac_resv; |
60 | }; | 63 | }; |
61 | 64 | ||
@@ -197,4 +200,22 @@ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_extent_tree *et, | |||
197 | struct ocfs2_alloc_context **meta_ac); | 200 | struct ocfs2_alloc_context **meta_ac); |
198 | 201 | ||
199 | int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res); | 202 | int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res); |
203 | |||
204 | |||
205 | |||
206 | /* | ||
207 | * The following two interfaces are for ocfs2_create_inode_in_orphan(). | ||
208 | */ | ||
209 | int ocfs2_find_new_inode_loc(struct inode *dir, | ||
210 | struct buffer_head *parent_fe_bh, | ||
211 | struct ocfs2_alloc_context *ac, | ||
212 | u64 *fe_blkno); | ||
213 | |||
214 | int ocfs2_claim_new_inode_at_loc(handle_t *handle, | ||
215 | struct inode *dir, | ||
216 | struct ocfs2_alloc_context *ac, | ||
217 | u64 *suballoc_loc, | ||
218 | u16 *suballoc_bit, | ||
219 | u64 di_blkno); | ||
220 | |||
200 | #endif /* _CHAINALLOC_H_ */ | 221 | #endif /* _CHAINALLOC_H_ */ |