Blame SOURCES/lvm2-2_03_06-increase-soft-open-file-limit.patch

26e710
 lib/label/label.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
26e710
 1 file changed, 61 insertions(+)
26e710
26e710
diff --git a/lib/label/label.c b/lib/label/label.c
26e710
index 72be5ec..09bbb92 100644
26e710
--- a/lib/label/label.c
26e710
+++ b/lib/label/label.c
26e710
@@ -29,6 +29,7 @@
26e710
 #include <fcntl.h>
26e710
 #include <unistd.h>
26e710
 #include <sys/types.h>
26e710
+#include <sys/resource.h>
26e710
 
26e710
 /* FIXME Allow for larger labels?  Restricted to single sector currently */
26e710
 
26e710
@@ -867,6 +868,57 @@ static void _free_hints(struct dm_list *hints)
26e710
 }
26e710
 
26e710
 /*
26e710
+ * We don't know how many of num_devs will be PVs that we need to
26e710
+ * keep open, but if it's greater than the soft limit, then we'll
26e710
+ * need the soft limit raised, so do that before starting.
26e710
+ *
26e710
+ * If opens approach the raised soft/hard limit while scanning, then
26e710
+ * we could also attempt to raise the soft/hard limits during the scan.
26e710
+ */
26e710
+
26e710
+#define BASE_FD_COUNT 32 /* Number of open files we want apart from devs */
26e710
+
26e710
+static void _prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_devs)
26e710
+{
26e710
+	struct rlimit old, new;
26e710
+	unsigned int want = num_devs + BASE_FD_COUNT;
26e710
+	int rv;
26e710
+
26e710
+	rv = prlimit(0, RLIMIT_NOFILE, NULL, &old;;
26e710
+	if (rv < 0) {
26e710
+		log_debug("Checking fd limit for num_devs %u failed %d", num_devs, errno);
26e710
+		return;
26e710
+	}
26e710
+
26e710
+	log_debug("Checking fd limit for num_devs %u want %u soft %lld hard %lld",
26e710
+		  num_devs, want, (long long)old.rlim_cur, (long long)old.rlim_max);
26e710
+
26e710
+	/* Current soft limit is enough */
26e710
+	if (old.rlim_cur > want)
26e710
+		return;
26e710
+
26e710
+	/* Soft limit already raised to max */
26e710
+	if (old.rlim_cur == old.rlim_max)
26e710
+		return;
26e710
+
26e710
+	/* Raise soft limit up to hard/max limit */
26e710
+	new.rlim_cur = old.rlim_max;
26e710
+	new.rlim_max = old.rlim_max;
26e710
+
26e710
+	log_debug("Setting fd limit for num_devs %u soft %lld hard %lld",
26e710
+		  num_devs, (long long)new.rlim_cur, (long long)new.rlim_max);
26e710
+
26e710
+	rv = prlimit(0, RLIMIT_NOFILE, &new, &old;;
26e710
+	if (rv < 0) {
26e710
+		if (errno == EPERM)
26e710
+			log_warn("WARNING: permission error setting open file limit for scanning %u devices.", num_devs);
26e710
+		else
26e710
+			log_warn("WARNING: cannot set open file limit for scanning %u devices.", num_devs);
26e710
+		return;
26e710
+	}
26e710
+}
26e710
+
26e710
+/*
26e710
  * Scan devices on the system to discover which are LVM devices.
26e710
  * Info about the LVM devices (PVs) is saved in lvmcache in a
26e710
  * basic/summary form (info/vginfo structs).  The vg_read phase
26e710
@@ -984,6 +1036,15 @@ int label_scan(struct cmd_context *cmd)
26e710
 	log_debug("Will scan %d devices skip %d", dm_list_size(&scan_devs), dm_list_size(&all_devs));
26e710
 
26e710
 	/*
26e710
+	 * If the total number of devices exceeds the soft open file
26e710
+	 * limit, then increase the soft limit to the hard/max limit
26e710
+	 * in case the number of PVs in scan_devs (it's only the PVs
26e710
+	 * which we want to keep open) is higher than the current
26e710
+	 * soft limit.
26e710
+	 */
26e710
+	_prepare_open_file_limit(cmd, dm_list_size(&scan_devs));
26e710
+
26e710
+	/*
26e710
 	 * Do the main scan.
26e710
 	 */
26e710
 	_scan_list(cmd, cmd->filter, &scan_devs, NULL);