Skip to content

Commit 2103cf9

Browse files
xzpetertorvalds
authored andcommitted
hugetlb: dedup the code to add a new file_region
Patch series "mm/hugetlb: Early cow on fork, and a few cleanups", v5. As reported by Gal [1], we still miss the code clip to handle early cow for hugetlb case, which is true. Again, it still feels odd to fork() after using a few huge pages, especially if they're privately mapped to me.. However I do agree with Gal and Jason in that we should still have that since that'll complete the early cow on fork effort at least, and it'll still fix issues where buffers are not well under control and not easy to apply MADV_DONTFORK. The first two patches (1-2) are some cleanups I noticed when reading into the hugetlb reserve map code. I think it's good to have but they're not necessary for fixing the fork issue. The last two patches (3-4) are the real fix. I tested this with a fork() after some vfio-pci assignment, so I'm pretty sure the page copy path could trigger well (page will be accounted right after the fork()), but I didn't do data check since the card I assigned is some random nic. https://github.com/xzpeter/linux/tree/fork-cow-pin-huge [1] https://lore.kernel.org/lkml/[email protected]/ Introduce hugetlb_resv_map_add() helper to add a new file_region rather than duplication the similar code twice in add_reservation_in_range(). Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Peter Xu <[email protected]> Reviewed-by: Mike Kravetz <[email protected]> Reviewed-by: Miaohe Lin <[email protected]> Cc: Gal Pressman <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Wei Zhang <[email protected]> Cc: Mike Rapoport <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: David Gibson <[email protected]> Cc: Jason Gunthorpe <[email protected]> Cc: Jann Horn <[email protected]> Cc: Kirill Tkhai <[email protected]> Cc: Kirill Shutemov <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Jan Kara <[email protected]> Cc: Alexey Dobriyan <[email protected]> Cc: Daniel Vetter <[email protected]> Cc: David Airlie <[email protected]> Cc: Roland Scheidegger <[email protected]> Cc: VMware Graphics <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 82e69a1 commit 2103cf9

File tree

1 file changed

+27
-24
lines changed

1 file changed

+27
-24
lines changed

mm/hugetlb.c

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,24 @@ static void coalesce_file_region(struct resv_map *resv, struct file_region *rg)
331331
}
332332
}
333333

334+
static inline long
335+
hugetlb_resv_map_add(struct resv_map *map, struct file_region *rg, long from,
336+
long to, struct hstate *h, struct hugetlb_cgroup *cg,
337+
long *regions_needed)
338+
{
339+
struct file_region *nrg;
340+
341+
if (!regions_needed) {
342+
nrg = get_file_region_entry_from_cache(map, from, to);
343+
record_hugetlb_cgroup_uncharge_info(cg, h, map, nrg);
344+
list_add(&nrg->link, rg->link.prev);
345+
coalesce_file_region(map, nrg);
346+
} else
347+
*regions_needed += 1;
348+
349+
return to - from;
350+
}
351+
334352
/*
335353
* Must be called with resv->lock held.
336354
*
@@ -346,7 +364,7 @@ static long add_reservation_in_range(struct resv_map *resv, long f, long t,
346364
long add = 0;
347365
struct list_head *head = &resv->regions;
348366
long last_accounted_offset = f;
349-
struct file_region *rg = NULL, *trg = NULL, *nrg = NULL;
367+
struct file_region *rg = NULL, *trg = NULL;
350368

351369
if (regions_needed)
352370
*regions_needed = 0;
@@ -375,36 +393,21 @@ static long add_reservation_in_range(struct resv_map *resv, long f, long t,
375393
/* Add an entry for last_accounted_offset -> rg->from, and
376394
* update last_accounted_offset.
377395
*/
378-
if (rg->from > last_accounted_offset) {
379-
add += rg->from - last_accounted_offset;
380-
if (!regions_needed) {
381-
nrg = get_file_region_entry_from_cache(
382-
resv, last_accounted_offset, rg->from);
383-
record_hugetlb_cgroup_uncharge_info(h_cg, h,
384-
resv, nrg);
385-
list_add(&nrg->link, rg->link.prev);
386-
coalesce_file_region(resv, nrg);
387-
} else
388-
*regions_needed += 1;
389-
}
396+
if (rg->from > last_accounted_offset)
397+
add += hugetlb_resv_map_add(resv, rg,
398+
last_accounted_offset,
399+
rg->from, h, h_cg,
400+
regions_needed);
390401

391402
last_accounted_offset = rg->to;
392403
}
393404

394405
/* Handle the case where our range extends beyond
395406
* last_accounted_offset.
396407
*/
397-
if (last_accounted_offset < t) {
398-
add += t - last_accounted_offset;
399-
if (!regions_needed) {
400-
nrg = get_file_region_entry_from_cache(
401-
resv, last_accounted_offset, t);
402-
record_hugetlb_cgroup_uncharge_info(h_cg, h, resv, nrg);
403-
list_add(&nrg->link, rg->link.prev);
404-
coalesce_file_region(resv, nrg);
405-
} else
406-
*regions_needed += 1;
407-
}
408+
if (last_accounted_offset < t)
409+
add += hugetlb_resv_map_add(resv, rg, last_accounted_offset,
410+
t, h, h_cg, regions_needed);
408411

409412
VM_BUG_ON(add < 0);
410413
return add;

0 commit comments

Comments
 (0)