linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
@ 2008-07-28 16:13 Eric Sandeen
  2008-07-28 16:25 ` Michael Halcrow
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Eric Sandeen @ 2008-07-28 16:13 UTC (permalink / raw)
  To: linux-kernel Mailing List; +Cc: Michael Halcrow, Andrew Morton

With SLUB debugging turned on in 2.6.26, I was getting memory corruption
when testing eCryptfs.  The root cause turned out to be that eCryptfs
was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
as a nice page-aligned chunk of memory.  But at least with SLUB debugging
on, this is not always true, and the page we get from virt_to_page does
not necessarily match the PAGE_CACHE_SIZE worth of memory we got from 
kmalloc.

My simple testcase was 2 loops doing "rm -f fileX; cp /tmp/fileX ." for
2 different multi-megabyte files.  With this change I no longer see
the corruption.

Thanks,
-Eric

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---

Index: linux-2.6.26/fs/ecryptfs/crypto.c
===================================================================
--- linux-2.6.26.orig/fs/ecryptfs/crypto.c
+++ linux-2.6.26/fs/ecryptfs/crypto.c
@@ -474,8 +474,8 @@ int ecryptfs_encrypt_page(struct page *p
 {
 	struct inode *ecryptfs_inode;
 	struct ecryptfs_crypt_stat *crypt_stat;
-	char *enc_extent_virt = NULL;
-	struct page *enc_extent_page;
+	char *enc_extent_virt;
+	struct page *enc_extent_page = NULL;
 	loff_t extent_offset;
 	int rc = 0;
 
@@ -491,14 +491,14 @@ int ecryptfs_encrypt_page(struct page *p
 			       page->index);
 		goto out;
 	}
-	enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
-	if (!enc_extent_virt) {
+	enc_extent_page = alloc_page(GFP_USER);
+	if (!enc_extent_page) {
 		rc = -ENOMEM;
 		ecryptfs_printk(KERN_ERR, "Error allocating memory for "
 				"encrypted extent\n");
 		goto out;
 	}
-	enc_extent_page = virt_to_page(enc_extent_virt);
+	enc_extent_virt = kmap(enc_extent_page);
 	for (extent_offset = 0;
 	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
 	     extent_offset++) {
@@ -526,7 +526,10 @@ int ecryptfs_encrypt_page(struct page *p
 		}
 	}
 out:
-	kfree(enc_extent_virt);
+	if (enc_extent_page) {
+		kunmap(enc_extent_page);
+		__free_page(enc_extent_page);
+	}
 	return rc;
 }
 
@@ -608,8 +611,8 @@ int ecryptfs_decrypt_page(struct page *p
 {
 	struct inode *ecryptfs_inode;
 	struct ecryptfs_crypt_stat *crypt_stat;
-	char *enc_extent_virt = NULL;
-	struct page *enc_extent_page;
+	char *enc_extent_virt;
+	struct page *enc_extent_page = NULL;
 	unsigned long extent_offset;
 	int rc = 0;
 
@@ -626,14 +629,14 @@ int ecryptfs_decrypt_page(struct page *p
 			       page->index);
 		goto out;
 	}
-	enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
-	if (!enc_extent_virt) {
+	enc_extent_page = alloc_page(GFP_USER);
+	if (!enc_extent_page) {
 		rc = -ENOMEM;
 		ecryptfs_printk(KERN_ERR, "Error allocating memory for "
 				"encrypted extent\n");
 		goto out;
 	}
-	enc_extent_page = virt_to_page(enc_extent_virt);
+	enc_extent_virt = kmap(enc_extent_page);
 	for (extent_offset = 0;
 	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
 	     extent_offset++) {
@@ -661,7 +664,10 @@ int ecryptfs_decrypt_page(struct page *p
 		}
 	}
 out:
-	kfree(enc_extent_virt);
+	if (enc_extent_page) {
+		kunmap(enc_extent_page);
+		__free_page(enc_extent_page);
+	}
 	return rc;
 }
 


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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 16:13 [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory Eric Sandeen
@ 2008-07-28 16:25 ` Michael Halcrow
  2008-07-28 16:53 ` Rik van Riel
  2008-07-28 20:35 ` Andrew Morton
  2 siblings, 0 replies; 10+ messages in thread
From: Michael Halcrow @ 2008-07-28 16:25 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: linux-kernel Mailing List, Andrew Morton

On Mon, Jul 28, 2008 at 11:13:03AM -0500, Eric Sandeen wrote:
> With SLUB debugging turned on in 2.6.26, I was getting memory corruption
> when testing eCryptfs.  The root cause turned out to be that eCryptfs
> was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
> as a nice page-aligned chunk of memory.  But at least with SLUB debugging
> on, this is not always true, and the page we get from virt_to_page does
> not necessarily match the PAGE_CACHE_SIZE worth of memory we got from 
> kmalloc.
> 
> My simple testcase was 2 loops doing "rm -f fileX; cp /tmp/fileX ." for
> 2 different multi-megabyte files.  With this change I no longer see
> the corruption.
> 
> Thanks,
> -Eric
> 
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>

Acked-by: Michael Halcrow <mhalcrow@us.ibm.com>

> ---
> 
> Index: linux-2.6.26/fs/ecryptfs/crypto.c
> ===================================================================
> --- linux-2.6.26.orig/fs/ecryptfs/crypto.c
> +++ linux-2.6.26/fs/ecryptfs/crypto.c
> @@ -474,8 +474,8 @@ int ecryptfs_encrypt_page(struct page *p
>  {
>  	struct inode *ecryptfs_inode;
>  	struct ecryptfs_crypt_stat *crypt_stat;
> -	char *enc_extent_virt = NULL;
> -	struct page *enc_extent_page;
> +	char *enc_extent_virt;
> +	struct page *enc_extent_page = NULL;
>  	loff_t extent_offset;
>  	int rc = 0;
> 
> @@ -491,14 +491,14 @@ int ecryptfs_encrypt_page(struct page *p
>  			       page->index);
>  		goto out;
>  	}
> -	enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
> -	if (!enc_extent_virt) {
> +	enc_extent_page = alloc_page(GFP_USER);
> +	if (!enc_extent_page) {
>  		rc = -ENOMEM;
>  		ecryptfs_printk(KERN_ERR, "Error allocating memory for "
>  				"encrypted extent\n");
>  		goto out;
>  	}
> -	enc_extent_page = virt_to_page(enc_extent_virt);
> +	enc_extent_virt = kmap(enc_extent_page);
>  	for (extent_offset = 0;
>  	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
>  	     extent_offset++) {
> @@ -526,7 +526,10 @@ int ecryptfs_encrypt_page(struct page *p
>  		}
>  	}
>  out:
> -	kfree(enc_extent_virt);
> +	if (enc_extent_page) {
> +		kunmap(enc_extent_page);
> +		__free_page(enc_extent_page);
> +	}
>  	return rc;
>  }
> 
> @@ -608,8 +611,8 @@ int ecryptfs_decrypt_page(struct page *p
>  {
>  	struct inode *ecryptfs_inode;
>  	struct ecryptfs_crypt_stat *crypt_stat;
> -	char *enc_extent_virt = NULL;
> -	struct page *enc_extent_page;
> +	char *enc_extent_virt;
> +	struct page *enc_extent_page = NULL;
>  	unsigned long extent_offset;
>  	int rc = 0;
> 
> @@ -626,14 +629,14 @@ int ecryptfs_decrypt_page(struct page *p
>  			       page->index);
>  		goto out;
>  	}
> -	enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);
> -	if (!enc_extent_virt) {
> +	enc_extent_page = alloc_page(GFP_USER);
> +	if (!enc_extent_page) {
>  		rc = -ENOMEM;
>  		ecryptfs_printk(KERN_ERR, "Error allocating memory for "
>  				"encrypted extent\n");
>  		goto out;
>  	}
> -	enc_extent_page = virt_to_page(enc_extent_virt);
> +	enc_extent_virt = kmap(enc_extent_page);
>  	for (extent_offset = 0;
>  	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);
>  	     extent_offset++) {
> @@ -661,7 +664,10 @@ int ecryptfs_decrypt_page(struct page *p
>  		}
>  	}
>  out:
> -	kfree(enc_extent_virt);
> +	if (enc_extent_page) {
> +		kunmap(enc_extent_page);
> +		__free_page(enc_extent_page);
> +	}
>  	return rc;
>  }
> 
> 

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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 16:13 [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory Eric Sandeen
  2008-07-28 16:25 ` Michael Halcrow
@ 2008-07-28 16:53 ` Rik van Riel
  2008-07-28 20:35 ` Andrew Morton
  2 siblings, 0 replies; 10+ messages in thread
From: Rik van Riel @ 2008-07-28 16:53 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: linux-kernel Mailing List, Michael Halcrow, Andrew Morton

On Mon, 28 Jul 2008 11:13:03 -0500
Eric Sandeen <sandeen@redhat.com> wrote:

> With SLUB debugging turned on in 2.6.26, I was getting memory corruption
> when testing eCryptfs.  The root cause turned out to be that eCryptfs
> was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
> as a nice page-aligned chunk of memory. 

uh oh

> Signed-off-by: Eric Sandeen <sandeen@redhat.com>

Acked-by: Rik van Riel <riel@redhat.com>

-- 
All Rights Reversed

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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 16:13 [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory Eric Sandeen
  2008-07-28 16:25 ` Michael Halcrow
  2008-07-28 16:53 ` Rik van Riel
@ 2008-07-28 20:35 ` Andrew Morton
  2008-07-28 20:38   ` Eric Sandeen
  2008-07-28 20:42   ` Pekka Enberg
  2 siblings, 2 replies; 10+ messages in thread
From: Andrew Morton @ 2008-07-28 20:35 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: linux-kernel, mhalcrow, stable

On Mon, 28 Jul 2008 11:13:03 -0500
Eric Sandeen <sandeen@redhat.com> wrote:

> With SLUB debugging turned on in 2.6.26, I was getting memory corruption
> when testing eCryptfs.  The root cause turned out to be that eCryptfs
> was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
> as a nice page-aligned chunk of memory.  But at least with SLUB debugging
> on, this is not always true, and the page we get from virt_to_page does
> not necessarily match the PAGE_CACHE_SIZE worth of memory we got from 
> kmalloc.
> 
> My simple testcase was 2 loops doing "rm -f fileX; cp /tmp/fileX ." for
> 2 different multi-megabyte files.  With this change I no longer see
> the corruption.

The fix applies to both 2.6.25 and to 2.6.26 and appears to be needed
in both kernel versions, so I have tagged it for backporting into both.


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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 20:35 ` Andrew Morton
@ 2008-07-28 20:38   ` Eric Sandeen
  2008-07-28 20:42   ` Pekka Enberg
  1 sibling, 0 replies; 10+ messages in thread
From: Eric Sandeen @ 2008-07-28 20:38 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, mhalcrow, stable

Andrew Morton wrote:
> On Mon, 28 Jul 2008 11:13:03 -0500
> Eric Sandeen <sandeen@redhat.com> wrote:
> 
>> With SLUB debugging turned on in 2.6.26, I was getting memory corruption
>> when testing eCryptfs.  The root cause turned out to be that eCryptfs
>> was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
>> as a nice page-aligned chunk of memory.  But at least with SLUB debugging
>> on, this is not always true, and the page we get from virt_to_page does
>> not necessarily match the PAGE_CACHE_SIZE worth of memory we got from 
>> kmalloc.
>>
>> My simple testcase was 2 loops doing "rm -f fileX; cp /tmp/fileX ." for
>> 2 different multi-megabyte files.  With this change I no longer see
>> the corruption.
> 
> The fix applies to both 2.6.25 and to 2.6.26 and appears to be needed
> in both kernel versions, so I have tagged it for backporting into both.

I agree, thanks.

-Eric

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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 20:35 ` Andrew Morton
  2008-07-28 20:38   ` Eric Sandeen
@ 2008-07-28 20:42   ` Pekka Enberg
  2008-07-28 21:03     ` Eric Sandeen
  2008-07-30 14:39     ` Christoph Lameter
  1 sibling, 2 replies; 10+ messages in thread
From: Pekka Enberg @ 2008-07-28 20:42 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Eric Sandeen, linux-kernel, mhalcrow, stable, Christoph Lameter

On Mon, Jul 28, 2008 at 11:35 PM, Andrew Morton
<akpm@linux-foundation.org> wrote:
> On Mon, 28 Jul 2008 11:13:03 -0500
> Eric Sandeen <sandeen@redhat.com> wrote:
>
>> With SLUB debugging turned on in 2.6.26, I was getting memory corruption
>> when testing eCryptfs.  The root cause turned out to be that eCryptfs
>> was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
>> as a nice page-aligned chunk of memory.  But at least with SLUB debugging
>> on, this is not always true, and the page we get from virt_to_page does
>> not necessarily match the PAGE_CACHE_SIZE worth of memory we got from
>> kmalloc.
>>
>> My simple testcase was 2 loops doing "rm -f fileX; cp /tmp/fileX ." for
>> 2 different multi-megabyte files.  With this change I no longer see
>> the corruption.
>
> The fix applies to both 2.6.25 and to 2.6.26 and appears to be needed
> in both kernel versions, so I have tagged it for backporting into both.

Hmm, SLUB will use the page allocator directly for PAGE_CACHE_SIZE
regadless of whether debugging is enabled or not...

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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 20:42   ` Pekka Enberg
@ 2008-07-28 21:03     ` Eric Sandeen
  2008-07-28 21:12       ` Pekka Enberg
  2008-07-30 14:39     ` Christoph Lameter
  1 sibling, 1 reply; 10+ messages in thread
From: Eric Sandeen @ 2008-07-28 21:03 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Andrew Morton, linux-kernel, mhalcrow, stable, Christoph Lameter

Pekka Enberg wrote:
> On Mon, Jul 28, 2008 at 11:35 PM, Andrew Morton
> <akpm@linux-foundation.org> wrote:
>> On Mon, 28 Jul 2008 11:13:03 -0500
>> Eric Sandeen <sandeen@redhat.com> wrote:
>>
>>> With SLUB debugging turned on in 2.6.26, I was getting memory corruption
>>> when testing eCryptfs.  The root cause turned out to be that eCryptfs
>>> was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
>>> as a nice page-aligned chunk of memory.  But at least with SLUB debugging
>>> on, this is not always true, and the page we get from virt_to_page does
>>> not necessarily match the PAGE_CACHE_SIZE worth of memory we got from
>>> kmalloc.
>>>
>>> My simple testcase was 2 loops doing "rm -f fileX; cp /tmp/fileX ." for
>>> 2 different multi-megabyte files.  With this change I no longer see
>>> the corruption.
>> The fix applies to both 2.6.25 and to 2.6.26 and appears to be needed
>> in both kernel versions, so I have tagged it for backporting into both.
> 
> Hmm, SLUB will use the page allocator directly for PAGE_CACHE_SIZE
> regadless of whether debugging is enabled or not...

For whatever reason, I did see non-page-aligned memory returned from
kmalloc(PAGE_CACHE_SIZE), and I think this is what caused the problem
once virt_to_page() was used to get hold of a page to pass around in the
ecryptfs/crypto code...

-Eric

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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 21:03     ` Eric Sandeen
@ 2008-07-28 21:12       ` Pekka Enberg
  2008-07-30 14:48         ` Christoph Lameter
  0 siblings, 1 reply; 10+ messages in thread
From: Pekka Enberg @ 2008-07-28 21:12 UTC (permalink / raw)
  To: Eric Sandeen
  Cc: Andrew Morton, linux-kernel, mhalcrow, stable, Christoph Lameter

Hi Eric,

Eric Sandeen wrote:
> Pekka Enberg wrote:
>> On Mon, Jul 28, 2008 at 11:35 PM, Andrew Morton
>> <akpm@linux-foundation.org> wrote:
>>> On Mon, 28 Jul 2008 11:13:03 -0500
>>> Eric Sandeen <sandeen@redhat.com> wrote:
>>>
>>>> With SLUB debugging turned on in 2.6.26, I was getting memory corruption
>>>> when testing eCryptfs.  The root cause turned out to be that eCryptfs
>>>> was doing kmalloc(PAGE_CACHE_SIZE); virt_to_page() and treating that
>>>> as a nice page-aligned chunk of memory.  But at least with SLUB debugging
>>>> on, this is not always true, and the page we get from virt_to_page does
>>>> not necessarily match the PAGE_CACHE_SIZE worth of memory we got from
>>>> kmalloc.
>>>>
>>>> My simple testcase was 2 loops doing "rm -f fileX; cp /tmp/fileX ." for
>>>> 2 different multi-megabyte files.  With this change I no longer see
>>>> the corruption.
>>> The fix applies to both 2.6.25 and to 2.6.26 and appears to be needed
>>> in both kernel versions, so I have tagged it for backporting into both.
>> Hmm, SLUB will use the page allocator directly for PAGE_CACHE_SIZE
>> regadless of whether debugging is enabled or not...
> 
> For whatever reason, I did see non-page-aligned memory returned from
> kmalloc(PAGE_CACHE_SIZE), and I think this is what caused the problem
> once virt_to_page() was used to get hold of a page to pass around in the
> ecryptfs/crypto code...

With SLUB? I can't see how that's possible. I can see this with SLAB, 
though, for 4K pages.

In any case, the patch, of course, make sense as kmalloc() behavior 
varies between allocators.

		Pekka

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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 20:42   ` Pekka Enberg
  2008-07-28 21:03     ` Eric Sandeen
@ 2008-07-30 14:39     ` Christoph Lameter
  1 sibling, 0 replies; 10+ messages in thread
From: Christoph Lameter @ 2008-07-30 14:39 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Andrew Morton, Eric Sandeen, linux-kernel, mhalcrow, stable

Pekka Enberg wrote:

> Hmm, SLUB will use the page allocator directly for PAGE_CACHE_SIZE
> regadless of whether debugging is enabled or not...

Only until 2.6.24. SLUB uses page allocator for > PAGE_CACHE_SIZE



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

* Re: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
  2008-07-28 21:12       ` Pekka Enberg
@ 2008-07-30 14:48         ` Christoph Lameter
  0 siblings, 0 replies; 10+ messages in thread
From: Christoph Lameter @ 2008-07-30 14:48 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Eric Sandeen, Andrew Morton, linux-kernel, mhalcrow, stable

Pekka Enberg wrote:
>> For whatever reason, I did see non-page-aligned memory returned from
>> kmalloc(PAGE_CACHE_SIZE), and I think this is what caused the problem
>> once virt_to_page() was used to get hold of a page to pass around in the
>> ecryptfs/crypto code...
> 
> With SLUB? I can't see how that's possible. I can see this with SLAB,
> though, for 4K pages.

It possible because PAGE_CACHE_SIZE is still handled by SLUB and if debugging is on then   kmalloc may return non page aligned objects. The handoff to the page allocator only occurs for objects > 4k. We used to do this also for 4k objects but then we got performance regressions in tbench.



> In any case, the patch, of course, make sense as kmalloc() behavior
> varies between allocators.
> 
>         Pekka


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

end of thread, other threads:[~2008-07-30 14:56 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-28 16:13 [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory Eric Sandeen
2008-07-28 16:25 ` Michael Halcrow
2008-07-28 16:53 ` Rik van Riel
2008-07-28 20:35 ` Andrew Morton
2008-07-28 20:38   ` Eric Sandeen
2008-07-28 20:42   ` Pekka Enberg
2008-07-28 21:03     ` Eric Sandeen
2008-07-28 21:12       ` Pekka Enberg
2008-07-30 14:48         ` Christoph Lameter
2008-07-30 14:39     ` Christoph Lameter

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).