This series sanitizes the interface to unmap_vma(). The crazy interface annoyed me no end when I was looking at unmap_single_vma(), which we can spend quite a lot of time in (especially with loads that have a lot of small fork/exec's: shell scripts etc). Moving the nr_accounted calculations to where they belong at least clarifies things a little. I hope to come back to look at the performance of this later, but if/when I get back to it I at least don't have to see the crazy interfaces any more. * vm-cleanups: vm: remove 'nr_accounted' calculations from the unmap_vmas() interfaces vm: simplify unmap_vmas() calling convention
Unified · Split
| @@ -896,10 +896,8 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address, · 895 unmodified lines | ||
| 896 | 896 | unsigned long size); |
| 897 | 897 | void zap_page_range(struct vm_area_struct *vma, unsigned long address, |
| 898 | 898 | unsigned long size, struct zap_details *); |
| 899 | −void unmap_vmas(struct mmu_gather *tlb, | |
| 900 | − struct vm_area_struct *start_vma, unsigned long start_addr, | |
| 901 | − unsigned long end_addr, unsigned long *nr_accounted, | |
| 902 | − struct zap_details *); | |
| 899 | +void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma, | |
| 900 | + unsigned long start, unsigned long end); | |
| 903 | 901 | |
| 904 | 902 | /** |
| 905 | 903 | * mm_walk - callbacks for walk_page_range |
| @@ -1295,7 +1295,7 @@ static void unmap_page_range(struct mmu_gather *tlb, · 1294 unmodified lines | ||
| 1295 | 1295 | |
| 1296 | 1296 | static void unmap_single_vma(struct mmu_gather *tlb, |
| 1297 | 1297 | struct vm_area_struct *vma, unsigned long start_addr, |
| 1298 | − unsigned long end_addr, unsigned long *nr_accounted, | |
| 1298 | + unsigned long end_addr, | |
| 1299 | 1299 | struct zap_details *details) |
| 1300 | 1300 | { |
| 1301 | 1301 | unsigned long start = max(vma->vm_start, start_addr); |
| @@ -1307,9 +1307,6 @@ static void unmap_single_vma(struct mmu_gather *tlb, · 5 unmodified lines | ||
| 1307 | 1307 | if (end <= vma->vm_start) |
| 1308 | 1308 | return; |
| 1309 | 1309 | |
| 1310 | − if (vma->vm_flags & VM_ACCOUNT) | |
| 1311 | − *nr_accounted += (end - start) >> PAGE_SHIFT; | |
| 1312 | − | |
| 1313 | 1310 | if (unlikely(is_pfn_mapping(vma))) |
| 1314 | 1311 | untrack_pfn_vma(vma, 0, 0); |
| 1315 | 1312 | |
| @@ -1339,8 +1336,6 @@ static void unmap_single_vma(struct mmu_gather *tlb, · 23 unmodified lines | ||
| 1339 | 1336 | * @vma: the starting vma |
| 1340 | 1337 | * @start_addr: virtual address at which to start unmapping |
| 1341 | 1338 | * @end_addr: virtual address at which to end unmapping |
| 1342 | − * @nr_accounted: Place number of unmapped pages in vm-accountable vma's here | |
| 1343 | − * @details: details of nonlinear truncation or shared cache invalidation | |
| 1344 | 1339 | * |
| 1345 | 1340 | * Unmap all pages in the vma list. |
| 1346 | 1341 | * |
| @@ -1355,15 +1350,13 @@ static void unmap_single_vma(struct mmu_gather *tlb, · 8 unmodified lines | ||
| 1355 | 1350 | */ |
| 1356 | 1351 | void unmap_vmas(struct mmu_gather *tlb, |
| 1357 | 1352 | struct vm_area_struct *vma, unsigned long start_addr, |
| 1358 | − unsigned long end_addr, unsigned long *nr_accounted, | |
| 1359 | − struct zap_details *details) | |
| 1353 | + unsigned long end_addr) | |
| 1360 | 1354 | { |
| 1361 | 1355 | struct mm_struct *mm = vma->vm_mm; |
| 1362 | 1356 | |
| 1363 | 1357 | mmu_notifier_invalidate_range_start(mm, start_addr, end_addr); |
| 1364 | 1358 | for ( ; vma && vma->vm_start < end_addr; vma = vma->vm_next) |
| 1365 | − unmap_single_vma(tlb, vma, start_addr, end_addr, nr_accounted, | |
| 1366 | − details); | |
| 1359 | + unmap_single_vma(tlb, vma, start_addr, end_addr, NULL); | |
| 1367 | 1360 | mmu_notifier_invalidate_range_end(mm, start_addr, end_addr); |
| 1368 | 1361 | } |
| 1369 | 1362 | |
| @@ -1376,19 +1369,21 @@ void unmap_vmas(struct mmu_gather *tlb, · 6 unmodified lines | ||
| 1376 | 1369 | * |
| 1377 | 1370 | * Caller must protect the VMA list |
| 1378 | 1371 | */ |
| 1379 | −void zap_page_range(struct vm_area_struct *vma, unsigned long address, | |
| 1372 | +void zap_page_range(struct vm_area_struct *vma, unsigned long start, | |
| 1380 | 1373 | unsigned long size, struct zap_details *details) |
| 1381 | 1374 | { |
| 1382 | 1375 | struct mm_struct *mm = vma->vm_mm; |
| 1383 | 1376 | struct mmu_gather tlb; |
| 1384 | − unsigned long end = address + size; | |
| 1385 | − unsigned long nr_accounted = 0; | |
| 1377 | + unsigned long end = start + size; | |
| 1386 | 1378 | |
| 1387 | 1379 | lru_add_drain(); |
| 1388 | 1380 | tlb_gather_mmu(&tlb, mm, 0); |
| 1389 | 1381 | update_hiwater_rss(mm); |
| 1390 | − unmap_vmas(&tlb, vma, address, end, &nr_accounted, details); | |
| 1391 | − tlb_finish_mmu(&tlb, address, end); | |
| 1382 | + mmu_notifier_invalidate_range_start(mm, start, end); | |
| 1383 | + for ( ; vma && vma->vm_start < end; vma = vma->vm_next) | |
| 1384 | + unmap_single_vma(&tlb, vma, start, end, details); | |
| 1385 | + mmu_notifier_invalidate_range_end(mm, start, end); | |
| 1386 | + tlb_finish_mmu(&tlb, start, end); | |
| 1392 | 1387 | } |
| 1393 | 1388 | |
| 1394 | 1389 | /** |
| @@ -1406,13 +1401,12 @@ static void zap_page_range_single(struct vm_area_struct *vma, unsigned long addr · 11 unmodified lines | ||
| 1406 | 1401 | struct mm_struct *mm = vma->vm_mm; |
| 1407 | 1402 | struct mmu_gather tlb; |
| 1408 | 1403 | unsigned long end = address + size; |
| 1409 | − unsigned long nr_accounted = 0; | |
| 1410 | 1404 | |
| 1411 | 1405 | lru_add_drain(); |
| 1412 | 1406 | tlb_gather_mmu(&tlb, mm, 0); |
| 1413 | 1407 | update_hiwater_rss(mm); |
| 1414 | 1408 | mmu_notifier_invalidate_range_start(mm, address, end); |
| 1415 | − unmap_single_vma(&tlb, vma, address, end, &nr_accounted, details); | |
| 1409 | + unmap_single_vma(&tlb, vma, address, end, details); | |
| 1416 | 1410 | mmu_notifier_invalidate_range_end(mm, address, end); |
| 1417 | 1411 | tlb_finish_mmu(&tlb, address, end); |
| 1418 | 1412 | } |
| @@ -1889,15 +1889,20 @@ find_extend_vma(struct mm_struct * mm, unsigned long addr) · 1888 unmodified lines | ||
| 1889 | 1889 | */ |
| 1890 | 1890 | static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) |
| 1891 | 1891 | { |
| 1892 | + unsigned long nr_accounted = 0; | |
| 1893 | + | |
| 1892 | 1894 | /* Update high watermark before we lower total_vm */ |
| 1893 | 1895 | update_hiwater_vm(mm); |
| 1894 | 1896 | do { |
| 1895 | 1897 | long nrpages = vma_pages(vma); |
| 1896 | 1898 | |
| 1899 | + if (vma->vm_flags & VM_ACCOUNT) | |
| 1900 | + nr_accounted += nrpages; | |
| 1897 | 1901 | mm->total_vm -= nrpages; |
| 1898 | 1902 | vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages); |
| 1899 | 1903 | vma = remove_vma(vma); |
| 1900 | 1904 | } while (vma); |
| 1905 | + vm_unacct_memory(nr_accounted); | |
| 1901 | 1906 | validate_mm(mm); |
| 1902 | 1907 | } |
| 1903 | 1908 | |
| @@ -1912,13 +1917,11 @@ static void unmap_region(struct mm_struct *mm, · 8 unmodified lines | ||
| 1912 | 1917 | { |
| 1913 | 1918 | struct vm_area_struct *next = prev? prev->vm_next: mm->mmap; |
| 1914 | 1919 | struct mmu_gather tlb; |
| 1915 | − unsigned long nr_accounted = 0; | |
| 1916 | 1920 | |
| 1917 | 1921 | lru_add_drain(); |
| 1918 | 1922 | tlb_gather_mmu(&tlb, mm, 0); |
| 1919 | 1923 | update_hiwater_rss(mm); |
| 1920 | − unmap_vmas(&tlb, vma, start, end, &nr_accounted, NULL); | |
| 1921 | − vm_unacct_memory(nr_accounted); | |
| 1924 | + unmap_vmas(&tlb, vma, start, end); | |
| 1922 | 1925 | free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS, |
| 1923 | 1926 | next ? next->vm_start : 0); |
| 1924 | 1927 | tlb_finish_mmu(&tlb, start, end); |
| @@ -2305,8 +2308,7 @@ void exit_mmap(struct mm_struct *mm) · 380 unmodified lines | ||
| 2305 | 2308 | tlb_gather_mmu(&tlb, mm, 1); |
| 2306 | 2309 | /* update_hiwater_rss(mm) here? but nobody should be looking */ |
| 2307 | 2310 | /* Use -1 here to ensure all VMAs in the mm are unmapped */ |
| 2308 | − unmap_vmas(&tlb, vma, 0, -1, &nr_accounted, NULL); | |
| 2309 | − vm_unacct_memory(nr_accounted); | |
| 2311 | + unmap_vmas(&tlb, vma, 0, -1); | |
| 2310 | 2312 | |
| 2311 | 2313 | free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0); |
| 2312 | 2314 | tlb_finish_mmu(&tlb, 0, -1); |
| @@ -2315,8 +2317,12 @@ void exit_mmap(struct mm_struct *mm) · 2 unmodified lines | ||
| 2315 | 2317 | * Walk the list again, actually closing and freeing it, |
| 2316 | 2318 | * with preemption enabled, without holding any MM locks. |
| 2317 | 2319 | */ |
| 2318 | − while (vma) | |
| 2320 | + while (vma) { | |
| 2321 | + if (vma->vm_flags & VM_ACCOUNT) | |
| 2322 | + nr_accounted += vma_pages(vma); | |
| 2319 | 2323 | vma = remove_vma(vma); |
| 2324 | + } | |
| 2325 | + vm_unacct_memory(nr_accounted); | |
| 2320 | 2326 | |
| 2321 | 2327 | BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); |
| 2322 | 2328 | } |