linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: Poor floppy performance in kernel 2.4.10
@ 2001-10-27 15:00 Alain Knaff
  2001-10-27 15:15 ` Alexander Viro
  0 siblings, 1 reply; 67+ messages in thread
From: Alain Knaff @ 2001-10-27 15:00 UTC (permalink / raw)
  To: torvalds, linux-kernel; +Cc: viro

Appended to this mail is a patch meant to fix the "non-cached floppy"
problem.

The  block_device_operations structure now has a new member:
  can_trust_media_change
If this returns 1, the VFS trusts the driver's check_media_change
function, and skips the call to kill_bdev in blkdev_put. If the driver
provides no such function, it defaults to "don't trust" (i.e. call
kill_bdev)

The floppy driver implements this new function in the following way:
 1. if broken_dcl on a drive is set, can_trust_media_change always
returns false
 2. if broken_dcl is not set, the function initially returns false,
until a disk change signal is seen. From then on, it always returns
true.

Other block devices could implement this by using black or whitelists,
or hardwiring a value.

HOWEVER, even after these changes, the caching problem still wasn't
solved (I confirmed with additional printk's that invalidate_bdev was
indeed no longer called).

Further investigation showed that the real culprit was actually
bdput. This function seems to de-allocate all structures attached to
the block device, including the cache... Ifdeffing it out did indeed
restore cache functionality. However, I understand that this would not
be a proper way to address the problem, as it would certainly cause a
memory leak.

Appended to this mail is the patch (without the debugging printk's,
and with bdput still intact); however in order to make it really work
bdput would need to be changed to not free up the cache, if that is
possible... Any ideas?

Regards,

Alain

diff -ur 2.4.13/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- 2.4.13/linux/drivers/block/floppy.c	Sat Oct 27 09:42:34 2001
+++ linux/drivers/block/floppy.c	Sat Oct 27 16:17:33 2001
@@ -741,6 +741,7 @@
 		return UTESTF(FD_DISK_CHANGED);
 	if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80){
 		USETF(FD_VERIFY); /* verify write protection */
+		USETF(FD_DCL_SEEN); /* DCL for this drive has been seen */
 		if (UDRS->maxblock){
 			/* mark it changed */
 			USETF(FD_DISK_CHANGED);
@@ -3901,12 +3902,23 @@
 	return 0;
 }
 
+/* determines whether we can trust media change
+ * answers true if we have seen disk change at least once, and not marked as
+ * broken */
+static int floppy_can_trust_media_change(kdev_t dev)
+{
+	int drive=DRIVE(dev);
+	return (UTESTF(FD_DCL_SEEN) &&
+		((UDP->flags & FD_BROKEN_DCL) == 0));
+}
+
 static struct block_device_operations floppy_fops = {
 	open:			floppy_open,
 	release:		floppy_release,
 	ioctl:			fd_ioctl,
 	check_media_change:	check_floppy_change,
 	revalidate:		floppy_revalidate,
+	can_trust_media_change: floppy_can_trust_media_change
 };
 
 static void __init register_devfs_entries (int drive)
diff -ur 2.4.13/linux/fs/block_dev.c linux/fs/block_dev.c
--- 2.4.13/linux/fs/block_dev.c	Sat Oct 27 09:43:27 2001
+++ linux/fs/block_dev.c	Sat Oct 27 16:18:19 2001
@@ -601,8 +601,12 @@
 		__block_fsync(bd_inode);
 	else if (kind == BDEV_FS)
 		fsync_no_super(rdev);
-	if (!--bdev->bd_openers)
-		kill_bdev(bdev);
+	if (!--bdev->bd_openers) {
+		if(!bdev->bd_op->can_trust_media_change ||
+		   !bdev->bd_op->can_trust_media_change(rdev)) {
+			kill_bdev(bdev);
+		}
+	}
 	if (bdev->bd_op->release)
 		ret = bdev->bd_op->release(bd_inode, NULL);
 	if (!bdev->bd_openers)
diff -ur 2.4.13/linux/include/linux/fd.h linux/include/linux/fd.h
--- 2.4.13/linux/include/linux/fd.h	Fri Aug 13 21:16:16 1999
+++ linux/include/linux/fd.h	Sat Oct 27 13:37:08 2001
@@ -177,7 +177,8 @@
 				 * to clear media change status */
 	FD_UNUSED_BIT,
 	FD_DISK_CHANGED_BIT,	/* disk has been changed since last i/o */
-	FD_DISK_WRITABLE_BIT	/* disk is writable */
+	FD_DISK_WRITABLE_BIT,	/* disk is writable */
+	FD_DCL_SEEN_BIT		/* have we seen DCL? */
 };
 
 #define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params)
@@ -196,6 +197,7 @@
 #define FD_DISK_NEWCHANGE (1 << FD_DISK_NEWCHANGE_BIT)
 #define FD_DISK_CHANGED (1 << FD_DISK_CHANGED_BIT)
 #define FD_DISK_WRITABLE (1 << FD_DISK_WRITABLE_BIT)
+#define FD_DCL_SEEN (1 << FD_DCL_SEEN)
 
 	unsigned long spinup_date;
 	unsigned long select_date;
diff -ur 2.4.13/linux/include/linux/fs.h linux/include/linux/fs.h
--- 2.4.13/linux/include/linux/fs.h	Sat Oct 27 11:53:28 2001
+++ linux/include/linux/fs.h	Sat Oct 27 13:05:03 2001
@@ -793,6 +793,7 @@
 	int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
 	int (*check_media_change) (kdev_t);
 	int (*revalidate) (kdev_t);
+	int (*can_trust_media_change) (kdev_t);
 };
 
 /*

^ permalink raw reply	[flat|nested] 67+ messages in thread
* Re: Poor floppy performance in kernel 2.4.10
@ 2001-10-21 11:36 Alain Knaff
  2001-10-22  9:59 ` Andrea Arcangeli
                   ` (2 more replies)
  0 siblings, 3 replies; 67+ messages in thread
From: Alain Knaff @ 2001-10-21 11:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: torvalds, kamil, adilger, vherva, nleroy, davidsen, viro, andrea,
	landley, manfred

Sorry for joining this discussion so late, but I only check
linux-kernel only about once or twice a week.

Rather than responding to each message individually, here's a small
summary about my take on the issues:

Andreas Dilger writes:
>In the case of a floppy drive, this is very important, as you don't
>want to be cacheing data from one floppy after you have inserted a new
>floppy.

Actually, the floppy drive is able to detect disk changes just fine,
and since 1.0's the disk change signal (DCL) has been used to trigger
cache flushing.

Ville Herva wrote:
>That's propably beacause it syncs the writes on close(). 

This is done for the benefit of those OS'es that don't automatically
sync() removeable media on last close. On Linux this is not necessary
(or at least, it wasn't when I last looked at the code, but that's a
long while ago...), but it is not harmful either: even though the sync
would hold up mtools for a while, the close would go through much
faster, as the work already will have done. And besides, as far as I
understood, Kamil was speaking about read performance, where the sync
would be a non-issue.

Nick LeRoy wrote:
>Perhaps there should be a pair of "mtools" added: mopen and mclose, that do 
>basically this. That way it could be a "standard" item, documented in man 
>pages, etc., not some secret that only the l-k users know. Thoughts? 

A nice workaround. However, personnally I'd rather have this fixed in
the kernel, rather than having to resort to those kinds of
workarounds. Moreover, this is potentially dangerous: it could
actually mask a real disk change, if the user forgets the mclose.  The
same holds for other techniques, such as sleep 3600 </dev/fd0 & Btw,
it works now (actual disk change detected, even while the sleep runs),
but who will guarantee it still will work in 2.6 ?

Nevertheless, I'm thinking about introducing this to mtools as a
stop-gap measure, but with ample warnings in the manpage...

Bill Davidsen wrote:
>That said, I have a few other thoughts. First, can't the kernel 
>detect when a new floppy is inserted?

Yes, the kernel (floppy driver) can do this, and indeed it does.

>I can't remember if there is an 
>interupt generated when the floppy seats or not. 

Actually, it is not really an interrupt, but a bit that is set in the
FD_DIR register. It stays set until the floppy disk driver
acknowledges it by seeking the drive, or by selecting/unselecting it.

Before reading from the disk (or whenever it needs to know whether a
disk has been changed or not), the floppy driver reads this bit, and
if set notifies the VFS of the disk change. It then proceeds to seek,
in order to clear this flag (needed in order to detect further
changes)


>I 
>seem to remember that not all drives provide the signal, at least back 
>when I wrote my last floppy driver (DEC Rainbow, about 20 years
ago). 

Yes, very old drives have problems supplying the signal. However, most
_recent_ cases of broken disk change line are due to ... badly
inserted cabled (d'oh). The problem is that the DCL is near the edge
(pin 34, according to http://www.moria.de/~michael/floppy/floppy.ps),
and if the cable is not inserted straight, the other wires may still
make contact, but not the DCL. Hence the drive "appears" to work at
first glance, except for the problem with the cached stale
data. Actually, in the last couple of years, I got less than a dozen
bug reports about a broken disk change line, and those could all be
traced to a badly inserted cable...

A compounding problem is that there are different ways to clear the
DCL signal. Many drives need a seek, but for some drives you can clear
the signal just by selecting/unselecting the drive, which makes it far
too easy to accidentally clear it. This was causing many problems in
the 1.0 days, but has been solved since long ago (by being extra
careful to check the DCL before unselecting a drive. This is also the
major reason for the convolutedness of that part of the code).

Alexander Viro wrote:
>We had been flushing the cache upon final close() for quite a while; recent 
>changes come from something else and figuring out WTF had happened in 2.4.12 
>would be a Good Thing(tm). 

Andrea Arcangeli wrote:
>Indeed, only 2.2 trusted the check media change information and left the 
>cache valid on top of the floppy across close/open of the blkdev. 

You are right: indeed, 2.4.4 seems to have the same problem. If you do
mcopy a:somefile . in a row, the second one is as slow as the first
one!

Only mdir a: seems to behave differently between 2.4.4 (on my laptop)
and 2.4.12 (on my desktop): in 2.4.4 the second one is instantaneous,
whereas in 2.4.12 it is slow.  Possible explanation: mdir reads so few
data that it fits in one track. And the floppy driver has an own
internal "track cache", which caches one track worth of data (needed
for some low-level optimizations, just like the on-board cache of hard
disks). Obviously, the floppy driver itself does not ignore the fact
that the disk has not been changed when deciding whether to flush its
own cache or not. Apparently, it's this particular feature which has
been broken in 2.4.10. I'll have to investigate further to find out
why exactly there is this difference. (I'll probably get around it
next weekend unfortunately, I'm somewhat busy right now).

>if mtools is doing something 
>stupid that sorted out to work ok when partial reads were supported. 

The problem can be easily demonstrated with doing 'cat /dev/fd0 >x'
twice in a row to simulate an mcopy. On both kernels that I tried, the
second one is as slow the first. So I don't think it's related to
mtools per se.

In order to simulate an mdir:
dd if=/dev/fd0 bs=1k count=18 of=/dev/null

Here, the second one is instantaneous on 2.4.4, but slow on
2.4.12. Changing the 18 into 19 makes it slow on both kernels (because
that's now two tracks, rather than one).

However, for the following one, it's fast the second time on both
kernels:
dd if=/dev/fd0 bs=1k count=2 of=/dev/null

Changing 2 into 3 makes it slow on 2.4.12

Maybe, it's some kind of read-ahead issue, that the kernel decides to
internally read much more sectors than fit in one track, which would
"push" the sectors of the first cylinder out of the floppy driver's
internal cache?

Andrea Arcangeli wrote:
>Yes, I was aware of that. We'd need a kind of "media change enabler" 
>bitflag in each lowlevel driver, to implement a blacklist (or whitelist 
>if you feel safer) that will tell us if to trust the media change info 
>or not.

Exactly!

Linus Torvalds wrote:
>And with 
>the floppy case, there was no way to notice at run-time whether the unit 
>was broken or not - the floppy drives have no ID's to blacklist etc.

True. However, we could use an ioctl to instruct the floppy driver,
(which would then instruct the VFS layer) whether it can trust the
disk change line or not.
That way, users with known broken drives can pluck that into their
/etc/rc.d/boot.local
Actually, we do have such a setting right now, it's called BROKEN_DCL
Just to floppycontrol --broken_dcl /dev/fd0 to set it.
Its effect can be easily verified: after doing this, mdir a: is slow
on both kernels...
You can also set it on the boot (LILO) command line: append="floppy=broken_dcl"
The only thing is, right now this is handled locally in the floppy
driver, and not communicated to the VFS. What we would need is a way
to tell the VFS "yes, you _can_ trust check_media_change". Or is there
already such a way?

Rob Landley wrote:
>Also, enough drives do it right (the vast majority), that a 
>"broken_disk_change" module/boot option seems more sensible as a non-default 
>thing for those that really are hosed... 

Surprise! There is such a setting (see above): broken_dcl and it works
as well for module (insmod floppy.o floppy=broken_dcl), as for boot
(see above), as for iotctl.
Only problem: although the floppy driver takes it into account, the
VFS layer seems to happily ignore it...

This happens in the following function, which is called
unconditionnally, whenever the numbers of "openers" (processes having
an open filehandle to the device) drops to zero:

(blkdev_put)
	if (kind == BDEV_FILE)
		__block_fsync(bd_inode);
	else if (kind == BDEV_FS)
		fsync_no_super(rdev);
	if (!--bdev->bd_openers)
		kill_bdev(bdev);


/* Kill _all_ buffers, dirty or not.. */
static void kill_bdev(struct block_device *bdev)
{
	invalidate_bdev(bdev, 1);
	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
}	

And in the comment for invalidate_bdev, we find the following comment:

   NOTE: In the case where the user removed a removable-media-disk even if
   there's still dirty data not synced on disk (due a bug in the device driver
   or due an error of the user), by not destroying the dirty buffers we could
   generate corruption also on the next media inserted, thus a parameter is
   necessary to handle this case in the most safe way possible (trying
   to not corrupt also the new disk inserted with the data belonging to
   the old now corrupted disk). Also for the ramdisk the natural thing
   to do in order to release the ramdisk memory is to destroy dirty buffers.

So, if the goal is only to catch user and/or driver error, maybe the
same thing could be achieved by _only_ flushing the dirty buffers (and
loudly complaining if it finds any: indeed, because of the call to
__block_fsync(bd_inode); there really shouldn't be any dirty buffers
at this point of time...


Manfred Spraul wrote:
>The standard trick is to start with media-change not supported, and 
>enable it if you get the first change signal. 
>There are really old floppies that don't support media-change signals, 
>and they _never_ send it. If you see a media-change signal, then you 
>know that the floppy is not broken.

Good idea! I'll think about implementing something like that.

Regards,

Alain

^ permalink raw reply	[flat|nested] 67+ messages in thread
* Re: Poor floppy performance in kernel 2.4.10
@ 2001-10-19 16:58 Manfred Spraul
  0 siblings, 0 replies; 67+ messages in thread
From: Manfred Spraul @ 2001-10-19 16:58 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

 
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

> And with
> the floppy case, there was no way to notice at run-time whether the
> unit was broken or not - the floppy drives have no ID's to blacklist
> etc. 

The standard trick is to start with media-change not supported, and
enable it if you get the first change signal.
There are really old floppies that don't support media-change signals,
and they _never_ send it. If you see a media-change signal, then you
know that the floppy is not broken.

Probably a timer (2 seconds) and a delayed cache flush should fix the
problem.

If the device supports media-change and media-lock, then it could
increase the timeout value.

--
	Manfred

^ permalink raw reply	[flat|nested] 67+ messages in thread
* Poor floppy performance in kernel 2.4.10
@ 2001-10-17  7:36 Kamil Iskra
  2001-10-17 20:45 ` Steve Kieu
  0 siblings, 1 reply; 67+ messages in thread
From: Kamil Iskra @ 2001-10-17  7:36 UTC (permalink / raw)
  To: linux-kernel


Hi,

Since kernel 2.4.10, I observe a rather poor performance of the good old
floppy drive.  It used to work find in kernel 2.4.9.  Kernel 2.4.10 broke
it, and 2.4.12 did not fix it.  I access my floppy using mtools-3.9.7-4 as
found in RH 7.1.

Not knowing anything about the kernel internals, I would say that the
floppy driver does not do any caching anymore.  With kernel 2.4.9, "mdir"
of a standard 1.44 MB, completely empty floppy disk takes about 1 second
for the first invocation, and next to nothing for the subsequent ones.
>From 2.4.10 on, it takes over 2 seconds every time.  Writing a 30 KB file
with 2.4.9 takes below 3 seconds, with >=2.4.10 it's over 6 seconds.

Maybe I should just keep quiet and be happy that it works at all, after
all floppies are rarely used nowadays, but letting such a performance
degradation go unreported is just beyond me :-).

Regards,

-- 
Kamil Iskra                 http://www.science.uva.nl/~kamil/
Section Computational Science, Faculty of Science, Universiteit van Amsterdam
kamil@science.uva.nl  tel. +31 20 525 75 35  fax. +31 20 525 74 90
Kruislaan 403  room F.202  1098 SJ Amsterdam  The Netherlands


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

end of thread, other threads:[~2001-12-09  5:38 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-10-27 15:00 Poor floppy performance in kernel 2.4.10 Alain Knaff
2001-10-27 15:15 ` Alexander Viro
2001-10-27 17:12   ` Alain Knaff
2001-10-27 17:42     ` Alexander Viro
2001-10-27 18:00       ` Alain Knaff
2001-10-27 18:13         ` Alexander Viro
2001-10-27 18:26         ` Alexander Viro
2001-10-27 19:02           ` more devfs fun Alexander Viro
2001-10-27 19:16             ` Alexander Viro
2001-10-27 19:50               ` more devfs fun (Piled Higher and Deeper) Alexander Viro
2001-10-27 20:06                 ` Alexander Viro
2001-10-27 21:09                   ` Ryan Cumming
2001-10-27 21:22                     ` Alexander Viro
2001-10-28  1:00                     ` Rik van Riel
2001-10-28  8:45                     ` Richard Gooch
2001-10-28  9:54                       ` Alexander Viro
2001-10-28 12:27                       ` Roman Zippel
2001-10-28 13:16                         ` Alexander Viro
2001-10-28 22:31                       ` Richard Gooch
2001-10-28 23:11                         ` Alexander Viro
2001-10-27 21:01                 ` Alexander Viro
2001-11-06  6:35                 ` Richard Gooch
2001-11-06  7:10                   ` Alexander Viro
2001-11-06  7:14                   ` Richard Gooch
2001-11-06  7:17                     ` Alexander Viro
2001-11-06 20:14                     ` Richard Gooch
2001-10-28 10:06               ` Lorenzo Allegrucci
2001-11-06  5:21               ` Richard Gooch
2001-11-06  5:17             ` more devfs fun Richard Gooch
2001-11-06  5:06           ` Richard Gooch
2001-11-06  7:01         ` Poor floppy performance in kernel 2.4.10 Richard Gooch
2001-11-06  7:03           ` Alexander Viro
2001-12-09  5:38           ` Devfs races with block devices Richard Gooch
2001-11-06  7:19         ` Poor floppy performance in kernel 2.4.10 Richard Gooch
2001-11-06  7:22           ` Alexander Viro
2001-10-27 19:13       ` Alain Knaff
2001-10-27 19:19         ` Alexander Viro
2001-10-27 19:26           ` Alain Knaff
2001-10-28 20:40           ` Alain Knaff
2001-10-28 20:57             ` Peter T. Breuer
2001-10-29  5:38               ` Alain Knaff
2001-10-29  6:07                 ` Alexander Viro
2001-10-29  6:34                   ` Alain Knaff
2001-10-28 21:42             ` Alexander Viro
  -- strict thread matches above, loose matches on Subject: below --
2001-10-21 11:36 Alain Knaff
2001-10-22  9:59 ` Andrea Arcangeli
2001-10-22 10:06   ` Alexander Viro
2001-10-22 14:07 ` Nick LeRoy
2001-10-22 18:28 ` bill davidsen
2001-10-19 16:58 Manfred Spraul
2001-10-17  7:36 Kamil Iskra
2001-10-17 20:45 ` Steve Kieu
2001-10-18 10:11   ` Kamil Iskra
2001-10-18 15:28     ` Andreas Dilger
2001-10-18 15:42       ` Kamil Iskra
2001-10-18 16:17         ` Ville Herva
2001-10-18 16:30           ` Nick LeRoy
2001-10-18 19:57             ` bill davidsen
2001-10-18 20:47               ` Nick LeRoy
2001-10-18 20:05             ` bill davidsen
2001-10-18 20:15               ` Alexander Viro
2001-10-18 16:18       ` Alexander Viro
2001-10-18 17:44         ` Andrea Arcangeli
2001-10-19  7:50           ` Giuliano Pochini
2001-10-19 13:46             ` Andrea Arcangeli
2001-10-19 15:57             ` Linus Torvalds
2001-10-20  4:20               ` Rob Landley

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