* [PATCH] Fix up xfs_buf_associate_memory()
@ 2007-11-23 4:29 Lachlan McIlroy
2007-11-23 13:43 ` Christoph Hellwig
0 siblings, 1 reply; 3+ messages in thread
From: Lachlan McIlroy @ 2007-11-23 4:29 UTC (permalink / raw)
To: xfs-dev, xfs-oss
[-- Attachment #1: Type: text/plain, Size: 654 bytes --]
Fixed a few bugs in xfs_buf_associate_memory() including:
- calculation of 'page_count' was incorrect as it did not
consider the offset of 'mem' into the first page. The
logic to bump 'page_count' didn't work if 'len' was <=
PAGE_CACHE_SIZE (ie offset = 3k, len = 2k).
- setting b_buffer_length to 'len' is incorrect if
'offset' is > 0. Set it to the total length of the
buffer.
- I suspect that passing a non-aligned address into
mem_to_page() for the first page may have been causing
issues - don't know but just tidy up that code anyway.
These fixes prevent an data corruption issue that can
occur during log replay.
Lachlan
[-- Attachment #2: xfs_buf.diff --]
[-- Type: text/x-patch, Size: 1419 bytes --]
--- fs/xfs/linux-2.6/xfs_buf.c_1.247 2007-11-23 12:03:16.000000000 +1100
+++ fs/xfs/linux-2.6/xfs_buf.c 2007-11-23 12:02:32.000000000 +1100
@@ -726,14 +726,14 @@ xfs_buf_associate_memory(
int rval;
int i = 0;
size_t ptr;
- size_t end, end_cur;
+ size_t buflen;
off_t offset;
int page_count;
- page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT;
- offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK);
- if (offset && (len > PAGE_CACHE_SIZE))
- page_count++;
+ ptr = (size_t) mem & PAGE_CACHE_MASK;
+ offset = (off_t) mem - (off_t) ptr;
+ buflen = PAGE_CACHE_ALIGN(len + offset);
+ page_count = buflen >> PAGE_CACHE_SHIFT;
/* Free any previous set of page pointers */
if (bp->b_pages)
@@ -747,22 +747,15 @@ xfs_buf_associate_memory(
return rval;
bp->b_offset = offset;
- ptr = (size_t) mem & PAGE_CACHE_MASK;
- end = PAGE_CACHE_ALIGN((size_t) mem + len);
- end_cur = end;
- /* set up first page */
- bp->b_pages[0] = mem_to_page(mem);
-
- ptr += PAGE_CACHE_SIZE;
- bp->b_page_count = ++i;
- while (ptr < end) {
- bp->b_pages[i] = mem_to_page((void *)ptr);
- bp->b_page_count = ++i;
+
+ while (i < bp->b_page_count) {
+ bp->b_pages[i++] = mem_to_page((void *)ptr);
ptr += PAGE_CACHE_SIZE;
}
bp->b_locked = 0;
- bp->b_count_desired = bp->b_buffer_length = len;
+ bp->b_count_desired = len;
+ bp->b_buffer_length = buflen;
bp->b_flags |= XBF_MAPPED;
return 0;
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Fix up xfs_buf_associate_memory()
2007-11-23 4:29 [PATCH] Fix up xfs_buf_associate_memory() Lachlan McIlroy
@ 2007-11-23 13:43 ` Christoph Hellwig
2007-11-26 0:25 ` Lachlan McIlroy
0 siblings, 1 reply; 3+ messages in thread
From: Christoph Hellwig @ 2007-11-23 13:43 UTC (permalink / raw)
To: Lachlan McIlroy; +Cc: xfs-dev, xfs-oss
On Fri, Nov 23, 2007 at 03:29:06PM +1100, Lachlan McIlroy wrote:
> Fixed a few bugs in xfs_buf_associate_memory() including:
>
> - calculation of 'page_count' was incorrect as it did not
> consider the offset of 'mem' into the first page. The
> logic to bump 'page_count' didn't work if 'len' was <=
> PAGE_CACHE_SIZE (ie offset = 3k, len = 2k).
> - setting b_buffer_length to 'len' is incorrect if
> 'offset' is > 0. Set it to the total length of the
> buffer.
> - I suspect that passing a non-aligned address into
> mem_to_page() for the first page may have been causing
> issues - don't know but just tidy up that code anyway.
>
> These fixes prevent an data corruption issue that can
> occur during log replay.
Last time I tried to clean up this gem everything went bezerk, so be
aware :)
--- fs/xfs/linux-2.6/xfs_buf.c_1.247 2007-11-23 12:03:16.000000000 +1100
+++ fs/xfs/linux-2.6/xfs_buf.c 2007-11-23 12:02:32.000000000 +1100
@@ -726,14 +726,14 @@ xfs_buf_associate_memory(
int rval;
int i = 0;
size_t ptr;
+ size_t buflen;
off_t offset;
int page_count;
+ ptr = (size_t) mem & PAGE_CACHE_MASK;
+ offset = (off_t) mem - (off_t) ptr;
Casting pointers to size_t or off_t makes little sense, these should be
unsigned long. And using a variable name of ptr is quite odd :)
+ while (i < bp->b_page_count) {
+ bp->b_pages[i++] = mem_to_page((void *)ptr);
ptr += PAGE_CACHE_SIZE;
}
This could be much cleaner written as:
for (i = 0; i < bp->b_page_count; i++) {
bp->b_pages[i] = mem_to_page((void *)ptr);
ptr += PAGE_CACHE_SIZE;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Fix up xfs_buf_associate_memory()
2007-11-23 13:43 ` Christoph Hellwig
@ 2007-11-26 0:25 ` Lachlan McIlroy
0 siblings, 0 replies; 3+ messages in thread
From: Lachlan McIlroy @ 2007-11-26 0:25 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs-dev, xfs-oss
Christoph Hellwig wrote:
> On Fri, Nov 23, 2007 at 03:29:06PM +1100, Lachlan McIlroy wrote:
>> Fixed a few bugs in xfs_buf_associate_memory() including:
>>
>> - calculation of 'page_count' was incorrect as it did not
>> consider the offset of 'mem' into the first page. The
>> logic to bump 'page_count' didn't work if 'len' was <=
>> PAGE_CACHE_SIZE (ie offset = 3k, len = 2k).
>> - setting b_buffer_length to 'len' is incorrect if
>> 'offset' is > 0. Set it to the total length of the
>> buffer.
>> - I suspect that passing a non-aligned address into
>> mem_to_page() for the first page may have been causing
>> issues - don't know but just tidy up that code anyway.
>>
>> These fixes prevent an data corruption issue that can
>> occur during log replay.
>
> Last time I tried to clean up this gem everything went bezerk, so be
> aware :)
>
>
> --- fs/xfs/linux-2.6/xfs_buf.c_1.247 2007-11-23 12:03:16.000000000 +1100
> +++ fs/xfs/linux-2.6/xfs_buf.c 2007-11-23 12:02:32.000000000 +1100
> @@ -726,14 +726,14 @@ xfs_buf_associate_memory(
> int rval;
> int i = 0;
> size_t ptr;
> + size_t buflen;
> off_t offset;
> int page_count;
>
> + ptr = (size_t) mem & PAGE_CACHE_MASK;
> + offset = (off_t) mem - (off_t) ptr;
>
> Casting pointers to size_t or off_t makes little sense, these should be
> unsigned long. And using a variable name of ptr is quite odd :)
I just left those as they were before the change. I'll tidy them too.
>
> + while (i < bp->b_page_count) {
> + bp->b_pages[i++] = mem_to_page((void *)ptr);
> ptr += PAGE_CACHE_SIZE;
> }
>
> This could be much cleaner written as:
>
> for (i = 0; i < bp->b_page_count; i++) {
> bp->b_pages[i] = mem_to_page((void *)ptr);
> ptr += PAGE_CACHE_SIZE;
> }
>
Fine with me.
Thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-11-26 0:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-23 4:29 [PATCH] Fix up xfs_buf_associate_memory() Lachlan McIlroy
2007-11-23 13:43 ` Christoph Hellwig
2007-11-26 0:25 ` Lachlan McIlroy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox