Skip to contentSkip to conversation

Fix do_move_pages_to_node() error handling

PATCH In review [email protected] 3 participants 9 messages Nov 14, 2018 – Nov 16, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix do_move_pages_to_node() error handling

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Fixes a49bd4d71637 ("mm, numa: rework do_pages_move")
---
 mm/migrate.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
mm/migrate.c +10 -0
index 8baeb7ff2f6d..b42efef780d6 100644
@@ -1461,6 +1461,7 @@ static int store_status(int __user *status, int start, int value, int nr)
 	return 0;
 }
 
+/* Returns 0 or an error code. */
 static int do_move_pages_to_node(struct mm_struct *mm,
 		struct list_head *pagelist, int node)
 {
@@ -1473,6 +1474,15 @@ static int do_move_pages_to_node(struct mm_struct *mm,
 			MIGRATE_SYNC, MR_SYSCALL);
 	if (err)
 		putback_movable_pages(pagelist);
+
+	/*
+	 * migrate_pages() can return the number of not migrated pages, but the
+	 * callers of do_move_pages_to_node() only care about and handle hard
+	 * failures.
+	 */
+	if (err > 0)
+		err = 0;
+
 	return err;
 }
 
Signature · 1 line
2.11.0.262.g4b0a5b2.dirty
#1 lore raw
Quoted 8 lines · On Tue 13-11-18 16:40:59, [email protected] wrote:

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Yes this is correct.

Quoted 6 lines

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Yes, I believe the previous semantic was just wrong and we want to fix it. Jan has already brought this up [1]. I believe we want to update the documentation rather than restore the previous hazy semantic.

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

[1] http://lkml.kernel.org/r/0329efa0984b9b0252ef166abb4498c0795fab36.1535113317.git.jstancek@redhat.com

Quoted 38 lines
Fixes a49bd4d71637 ("mm, numa: rework do_pages_move")
---
 mm/migrate.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
mm/migrate.c +10 -0
index 8baeb7ff2f6d..b42efef780d6 100644
@@ -1461,6 +1461,7 @@ static int store_status(int __user *status, int start, int value, int nr)
 	return 0;
 }
 
+/* Returns 0 or an error code. */
 static int do_move_pages_to_node(struct mm_struct *mm,
 		struct list_head *pagelist, int node)
 {
@@ -1473,6 +1474,15 @@ static int do_move_pages_to_node(struct mm_struct *mm,
 			MIGRATE_SYNC, MR_SYSCALL);
 	if (err)
 		putback_movable_pages(pagelist);
+
+	/*
+	 * migrate_pages() can return the number of not migrated pages, but the
+	 * callers of do_move_pages_to_node() only care about and handle hard
+	 * failures.
+	 */
+	if (err > 0)
+		err = 0;
+
 	return err;
 }
 
Signature · 1 line
2.11.0.262.g4b0a5b2.dirty
Signature · 2 lines
Michal Hocko
SUSE Labs
#2 lore raw
Quoted 19 lines · Michal Hocko
Quoted 8 lines · On Tue 13-11-18 16:40:59, [email protected] wrote:

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Yes this is correct.

Quoted 6 lines

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Quoted 8 lines

Yes, I believe the previous semantic was just wrong and we want to fix it. Jan has already brought this up [1]. I believe we want to update the documentation rather than restore the previous hazy semantic.

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

[1] http://lkml.kernel.org/r/0329efa0984b9b0252ef166abb4498c0795fab36.1535113317.git.jstancek@redhat.com

Btw. this is what I was suggesting back then (along with the man page update suggested by Jan)

#3 lore raw
Quoted 20 lines · Michal Hocko
Quoted 19 lines · Michal Hocko
Quoted 8 lines · On Tue 13-11-18 16:40:59, [email protected] wrote:

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Yes this is correct.

Quoted 6 lines

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Quoted 3 lines
Quoted 3 lines

Yes, I believe the previous semantic was just wrong and we want to fix it. Jan has already brought this up [1]. I believe we want to update the documentation rather than restore the previous hazy semantic.

That's probably fair although at least some code we have will have to be updated as it just checks for non-zero returns from move_pages() and assumes errno is set when that happens.

Quoted 3 lines
Quoted 3 lines

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

I have a test that creates a tmp file, mmaps it as shared, memsets the memory and then attempts to move it to a different node. It used to work, but now fails. I suspect the filesystem's migratepage() callback regressed and will look into it next. So far I have only tested this on powerpc with the xfs filesystem.

Quoted 37 lines
Quoted 2 lines

[1] http://lkml.kernel.org/r/0329efa0984b9b0252ef166abb4498c0795fab36.1535113317.git.jstancek@redhat.com

Btw. this is what I was suggesting back then (along with the man page update suggested by Jan)

From cfb88c266b645197135cde2905c2bfc82f6d82a9 Mon Sep 17 00:00:00 2001
From: Michal Hocko <[email protected]>
Date: Wed, 14 Nov 2018 12:19:09 +0100
Subject: [PATCH] mm: fix do_pages_move error reporting

a49bd4d71637 ("mm, numa: rework do_pages_move") has changed the way how we report error to layers above. As the changelog mentioned the semantic was quite unclear previously because the return 0 could mean both success and failure.

The above mentioned commit didn't get all the way down to fix this completely because it doesn't report pages that we even haven't attempted to migrate and therefore we cannot simply say that the semantic is:
- err < 0 - errno
- err >= 0 number of non-migrated pages.

Fixes a49bd4d71637 ("mm, numa: rework do_pages_move")
---
 mm/migrate.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
mm/migrate.c +0 -0
index f7e4bfdc13b7..aa53ebc523eb 100644
@@ -1615,8 +1615,16 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
 			goto out_flush;
 
 		err = do_move_pages_to_node(mm, &pagelist, current_node);

mm/migrate.c static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes, · line 1626

Quoted 10 lines
mm/migrate.c +8 -1
-		if (err)
+		if (err) {
+			/*
+			 * Possitive err means the number of failed pages to
+			 * migrate. Make sure to report the rest of the
+			 * nr_pages is not migrated as well.
+			 */
+			if (err > 0)
+				err += nr_pages - i - 1;
 			goto out;

Ok, so we give up after the first failure to migrate everything. That probably makes sense although I don't have a good idea about how frequent it is for the migration to give up in such a manner (short of the issue I'm seeing that I suspect is a separate bug). In this case, should the status of each page be updated to something instead of being left undefined? Or should it be specified that page status is only valid for the first N - not migrated pages?

Quoted 5 lines
mm/migrate.c +1 -0
+		}
 		if (i > start) {
 			err = store_status(status, start, current_node, i - start);
 			if (err)
#4 lore raw
Quoted 21 lines · Piotr Jaroszynski
Quoted 20 lines · Michal Hocko
Quoted 19 lines · Michal Hocko
Quoted 8 lines · On Tue 13-11-18 16:40:59, [email protected] wrote:

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Yes this is correct.

Quoted 6 lines

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Quoted 7 lines
Quoted 3 lines
Quoted 3 lines

Yes, I believe the previous semantic was just wrong and we want to fix it. Jan has already brought this up [1]. I believe we want to update the documentation rather than restore the previous hazy semantic.

That's probably fair although at least some code we have will have to be updated as it just checks for non-zero returns from move_pages() and assumes errno is set when that happens.

Can you tell me more about your usecase plase? I definitely do not want to break any existing userspace. Making the syscall return code more reasonable is still attractive. So if this new semantic can work better for you it would be one argument more to keep it this way.

Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

I have a test that creates a tmp file, mmaps it as shared, memsets the memory and then attempts to move it to a different node. It used to work, but now fails. I suspect the filesystem's migratepage() callback regressed and will look into it next. So far I have only tested this on powerpc with the xfs filesystem.

I would be surprise if the rewor changed the migration behavior.

[...]

Quoted 19 lines
Quoted 8 lines
mm/migrate.c +0 -0
index f7e4bfdc13b7..aa53ebc523eb 100644
@@ -1615,8 +1615,16 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
 			goto out_flush;
 
 		err = do_move_pages_to_node(mm, &pagelist, current_node);

mm/migrate.c static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes, · line 1626

Quoted 10 lines
mm/migrate.c +8 -1
-		if (err)
+		if (err) {
+			/*
+			 * Possitive err means the number of failed pages to
+			 * migrate. Make sure to report the rest of the
+			 * nr_pages is not migrated as well.
+			 */
+			if (err > 0)
+				err += nr_pages - i - 1;
 			goto out;
Quoted 7 lines

Ok, so we give up after the first failure to migrate everything. That probably makes sense although I don't have a good idea about how frequent it is for the migration to give up in such a manner (short of the issue I'm seeing that I suspect is a separate bug). In this case, should the status of each page be updated to something instead of being left undefined? Or should it be specified that page status is only valid for the first N - not migrated pages?

I believe this is consistent with the previous behavior. I do not remember in detail but I believe we haven't set the status for the remaining pages. With this patch it seems straightforward to skip over exact number of pages that failed.

Signature · 2 lines
Michal Hocko
SUSE Labs
#5 lore raw
Quoted 26 lines · Michal Hocko
Quoted 25 lines · Piotr Jaroszynski
Quoted 23 lines · Michal Hocko
Quoted 22 lines · Michal Hocko
Quoted 8 lines · On Tue 13-11-18 16:40:59, [email protected] wrote:

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Yes this is correct.

Quoted 6 lines

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Yes, I believe the previous semantic was just wrong and we want to fix it. Jan has already brought this up [1]. I believe we want to update the documentation rather than restore the previous hazy semantic.

Quoted 9 lines
Quoted 3 lines

That's probably fair although at least some code we have will have to be updated as it just checks for non-zero returns from move_pages() and assumes errno is set when that happens.

Can you tell me more about your usecase plase? I definitely do not want to break any existing userspace. Making the syscall return code more reasonable is still attractive. So if this new semantic can work better for you it would be one argument more to keep it this way.

One of our APIs exposes a way to move a VA range to a GPU NUMA node or one of the CPU NUMA nodes. The code keeps retrying move_pages() and relies on the reported page status to decide whether each page is done, needs a retry (EAGAIN or EBUSY) or possibly needs a fallback (EMEM).

With the previous behaviour we would get a success, but the page status would be reported incorrectly. That's bad as we skip the migration without knowing about it.

With the current code we get what we interpret as success as errno is 0, but the page status is gargabe/untouched. That's also bad.

The proposed solution adds a new case to handle, but it will just tell us the page status is unusable and all we can do is just retry blindly. If it was possible to plumb through the migration status for each page accurately that would allow us to save redoing the call for pages that actually worked. Perhaps we would need a special status for pages skipped due to errors.

But maybe this is all a tiny corner case short of the bug I hit (see more below) and it's not worth thinking too much about.

Quoted 10 lines
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

I have a test that creates a tmp file, mmaps it as shared, memsets the memory and then attempts to move it to a different node. It used to work, but now fails. I suspect the filesystem's migratepage() callback regressed and will look into it next. So far I have only tested this on powerpc with the xfs filesystem.

I would be surprise if the rewor changed the migration behavior.

It didn't, I tracked it down to the new fs/iomap.c code used by xfs not being compatible with migrate_page_move_mapping() and prepared a perhaps naive fix in [1].

Quoted 29 lines

[...]

Quoted 19 lines
Quoted 8 lines
mm/migrate.c +0 -0
index f7e4bfdc13b7..aa53ebc523eb 100644
@@ -1615,8 +1615,16 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
 			goto out_flush;
 
 		err = do_move_pages_to_node(mm, &pagelist, current_node);

mm/migrate.c static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes, · line 1626

Quoted 10 lines
mm/migrate.c +8 -1
-		if (err)
+		if (err) {
+			/*
+			 * Possitive err means the number of failed pages to
+			 * migrate. Make sure to report the rest of the
+			 * nr_pages is not migrated as well.
+			 */
+			if (err > 0)
+				err += nr_pages - i - 1;
 			goto out;
Quoted 7 lines

Ok, so we give up after the first failure to migrate everything. That probably makes sense although I don't have a good idea about how frequent it is for the migration to give up in such a manner (short of the issue I'm seeing that I suspect is a separate bug). In this case, should the status of each page be updated to something instead of being left undefined? Or should it be specified that page status is only valid for the first N - not migrated pages?

Quoted 5 lines

I believe this is consistent with the previous behavior. I do not remember in detail but I believe we haven't set the status for the remaining pages. With this patch it seems straightforward to skip over exact number of pages that failed.

Yeah, I was just wondering whether the semantics could be improved further, not arguing that the previous behaviour was any better.

[1] - https://lore.kernel.org/lkml/[email protected]/

Thanks,
Piotr

#6 lore raw
Quoted 37 lines · Piotr Jaroszynski
Quoted 26 lines · Michal Hocko
Quoted 25 lines · Piotr Jaroszynski
Quoted 23 lines · Michal Hocko
Quoted 22 lines · Michal Hocko
Quoted 8 lines · On Tue 13-11-18 16:40:59, [email protected] wrote:

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Yes this is correct.

Quoted 6 lines

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Yes, I believe the previous semantic was just wrong and we want to fix it. Jan has already brought this up [1]. I believe we want to update the documentation rather than restore the previous hazy semantic.

Quoted 9 lines
Quoted 3 lines

That's probably fair although at least some code we have will have to be updated as it just checks for non-zero returns from move_pages() and assumes errno is set when that happens.

Can you tell me more about your usecase plase? I definitely do not want to break any existing userspace. Making the syscall return code more reasonable is still attractive. So if this new semantic can work better for you it would be one argument more to keep it this way.

Quoted 8 lines

One of our APIs exposes a way to move a VA range to a GPU NUMA node or one of the CPU NUMA nodes. The code keeps retrying move_pages() and relies on the reported page status to decide whether each page is done, needs a retry (EAGAIN or EBUSY) or possibly needs a fallback (EMEM).

With the previous behaviour we would get a success, but the page status would be reported incorrectly. That's bad as we skip the migration without knowing about it.

Exactly.

Quoted 2 lines

With the current code we get what we interpret as success as errno is 0, but the page status is gargabe/untouched. That's also bad.

Agreed.

Quoted 6 lines

The proposed solution adds a new case to handle, but it will just tell us the page status is unusable and all we can do is just retry blindly. If it was possible to plumb through the migration status for each page accurately that would allow us to save redoing the call for pages that actually worked. Perhaps we would need a special status for pages skipped due to errors.

This would be possible but with this patch applied you should know how many pages to skip from the tail of the array.

Quoted 12 lines

But maybe this is all a tiny corner case short of the bug I hit (see more below) and it's not worth thinking too much about.

Quoted 9 lines
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

I have a test that creates a tmp file, mmaps it as shared, memsets the memory and then attempts to move it to a different node. It used to work, but now fails. I suspect the filesystem's migratepage() callback regressed and will look into it next. So far I have only tested this on powerpc with the xfs filesystem.

Quoted 5 lines
Quoted 1 line

I would be surprise if the rewor changed the migration behavior.

It didn't, I tracked it down to the new fs/iomap.c code used by xfs not being compatible with migrate_page_move_mapping() and prepared a perhaps naive fix in [1].

I am not familiar with iomap code much TBH so I cannot really judge your fix.

Signature · 2 lines
Michal Hocko
SUSE Labs
#7 lore raw
Quoted 61 lines · Michal Hocko
Quoted 37 lines · Piotr Jaroszynski
Quoted 26 lines · Michal Hocko
Quoted 25 lines · Piotr Jaroszynski
Quoted 23 lines · Michal Hocko
Quoted 22 lines · Michal Hocko
Quoted 8 lines · On Tue 13-11-18 16:40:59, [email protected] wrote:

From: Piotr Jaroszynski <[email protected]>

migrate_pages() can return the number of pages that failed to migrate instead of 0 or an error code. If that happens, the positive return is treated as an error all the way up through the stack leading to the move_pages() syscall returning a positive number. I believe this regressed with commit a49bd4d71637 ("mm, numa: rework do_pages_move") that refactored a lot of this code.

Yes this is correct.

Quoted 6 lines

Fix this by treating positive returns as success in do_move_pages_to_node() as that seems to most closely follow the previous code. This still leaves the question whether silently considering this case a success is the right thing to do as even the status of the pages will be set as if they were successfully migrated, but that seems to have been the case before as well.

Yes, I believe the previous semantic was just wrong and we want to fix it. Jan has already brought this up [1]. I believe we want to update the documentation rather than restore the previous hazy semantic.

Quoted 9 lines
Quoted 3 lines

That's probably fair although at least some code we have will have to be updated as it just checks for non-zero returns from move_pages() and assumes errno is set when that happens.

Can you tell me more about your usecase plase? I definitely do not want to break any existing userspace. Making the syscall return code more reasonable is still attractive. So if this new semantic can work better for you it would be one argument more to keep it this way.

Quoted 8 lines

One of our APIs exposes a way to move a VA range to a GPU NUMA node or one of the CPU NUMA nodes. The code keeps retrying move_pages() and relies on the reported page status to decide whether each page is done, needs a retry (EAGAIN or EBUSY) or possibly needs a fallback (EMEM).

With the previous behaviour we would get a success, but the page status would be reported incorrectly. That's bad as we skip the migration without knowing about it.

Exactly.

Quoted 2 lines

With the current code we get what we interpret as success as errno is 0, but the page status is gargabe/untouched. That's also bad.

Agreed.

Quoted 6 lines

The proposed solution adds a new case to handle, but it will just tell us the page status is unusable and all we can do is just retry blindly. If it was possible to plumb through the migration status for each page accurately that would allow us to save redoing the call for pages that actually worked. Perhaps we would need a special status for pages skipped due to errors.

Quoted 2 lines

This would be possible but with this patch applied you should know how many pages to skip from the tail of the array.

At least in our case the node target is the same for all the pages so we would just learn that all the pages failed to migrate as they would be all batched together to the do_move_pages_to_node() call.

Quoted 13 lines
Quoted 13 lines

But maybe this is all a tiny corner case short of the bug I hit (see more below) and it's not worth thinking too much about.

Quoted 9 lines
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

I have a test that creates a tmp file, mmaps it as shared, memsets the memory and then attempts to move it to a different node. It used to work, but now fails. I suspect the filesystem's migratepage() callback regressed and will look into it next. So far I have only tested this on powerpc with the xfs filesystem.

Quoted 9 lines
Quoted 5 lines
Quoted 1 line

I would be surprise if the rewor changed the migration behavior.

It didn't, I tracked it down to the new fs/iomap.c code used by xfs not being compatible with migrate_page_move_mapping() and prepared a perhaps naive fix in [1].

I am not familiar with iomap code much TBH so I cannot really judge your fix.

Christoph reviewed it already (thanks!) so it should be good after all. But in its context, I wanted to ask about migrate_page_move_mapping() page count checks that it was hitting. Is it true that the count checks are to handle the case when a page might be temporarily pinned and hence have the count too high temporarily? That would explain why it returns EAGAIN in this case. But should having the count too low (what the bug was hitting) be a fatal error with a WARN maybe? Or are there expected cases where the count is too low temporarily too? I could send a patch for that, but also just wanted to understand the expectations.

#8 lore raw
Quoted 2 lines · Piotr Jaroszynski
Quoted 1 line · Michal Hocko

On Wed 14-11-18 17:04:37, Piotr Jaroszynski wrote:

[...]

Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

The proposed solution adds a new case to handle, but it will just tell us the page status is unusable and all we can do is just retry blindly. If it was possible to plumb through the migration status for each page accurately that would allow us to save redoing the call for pages that actually worked. Perhaps we would need a special status for pages skipped due to errors.

Quoted 6 lines
Quoted 2 lines

This would be possible but with this patch applied you should know how many pages to skip from the tail of the array.

At least in our case the node target is the same for all the pages so we would just learn that all the pages failed to migrate as they would be all batched together to the do_move_pages_to_node() call.

Anyway, could you give this patch a try please? I would appreciate some Tested-bys to push this forward ;)

Quoted 22 lines
Quoted 12 lines
Quoted 12 lines

But maybe this is all a tiny corner case short of the bug I hit (see more below) and it's not worth thinking too much about.

Quoted 9 lines
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

Just wondering, how have you found out? Is there any real application failing because of the change or this is a result of some test?

I have a test that creates a tmp file, mmaps it as shared, memsets the memory and then attempts to move it to a different node. It used to work, but now fails. I suspect the filesystem's migratepage() callback regressed and will look into it next. So far I have only tested this on powerpc with the xfs filesystem.

Quoted 9 lines
Quoted 5 lines
Quoted 1 line

I would be surprise if the rewor changed the migration behavior.

It didn't, I tracked it down to the new fs/iomap.c code used by xfs not being compatible with migrate_page_move_mapping() and prepared a perhaps naive fix in [1].

I am not familiar with iomap code much TBH so I cannot really judge your fix.

Quoted 5 lines

Christoph reviewed it already (thanks!) so it should be good after all. But in its context, I wanted to ask about migrate_page_move_mapping() page count checks that it was hitting. Is it true that the count checks are to handle the case when a page might be temporarily pinned and hence have the count too high temporarily?

Yes. We cannot really migrate pinned pages.

Quoted 4 lines

That would explain why it returns
EAGAIN in this case. But should having the count too low (what the bug was hitting) be a fatal error with a WARN maybe? Or are there expected cases where the count is too low temporarily too?

Nope, page reference count too low is a bug.

Quoted 2 lines

I could send a patch
for that, but also just wanted to understand the expectations.

Signature · 2 lines
Michal Hocko
SUSE Labs