@@ -2013,250 +2013,63 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
20132013 return error ;
20142014}
20152015
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+ */
20162026static unsigned long unmapped_area (struct vm_unmapped_area_info * info )
20172027{
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 ;
20252029
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 );
20312031
20322032 /* Adjust search length to account for worst case alignment overhead */
20332033 length = info -> length + info -> align_mask ;
20342034 if (length < info -> length )
20352035 return - ENOMEM ;
20362036
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 ))
20442039 return - ENOMEM ;
2045- high_limit = info -> high_limit - length ;
20462040
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 ;
21262044}
21272045
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+ */
21282056static unsigned long unmapped_area_topdown (struct vm_unmapped_area_info * info )
21292057{
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 ;
21372059
2060+ MA_STATE (mas , & current -> mm -> mm_mt , 0 , 0 );
21382061 /* Adjust search length to account for worst case alignment overhead */
21392062 length = info -> length + info -> align_mask ;
21402063 if (length < info -> length )
21412064 return - ENOMEM ;
21422065
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 ))
21582068 return - ENOMEM ;
2159- low_limit = info -> low_limit + length ;
21602069
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 ;
22602073}
22612074
22622075/*
0 commit comments