forked from pool/parted
Copy from home:puzel:branches:Base:System/parted via accept of submit request 30480 revision 2. Request was accepted with message: OBS-URL: https://build.opensuse.org/request/show/30480 OBS-URL: https://build.opensuse.org/package/show/Base:System/parted?expand=0&rev=14
97 lines
3.5 KiB
Diff
97 lines
3.5 KiB
Diff
From 2a6936fab4d4499a4b812dd330d3db50549029e0 Mon Sep 17 00:00:00 2001
|
|
From: Hans de Goede <hdegoede@redhat.com>
|
|
Date: Fri, 28 Aug 2009 17:05:55 +0200
|
|
Subject: [PATCH] linux-commit: do not unnecessarily open partition device nodes
|
|
|
|
After patching parted with my do-not-use-BLKPG patch, I started
|
|
to get EBUSY errors on commit_to_os. Note this is not caused
|
|
by the do-not-use-BLKPG patch, this was already happening, but
|
|
parted was silently ignoring the errors (and the kernel was
|
|
not notified of the changes, which is bad). The error now
|
|
actually gets reported.
|
|
|
|
The problem turns out to be in libparted/arch/linux.c's
|
|
_flush_cache function, which walks all the partitions of the
|
|
disk and does BLKFLSBUF calls on them. This causes the following:
|
|
|
|
commit_to_os -> device_open -> fd = open /dev/sda ->
|
|
_flush_cache -> for each /dev/sda# open, ioctl, close
|
|
-> ioctl(fd, BLKRRPART) -> EBUSY
|
|
|
|
What is happening here is that the:
|
|
for each /dev/sda# open, ioctl, close
|
|
|
|
Is causing udev change events for all the /dev/sda#
|
|
nodes, which causes udev to call blkid on all these nodes
|
|
(on systems which use DeviceKit), so blkid has /dev/sda# nodes
|
|
open while BLKRRPART gets called on /dev/sda -> EBUSY.
|
|
|
|
I've checked with two independend storage subsystem kernel
|
|
developers, and /dev/sda and /dev/sda#, guarantee cache coherency
|
|
now-a-days. So there is no need to do this for 2.6, which also
|
|
eliminates the need to call _flush_cache() on device open at all.
|
|
|
|
* libparted/arch/linux.c (_have_kern26): New function.
|
|
(_flush_cache): For linux kernels 2.6 and newer, don't flush
|
|
partition devices.
|
|
(linux_open): Skip _flush_cache on newer kernels here, too.
|
|
---
|
|
libparted/arch/linux.c | 25 ++++++++++++++++++++++---
|
|
1 files changed, 22 insertions(+), 3 deletions(-)
|
|
|
|
Index: parted-1.9.0/libparted/arch/linux.c
|
|
===================================================================
|
|
--- parted-1.9.0.orig/libparted/arch/linux.c 2009-12-03 17:04:44.000000000 +0100
|
|
+++ parted-1.9.0/libparted/arch/linux.c 2009-12-03 17:05:06.000000000 +0100
|
|
@@ -601,6 +601,19 @@ _have_devfs ()
|
|
return have_devfs = S_ISCHR(sb.st_mode) ? 1 : 0;
|
|
}
|
|
|
|
+static int
|
|
+_have_kern26 ()
|
|
+{
|
|
+ static int have_kern26 = -1;
|
|
+ int kver;
|
|
+
|
|
+ if (have_kern26 != -1)
|
|
+ return have_kern26;
|
|
+
|
|
+ kver = _get_linux_version();
|
|
+ return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
|
|
+}
|
|
+
|
|
static void
|
|
_device_set_sector_size (PedDevice* dev)
|
|
{
|
|
@@ -1374,8 +1387,8 @@ linux_is_busy (PedDevice* dev)
|
|
return 0;
|
|
}
|
|
|
|
-/* we need to flush the master device, and all the partition devices,
|
|
- * because there is no coherency between the caches.
|
|
+/* we need to flush the master device, and with kernel < 2.6 all the partition
|
|
+ * devices, because there is no coherency between the caches with old kernels.
|
|
* We should only flush unmounted partition devices, because:
|
|
* - there is never a need to flush them (we're not doing IO there)
|
|
* - flushing a device that is mounted causes unnecessary IO, and can
|
|
@@ -1393,6 +1406,10 @@ _flush_cache (PedDevice* dev)
|
|
|
|
ioctl (arch_specific->fd, BLKFLSBUF);
|
|
|
|
+ /* With linux-2.6.0 and newer, we're done. */
|
|
+ if (_have_kern26())
|
|
+ return;
|
|
+
|
|
for (i = 1; i < 16; i++) {
|
|
char* name;
|
|
int fd;
|
|
@@ -1449,6 +1466,8 @@ retry:
|
|
dev->read_only = 0;
|
|
}
|
|
|
|
+ /* With kernels < 2.6 flush cache for cache coherence issues */
|
|
+ if (!_have_kern26())
|
|
_flush_cache (dev);
|
|
|
|
return 1;
|