Skip to contentSkip to conversation

mm: call pte_unmap() against a proper pte (Re: [PATCH 7/9] swap_info: swap count continuations)

PATCH [email protected] 1 participant 1 message Oct 17, 2009 Memory management

lore
Share & tools
lore

[email protected]

author Acked-by
#0 lore raw
Quoted 7 lines

----Original Message----
From: [email protected]
Date: 16/10/2009 7:30
To: "Hugh Dickins"<[email protected]>
Cc: "Andrew Morton"<[email protected]>, "Nitin Gupta"<ngupta@vflare.

org>, "KAMEZAWA Hiroyuki"<[email protected]>, <hongshin@gmail. com>, <[email protected]>, <[email protected]>, "Daisuke Nishimura" <[email protected]>

Quoted 1 line

Subj: [PATCH] mm: call pte_unmap() against a proper pte (Re: [PATCH 7/9]

swap_info: swap count continuations)

Quoted 9 lines

Hi.

Quoted 6 lines
(quoted diff) +1 -0
@@ -645,6 +648,7 @@ static int copy_pte_range(struct mm_stru
 	spinlock_t *src_ptl, *dst_ptl;
 	int progress = 0;
 	int rss[2];
+	swp_entry_t entry = (swp_entry_t){0};
 
Quoted 15 lines
Quoted 4 lines
(quoted diff) +0 -0
 again:
 	rss[1] = rss[0] = 0;
@@ -671,7 +675,10 @@ again:
 			progress++;

Review again: · line 684

Quoted 10 lines
(quoted diff) +4 -1
 			continue;
 		}
-		copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, vma, addr, rss);
+		entry.val = copy_one_pte(dst_mm, src_mm, dst_pte, src_pte,
+							vma, addr, rss);
+		if (entry.val)
+			break;
 		progress += 8;
 	} while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
 

It isn't the fault of only this patch, but I think breaking the loop without

incrementing

Quoted 1 line

dst_pte(and src_pte) would be bad behavior because we do unmap_pte(dst_pte -

1) later.

Quoted 1 line

(current copy_pte_range() already does it though... and this is only

problematic

Quoted 1 line

when we break the first loop, IIUC.)

Good catch, thanks a lot for finding that. I believe this is entirely a fault in my 7/9, the existing code
takes care not to break before it has made some progress (in part because of this unmap issue).

Quoted 16 lines
Quoted 4 lines
(quoted diff) +0 -0
@@ -681,6 +688,12 @@ again:
 	add_mm_rss(dst_mm, rss[0], rss[1]);
 	pte_unmap_unlock(dst_pte - 1, dst_ptl);

Review again: · line 699

Quoted 10 lines
(quoted diff) +6 -0
 	cond_resched();
+
+	if (entry.val) {
+		if (add_swap_count_continuation(entry, GFP_KERNEL) < 0)
+			return -ENOMEM;
+		progress = 0;
+	}
 	if (addr != end)
 		goto again;
 	return 0;

I've searched other places where we break a similar loop and do pte_unmap(pte

- 1).

Quoted 1 line

Current copy_pte_range() and apply_to_pte_range() has the same problem.

And thank you for taking the trouble to look further afield: yes, apply_to_pte_range()
was already wrong.

Quoted 13 lines

How about a patch like this ?
===
From: Daisuke Nishimura <[email protected]>

There are some places where we do like:

	pte = pte_map();
	do {
		(do break in some conditions)
	} while (pte++, ...);
	pte_unmap(pte - 1);
Quoted 5 lines

But if the loop breaks at the first loop, pte_unmap() unmaps invalid pte.

This patch is a fix for this problem.

Forget the rest, get the best - http://www.tiscali.co.uk/music