lkml.org 
[lkml]   [2008]   [Jul]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH] eCryptfs - use page_alloc not kmalloc to get a page of memory
    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;
    > }
    >
    >


    \
     
     \ /
      Last update: 2008-07-28 18:27    [W:0.030 / U:30.244 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site