dax: Release PMD lock even when there is no PMD support in DAX
Subsystems (2)
PATCH 1/1 dax: Release PMD lock even when there is no PMD support in DAX
The function follow_pte_pmd() can theoretically return after having acquired a PMD lock, even when DAX was not compiled with CONFIG_FS_DAX_PMD.
Release the PMD lock unconditionally.
--- fs/dax.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/dax.c +1 -1
@@ -636,8 +636,8 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping, pmd =pmd_mkclean (pmd);set_pmd_at (vma->vm_mm, address, pmdp, pmd); unlock_pmd: -spin_unlock (ptl);#endif +spin_unlock (ptl); }else {if (pfn !=pte_pfn (*ptep)) goto unlock_pte;
Signature · 1 line
2.9.3.1.gcba166c.dirty
Matthew Wilcox
reviewerQuoted 3 lines · Jan H. Sch�nherr
The function
follow_pte_pmd()can theoretically return after having acquired a PMD lock, even when DAX was not compiled withCONFIG_FS_DAX_PMD.
I don't think it can. How would a PMD entry get into a DAX VMA if we compiled the kernel without CONFIG_FS_DAX_PMD?
Matthew Wilcox
reviewerQuoted 7 lines · Matthew Wilcox
Quoted 3 lines · Jan H. Sch�nherr
The function
follow_pte_pmd()can theoretically return after having acquired a PMD lock, even when DAX was not compiled withCONFIG_FS_DAX_PMD.I don't think it can. How would a PMD entry get into a DAX VMA if we compiled the kernel without
CONFIG_FS_DAX_PMD?
How about this patch instead? Should shut up sparse nicely.
fs/dax.c +7 -3
@@ -586,6 +586,12 @@ pgoff_address(pgoff_t pgoff, struct vm_area_struct *vma)return address; } +#ifdef CONFIG_FS_DAX_PMD +#define dax_pmd (pmdp) pmdp +#else +#define dax_pmd (pmdp) 0 +#endif +/* Walk all mappings of a given index of a file and writeprotect them */ static void dax_mapping_entry_mkclean (struct address_space *mapping,pgoff_t index,unsigned long pfn)
@@ -621,8 +627,7 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,* * See Documentation/vm/mmu_notifier.txt */ -if (pmdp) { -#ifdef CONFIG_FS_DAX_PMD +if (dax_pmd (pmdp)) {pmd_t pmd;if (pfn !=pmd_pfn (*pmdp))
@@ -638,7 +643,6 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,set_pmd_at (vma->vm_mm, address, pmdp, pmd); unlock_pmd:spin_unlock (ptl); -#endif }else {if (pfn !=pte_pfn (*ptep)) goto unlock_pte;
Quoted 10 lines · Matthew Wilcox
Quoted 7 lines · Matthew Wilcox
Quoted 3 lines · Jan H. Schönherr
The function
follow_pte_pmd()can theoretically return after having acquired a PMD lock, even when DAX was not compiled withCONFIG_FS_DAX_PMD.I don't think it can. How would a PMD entry get into a DAX VMA if we compiled the kernel without
CONFIG_FS_DAX_PMD?How about this patch instead? Should shut up sparse nicely.
It would still skip the unlock, in case pmdp is !=NULL (and locked) after follow_pte_pmd(). So it wouldn't address, what I intended to address with the patch.
Regards
Jan
Quoted 37 lines
fs/dax.c +7
-3@@ -586,6 +586,12 @@ pgoff_address(pgoff_t pgoff, struct vm_area_struct *vma)return address; } +#ifdef CONFIG_FS_DAX_PMD +#define dax_pmd (pmdp) pmdp +#else +#define dax_pmd (pmdp) 0 +#endif +/* Walk all mappings of a given index of a file and writeprotect them */ static void dax_mapping_entry_mkclean (struct address_space *mapping,pgoff_t index,unsigned long pfn)@@ -621,8 +627,7 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,* * See Documentation/vm/mmu_notifier.txt */ -if (pmdp) { -#ifdef CONFIG_FS_DAX_PMD +if (dax_pmd (pmdp)) {pmd_t pmd;if (pfn !=pmd_pfn (*pmdp))@@ -638,7 +643,6 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,set_pmd_at (vma->vm_mm, address, pmdp, pmd); unlock_pmd:spin_unlock (ptl); -#endif }else {if (pfn !=pte_pfn (*ptep)) goto unlock_pte;
Quoted 2 lines · Jan H. Schönherr
It would still skip the unlock, in case pmdp is !=NULL (and locked) after
follow_pte_pmd(). So it wouldn't address, what I intended to address with the patch.
Small correction: we'd take the "else" branch, which would do some stuff it's not supposed to do when follow_pte_pmd() returns with pmdp!=NULL. And we'd actually do a unlock, but thinking it's a PTE, not a PMD.
So, defensive-wise, may point still stands, that we're not correctly handling an unexpectedly returned PMD entry.
Regards
Jan
Quoted 8 lines · Matthew Wilcox
Quoted 3 lines · Jan H. Schönherr
The function
follow_pte_pmd()can theoretically return after having acquired a PMD lock, even when DAX was not compiled withCONFIG_FS_DAX_PMD.I don't think it can. How would a PMD entry get into a DAX VMA if we compiled the kernel without
CONFIG_FS_DAX_PMD?
Maybe it can not in happy cases. But the PMD parts in follow_pte_pmd() are compiled in unconditionally. So, if there's an issue elsewhere, and for some weird reason we get a PMD entry in the page table, it would screw the lock balance.
I haven't run into an actual issue with this, it's just supposed to be defensive.
Regards
Jan
Quoted 17 lines · Jan H. Sch�nherr
The function
follow_pte_pmd()can theoretically return after having acquired a PMD lock, even when DAX was not compiled withCONFIG_FS_DAX_PMD.Release the PMD lock unconditionally.
Fixes f729c8c9b24f ("dax: wrprotect pmd_t in dax_mapping_entry_mkclean")Signed-off-by Jan H. Sch�nherr <[email protected]>--- fs/dax.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)fs/dax.c +0
-0
fs/dax.c static void dax_mapping_entry_mkclean(struct address_space *mapping, · line 643
Quoted 9 lines
fs/dax.c +1
-1@@ -636,8 +636,8 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping, pmd =pmd_mkclean (pmd);set_pmd_at (vma->vm_mm, address, pmdp, pmd); unlock_pmd: -spin_unlock (ptl);#endif +spin_unlock (ptl); }else {if (pfn !=pte_pfn (*ptep)) goto unlock_pte;
Sure, this seems fine to me. This seems simple and correct - you're right that we aren't taking the PTL on the PMD conditionally based on whether CONFIG_DAX_PMD is defined, so it doesn't make sense to release it conditionally. I think if we ever hit this lock imbalance we're totally insane anyway, but it the fix is correct and doesn't mess with our code flow.
You can add:
Quoted 34 lines · Ross Zwisler
Quoted 17 lines · Jan H. Sch�nherr
The function
follow_pte_pmd()can theoretically return after having acquired a PMD lock, even when DAX was not compiled withCONFIG_FS_DAX_PMD.Release the PMD lock unconditionally.
Fixes f729c8c9b24f ("dax: wrprotect pmd_t in dax_mapping_entry_mkclean")Signed-off-by Jan H. Sch�nherr <[email protected]>--- fs/dax.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)fs/dax.c +0
-0fs/dax.c static void dax_mapping_entry_mkclean(struct address_space *mapping, · line 643
Quoted 9 lines
fs/dax.c +1
-1@@ -636,8 +636,8 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping, pmd =pmd_mkclean (pmd);set_pmd_at (vma->vm_mm, address, pmdp, pmd); unlock_pmd: -spin_unlock (ptl);#endif +spin_unlock (ptl); }else {if (pfn !=pte_pfn (*ptep)) goto unlock_pte;Sure, this seems fine to me. This seems simple and correct - you're right that we aren't taking the PTL on the PMD conditionally based on whether
CONFIG_DAX_PMDis defined, so it doesn't make sense to release it conditionally. I think if we ever hit this lock imbalance we're totally insane anyway, but it the fix is correct and doesn't mess with our code flow.
Quoted 2 lines
You can add:
Reviewed-by Ross Zwisler <[email protected]>
Ah, I just realized that this patch didn't CC Andrew, and he's the one that usually takes our DAX patches.
Andrew, can you pick this up? Here's the fsdevel patchwork:
https://patchwork.kernel.org/patch/10173255/
Thanks,
- Ross
Quoted 6 lines · Ross Zwisler
Ah, I just realized that this patch didn't CC Andrew, and he's the one that usually takes our DAX patches.
Andrew, can you pick this up? Here's the fsdevel patchwork:
Thanks for that, I didn't know.
Let me know, if I should resend instead (in case it makes things easier).
Regards
Jan