* [PATCH] invalidate buffers on blkdev_put
@ 2001-09-25 3:18 Chris Mason
2001-09-25 3:52 ` Alexander Viro
0 siblings, 1 reply; 9+ messages in thread
From: Chris Mason @ 2001-09-25 3:18 UTC (permalink / raw)
To: linux-kernel; +Cc: andrea, viro, torvalds
Hi guys,
I had sent this to Al, but couldn't tell if he hated it, thought it was
broken, or just didn't think it was required. So, I opted for wider
testing. This only affects 2.4.10pre15+, as it was caused by the blkdev
changes there.
Anyway, the bug looks like this:
dd if=ext2-image-1 of=/dev/ram0
mount /dev/ram0 /mnt
umount /mnt
dd if=ext2-image-2 of=/dev/ram0
mount /dev/ram0 /mnt
ls -la /mnt (FS looks corrupted and wrong).
The problem is that on unmount, the ramdisk's buffer cache isn't cleared
because bd_openers is still one. So, even if a new image is copied in, you
still see the old image's superblock/inodes etc on mount.
In this case, we want to leave the dirty pages in the page cache, but get
rid of the buffer cache copies.
This should not drop any updated data in the ramdisk because
rd_blkdev_pagecache_IO dirties pages as the higher layers send down
modified buffer heads (and other rd.c funcs do the same). Patch is below.
Linus, please consider (pending lack of nays from Al).
An additional patch is probably to remove the second invalidate_buffers
call, since only the filesystems should have buffer cache entries.
-chris
--- 3.1/fs/block_dev.c Sun, 23 Sep 2001 20:11:16 -0400
+++ 3.1(w)/fs/block_dev.c Mon, 24 Sep 2001 15:11:49 -0400
@@ -802,8 +802,10 @@
unlock_super(sb);
drop_super(sb);
}
- } else if (kind == BDEV_FS)
+ } else if (kind == BDEV_FS) {
fsync_no_super(rdev);
+ invalidate_buffers(rdev);
+ }
if (!--bdev->bd_openers) {
truncate_inode_pages(bd_inode->i_mapping, 0);
invalidate_buffers(rdev);
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-25 3:18 [PATCH] invalidate buffers on blkdev_put Chris Mason
@ 2001-09-25 3:52 ` Alexander Viro
2001-09-25 4:21 ` Linus Torvalds
2001-09-25 22:59 ` Anton Altaparmakov
0 siblings, 2 replies; 9+ messages in thread
From: Alexander Viro @ 2001-09-25 3:52 UTC (permalink / raw)
To: Chris Mason; +Cc: linux-kernel, andrea, torvalds
On Mon, 24 Sep 2001, Chris Mason wrote:
>
> Hi guys,
>
> I had sent this to Al, but couldn't tell if he hated it, thought it was
> broken, or just didn't think it was required. So, I opted for wider
> testing. This only affects 2.4.10pre15+, as it was caused by the blkdev
> changes there.
>
> Anyway, the bug looks like this:
>
> dd if=ext2-image-1 of=/dev/ram0
> mount /dev/ram0 /mnt
> umount /mnt
>
> dd if=ext2-image-2 of=/dev/ram0
> mount /dev/ram0 /mnt
> ls -la /mnt (FS looks corrupted and wrong).
>
> The problem is that on unmount, the ramdisk's buffer cache isn't cleared
> because bd_openers is still one. So, even if a new image is copied in, you
> still see the old image's superblock/inodes etc on mount.
>
> In this case, we want to leave the dirty pages in the page cache, but get
> rid of the buffer cache copies.
>
> This should not drop any updated data in the ramdisk because
> rd_blkdev_pagecache_IO dirties pages as the higher layers send down
> modified buffer heads (and other rd.c funcs do the same). Patch is below.
> Linus, please consider (pending lack of nays from Al).
OK, not exactly nay, but... What you are trying to do is a workaround
for problem that can be solved in somewhat saner way. Namely, we can
make getblk() return buffres backed by pages from device page cache.
It's _not_ an obvious step. The most sensitive parts are
* need to allocate all bdev pages with GFP_BUFFER. Otherwise
we'll eat flaming death on VM deadlocks. Doable (we can set ->i_data.gfp_mask)
but may lead to interesting effects wrt VM balancing.
* implementation of bforget()
* we'll need to kill buffer hash or deal with the new access path
to page-private buffer_heads.
It's solvable, but not obvious. It _does_ solve coherency problems between
device page cache and buffer cache (thus killing update_buffers() and its
ilk), but the last issue (new access path to page-private buffer_heads)
may be rather nasty.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-25 3:52 ` Alexander Viro
@ 2001-09-25 4:21 ` Linus Torvalds
2001-09-27 14:03 ` Pavel Machek
2001-09-25 22:59 ` Anton Altaparmakov
1 sibling, 1 reply; 9+ messages in thread
From: Linus Torvalds @ 2001-09-25 4:21 UTC (permalink / raw)
To: Alexander Viro; +Cc: Chris Mason, linux-kernel, andrea
On Mon, 24 Sep 2001, Alexander Viro wrote:
>
> OK, not exactly nay, but... What you are trying to do is a workaround
> for problem that can be solved in somewhat saner way. Namely, we can
> make getblk() return buffres backed by pages from device page cache.
I now have the patches for this, but I have to fix up fs/block_dev.c to
also honour the block size thing because otherwise the two are still not
in sync.
I'll send out a test-patch later this evening, I hope.
> It's solvable, but not obvious. It _does_ solve coherency problems between
> device page cache and buffer cache (thus killing update_buffers() and its
> ilk), but the last issue (new access path to page-private buffer_heads)
> may be rather nasty.
It's certainly solvable, but it is also certainly very fraught with tons
of small details. I'll be very happy if people end up looking through the
patches _very_ critically (and don't even bother testing them if you don't
have a machine where you can lose a filesystem or two).
Hopefully in another hour or two (but the first version is going to have
some ugly stuff in it still).
Linus
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-25 3:52 ` Alexander Viro
2001-09-25 4:21 ` Linus Torvalds
@ 2001-09-25 22:59 ` Anton Altaparmakov
2001-09-26 3:39 ` Linus Torvalds
2001-09-26 22:42 ` Anton Altaparmakov
1 sibling, 2 replies; 9+ messages in thread
From: Anton Altaparmakov @ 2001-09-25 22:59 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Alexander Viro, Chris Mason, linux-kernel, andrea
At 05:21 25/09/01, Linus Torvalds wrote:
>On Mon, 24 Sep 2001, Alexander Viro wrote:
> > OK, not exactly nay, but... What you are trying to do is a workaround
> > for problem that can be solved in somewhat saner way. Namely, we can
> > make getblk() return buffres backed by pages from device page cache.
>
>I now have the patches for this, but I have to fix up fs/block_dev.c to
>also honour the block size thing because otherwise the two are still not
>in sync.
>
>I'll send out a test-patch later this evening, I hope.
>
> > It's solvable, but not obvious. It _does_ solve coherency problems between
> > device page cache and buffer cache (thus killing update_buffers() and its
> > ilk), but the last issue (new access path to page-private buffer_heads)
> > may be rather nasty.
>
>It's certainly solvable, but it is also certainly very fraught with tons
>of small details. I'll be very happy if people end up looking through the
>patches _very_ critically (and don't even bother testing them if you don't
>have a machine where you can lose a filesystem or two).
>
>Hopefully in another hour or two (but the first version is going to have
>some ugly stuff in it still).
Looking at the patch, you introduce a static inline blksize_bits. Wouldn't
it be a lot more efficient to change the function to say:
static inline unsigned int blksize_bits(unsigned int size)
{
return ffs(size) - 1;
}
and optionally, throw in a power of two assertion a-la:
static inline unsigned int blksize_bits(unsigned int size)
{
if (!(size & size - 1))
return ffs(size) - 1;
BUG();
}
Or am I barking mad and block sizes which are not a power of two are valid? (-;
Your version is not too happy with such beasts either but it does round
down rather than do god knows what in arch specific ffs() implementation...
Haven't looked at non-ia32 code but at least ia32's implementation fails
miserably for non-powers of two by it's design. But it should be a lot
faster than doing the while loop considering ffs() just uses a single CPU
instruction instead of the loop (on ia32 anyway).
Best regards,
Anton
--
"Nothing succeeds like success." - Alexandre Dumas
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Linux NTFS Maintainer / WWW: http://linux-ntfs.sf.net/
ICQ: 8561279 / WWW: http://www-stu.christs.cam.ac.uk/~aia21/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-25 22:59 ` Anton Altaparmakov
@ 2001-09-26 3:39 ` Linus Torvalds
2001-09-26 22:42 ` Anton Altaparmakov
1 sibling, 0 replies; 9+ messages in thread
From: Linus Torvalds @ 2001-09-26 3:39 UTC (permalink / raw)
To: Anton Altaparmakov; +Cc: Alexander Viro, Chris Mason, linux-kernel, andrea
On Tue, 25 Sep 2001, Anton Altaparmakov wrote:
>
> Looking at the patch, you introduce a static inline blksize_bits. Wouldn't
> it be a lot more efficient to change the function to say:
More efficient? Probably not. We know that the result of blksize_bits is
in the range of 9-12 on x86, and if you look at the thing it uses that
knowledge.
More importantly, I think the whole code will go away, because the bits
(and the size) should be in the bdev structure in the first place (or,
even better, the inode, at which point all the special-case functions go
away and just become calls to the generic ones)
Linus
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-25 22:59 ` Anton Altaparmakov
2001-09-26 3:39 ` Linus Torvalds
@ 2001-09-26 22:42 ` Anton Altaparmakov
2001-09-27 0:03 ` Andreas Dilger
1 sibling, 1 reply; 9+ messages in thread
From: Anton Altaparmakov @ 2001-09-26 22:42 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Alexander Viro, Chris Mason, linux-kernel, andrea
At 04:39 26/09/01, Linus Torvalds wrote:
>On Tue, 25 Sep 2001, Anton Altaparmakov wrote:
> > Looking at the patch, you introduce a static inline blksize_bits. Wouldn't
> > it be a lot more efficient to change the function to say:
>
>More efficient? Probably not. We know that the result of blksize_bits is
>in the range of 9-12 on x86, and if you look at the thing it uses that
>knowledge.
Of course. I saw that. However the do/while approach is a O(N) algorithm
while the ffs() using algorithm can be O(1) if the CPU allows it.
I wrote a quick benchmark program + script (appended at bottom of this
mail) and did 50 million iterations of either the do/while function or the
ffs() equivalent (including the BUG() check for power of 2) and it turns
out that on all CPUs tested (Pentium 133S, Pentium III 800, Alpha EV56
533(or so), Athlon 1.33GHz 266FSB) the do/while loop is marginally faster
for sizes of 256 and 512 (except P3/800 where the ffs is faster even for
these smaller sizes) but is increasingly slower for increasing sizes. For
large sizes the do/while loop becomes significantly slower than the ffs()
approach, which of course is irrelevant at the moment with the block size
limitation...
The values in below tables are in seconds (user field from time output)
needed to complete 50 million cycles.
For those who prefer graphs rather than tables, I have created line charts
comparing the two methods for each CPU which you can view at URL (note the
charts contain data points for higher sizes, too, not shown in below tables
and also note that each point shown is from a single benchmark run simply
because I couldn't be bothered to do the stats on more than one go, but the
values shown are representative of several runs, if you don't believe me,
the program and script are at the bottom of this mail...):
http://www-stu.christs.cam.ac.uk/~aia21/ffs_test.gif
do/while based function
=======================
| Size
CPU | 256 512 1024 2048 4096 8192 16384
---------------+----------------------------------------------------
P1/133 | 2.26 2.38 4.62 5.29 6.04 6.78 7.56
P3/800 | 0.30 0.30 0.42 0.56 0.70 1.40 1.65
Alpha/533 | 0.48 0.48 1.93 2.22 2.52 2.31 2.61
Athlon/1333 | 0.13 0.14 0.27 0.34 0.41 0.49 0.57
ffs based function
==================
| Size
CPU | 256 512 1024 2048 4096 8192 16384
---------------+----------------------------------------------------
P1/133 | 3.73 3.73 3.78 3.77 3.77 3.78 3.84
P3/800 | 0.27 0.26 0.25 0.26 0.26 0.25 0.27
Alpha/533 | 0.58 0.58 0.58 0.58 0.58 0.58 0.58
Athlon/1333 | 0.15 0.15 0.15 0.15 0.15 0.15 0.15
And just for fun the comparison for the completely irrelevant and insane
size of 2^30 (1073741824), again 50 million iterations:
CPU | do/while | ffs
---------------+----------+--------
P1/133 | 19.62 | 3.76
P3/800 | 3.70 | 0.25
Alpha/533 | 7.25 | 0.58
Athlon/1333 | 2.18 | 0.15
Yeah, I know, benchmarks are to be taken with a pinch of salt, are
meaningless most of the time, etc, but it was fun doing this just to see
how different CPUs perform (on this specific piece of code). And it was a
good way to relax my brain after 11 hours of work at the lab today... (-:
>More importantly, I think the whole code will go away, because the bits
>(and the size) should be in the bdev structure in the first place (or,
>even better, the inode, at which point all the special-case functions go
>away and just become calls to the generic ones)
Yes, that would be a very good thing indeed and yes it renders the
discussion pointless. But a lot of code in the kernel does the same
calculation all the time, in particular in file systems and block devices
(which will probably go away once we have the value in the inode) and
almost none I have seen use ffs() but use variations of unoptimized
for/while/do loops and I think the above benchmark results show that using
ffs() would benefit all those cases unless they expect the normal case to
be a size of less or equal 512.
Best regards,
Anton
--- test_ffs.sh ---
#!/bin/bash
iters=50000000
if [ ! -f ./test_ffs ]; then
gcc -O2 -m486 -o test_ffs test_ffs.c
fi
echo
echo Performing $iters iterations with each blocksize.
for l in 256 512 1024 2048 4096 8192 16384 32768 65536 131072 1073741824; do
time ./test_ffs 1 $iters $l
time ./test_ffs 2 $iters $l
done
exit 0
--- test_ffs.c ---
static inline unsigned int blksize_bits(unsigned int size)
{
unsigned int bits = 8;
do {
bits++;
size >>= 1;
} while (size > 256);
return bits;
}
/*
* Replace this with ffs() from linux/include/asm/bitops.h
* for your arch on non ia32.
*/
static __inline__ int kernel_ia32_ffs(int x)
{
int r;
__asm__("bsfl %1,%0\n\t"
"jnz 1f\n\t"
"movl $-1,%0\n"
"1:" : "=r" (r) : "g" (x));
return r+1;
}
static inline unsigned int blksize_bits_ffs(unsigned int size)
{
if (!(size & size - 1))
return kernel_ia32_ffs(size) - 1;
puts("size not power of 2!");
exit(1);
}
int main(int argc, char *argv[])
{
long i, j, iters, testval;
char test;
if (argc != 4) {
parm_err:
printf("Syntax: test_ffs test iterations testvalue\n"
"test = 1 -> use do/while blksize_bits\n"
"test = 2 -> use ffs blksize_bits\n"
"iterations = number of iterations of "
"blksize_bits call\n"
"testvalue = value to pass to
blksize_bits\n");
exit(1);
}
test = *argv[1];
if (test != '1' && test != '2')
goto parm_err;
iters = atol(argv[2]);
testval = atol(argv[3]);
if (iters <= 0 || testval <= 0)
goto parm_err;
printf("\n\nPerforming %li million iterations of %s test with test "
"value %li.\n", iters/1000000, test == '1' ?
"do/while" : "ffs", testval);
switch (test) {
case '1':
for (i = 0; i < iters; i++)
j = blksize_bits(testval);
break;
case '2':
for (i = 0; i < iters; i++)
j = blksize_bits_ffs(testval);
break;
}
return 0;
}
--
"Nothing succeeds like success." - Alexandre Dumas
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Linux NTFS Maintainer / WWW: http://linux-ntfs.sf.net/
ICQ: 8561279 / WWW: http://www-stu.christs.cam.ac.uk/~aia21/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-26 22:42 ` Anton Altaparmakov
@ 2001-09-27 0:03 ` Andreas Dilger
0 siblings, 0 replies; 9+ messages in thread
From: Andreas Dilger @ 2001-09-27 0:03 UTC (permalink / raw)
To: Anton Altaparmakov; +Cc: linux-kernel
On Sep 26, 2001 23:42 +0100, Anton Altaparmakov wrote:
> I wrote a quick benchmark program + script (appended at bottom of this
> mail) and did 50 million iterations of either the do/while function or the
> ffs() equivalent (including the BUG() check for power of 2) and it turns
> out that on all CPUs tested (Pentium 133S, Pentium III 800, Alpha EV56
> 533(or so), Athlon 1.33GHz 266FSB) the do/while loop is marginally faster
> for sizes of 256 and 512 (except P3/800 where the ffs is faster even for
> these smaller sizes) but is increasingly slower for increasing sizes. For
> large sizes the do/while loop becomes significantly slower than the ffs()
> approach, which of course is irrelevant at the moment with the block size
> limitation...
How does this comapre with:
switch(blocksize) {
case 512: bits = 9; break;
case 1024: bits = 10; break;
case 2048: bits = 11; break;
case 4096: bits = 12; break;
case 8192: bits = 13; break;
default: BUG();
}
Cheers, Andreas
--
Andreas Dilger \ "If a man ate a pound of pasta and a pound of antipasto,
\ would they cancel out, leaving him still hungry?"
http://www-mddsp.enel.ucalgary.ca/People/adilger/ -- Dogbert
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-25 4:21 ` Linus Torvalds
@ 2001-09-27 14:03 ` Pavel Machek
2001-10-01 20:02 ` Dave Cinege
0 siblings, 1 reply; 9+ messages in thread
From: Pavel Machek @ 2001-09-27 14:03 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Alexander Viro, Chris Mason, linux-kernel, andrea
Hi!
> > OK, not exactly nay, but... What you are trying to do is a workaround
> > for problem that can be solved in somewhat saner way. Namely, we can
> > make getblk() return buffres backed by pages from device page cache.
>
> I now have the patches for this, but I have to fix up fs/block_dev.c to
> also honour the block size thing because otherwise the two are still not
> in sync.
>
> I'll send out a test-patch later this evening, I hope.
>
> > It's solvable, but not obvious. It _does_ solve coherency problems between
> > device page cache and buffer cache (thus killing update_buffers() and its
> > ilk), but the last issue (new access path to page-private buffer_heads)
> > may be rather nasty.
>
> It's certainly solvable, but it is also certainly very fraught with tons
> of small details. I'll be very happy if people end up looking through the
> patches _very_ critically (and don't even bother testing them if you don't
> have a machine where you can lose a filesystem or two).
Time to rename 2.4.10 to 2.5.0? ;-)
Pavel
--
Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] invalidate buffers on blkdev_put
2001-09-27 14:03 ` Pavel Machek
@ 2001-10-01 20:02 ` Dave Cinege
0 siblings, 0 replies; 9+ messages in thread
From: Dave Cinege @ 2001-10-01 20:02 UTC (permalink / raw)
To: Pavel Machek; +Cc: linux-kernel
On Thursday 27 September 2001 10:03, Pavel Machek wrote:
> Hi!
>
> > > It's solvable, but not obvious. It _does_ solve coherency problems
> > > between device page cache and buffer cache (thus killing
> > > update_buffers() and its ilk), but the last issue (new access path to
> > > page-private buffer_heads) may be rather nasty.
> >
> > It's certainly solvable, but it is also certainly very fraught with tons
> > of small details. I'll be very happy if people end up looking through the
> > patches _very_ critically (and don't even bother testing them if you
> > don't have a machine where you can lose a filesystem or two).
>
> Time to rename 2.4.10 to 2.5.0? ;-)
<Waving hand> It broke my feature patch. Good enough for me. ; >
--
The time is now 22:19 (Totalitarian) - http://www.ccops.org/clock.html
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2001-10-01 20:00 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-09-25 3:18 [PATCH] invalidate buffers on blkdev_put Chris Mason
2001-09-25 3:52 ` Alexander Viro
2001-09-25 4:21 ` Linus Torvalds
2001-09-27 14:03 ` Pavel Machek
2001-10-01 20:02 ` Dave Cinege
2001-09-25 22:59 ` Anton Altaparmakov
2001-09-26 3:39 ` Linus Torvalds
2001-09-26 22:42 ` Anton Altaparmakov
2001-09-27 0:03 ` Andreas Dilger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®