8a28aa4
From 66ceb82b6d51707a74174dfb7a74b943ea571a43 Mon Sep 17 00:00:00 2001
8a28aa4
From: Vratislav Podzimek <vpodzime@redhat.com>
8a28aa4
Date: Thu, 20 Oct 2016 15:43:23 +0200
8a28aa4
Subject: [PATCH] Prevent issues between libparted and udev
8a28aa4
8a28aa4
libparted does committing of a new partition table to disk in two steps:
8a28aa4
8a28aa4
1. committing (writing and flushing) to disk and
8a28aa4
2. telling OS about the partitions.
8a28aa4
8a28aa4
However, that means that if things go wrong, udev may step in between the above
8a28aa4
steps and trigger events when the block device file is closed (from being opened
8a28aa4
RW) that could lead to a failure of the second step because some other process
8a28aa4
may open the block device file in the reaction to the event.
8a28aa4
8a28aa4
In order to prevent such issues we need to acquire an exclusive lock on the
8a28aa4
block device file, which prevents udev from triggering events, for the time we
8a28aa4
let libparted perform the two operations above.
8a28aa4
8a28aa4
(cherry picked from commit 0a65466154994759cbec15ce984b751b073a891f)
8a28aa4
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
8a28aa4
---
8a28aa4
 src/plugins/part.c | 15 +++++++++++++++
8a28aa4
 1 file changed, 15 insertions(+)
8a28aa4
8a28aa4
diff --git a/src/plugins/part.c b/src/plugins/part.c
8a28aa4
index 4634ef8..d5239e3 100644
8a28aa4
--- a/src/plugins/part.c
8a28aa4
+++ b/src/plugins/part.c
8a28aa4
@@ -23,6 +23,8 @@
8a28aa4
 #include <stdlib.h>
8a28aa4
 #include <math.h>
8a28aa4
 #include <inttypes.h>
8a28aa4
+#include <unistd.h>
8a28aa4
+#include <sys/file.h>
8a28aa4
 #include <utils.h>
8a28aa4
 
8a28aa4
 #include "part.h"
8a28aa4
@@ -150,11 +152,22 @@ static const gchar *table_type_str[BD_PART_TABLE_UNDEF] = {"msdos", "gpt"};
8a28aa4
 
8a28aa4
 static gboolean disk_commit (PedDisk *disk, gchar *path, GError **error) {
8a28aa4
     gint ret = 0;
8a28aa4
+    gint dev_fd = 0;
8a28aa4
+
8a28aa4
+    /* XXX: try to grab an exclusive lock for the device so that udev doesn't
8a28aa4
+       trigger events for it in between the two operations we need to perform
8a28aa4
+       (see below) */
8a28aa4
+    dev_fd = open (disk->dev->path, O_RDONLY|O_CLOEXEC);
8a28aa4
+    if (dev_fd >= 0)
8a28aa4
+        /* if this fails, we can do no better anyway, so just ignore the return
8a28aa4
+           value */
8a28aa4
+        flock (dev_fd, LOCK_EX);
8a28aa4
 
8a28aa4
     ret = ped_disk_commit_to_dev (disk);
8a28aa4
     if (ret == 0) {
8a28aa4
         set_parted_error (error, BD_PART_ERROR_FAIL);
8a28aa4
         g_prefix_error (error, "Failed to commit changes to device '%s'", path);
8a28aa4
+        close (dev_fd);
8a28aa4
         return FALSE;
8a28aa4
     }
8a28aa4
 
8a28aa4
@@ -162,9 +175,11 @@ static gboolean disk_commit (PedDisk *disk, gchar *path, GError **error) {
8a28aa4
     if (ret == 0) {
8a28aa4
         set_parted_error (error, BD_PART_ERROR_FAIL);
8a28aa4
         g_prefix_error (error, "Failed to inform OS about changes on the '%s' device", path);
8a28aa4
+        close (dev_fd);
8a28aa4
         return FALSE;
8a28aa4
     }
8a28aa4
 
8a28aa4
+    close (dev_fd);
8a28aa4
     return TRUE;
8a28aa4
 }
8a28aa4
 
8a28aa4
-- 
8a28aa4
2.7.4
8a28aa4