xfs
[Top] [All Lists]

Initial fix for non 4k page systems.

To: linux-xfs@xxxxxxxxxxx
Subject: Initial fix for non 4k page systems.
From: Russell Cattelan <cattelan@xxxxxxxxxxx>
Date: Mon, 11 Dec 2000 12:42:49 -0600
Sender: owner-linux-xfs@xxxxxxxxxxx
I need to rework this to make it a bit cleaner.
But I finally tracked down the problem with meta data corruption on
non 4k page systems.

Basically the problem is due to kmalloc returning memory that isn't disk
block aligned (512).
In the case of the super block; kmalloc was returning a pointer 768
bytes into a page.
Pagebuf keeps track of individual disk block via a bit array in the page
structure, but
this works under the assumption that the page is divided equally on 512
byte boundaries.
Obviously 768 is not on a 512 byte boundary, this was confusing the rest
of the pagebuf code
causing it incorrectly think it needed to write out 2 blocks (1024) for
the superblock.

I'm not sure if there is a way to force kmalloc to align memory, if
anybody has a suggest let me know
in the mean time this patch will realign things to the correct boundary.

I've only testing this on an alpha system, so I curious to see if this
fixes ppc and ia64.



*** /usr/tmp/TmpDir.23191-0/linux/fs/pagebuf/page_buf.c_1.44    Mon Dec
11 12:31:19 2000
--- linux/fs/pagebuf/page_buf.c Tue Nov  5 04:32:05 1912
***************
*** 862,867 ****
--- 862,868 ----
  {
        int rval;
        void *rmem;
+       size_t tlen = len;
        int flags = _PBF_LOCKABLE | PBF_FORCEIO;
        page_buf_t *pb;

***************
*** 870,879 ****
        if (0 != rval)
                return (NULL);

!       if ((rmem = kmalloc(len, GFP_KERNEL)) == 0) {
                pagebuf_free(pb);
                return (NULL);
        }
        if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) {
                kfree(rmem);
                pagebuf_free(pb);
--- 871,897 ----
        if (0 != rval)
                return (NULL);

! alloc:
!       if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) {
                pagebuf_free(pb);
                return (NULL);
        }
+ #define BLOCK_MASK (~(512-1))
+       if ((size_t)rmem != ((size_t)rmem & (size_t)BLOCK_MASK)){
+               if(tlen != len){
+                       rmem =  (size_t)rmem + (size_t)512 &
(size_t)BLOCK_MASK;
+                       printk("OK NEW 0x%p tlen %d\n",rmem,tlen);
+                       goto out;
+               }
+               printk("pb_get_no_daddr NOT block 0x%p mask 0x%p len
%d\n",
+                       rmem,
+                       ((size_t)rmem & (size_t)BLOCK_MASK),
+                       len);
+               kfree(rmem);
+               tlen = len << 1;
+               goto alloc;
+ }
+ out:
        if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) {
                kfree(rmem);
                pagebuf_free(pb);


<Prev in Thread] Current Thread [Next in Thread>