File s390-tools-sles11sp2-zipl-flush-cache.patch of Package s390-tools
Subject: [PATCH] [BZ 85124] zipl: Flush disk buffers before installing IPL record
From: Stefan Haberland <stefan.haberland@de.ibm.com>
Description: zipl: Flush disk buffers before installing IPL record
Symptom: Running zipl on an FBA DASD may cause a previously initialized
physical volume on the partition to be no longer recognized by
LVM.
Problem: The Linux kernel maintains caches for block devices in
granularity of pages (4096 bytes). A disk and its partitions are
represented by separate block devices. As a result, the same area
on disk may be represented by entries in both the disk and
partition cache.
The following sequence of block device access requests can
lead to inconsistent cache contents for the first 4096 bytes on
an FBA DASD:
A) read block 0 from DISK (done for example by the kernel
during partition detection)
B) write block 0 to PARTITION (done for example by pvcreate
when initializing the partition as physical volume)
When zipl is run, it writes the IPL record to block 0 on DISK.
Since the IPL record is less than 4096 bytes but a write to the
disk device is ultimately done in multiples of the page size, the
remaining data is taken from the disk block device cache which
contains the contents resulting from A). As a result, the effects
of B) are effectively undone on disk.
Solution: Flush the cache for the disk and partition block devices before
installing the IPL record.
Reproduction: A) read block 0 from DISK (done for example by the kernel during
partition detection)
B) write block 0 to PARTITION (done for example by pvcreate when
initializing the partition as physical volume)
C) run zipl
Problem-ID: 85124
---
zipl/src/install.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/zipl/src/install.c
+++ b/zipl/src/install.c
@@ -30,6 +30,9 @@
#include "error.h"
#include "misc.h"
+/* From linux/fs.h */
+#define BLKFLSBUF _IO(0x12, 97)
+
/* Types of SCSI disk layouts */
enum scsi_layout {
@@ -311,6 +314,14 @@ install_bootloader(const char* device, d
device);
return -1;
}
+ /* Ensure that potential cache inconsistencies between disk and
+ * partition are resolved by flushing the corresponding buffers. */
+ if (!dry_run) {
+ if (ioctl(fd, BLKFLSBUF)) {
+ fprintf(stderr, "Warning: Could not flush disk "
+ "caches.\n");
+ }
+ }
/* Call disk specific install functions */
rc = -1;
switch (info->type) {