linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] exfat: Avoid allocating upcase table using kcalloc()
@ 2020-11-24 19:47 ` Artem Labazov
  2020-11-24 22:17   ` David Laight
  2020-12-02  4:58   ` Sungjong Seo
  0 siblings, 2 replies; 10+ messages in thread
From: Artem Labazov @ 2020-11-24 19:47 UTC (permalink / raw)
  Cc: 123321artyom, stable, Namjae Jeon, Sungjong Seo, linux-fsdevel,
	linux-kernel

The table for Unicode upcase conversion requires an order-5 allocation,
which may fail on a highly-fragmented system:

 pool-udisksd: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0
 CPU: 4 PID: 3756880 Comm: pool-udisksd Tainted: G     U            5.8.10-200.fc32.x86_64 #1
 Hardware name: Dell Inc. XPS 13 9360/0PVG6D, BIOS 2.13.0 11/14/2019
 Call Trace:
  dump_stack+0x6b/0x88
  warn_alloc.cold+0x75/0xd9
  ? _cond_resched+0x16/0x40
  ? __alloc_pages_direct_compact+0x144/0x150
  __alloc_pages_slowpath.constprop.0+0xcfa/0xd30
  ? __schedule+0x28a/0x840
  ? __wait_on_bit_lock+0x92/0xa0
  __alloc_pages_nodemask+0x2df/0x320
  kmalloc_order+0x1b/0x80
  kmalloc_order_trace+0x1d/0xa0
  exfat_create_upcase_table+0x115/0x390 [exfat]
  exfat_fill_super+0x3ef/0x7f0 [exfat]
  ? sget_fc+0x1d0/0x240
  ? exfat_init_fs_context+0x120/0x120 [exfat]
  get_tree_bdev+0x15c/0x250
  vfs_get_tree+0x25/0xb0
  do_mount+0x7c3/0xaf0
  ? copy_mount_options+0xab/0x180
  __x64_sys_mount+0x8e/0xd0
  do_syscall_64+0x4d/0x90
  entry_SYSCALL_64_after_hwframe+0x44/0xa9

Make the driver use vmalloc() to eliminate the issue.

Cc: stable@vger.kernel.org # v5.7+
Signed-off-by: Artem Labazov <123321artyom@gmail.com>
---
 fs/exfat/nls.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
index 675d0e7058c5..0582faf8de77 100644
--- a/fs/exfat/nls.c
+++ b/fs/exfat/nls.c
@@ -6,6 +6,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/vmalloc.h>
 #include <asm/unaligned.h>
 
 #include "exfat_raw.h"
@@ -659,7 +660,7 @@ static int exfat_load_upcase_table(struct super_block *sb,
 	unsigned char skip = false;
 	unsigned short *upcase_table;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = vmalloc(UTBL_COUNT*sizeof(unsigned short));
 	if (!upcase_table)
 		return -ENOMEM;
 
@@ -715,7 +716,7 @@ static int exfat_load_default_upcase_table(struct super_block *sb)
 	unsigned short uni = 0, *upcase_table;
 	unsigned int index = 0;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = vmalloc(UTBL_COUNT*sizeof(unsigned short));
 	if (!upcase_table)
 		return -ENOMEM;
 
@@ -803,5 +804,5 @@ int exfat_create_upcase_table(struct super_block *sb)
 
 void exfat_free_upcase_table(struct exfat_sb_info *sbi)
 {
-	kfree(sbi->vol_utbl);
+	vfree(sbi->vol_utbl);
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* RE: [PATCH] exfat: Avoid allocating upcase table using kcalloc()
  2020-11-24 19:47 ` [PATCH] exfat: Avoid allocating upcase table using kcalloc() Artem Labazov
@ 2020-11-24 22:17   ` David Laight
  2020-12-02  4:58   ` Sungjong Seo
  1 sibling, 0 replies; 10+ messages in thread
From: David Laight @ 2020-11-24 22:17 UTC (permalink / raw)
  To: 'Artem Labazov'
  Cc: stable, Namjae Jeon, Sungjong Seo, linux-fsdevel, linux-kernel

From: Artem Labazov
> Sent: 24 November 2020 19:48
> 
> The table for Unicode upcase conversion requires an order-5 allocation,
> which may fail on a highly-fragmented system:

ISTM that is the wrong way to do the case conversion.
It is also why having to do it is bloody stupid.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] exfat: Avoid allocating upcase table using kcalloc()
  2020-11-24 19:47 ` [PATCH] exfat: Avoid allocating upcase table using kcalloc() Artem Labazov
  2020-11-24 22:17   ` David Laight
@ 2020-12-02  4:58   ` Sungjong Seo
  2020-12-04 12:57     ` Artem Labazov
  2020-12-04 13:33     ` [PATCH v2] " Artem Labazov
  1 sibling, 2 replies; 10+ messages in thread
From: Sungjong Seo @ 2020-12-02  4:58 UTC (permalink / raw)
  To: 'Artem Labazov'
  Cc: stable, 'Namjae Jeon', linux-fsdevel, linux-kernel

> The table for Unicode upcase conversion requires an order-5 allocation,
> which may fail on a highly-fragmented system:
> 
>  pool-udisksd: page allocation failure: order:5,
> mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO),
> nodemask=(null),cpuset=/,mems_allowed=0
>  CPU: 4 PID: 3756880 Comm: pool-udisksd Tainted: G     U
5.8.10-
> 200.fc32.x86_64 #1
>  Hardware name: Dell Inc. XPS 13 9360/0PVG6D, BIOS 2.13.0 11/14/2019  Call
> Trace:
>   dump_stack+0x6b/0x88
>   warn_alloc.cold+0x75/0xd9
>   ? _cond_resched+0x16/0x40
>   ? __alloc_pages_direct_compact+0x144/0x150
>   __alloc_pages_slowpath.constprop.0+0xcfa/0xd30
>   ? __schedule+0x28a/0x840
>   ? __wait_on_bit_lock+0x92/0xa0
>   __alloc_pages_nodemask+0x2df/0x320
>   kmalloc_order+0x1b/0x80
>   kmalloc_order_trace+0x1d/0xa0
>   exfat_create_upcase_table+0x115/0x390 [exfat]
>   exfat_fill_super+0x3ef/0x7f0 [exfat]
>   ? sget_fc+0x1d0/0x240
>   ? exfat_init_fs_context+0x120/0x120 [exfat]
>   get_tree_bdev+0x15c/0x250
>   vfs_get_tree+0x25/0xb0
>   do_mount+0x7c3/0xaf0
>   ? copy_mount_options+0xab/0x180
>   __x64_sys_mount+0x8e/0xd0
>   do_syscall_64+0x4d/0x90
>   entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> Make the driver use vmalloc() to eliminate the issue.

I have not yet received a report of the same issue.
But I agree that this problem is likely to occur even if it is low
probability.

I think it would be more appropriate to use kvcalloc and kvfree instead.
Could you send me v2 patch?



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] exfat: Avoid allocating upcase table using kcalloc()
  2020-12-02  4:58   ` Sungjong Seo
@ 2020-12-04 12:57     ` Artem Labazov
  2020-12-07  6:23       ` Sungjong Seo
  2020-12-04 13:33     ` [PATCH v2] " Artem Labazov
  1 sibling, 1 reply; 10+ messages in thread
From: Artem Labazov @ 2020-12-04 12:57 UTC (permalink / raw)
  To: Sungjong Seo; +Cc: stable, 'Namjae Jeon', linux-fsdevel, linux-kernel

> I have not yet received a report of the same issue.
> But I agree that this problem is likely to occur even if it is low
> probability.

Perhaps I should clarify my setup a little bit more.
The issue can be reliably reproduced on my laptop. It has 8 GBs of RAM
(pretty common amount nowadays) and runs an unmodified Fedora 32 kernel.
Also, I use zswap, which seems to be contributing to fragmentation as well.

> I think it would be more appropriate to use kvcalloc and kvfree instead.

I do not think this is really needed.
Upcase table allocation is relatively large (32 pages of 4KB size) and
happens only once, when the drive is being mounted. Also, exfat driver
does not rely on the fact that the table is physically contiguous.
That said, vmalloc/vfree seems to be the best option, according to kernel's
"Memory Allocation Guide".

--
Artem

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2] exfat: Avoid allocating upcase table using kcalloc()
  2020-12-02  4:58   ` Sungjong Seo
  2020-12-04 12:57     ` Artem Labazov
@ 2020-12-04 13:33     ` Artem Labazov
  2020-12-07  4:32       ` Namjae Jeon
  1 sibling, 1 reply; 10+ messages in thread
From: Artem Labazov @ 2020-12-04 13:33 UTC (permalink / raw)
  Cc: 123321artyom, stable, Namjae Jeon, Sungjong Seo, linux-fsdevel,
	linux-kernel

The table for Unicode upcase conversion requires an order-5 allocation,
which may fail on a highly-fragmented system:

 pool-udisksd: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0
 CPU: 4 PID: 3756880 Comm: pool-udisksd Tainted: G     U            5.8.10-200.fc32.x86_64 #1
 Hardware name: Dell Inc. XPS 13 9360/0PVG6D, BIOS 2.13.0 11/14/2019
 Call Trace:
  dump_stack+0x6b/0x88
  warn_alloc.cold+0x75/0xd9
  ? _cond_resched+0x16/0x40
  ? __alloc_pages_direct_compact+0x144/0x150
  __alloc_pages_slowpath.constprop.0+0xcfa/0xd30
  ? __schedule+0x28a/0x840
  ? __wait_on_bit_lock+0x92/0xa0
  __alloc_pages_nodemask+0x2df/0x320
  kmalloc_order+0x1b/0x80
  kmalloc_order_trace+0x1d/0xa0
  exfat_create_upcase_table+0x115/0x390 [exfat]
  exfat_fill_super+0x3ef/0x7f0 [exfat]
  ? sget_fc+0x1d0/0x240
  ? exfat_init_fs_context+0x120/0x120 [exfat]
  get_tree_bdev+0x15c/0x250
  vfs_get_tree+0x25/0xb0
  do_mount+0x7c3/0xaf0
  ? copy_mount_options+0xab/0x180
  __x64_sys_mount+0x8e/0xd0
  do_syscall_64+0x4d/0x90
  entry_SYSCALL_64_after_hwframe+0x44/0xa9

Make the driver use vzalloc() to eliminate the issue.

Cc: stable@vger.kernel.org # v5.7+
Signed-off-by: Artem Labazov <123321artyom@gmail.com>
---
v2: replace vmalloc with vzalloc to avoid uninitialized memory access

 fs/exfat/nls.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
index 675d0e7058c5..4cb2e2bc8cad 100644
--- a/fs/exfat/nls.c
+++ b/fs/exfat/nls.c
@@ -6,6 +6,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/vmalloc.h>
 #include <asm/unaligned.h>
 
 #include "exfat_raw.h"
@@ -659,7 +660,7 @@ static int exfat_load_upcase_table(struct super_block *sb,
 	unsigned char skip = false;
 	unsigned short *upcase_table;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = vzalloc(UTBL_COUNT * sizeof(unsigned short));
 	if (!upcase_table)
 		return -ENOMEM;
 
@@ -715,7 +716,7 @@ static int exfat_load_default_upcase_table(struct super_block *sb)
 	unsigned short uni = 0, *upcase_table;
 	unsigned int index = 0;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = vzalloc(UTBL_COUNT * sizeof(unsigned short));
 	if (!upcase_table)
 		return -ENOMEM;
 
@@ -803,5 +804,5 @@ int exfat_create_upcase_table(struct super_block *sb)
 
 void exfat_free_upcase_table(struct exfat_sb_info *sbi)
 {
-	kfree(sbi->vol_utbl);
+	vfree(sbi->vol_utbl);
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* RE: [PATCH v2] exfat: Avoid allocating upcase table using kcalloc()
  2020-12-04 13:33     ` [PATCH v2] " Artem Labazov
@ 2020-12-07  4:32       ` Namjae Jeon
  0 siblings, 0 replies; 10+ messages in thread
From: Namjae Jeon @ 2020-12-07  4:32 UTC (permalink / raw)
  To: 'Artem Labazov'
  Cc: stable, 'Sungjong Seo', linux-fsdevel, linux-kernel

> The table for Unicode upcase conversion requires an order-5 allocation, which may fail on a highly-
> fragmented system:
> 
>  pool-udisksd: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO),
> nodemask=(null),cpuset=/,mems_allowed=0
>  CPU: 4 PID: 3756880 Comm: pool-udisksd Tainted: G     U            5.8.10-200.fc32.x86_64 #1
>  Hardware name: Dell Inc. XPS 13 9360/0PVG6D, BIOS 2.13.0 11/14/2019  Call Trace:
>   dump_stack+0x6b/0x88
>   warn_alloc.cold+0x75/0xd9
>   ? _cond_resched+0x16/0x40
>   ? __alloc_pages_direct_compact+0x144/0x150
>   __alloc_pages_slowpath.constprop.0+0xcfa/0xd30
>   ? __schedule+0x28a/0x840
>   ? __wait_on_bit_lock+0x92/0xa0
>   __alloc_pages_nodemask+0x2df/0x320
>   kmalloc_order+0x1b/0x80
>   kmalloc_order_trace+0x1d/0xa0
>   exfat_create_upcase_table+0x115/0x390 [exfat]
>   exfat_fill_super+0x3ef/0x7f0 [exfat]
>   ? sget_fc+0x1d0/0x240
>   ? exfat_init_fs_context+0x120/0x120 [exfat]
>   get_tree_bdev+0x15c/0x250
>   vfs_get_tree+0x25/0xb0
>   do_mount+0x7c3/0xaf0
>   ? copy_mount_options+0xab/0x180
>   __x64_sys_mount+0x8e/0xd0
>   do_syscall_64+0x4d/0x90
>   entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> Make the driver use vzalloc() to eliminate the issue.
> 
> Cc: stable@vger.kernel.org # v5.7+
> Signed-off-by: Artem Labazov <123321artyom@gmail.com>
> ---
> v2: replace vmalloc with vzalloc to avoid uninitialized memory access
Applied.
Thanks for your work!


^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] exfat: Avoid allocating upcase table using kcalloc()
  2020-12-04 12:57     ` Artem Labazov
@ 2020-12-07  6:23       ` Sungjong Seo
  2020-12-07  9:34         ` [PATCH v3] " Artem Labazov
  0 siblings, 1 reply; 10+ messages in thread
From: Sungjong Seo @ 2020-12-07  6:23 UTC (permalink / raw)
  To: 'Artem Labazov'
  Cc: stable, 'Namjae Jeon', linux-fsdevel, linux-kernel

> > I have not yet received a report of the same issue.
> > But I agree that this problem is likely to occur even if it is low
> > probability.
> 
> Perhaps I should clarify my setup a little bit more.
> The issue can be reliably reproduced on my laptop. It has 8 GBs of RAM
> (pretty common amount nowadays) and runs an unmodified Fedora 32 kernel.
> Also, I use zswap, which seems to be contributing to fragmentation as
well.
> 
> > I think it would be more appropriate to use kvcalloc and kvfree instead.
> 
> I do not think this is really needed.
> Upcase table allocation is relatively large (32 pages of 4KB size) and
> happens only once, when the drive is being mounted. Also, exfat driver
> does not rely on the fact that the table is physically contiguous.
> That said, vmalloc/vfree seems to be the best option, according to
> kernel's "Memory Allocation Guide".

The address range available for vmalloc() allocations is limited on 32-bit
systems. If all kernel codes that need non-contiguous memory of the size
order 1 or larger try to allocate it by only vmalloc(), the address range
for vmalloc() could be insufficient.
So, I think it would be better to give kmalloc() "one" chance.

I know that kvmalloc() only tries kmalloc() once (noretry, nowarn) and if it
fails, it immediately falls back to vmalloc(). Therefore, I think kvmalloc()
and kvfree() are the best solution for solving the problem you are facing
and
the problem I mentioned above.

Could you send me patch v3 that uses kvcalloc() and kvfree()?

> 
> --
> Artem


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3] exfat: Avoid allocating upcase table using kcalloc()
  2020-12-07  6:23       ` Sungjong Seo
@ 2020-12-07  9:34         ` Artem Labazov
  2020-12-08  2:22           ` Sungjong Seo
  0 siblings, 1 reply; 10+ messages in thread
From: Artem Labazov @ 2020-12-07  9:34 UTC (permalink / raw)
  Cc: 123321artyom, stable, Namjae Jeon, Sungjong Seo, linux-fsdevel,
	linux-kernel

The table for Unicode upcase conversion requires an order-5 allocation,
which may fail on a highly-fragmented system:

 pool-udisksd: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0
 CPU: 4 PID: 3756880 Comm: pool-udisksd Tainted: G     U            5.8.10-200.fc32.x86_64 #1
 Hardware name: Dell Inc. XPS 13 9360/0PVG6D, BIOS 2.13.0 11/14/2019
 Call Trace:
  dump_stack+0x6b/0x88
  warn_alloc.cold+0x75/0xd9
  ? _cond_resched+0x16/0x40
  ? __alloc_pages_direct_compact+0x144/0x150
  __alloc_pages_slowpath.constprop.0+0xcfa/0xd30
  ? __schedule+0x28a/0x840
  ? __wait_on_bit_lock+0x92/0xa0
  __alloc_pages_nodemask+0x2df/0x320
  kmalloc_order+0x1b/0x80
  kmalloc_order_trace+0x1d/0xa0
  exfat_create_upcase_table+0x115/0x390 [exfat]
  exfat_fill_super+0x3ef/0x7f0 [exfat]
  ? sget_fc+0x1d0/0x240
  ? exfat_init_fs_context+0x120/0x120 [exfat]
  get_tree_bdev+0x15c/0x250
  vfs_get_tree+0x25/0xb0
  do_mount+0x7c3/0xaf0
  ? copy_mount_options+0xab/0x180
  __x64_sys_mount+0x8e/0xd0
  do_syscall_64+0x4d/0x90
  entry_SYSCALL_64_after_hwframe+0x44/0xa9

Convert kcalloc/kfree to their kv* variants to eliminate the issue.

Cc: stable@vger.kernel.org # v5.7+
Signed-off-by: Artem Labazov <123321artyom@gmail.com>
---
v2: replace vmalloc with vzalloc to avoid uninitialized memory access
v3: use kv* functions to attempt kmalloc first

 fs/exfat/nls.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
index 675d0e7058c5..314d5407a1be 100644
--- a/fs/exfat/nls.c
+++ b/fs/exfat/nls.c
@@ -659,7 +659,7 @@ static int exfat_load_upcase_table(struct super_block *sb,
 	unsigned char skip = false;
 	unsigned short *upcase_table;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = kvcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
 	if (!upcase_table)
 		return -ENOMEM;
 
@@ -715,7 +715,7 @@ static int exfat_load_default_upcase_table(struct super_block *sb)
 	unsigned short uni = 0, *upcase_table;
 	unsigned int index = 0;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = kvcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
 	if (!upcase_table)
 		return -ENOMEM;
 
@@ -803,5 +803,5 @@ int exfat_create_upcase_table(struct super_block *sb)
 
 void exfat_free_upcase_table(struct exfat_sb_info *sbi)
 {
-	kfree(sbi->vol_utbl);
+	kvfree(sbi->vol_utbl);
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* RE: [PATCH v3] exfat: Avoid allocating upcase table using kcalloc()
  2020-12-07  9:34         ` [PATCH v3] " Artem Labazov
@ 2020-12-08  2:22           ` Sungjong Seo
  0 siblings, 0 replies; 10+ messages in thread
From: Sungjong Seo @ 2020-12-08  2:22 UTC (permalink / raw)
  To: 'Artem Labazov'
  Cc: stable, 'Namjae Jeon', linux-fsdevel, linux-kernel

> The table for Unicode upcase conversion requires an order-5 allocation,
> which may fail on a highly-fragmented system:
> 
>  pool-udisksd: page allocation failure: order:5,
> mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO),
> nodemask=(null),cpuset=/,mems_allowed=0
>  CPU: 4 PID: 3756880 Comm: pool-udisksd Tainted: G     U
5.8.10-
> 200.fc32.x86_64 #1
>  Hardware name: Dell Inc. XPS 13 9360/0PVG6D, BIOS 2.13.0 11/14/2019  Call
> Trace:
>   dump_stack+0x6b/0x88
>   warn_alloc.cold+0x75/0xd9
>   ? _cond_resched+0x16/0x40
>   ? __alloc_pages_direct_compact+0x144/0x150
>   __alloc_pages_slowpath.constprop.0+0xcfa/0xd30
>   ? __schedule+0x28a/0x840
>   ? __wait_on_bit_lock+0x92/0xa0
>   __alloc_pages_nodemask+0x2df/0x320
>   kmalloc_order+0x1b/0x80
>   kmalloc_order_trace+0x1d/0xa0
>   exfat_create_upcase_table+0x115/0x390 [exfat]
>   exfat_fill_super+0x3ef/0x7f0 [exfat]
>   ? sget_fc+0x1d0/0x240
>   ? exfat_init_fs_context+0x120/0x120 [exfat]
>   get_tree_bdev+0x15c/0x250
>   vfs_get_tree+0x25/0xb0
>   do_mount+0x7c3/0xaf0
>   ? copy_mount_options+0xab/0x180
>   __x64_sys_mount+0x8e/0xd0
>   do_syscall_64+0x4d/0x90
>   entry_SYSCALL_64_after_hwframe+0x44/0xa9
> 
> Convert kcalloc/kfree to their kv* variants to eliminate the issue.
> 
> Cc: stable@vger.kernel.org # v5.7+
> Signed-off-by: Artem Labazov <123321artyom@gmail.com>

Looks good.
Thanks for your contribution.

Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>

> ---
> v2: replace vmalloc with vzalloc to avoid uninitialized memory access
> v3: use kv* functions to attempt kmalloc first
> 
>  fs/exfat/nls.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c index
> 675d0e7058c5..314d5407a1be 100644
> --- a/fs/exfat/nls.c
> +++ b/fs/exfat/nls.c
> @@ -659,7 +659,7 @@ static int exfat_load_upcase_table(struct super_block
> *sb,
>  	unsigned char skip = false;
>  	unsigned short *upcase_table;
> 
> -	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short),
> GFP_KERNEL);
> +	upcase_table = kvcalloc(UTBL_COUNT, sizeof(unsigned short),
> +GFP_KERNEL);
>  	if (!upcase_table)
>  		return -ENOMEM;
> 
> @@ -715,7 +715,7 @@ static int exfat_load_default_upcase_table(struct
> super_block *sb)
>  	unsigned short uni = 0, *upcase_table;
>  	unsigned int index = 0;
> 
> -	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short),
> GFP_KERNEL);
> +	upcase_table = kvcalloc(UTBL_COUNT, sizeof(unsigned short),
> +GFP_KERNEL);
>  	if (!upcase_table)
>  		return -ENOMEM;
> 
> @@ -803,5 +803,5 @@ int exfat_create_upcase_table(struct super_block *sb)
> 
>  void exfat_free_upcase_table(struct exfat_sb_info *sbi)  {
> -	kfree(sbi->vol_utbl);
> +	kvfree(sbi->vol_utbl);
>  }
> --
> 2.26.2



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] exfat: Avoid allocating upcase table using kcalloc()
@ 2020-11-24 18:50 Artem Labazov
  0 siblings, 0 replies; 10+ messages in thread
From: Artem Labazov @ 2020-11-24 18:50 UTC (permalink / raw)
  Cc: 123321artyom, stable, Namjae Jeon, Sungjong Seo, linux-fsdevel,
	linux-kernel

The table for Unicode upcase conversion requires an order-5 allocation,
which may fail on a highly-fragmented system:

 pool-udisksd: page allocation failure: order:5, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0
 CPU: 4 PID: 3756880 Comm: pool-udisksd Tainted: G     U            5.8.10-200.fc32.x86_64 #1
 Hardware name: Dell Inc. XPS 13 9360/0PVG6D, BIOS 2.13.0 11/14/2019
 Call Trace:
  dump_stack+0x6b/0x88
  warn_alloc.cold+0x75/0xd9
  ? _cond_resched+0x16/0x40
  ? __alloc_pages_direct_compact+0x144/0x150
  __alloc_pages_slowpath.constprop.0+0xcfa/0xd30
  ? __schedule+0x28a/0x840
  ? __wait_on_bit_lock+0x92/0xa0
  __alloc_pages_nodemask+0x2df/0x320
  kmalloc_order+0x1b/0x80
  kmalloc_order_trace+0x1d/0xa0
  exfat_create_upcase_table+0x115/0x390 [exfat]
  exfat_fill_super+0x3ef/0x7f0 [exfat]
  ? sget_fc+0x1d0/0x240
  ? exfat_init_fs_context+0x120/0x120 [exfat]
  get_tree_bdev+0x15c/0x250
  vfs_get_tree+0x25/0xb0
  do_mount+0x7c3/0xaf0
  ? copy_mount_options+0xab/0x180
  __x64_sys_mount+0x8e/0xd0
  do_syscall_64+0x4d/0x90
  entry_SYSCALL_64_after_hwframe+0x44/0xa9

Make the driver use vmalloc() to eliminate the issue.

Cc: stable@vger.kernel.org # v5.7+
Signed-off-by: Artem Labazov <123321artyom@gmail.com>
---
 fs/exfat/nls.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
index 675d0e7058c5..e415794e3ffc 100644
--- a/fs/exfat/nls.c
+++ b/fs/exfat/nls.c
@@ -6,6 +6,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/vmalloc.h>
 #include <asm/unaligned.h>
 
 #include "exfat_raw.h"
@@ -659,7 +660,7 @@ static int exfat_load_upcase_table(struct super_block *sb,
 	unsigned char skip = false;
 	unsigned short *upcase_table;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = vmalloc(UTBL_COUNT * sizeof(unsigned short));
 	if (!upcase_table)
 		return -ENOMEM;
 
@@ -715,7 +716,7 @@ static int exfat_load_default_upcase_table(struct super_block *sb)
 	unsigned short uni = 0, *upcase_table;
 	unsigned int index = 0;
 
-	upcase_table = kcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
+	upcase_table = vmalloc(UTBL_COUNT * sizeof(unsigned short));
 	if (!upcase_table)
 		return -ENOMEM;
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-12-08  2:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20201124194858epcas1p49cacda6a9b4877ff125f25f4dc5fcadf@epcas1p4.samsung.com>
2020-11-24 19:47 ` [PATCH] exfat: Avoid allocating upcase table using kcalloc() Artem Labazov
2020-11-24 22:17   ` David Laight
2020-12-02  4:58   ` Sungjong Seo
2020-12-04 12:57     ` Artem Labazov
2020-12-07  6:23       ` Sungjong Seo
2020-12-07  9:34         ` [PATCH v3] " Artem Labazov
2020-12-08  2:22           ` Sungjong Seo
2020-12-04 13:33     ` [PATCH v2] " Artem Labazov
2020-12-07  4:32       ` Namjae Jeon
2020-11-24 18:50 [PATCH] " Artem Labazov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).