@@ -2013,250 +2013,63 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
2013
2013
return error ;
2014
2014
}
2015
2015
2016
+ /**
2017
+ * unmapped_area() - Find an area between the low_limit and the high_limit with
2018
+ * the correct alignment and offset, all from @info. Note: current->mm is used
2019
+ * for the search.
2020
+ *
2021
+ * @info: The unmapped area information including the range (low_limit -
2022
+ * hight_limit), the alignment offset and mask.
2023
+ *
2024
+ * Return: A memory address or -ENOMEM.
2025
+ */
2016
2026
static unsigned long unmapped_area (struct vm_unmapped_area_info * info )
2017
2027
{
2018
- /*
2019
- * We implement the search by looking for an rbtree node that
2020
- * immediately follows a suitable gap. That is,
2021
- * - gap_start = vma->vm_prev->vm_end <= info->high_limit - length;
2022
- * - gap_end = vma->vm_start >= info->low_limit + length;
2023
- * - gap_end - gap_start >= length
2024
- */
2028
+ unsigned long length , gap ;
2025
2029
2026
- struct mm_struct * mm = current -> mm ;
2027
- struct vm_area_struct * vma ;
2028
- unsigned long length , low_limit , high_limit , gap_start , gap_end ;
2029
- unsigned long gap ;
2030
- MA_STATE (mas , & mm -> mm_mt , 0 , 0 );
2030
+ MA_STATE (mas , & current -> mm -> mm_mt , 0 , 0 );
2031
2031
2032
2032
/* Adjust search length to account for worst case alignment overhead */
2033
2033
length = info -> length + info -> align_mask ;
2034
2034
if (length < info -> length )
2035
2035
return - ENOMEM ;
2036
2036
2037
- mas_empty_area (& mas , info -> low_limit , info -> high_limit - 1 ,
2038
- length );
2039
- gap = mas .index ;
2040
- gap += (info -> align_offset - gap ) & info -> align_mask ;
2041
-
2042
- /* Adjust search limits by the desired length */
2043
- if (info -> high_limit < length )
2037
+ if (mas_empty_area (& mas , info -> low_limit , info -> high_limit - 1 ,
2038
+ length ))
2044
2039
return - ENOMEM ;
2045
- high_limit = info -> high_limit - length ;
2046
2040
2047
- if (info -> low_limit > high_limit )
2048
- return - ENOMEM ;
2049
- low_limit = info -> low_limit + length ;
2050
-
2051
- /* Check if rbtree root looks promising */
2052
- if (RB_EMPTY_ROOT (& mm -> mm_rb ))
2053
- goto check_highest ;
2054
- vma = rb_entry (mm -> mm_rb .rb_node , struct vm_area_struct , vm_rb );
2055
- if (vma -> rb_subtree_gap < length )
2056
- goto check_highest ;
2057
-
2058
- while (true) {
2059
- /* Visit left subtree if it looks promising */
2060
- gap_end = vm_start_gap (vma );
2061
- if (gap_end >= low_limit && vma -> vm_rb .rb_left ) {
2062
- struct vm_area_struct * left =
2063
- rb_entry (vma -> vm_rb .rb_left ,
2064
- struct vm_area_struct , vm_rb );
2065
- if (left -> rb_subtree_gap >= length ) {
2066
- vma = left ;
2067
- continue ;
2068
- }
2069
- }
2070
-
2071
- gap_start = vma -> vm_prev ? vm_end_gap (vma -> vm_prev ) : 0 ;
2072
- check_current :
2073
- /* Check if current node has a suitable gap */
2074
- if (gap_start > high_limit )
2075
- return - ENOMEM ;
2076
- if (gap_end >= low_limit &&
2077
- gap_end > gap_start && gap_end - gap_start >= length )
2078
- goto found ;
2079
-
2080
- /* Visit right subtree if it looks promising */
2081
- if (vma -> vm_rb .rb_right ) {
2082
- struct vm_area_struct * right =
2083
- rb_entry (vma -> vm_rb .rb_right ,
2084
- struct vm_area_struct , vm_rb );
2085
- if (right -> rb_subtree_gap >= length ) {
2086
- vma = right ;
2087
- continue ;
2088
- }
2089
- }
2090
-
2091
- /* Go back up the rbtree to find next candidate node */
2092
- while (true) {
2093
- struct rb_node * prev = & vma -> vm_rb ;
2094
- if (!rb_parent (prev ))
2095
- goto check_highest ;
2096
- vma = rb_entry (rb_parent (prev ),
2097
- struct vm_area_struct , vm_rb );
2098
- if (prev == vma -> vm_rb .rb_left ) {
2099
- gap_start = vm_end_gap (vma -> vm_prev );
2100
- gap_end = vm_start_gap (vma );
2101
- goto check_current ;
2102
- }
2103
- }
2104
- }
2105
-
2106
- check_highest :
2107
- /* Check highest gap, which does not precede any rbtree node */
2108
- gap_start = mm -> highest_vm_end ;
2109
- gap_end = ULONG_MAX ; /* Only for VM_BUG_ON below */
2110
- if (gap_start > high_limit )
2111
- return - ENOMEM ;
2112
-
2113
- found :
2114
- /* We found a suitable gap. Clip it with the original low_limit. */
2115
- if (gap_start < info -> low_limit )
2116
- gap_start = info -> low_limit ;
2117
-
2118
- /* Adjust gap address to the desired alignment */
2119
- gap_start += (info -> align_offset - gap_start ) & info -> align_mask ;
2120
-
2121
- VM_BUG_ON (gap_start + info -> length > info -> high_limit );
2122
- VM_BUG_ON (gap_start + info -> length > gap_end );
2123
-
2124
- VM_BUG_ON (gap != gap_start );
2125
- return gap_start ;
2041
+ gap = mas .index ;
2042
+ gap += (info -> align_offset - gap ) & info -> align_mask ;
2043
+ return gap ;
2126
2044
}
2127
2045
2046
+ /**
2047
+ * unmapped_area_topdown() - Find an area between the low_limit and the
2048
+ * high_limit with * the correct alignment and offset at the highest available
2049
+ * address, all from @info. Note: current->mm is used for the search.
2050
+ *
2051
+ * @info: The unmapped area information including the range (low_limit -
2052
+ * hight_limit), the alignment offset and mask.
2053
+ *
2054
+ * Return: A memory address or -ENOMEM.
2055
+ */
2128
2056
static unsigned long unmapped_area_topdown (struct vm_unmapped_area_info * info )
2129
2057
{
2130
- struct mm_struct * mm = current -> mm ;
2131
- struct vm_area_struct * vma = NULL ;
2132
- unsigned long length , low_limit , high_limit , gap_start , gap_end ;
2133
- unsigned long gap ;
2134
-
2135
- MA_STATE (mas , & mm -> mm_mt , 0 , 0 );
2136
- validate_mm_mt (mm );
2058
+ unsigned long length , gap ;
2137
2059
2060
+ MA_STATE (mas , & current -> mm -> mm_mt , 0 , 0 );
2138
2061
/* Adjust search length to account for worst case alignment overhead */
2139
2062
length = info -> length + info -> align_mask ;
2140
2063
if (length < info -> length )
2141
2064
return - ENOMEM ;
2142
2065
2143
- mas_empty_area_rev (& mas , info -> low_limit , info -> high_limit - 1 ,
2144
- length );
2145
- gap = mas .last + 1 - info -> length ;
2146
- gap -= (gap - info -> align_offset ) & info -> align_mask ;
2147
-
2148
- /*
2149
- * Adjust search limits by the desired length.
2150
- * See implementation comment at top of unmapped_area().
2151
- */
2152
- gap_end = info -> high_limit ;
2153
- if (gap_end < length )
2154
- return - ENOMEM ;
2155
- high_limit = gap_end - length ;
2156
-
2157
- if (info -> low_limit > high_limit )
2066
+ if (mas_empty_area_rev (& mas , info -> low_limit , info -> high_limit - 1 ,
2067
+ length ))
2158
2068
return - ENOMEM ;
2159
- low_limit = info -> low_limit + length ;
2160
2069
2161
- /* Check highest gap, which does not precede any rbtree node */
2162
- gap_start = mm -> highest_vm_end ;
2163
- if (gap_start <= high_limit )
2164
- goto found_highest ;
2165
-
2166
- /* Check if rbtree root looks promising */
2167
- if (RB_EMPTY_ROOT (& mm -> mm_rb ))
2168
- return - ENOMEM ;
2169
- vma = rb_entry (mm -> mm_rb .rb_node , struct vm_area_struct , vm_rb );
2170
- if (vma -> rb_subtree_gap < length )
2171
- return - ENOMEM ;
2172
-
2173
- while (true) {
2174
- /* Visit right subtree if it looks promising */
2175
- gap_start = vma -> vm_prev ? vm_end_gap (vma -> vm_prev ) : 0 ;
2176
- if (gap_start <= high_limit && vma -> vm_rb .rb_right ) {
2177
- struct vm_area_struct * right =
2178
- rb_entry (vma -> vm_rb .rb_right ,
2179
- struct vm_area_struct , vm_rb );
2180
- if (right -> rb_subtree_gap >= length ) {
2181
- vma = right ;
2182
- continue ;
2183
- }
2184
- }
2185
-
2186
- check_current :
2187
- /* Check if current node has a suitable gap */
2188
- gap_end = vm_start_gap (vma );
2189
- if (gap_end < low_limit )
2190
- return - ENOMEM ;
2191
- if (gap_start <= high_limit &&
2192
- gap_end > gap_start && gap_end - gap_start >= length )
2193
- goto found ;
2194
-
2195
- /* Visit left subtree if it looks promising */
2196
- if (vma -> vm_rb .rb_left ) {
2197
- struct vm_area_struct * left =
2198
- rb_entry (vma -> vm_rb .rb_left ,
2199
- struct vm_area_struct , vm_rb );
2200
- if (left -> rb_subtree_gap >= length ) {
2201
- vma = left ;
2202
- continue ;
2203
- }
2204
- }
2205
-
2206
- /* Go back up the rbtree to find next candidate node */
2207
- while (true) {
2208
- struct rb_node * prev = & vma -> vm_rb ;
2209
- if (!rb_parent (prev ))
2210
- return - ENOMEM ;
2211
- vma = rb_entry (rb_parent (prev ),
2212
- struct vm_area_struct , vm_rb );
2213
- if (prev == vma -> vm_rb .rb_right ) {
2214
- gap_start = vma -> vm_prev ?
2215
- vm_end_gap (vma -> vm_prev ) : 0 ;
2216
- goto check_current ;
2217
- }
2218
- }
2219
- }
2220
-
2221
- found :
2222
- /* We found a suitable gap. Clip it with the original high_limit. */
2223
- if (gap_end > info -> high_limit )
2224
- gap_end = info -> high_limit ;
2225
-
2226
- found_highest :
2227
- /* Compute highest gap address at the desired alignment */
2228
- gap_end -= info -> length ;
2229
- gap_end -= (gap_end - info -> align_offset ) & info -> align_mask ;
2230
-
2231
- VM_BUG_ON (gap_end < info -> low_limit );
2232
- VM_BUG_ON (gap_end < gap_start );
2233
-
2234
- if (gap != gap_end ) {
2235
- pr_err ("%s: %p Gap was found: mt %lu gap_end %lu\n" , __func__ ,
2236
- mm , gap , gap_end );
2237
- pr_err ("window was %lu - %lu size %lu\n" , info -> high_limit ,
2238
- info -> low_limit , length );
2239
- pr_err ("mas.min %lu max %lu mas.last %lu\n" , mas .min , mas .max ,
2240
- mas .last );
2241
- pr_err ("mas.index %lu align mask %lu offset %lu\n" , mas .index ,
2242
- info -> align_mask , info -> align_offset );
2243
- pr_err ("rb_find_vma find on %lu => %p (%p)\n" , mas .index ,
2244
- find_vma (mm , mas .index ), vma );
2245
- #if defined(CONFIG_DEBUG_VM_MAPLE_TREE )
2246
- mt_dump (& mm -> mm_mt );
2247
- #endif
2248
- {
2249
- struct vm_area_struct * dv = mm -> mmap ;
2250
-
2251
- while (dv ) {
2252
- pr_err ("vma %p %lu-%lu\n" , dv , dv -> vm_start , dv -> vm_end );
2253
- dv = dv -> vm_next ;
2254
- }
2255
- }
2256
- VM_BUG_ON (gap != gap_end );
2257
- }
2258
-
2259
- return gap_end ;
2070
+ gap = mas .last + 1 - info -> length ;
2071
+ gap -= (gap - info -> align_offset ) & info -> align_mask ;
2072
+ return gap ;
2260
2073
}
2261
2074
2262
2075
/*
0 commit comments