75b07eca3e
by importing the upstream release as patches. replace user namespace patch with version which has been applied usptream.
452 lines
15 KiB
Diff
452 lines
15 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: chrisrd <chris@onthe.net.au>
|
|
Date: Sat, 24 Feb 2018 03:50:06 +1100
|
|
Subject: [PATCH] Fix free memory calculation on v3.14+
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Provide infrastructure to auto-configure to enum and API changes in the
|
|
global page stats used for our free memory calculations.
|
|
|
|
arc_free_memory has been broken since an API change in Linux v3.14:
|
|
|
|
2016-07-28 v4.8 599d0c95 mm, vmscan: move LRU lists to node
|
|
2016-07-28 v4.8 75ef7184 mm, vmstat: add infrastructure for per-node
|
|
vmstats
|
|
|
|
These commits moved some of global_page_state() into
|
|
global_node_page_state(). The API change was particularly egregious as,
|
|
instead of breaking the old code, it silently did the wrong thing and we
|
|
continued using global_page_state() where we should have been using
|
|
global_node_page_state(), thus indexing into the wrong array via
|
|
NR_SLAB_RECLAIMABLE et al.
|
|
|
|
There have been further API changes along the way:
|
|
|
|
2017-07-06 v4.13 385386cf mm: vmstat: move slab statistics from zone to
|
|
node counters
|
|
2017-09-06 v4.14 c41f012a mm: rename global_page_state to
|
|
global_zone_page_state
|
|
|
|
...and various (incomplete, as it turns out) attempts to accomodate
|
|
these changes in ZoL:
|
|
|
|
2017-08-24 2209e409 Linux 4.8+ compatibility fix for vm stats
|
|
2017-09-16 787acae0 Linux 3.14 compat: IO acct, global_page_state, etc
|
|
2017-09-19 661907e6 Linux 4.14 compat: IO acct, global_page_state, etc
|
|
|
|
The config infrastructure provided here resolves these issues going back
|
|
to the original API change in v3.14 and is robust against further Linux
|
|
changes in this area.
|
|
|
|
Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov>
|
|
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
|
|
Reviewed-by: George Melikov <mail@gmelikov.ru>
|
|
Signed-off-by: Chris Dunlop <chris@onthe.net.au>
|
|
Closes #7170
|
|
(cherry picked from commit 338523dd6ec641cc4d552c3f67e1becfb9e22b0a)
|
|
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
|
---
|
|
include/linux/Makefile.am | 3 +-
|
|
scripts/Makefile.am | 2 +
|
|
include/linux/page_compat.h | 78 ++++++++++++++++++++++++++
|
|
module/zfs/arc.c | 23 ++------
|
|
config/kernel-global_page_state.m4 | 109 +++++++++++++++++++++++++++++++++++++
|
|
config/kernel-vm_node_stat.m4 | 22 --------
|
|
config/kernel.m4 | 2 +-
|
|
scripts/enum-extract.pl | 58 ++++++++++++++++++++
|
|
8 files changed, 256 insertions(+), 41 deletions(-)
|
|
create mode 100644 include/linux/page_compat.h
|
|
create mode 100644 config/kernel-global_page_state.m4
|
|
delete mode 100644 config/kernel-vm_node_stat.m4
|
|
create mode 100755 scripts/enum-extract.pl
|
|
|
|
diff --git a/include/linux/Makefile.am b/include/linux/Makefile.am
|
|
index 9bb0b3493..89c2689f6 100644
|
|
--- a/include/linux/Makefile.am
|
|
+++ b/include/linux/Makefile.am
|
|
@@ -9,7 +9,8 @@ KERNEL_H = \
|
|
$(top_srcdir)/include/linux/kmap_compat.h \
|
|
$(top_srcdir)/include/linux/simd_x86.h \
|
|
$(top_srcdir)/include/linux/simd_aarch64.h \
|
|
- $(top_srcdir)/include/linux/mod_compat.h
|
|
+ $(top_srcdir)/include/linux/mod_compat.h \
|
|
+ $(top_srcdir)/include/linux/page_compat.h
|
|
|
|
USER_H =
|
|
|
|
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
|
|
index 74b8b31a5..5a8abd135 100644
|
|
--- a/scripts/Makefile.am
|
|
+++ b/scripts/Makefile.am
|
|
@@ -5,6 +5,7 @@ EXTRA_DIST = dkms.mkconf dkms.postbuild kmodtool zfs2zol-patch.sed cstyle.pl
|
|
pkgdatadir = $(datadir)/@PACKAGE@
|
|
dist_pkgdata_SCRIPTS = \
|
|
$(top_builddir)/scripts/common.sh \
|
|
+ $(top_srcdir)/scripts/enum-extract.pl \
|
|
$(top_srcdir)/scripts/zimport.sh \
|
|
$(top_srcdir)/scripts/zfs.sh \
|
|
$(top_srcdir)/scripts/zfs-tests.sh \
|
|
@@ -15,3 +16,4 @@ dist_pkgdata_SCRIPTS = \
|
|
$(top_srcdir)/scripts/zpios-survey.sh \
|
|
$(top_srcdir)/scripts/smb.sh \
|
|
$(top_srcdir)/scripts/zfs-helpers.sh
|
|
+
|
|
diff --git a/include/linux/page_compat.h b/include/linux/page_compat.h
|
|
new file mode 100644
|
|
index 000000000..95acb7d53
|
|
--- /dev/null
|
|
+++ b/include/linux/page_compat.h
|
|
@@ -0,0 +1,78 @@
|
|
+#ifndef _ZFS_PAGE_COMPAT_H
|
|
+#define _ZFS_PAGE_COMPAT_H
|
|
+
|
|
+/*
|
|
+ * We have various enum members moving between two separate enum types,
|
|
+ * and accessed by different functions at various times. Centralise the
|
|
+ * insanity.
|
|
+ *
|
|
+ * < v4.8: all enums in zone_stat_item, via global_page_state()
|
|
+ * v4.8: some enums moved to node_stat_item, global_node_page_state() introduced
|
|
+ * v4.13: some enums moved from zone_stat_item to node_state_item
|
|
+ * v4.14: global_page_state() rename to global_zone_page_state()
|
|
+ *
|
|
+ * The defines used here are created by config/kernel-global_page_state.m4
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Create our own accessor functions to follow the Linux API changes
|
|
+ */
|
|
+#if defined(ZFS_GLOBAL_ZONE_PAGE_STATE)
|
|
+
|
|
+/* global_zone_page_state() introduced */
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_FILE_PAGES)
|
|
+#define nr_file_pages() global_node_page_state(NR_FILE_PAGES)
|
|
+#else
|
|
+#define nr_file_pages() global_zone_page_state(NR_FILE_PAGES)
|
|
+#endif
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_ANON)
|
|
+#define nr_inactive_anon_pages() global_node_page_state(NR_INACTIVE_ANON)
|
|
+#else
|
|
+#define nr_inactive_anon_pages() global_zone_page_state(NR_INACTIVE_ANON)
|
|
+#endif
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_FILE)
|
|
+#define nr_inactive_file_pages() global_node_page_state(NR_INACTIVE_FILE)
|
|
+#else
|
|
+#define nr_inactive_file_pages() global_zone_page_state(NR_INACTIVE_FILE)
|
|
+#endif
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE)
|
|
+#define nr_slab_reclaimable_pages() global_node_page_state(NR_SLAB_RECLAIMABLE)
|
|
+#else
|
|
+#define nr_slab_reclaimable_pages() global_zone_page_state(NR_SLAB_RECLAIMABLE)
|
|
+#endif
|
|
+
|
|
+#elif defined(ZFS_GLOBAL_NODE_PAGE_STATE)
|
|
+
|
|
+/* global_node_page_state() introduced */
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_FILE_PAGES)
|
|
+#define nr_file_pages() global_node_page_state(NR_FILE_PAGES)
|
|
+#else
|
|
+#define nr_file_pages() global_page_state(NR_FILE_PAGES)
|
|
+#endif
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_ANON)
|
|
+#define nr_inactive_anon_pages() global_node_page_state(NR_INACTIVE_ANON)
|
|
+#else
|
|
+#define nr_inactive_anon_pages() global_page_state(NR_INACTIVE_ANON)
|
|
+#endif
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_INACTIVE_FILE)
|
|
+#define nr_inactive_file_pages() global_node_page_state(NR_INACTIVE_FILE)
|
|
+#else
|
|
+#define nr_inactive_file_pages() global_page_state(NR_INACTIVE_FILE)
|
|
+#endif
|
|
+#if defined(ZFS_ENUM_NODE_STAT_ITEM_NR_SLAB_RECLAIMABLE)
|
|
+#define nr_slab_reclaimable_pages() global_node_page_state(NR_SLAB_RECLAIMABLE)
|
|
+#else
|
|
+#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE)
|
|
+#endif
|
|
+
|
|
+#else
|
|
+
|
|
+/* global_page_state() only */
|
|
+#define nr_file_pages() global_page_state(NR_FILE_PAGES)
|
|
+#define nr_inactive_anon_pages() global_page_state(NR_INACTIVE_ANON)
|
|
+#define nr_inactive_file_pages() global_page_state(NR_INACTIVE_FILE)
|
|
+#define nr_slab_reclaimable_pages() global_page_state(NR_SLAB_RECLAIMABLE)
|
|
+
|
|
+#endif /* ZFS_GLOBAL_ZONE_PAGE_STATE */
|
|
+
|
|
+#endif /* _ZFS_PAGE_COMPAT_H */
|
|
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
|
|
index 9d1d0db1d..236794672 100644
|
|
--- a/module/zfs/arc.c
|
|
+++ b/module/zfs/arc.c
|
|
@@ -280,6 +280,7 @@
|
|
#include <sys/fs/swapnode.h>
|
|
#include <sys/zpl.h>
|
|
#include <linux/mm_compat.h>
|
|
+#include <linux/page_compat.h>
|
|
#endif
|
|
#include <sys/callb.h>
|
|
#include <sys/kstat.h>
|
|
@@ -4016,17 +4017,11 @@ arc_free_memory(void)
|
|
si_meminfo(&si);
|
|
return (ptob(si.freeram - si.freehigh));
|
|
#else
|
|
-#ifdef ZFS_GLOBAL_NODE_PAGE_STATE
|
|
return (ptob(nr_free_pages() +
|
|
- global_node_page_state(NR_INACTIVE_FILE) +
|
|
- global_node_page_state(NR_INACTIVE_ANON) +
|
|
- global_node_page_state(NR_SLAB_RECLAIMABLE)));
|
|
-#else
|
|
- return (ptob(nr_free_pages() +
|
|
- global_page_state(NR_INACTIVE_FILE) +
|
|
- global_page_state(NR_INACTIVE_ANON) +
|
|
- global_page_state(NR_SLAB_RECLAIMABLE)));
|
|
-#endif /* ZFS_GLOBAL_NODE_PAGE_STATE */
|
|
+ nr_inactive_file_pages() +
|
|
+ nr_inactive_anon_pages() +
|
|
+ nr_slab_reclaimable_pages()));
|
|
+
|
|
#endif /* CONFIG_HIGHMEM */
|
|
#else
|
|
return (spa_get_random(arc_all_memory() * 20 / 100));
|
|
@@ -4437,13 +4432,7 @@ arc_evictable_memory(void)
|
|
* Scale reported evictable memory in proportion to page cache, cap
|
|
* at specified min/max.
|
|
*/
|
|
-#ifdef ZFS_GLOBAL_NODE_PAGE_STATE
|
|
- uint64_t min = (ptob(global_node_page_state(NR_FILE_PAGES)) / 100) *
|
|
- zfs_arc_pc_percent;
|
|
-#else
|
|
- uint64_t min = (ptob(global_page_state(NR_FILE_PAGES)) / 100) *
|
|
- zfs_arc_pc_percent;
|
|
-#endif
|
|
+ uint64_t min = (ptob(nr_file_pages()) / 100) * zfs_arc_pc_percent;
|
|
min = MAX(arc_c_min, MIN(arc_c_max, min));
|
|
|
|
if (arc_dirty >= min)
|
|
diff --git a/config/kernel-global_page_state.m4 b/config/kernel-global_page_state.m4
|
|
new file mode 100644
|
|
index 000000000..f4a40011f
|
|
--- /dev/null
|
|
+++ b/config/kernel-global_page_state.m4
|
|
@@ -0,0 +1,109 @@
|
|
+dnl #
|
|
+dnl # 4.8 API change
|
|
+dnl #
|
|
+dnl # 75ef71840539 mm, vmstat: add infrastructure for per-node vmstats
|
|
+dnl # 599d0c954f91 mm, vmscan: move LRU lists to node
|
|
+dnl #
|
|
+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE], [
|
|
+ AC_MSG_CHECKING([whether global_node_page_state() exists])
|
|
+ ZFS_LINUX_TRY_COMPILE([
|
|
+ #include <linux/mm.h>
|
|
+ #include <linux/vmstat.h>
|
|
+ ],[
|
|
+ (void) global_node_page_state(0);
|
|
+ ],[
|
|
+ AC_MSG_RESULT(yes)
|
|
+ AC_DEFINE(ZFS_GLOBAL_NODE_PAGE_STATE, 1, [global_node_page_state() exists])
|
|
+ ],[
|
|
+ AC_MSG_RESULT(no)
|
|
+ ])
|
|
+])
|
|
+
|
|
+dnl #
|
|
+dnl # 4.14 API change
|
|
+dnl #
|
|
+dnl # c41f012ade0b mm: rename global_page_state to global_zone_page_state
|
|
+dnl #
|
|
+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE], [
|
|
+ AC_MSG_CHECKING([whether global_zone_page_state() exists])
|
|
+ ZFS_LINUX_TRY_COMPILE([
|
|
+ #include <linux/mm.h>
|
|
+ #include <linux/vmstat.h>
|
|
+ ],[
|
|
+ (void) global_zone_page_state(0);
|
|
+ ],[
|
|
+ AC_MSG_RESULT(yes)
|
|
+ AC_DEFINE(ZFS_GLOBAL_ZONE_PAGE_STATE, 1, [global_zone_page_state() exists])
|
|
+ ],[
|
|
+ AC_MSG_RESULT(no)
|
|
+ ])
|
|
+])
|
|
+
|
|
+dnl #
|
|
+dnl # Create a define and autoconf variable for an enum member
|
|
+dnl #
|
|
+AC_DEFUN([ZFS_AC_KERNEL_ENUM_MEMBER], [
|
|
+ AC_MSG_CHECKING([whether enum $2 contains $1])
|
|
+ AS_IF([AC_TRY_COMMAND("${srcdir}/scripts/enum-extract.pl" "$2" "$3" | egrep -qx $1)],[
|
|
+ AC_MSG_RESULT([yes])
|
|
+ AC_DEFINE(m4_join([_], [ZFS_ENUM], m4_toupper($2), $1), 1, [enum $2 contains $1])
|
|
+ m4_join([_], [ZFS_ENUM], m4_toupper($2), $1)=1
|
|
+ ],[
|
|
+ AC_MSG_RESULT([no])
|
|
+ ])
|
|
+])
|
|
+
|
|
+dnl #
|
|
+dnl # Sanity check helpers
|
|
+dnl #
|
|
+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_ERROR],[
|
|
+ AC_MSG_RESULT(no)
|
|
+ AC_MSG_RESULT([$1 in either node_stat_item or zone_stat_item: $2])
|
|
+ AC_MSG_RESULT([configure needs updating, see: config/kernel-global_page_state.m4])
|
|
+ AC_MSG_FAILURE([SHUT 'ER DOWN CLANCY, SHE'S PUMPIN' MUD!])
|
|
+])
|
|
+
|
|
+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK], [
|
|
+ enum_check_a="m4_join([_], [$ZFS_ENUM_NODE_STAT_ITEM], $1)"
|
|
+ enum_check_b="m4_join([_], [$ZFS_ENUM_ZONE_STAT_ITEM], $1)"
|
|
+ AS_IF([test -n "$enum_check_a" -a -n "$enum_check_b"],[
|
|
+ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_ERROR([$1], [DUPLICATE])
|
|
+ ])
|
|
+ AS_IF([test -z "$enum_check_a" -a -z "$enum_check_b"],[
|
|
+ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_ERROR([$1], [NOT FOUND])
|
|
+ ])
|
|
+])
|
|
+
|
|
+dnl #
|
|
+dnl # Ensure the config tests are finding one and only one of each enum of interest
|
|
+dnl #
|
|
+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY], [
|
|
+ AC_MSG_CHECKING([global_page_state enums are sane])
|
|
+
|
|
+ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_FILE_PAGES])
|
|
+ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_INACTIVE_ANON])
|
|
+ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_INACTIVE_FILE])
|
|
+ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE_ENUM_CHECK([NR_SLAB_RECLAIMABLE])
|
|
+
|
|
+ AC_MSG_RESULT(yes)
|
|
+])
|
|
+
|
|
+dnl #
|
|
+dnl # enum members in which we're interested
|
|
+dnl #
|
|
+AC_DEFUN([ZFS_AC_KERNEL_GLOBAL_PAGE_STATE], [
|
|
+ ZFS_AC_KERNEL_GLOBAL_NODE_PAGE_STATE
|
|
+ ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE
|
|
+
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES], [node_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON], [node_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE], [node_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE], [node_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_FILE_PAGES], [zone_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_ANON], [zone_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_INACTIVE_FILE], [zone_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+ ZFS_AC_KERNEL_ENUM_MEMBER([NR_SLAB_RECLAIMABLE], [zone_stat_item], [$LINUX/include/linux/mmzone.h])
|
|
+
|
|
+ ZFS_AC_KERNEL_GLOBAL_ZONE_PAGE_STATE_SANITY
|
|
+])
|
|
diff --git a/config/kernel-vm_node_stat.m4 b/config/kernel-vm_node_stat.m4
|
|
deleted file mode 100644
|
|
index 5dcd9d827..000000000
|
|
--- a/config/kernel-vm_node_stat.m4
|
|
+++ /dev/null
|
|
@@ -1,22 +0,0 @@
|
|
-dnl #
|
|
-dnl # 4.8 API change
|
|
-dnl # kernel vm counters change
|
|
-dnl #
|
|
-AC_DEFUN([ZFS_AC_KERNEL_VM_NODE_STAT], [
|
|
- AC_MSG_CHECKING([whether to use vm_node_stat based fn's])
|
|
- ZFS_LINUX_TRY_COMPILE([
|
|
- #include <linux/mm.h>
|
|
- #include <linux/vmstat.h>
|
|
- ],[
|
|
- int a __attribute__ ((unused)) = NR_VM_NODE_STAT_ITEMS;
|
|
- long x __attribute__ ((unused)) =
|
|
- atomic_long_read(&vm_node_stat[0]);
|
|
- (void) global_node_page_state(0);
|
|
- ],[
|
|
- AC_MSG_RESULT(yes)
|
|
- AC_DEFINE(ZFS_GLOBAL_NODE_PAGE_STATE, 1,
|
|
- [using global_node_page_state()])
|
|
- ],[
|
|
- AC_MSG_RESULT(no)
|
|
- ])
|
|
-])
|
|
diff --git a/config/kernel.m4 b/config/kernel.m4
|
|
index 7bb86a96e..3e499e447 100644
|
|
--- a/config/kernel.m4
|
|
+++ b/config/kernel.m4
|
|
@@ -123,7 +123,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
|
|
ZFS_AC_KERNEL_RENAME_WANTS_FLAGS
|
|
ZFS_AC_KERNEL_HAVE_GENERIC_SETXATTR
|
|
ZFS_AC_KERNEL_CURRENT_TIME
|
|
- ZFS_AC_KERNEL_VM_NODE_STAT
|
|
+ ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
|
|
ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
|
|
|
|
AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
|
|
diff --git a/scripts/enum-extract.pl b/scripts/enum-extract.pl
|
|
new file mode 100755
|
|
index 000000000..5112cc807
|
|
--- /dev/null
|
|
+++ b/scripts/enum-extract.pl
|
|
@@ -0,0 +1,58 @@
|
|
+#!/usr/bin/perl -w
|
|
+
|
|
+my $usage = <<EOT;
|
|
+usage: config-enum enum [file ...]
|
|
+
|
|
+Returns the elements from an enum declaration.
|
|
+
|
|
+"Best effort": we're not building an entire C interpreter here!
|
|
+EOT
|
|
+
|
|
+use warnings;
|
|
+use strict;
|
|
+use Getopt::Std;
|
|
+
|
|
+my %opts;
|
|
+
|
|
+if (!getopts("", \%opts) || @ARGV < 1) {
|
|
+ print $usage;
|
|
+ exit 2;
|
|
+}
|
|
+
|
|
+my $enum = shift;
|
|
+
|
|
+my $in_enum = 0;
|
|
+
|
|
+while (<>) {
|
|
+ # comments
|
|
+ s/\/\*.*\*\///;
|
|
+ if (m/\/\*/) {
|
|
+ while ($_ .= <>) {
|
|
+ last if s/\/\*.*\*\///s;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ # preprocessor stuff
|
|
+ next if /^#/;
|
|
+
|
|
+ # find our enum
|
|
+ $in_enum = 1 if s/^\s*enum\s+${enum}(?:\s|$)//;
|
|
+ next unless $in_enum;
|
|
+
|
|
+ # remove explicit values
|
|
+ s/\s*=[^,]+,/,/g;
|
|
+
|
|
+ # extract each identifier
|
|
+ while (m/\b([a-z_][a-z0-9_]*)\b/ig) {
|
|
+ print $1, "\n";
|
|
+ }
|
|
+
|
|
+ #
|
|
+ # don't exit: there may be multiple versions of the same enum, e.g.
|
|
+ # inside different #ifdef blocks. Let's explicitly return all of
|
|
+ # them and let external tooling deal with it.
|
|
+ #
|
|
+ $in_enum = 0 if m/}\s*;/;
|
|
+}
|
|
+
|
|
+exit 0;
|
|
--
|
|
2.14.2
|
|
|