parted/do-not-unnecessarily-open-part-dev.patch
OBS User autobuild eca291a9ed Accepting request 26270 from Base:System
Copy from Base:System/parted based on submit request 26270 from user puzel

OBS-URL: https://build.opensuse.org/request/show/26270
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/parted?expand=0&rev=44
2009-12-16 08:45:27 +00:00

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;