diff --git a/SOURCES/0127-agetty-fix-etc-os-release-parsing.patch b/SOURCES/0127-agetty-fix-etc-os-release-parsing.patch new file mode 100644 index 0000000..0e2e04b --- /dev/null +++ b/SOURCES/0127-agetty-fix-etc-os-release-parsing.patch @@ -0,0 +1,50 @@ +From 6b70da7e86ae17c215c48156a59e76b9f89e8add Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 5 Oct 2017 11:07:41 +0200 +Subject: [PATCH 127/135] agetty: fix /etc/os-release parsing + +For example /etc/os-release: + + VERSION="26 (Twenty Six)" + VERSION_ID=26 + +agetty for \S{VERSION} returns + + _ID=26 + +because the parser does nor check for '=' after variable name. + +Upstream: http://github.com/karelzak/util-linux/commit/949e83997906ab8dd8442f28d74c34bb5a2395ee +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1498462 +Signed-off-by: Karel Zak +--- + term-utils/agetty.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/term-utils/agetty.c b/term-utils/agetty.c +index 5692126dd..b626cdbeb 100644 +--- a/term-utils/agetty.c ++++ b/term-utils/agetty.c +@@ -1280,6 +1280,7 @@ static char *xgetdomainname(void) + return NULL; + } + ++ + static char *read_os_release(struct options *op, const char *varname) + { + int fd = -1; +@@ -1329,6 +1330,11 @@ static char *read_os_release(struct options *op, const char *varname) + continue; + } + p += varsz; ++ p += strspn(p, " \t\n\r"); ++ ++ if (*p != '=') ++ continue; ++ + p += strspn(p, " \t\n\r=\""); + eol = p + strcspn(p, "\n\r"); + *eol = '\0'; +-- +2.13.6 + diff --git a/SOURCES/0127-libmount-fix-access-utab-write-test.patch b/SOURCES/0127-libmount-fix-access-utab-write-test.patch deleted file mode 100644 index 02caa94..0000000 --- a/SOURCES/0127-libmount-fix-access-utab-write-test.patch +++ /dev/null @@ -1,226 +0,0 @@ -From 945d26162e639fd9ae3a774f1debaaa9511c7919 Mon Sep 17 00:00:00 2001 -From: Karel Zak -Date: Wed, 8 Nov 2017 16:47:40 +0100 -Subject: [PATCH] libmount: fix access() utab write test - -The commit c08396c7691e1e6a04b6b45892e7e4612ceed8d7 replaces -open(O_CREATE) with ecaccess(). Unfortunately, another code depends on -the original behavior. - -* let's make utab when really necessary rather than in the try_write() test - -* __mnt_new_table_from_file() returns NULL if tab-file does not - exists. This is incorrect for tab_update.c stuff. We need empty table - in this case. - -* we can check /run/mount/ directory for write access if - eaccess(filename) return ENOENT (because file does not exist) - -Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1499760 -Upstream: http://github.com/karelzak/util-linux/commit/06ff935ec3ad2290025b555ff32b590680af565f -Signed-off-by: Karel Zak ---- - libmount/src/mountP.h | 2 +- - libmount/src/tab_parse.c | 11 +++++++---- - libmount/src/tab_update.c | 9 +++++---- - libmount/src/utils.c | 42 +++++++++++++++++++++++++++++++----------- - 4 files changed, 44 insertions(+), 20 deletions(-) - -diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h -index 6cabcedeb..8b3f92e17 100644 ---- a/libmount/src/mountP.h -+++ b/libmount/src/mountP.h -@@ -278,7 +278,7 @@ struct libmnt_table { - struct list_head ents; /* list of entries (libmnt_fs) */ - }; - --extern struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt); -+extern struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt, int empty_for_enoent); - - /* - * Tab file format -diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c -index 987e671fa..c629c67ad 100644 ---- a/libmount/src/tab_parse.c -+++ b/libmount/src/tab_parse.c -@@ -714,7 +714,7 @@ int mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) - return __mnt_table_parse_dir(tb, dirname); - } - --struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) -+struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt, int empty_for_enoent) - { - struct libmnt_table *tb; - struct stat st; -@@ -723,7 +723,8 @@ struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) - if (!filename) - return NULL; - if (stat(filename, &st)) -- return NULL; -+ return empty_for_enoent ? mnt_new_table() : NULL; -+ - tb = mnt_new_table(); - if (tb) { - tb->fmt = fmt; -@@ -748,8 +749,10 @@ struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) - */ - struct libmnt_table *mnt_new_table_from_file(const char *filename) - { -- assert(filename); -- return __mnt_new_table_from_file(filename, MNT_FMT_GUESS); -+ if (!filename) -+ return NULL; -+ -+ return __mnt_new_table_from_file(filename, MNT_FMT_GUESS, 0); - } - - /** -diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c -index 1e7f32be0..5f503cad7 100644 ---- a/libmount/src/tab_update.c -+++ b/libmount/src/tab_update.c -@@ -567,6 +567,7 @@ leave: - - unlink(uq); /* be paranoid */ - free(uq); -+ DBG(UPDATE, mnt_debug_h(upd, "%s: done [rc=%d]", upd->filename, rc)); - return rc; - } - -@@ -600,7 +601,7 @@ static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc) - return rc; - - tb = __mnt_new_table_from_file(upd->filename, -- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); -+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); - if (tb) - rc = add_file_entry(tb, upd); - if (lc) -@@ -626,7 +627,7 @@ static int update_remove_entry(struct libmnt_update *upd, struct libmnt_lock *lc - return rc; - - tb = __mnt_new_table_from_file(upd->filename, -- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); -+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); - if (tb) { - struct libmnt_fs *rem = mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD); - if (rem) { -@@ -656,7 +657,7 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l - return rc; - - tb = __mnt_new_table_from_file(upd->filename, -- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); -+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); - if (tb) { - struct libmnt_fs *cur = mnt_table_find_target(tb, - mnt_fs_get_srcpath(upd->fs), MNT_ITER_BACKWARD); -@@ -693,7 +694,7 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock * - return rc; - - tb = __mnt_new_table_from_file(upd->filename, -- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); -+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); - if (tb) { - struct libmnt_fs *cur = mnt_table_find_target(tb, - mnt_fs_get_target(fs), -diff --git a/libmount/src/utils.c b/libmount/src/utils.c -index a275d0a0e..fa33bd9a1 100644 ---- a/libmount/src/utils.c -+++ b/libmount/src/utils.c -@@ -651,18 +651,37 @@ done: - return rc; - } - --static int try_write(const char *filename) -+static int try_write(const char *filename, const char *directory) - { - int rc = 0; - - if (!filename) - return -EINVAL; - -+ DBG(UTILS, mnt_debug("try write %s dir: %s", filename, directory)); -+ - #ifdef HAVE_EACCESS -- if (eaccess(filename, R_OK|W_OK) != 0) -- rc = -errno; --#else -+ /* Try eaccess() first, because open() is overkill, may be monitored by -+ * audit and we don't want to fill logs by our checks... -+ */ -+ if (eaccess(filename, R_OK|W_OK) == 0) { -+ DBG(UTILS, mnt_debug(" access OK")); -+ return 0; -+ } else if (errno != ENOENT) { -+ DBG(UTILS, mnt_debug(" access FAILED")); -+ return -errno; -+ } else if (directory) { -+ /* file does not exist; try if directory is writable */ -+ if (eaccess(directory, R_OK|W_OK) != 0) -+ rc = -errno; -+ -+ DBG(UTILS, mnt_debug(" access %s [%s]", rc ? "FAILED" : "OK", directory)); -+ return rc; -+ } else -+#endif - { -+ DBG(UTILS, mnt_debug(" doing open-write test")); -+ - int fd = open(filename, O_RDWR|O_CREAT|O_CLOEXEC, - S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); - if (fd < 0) -@@ -670,7 +689,6 @@ static int try_write(const char *filename) - else - close(fd); - } --#endif - return rc; - } - -@@ -704,7 +722,7 @@ int mnt_has_regular_mtab(const char **mtab, int *writable) - /* file exist */ - if (S_ISREG(st.st_mode)) { - if (writable) -- *writable = !try_write(filename); -+ *writable = !try_write(filename, NULL); - return 1; - } - goto done; -@@ -712,7 +730,7 @@ int mnt_has_regular_mtab(const char **mtab, int *writable) - - /* try to create the file */ - if (writable) { -- *writable = !try_write(filename); -+ *writable = !try_write(filename, NULL); - if (*writable) - return 1; - } -@@ -750,7 +768,7 @@ int mnt_has_regular_utab(const char **utab, int *writable) - /* file exist */ - if (S_ISREG(st.st_mode)) { - if (writable) -- *writable = !try_write(filename); -+ *writable = !try_write(filename, NULL); - return 1; - } - goto done; /* it's not regular file */ -@@ -767,11 +785,13 @@ int mnt_has_regular_utab(const char **utab, int *writable) - rc = mkdir(dirname, S_IWUSR| - S_IRUSR|S_IRGRP|S_IROTH| - S_IXUSR|S_IXGRP|S_IXOTH); -- free(dirname); -- if (rc && errno != EEXIST) -+ if (rc && errno != EEXIST) { -+ free(dirname); - goto done; /* probably EACCES */ -+ } - -- *writable = !try_write(filename); -+ *writable = !try_write(filename, dirname); -+ free(dirname); - if (*writable) - return 1; - } --- -2.13.6 - diff --git a/SOURCES/0128-fdisk-remove-obsolete-info-about-GPT-from-man-page.patch b/SOURCES/0128-fdisk-remove-obsolete-info-about-GPT-from-man-page.patch new file mode 100644 index 0000000..fb8be18 --- /dev/null +++ b/SOURCES/0128-fdisk-remove-obsolete-info-about-GPT-from-man-page.patch @@ -0,0 +1,33 @@ +From 81ffb923caad0eff603c708cc4d2fe0e3cff295f Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 16 Oct 2017 12:20:40 +0200 +Subject: [PATCH 128/135] fdisk: remove obsolete info about GPT from man page + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1490984 +Signed-off-by: Karel Zak +--- + fdisks/fdisk.8 | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/fdisks/fdisk.8 b/fdisks/fdisk.8 +index e4e585f12..39e4ad5c3 100644 +--- a/fdisks/fdisk.8 ++++ b/fdisks/fdisk.8 +@@ -33,12 +33,8 @@ fdisk \- manipulate disk partition table + (in the first form of invocation) + is a menu-driven program for creation and manipulation of + partition tables. +-It understands DOS-type partition tables and BSD- or SUN-type disklabels. +- +-.B fdisk +-does not understand GUID partition tables (GPTs) and it is not designed +-for large partitions. In these cases, use the more advanced GNU +-.BR parted (8). ++It understands GPT (experimental for now), MBR, Sun, SGI and BSD ++partition tables. + + .B fdisk + does not use DOS-compatible mode and cylinders as display units by default. +-- +2.13.6 + diff --git a/SOURCES/0129-libfdisk-gpt-sync-type-UUIDs-with-upstream.patch b/SOURCES/0129-libfdisk-gpt-sync-type-UUIDs-with-upstream.patch new file mode 100644 index 0000000..4419581 --- /dev/null +++ b/SOURCES/0129-libfdisk-gpt-sync-type-UUIDs-with-upstream.patch @@ -0,0 +1,112 @@ +From bef54812223745e19561096283653048eae62d90 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 16 Oct 2017 12:28:03 +0200 +Subject: [PATCH 129/135] libfdisk: (gpt) sync type UUIDs with upstream + +This commit updates add types introduced by freedesktop.org, Ceph, +BSD, Plan 9, QNX, Sony, Lenovo, etc. + +Upstream: http://github.com/karelzak/util-linux/commit/5aa8d13b13c3c8eddbd9176ef493dfa70a10616b +Upstream: http://github.com/karelzak/util-linux/commit/5a1b4999f7f9d152654b4af56f73804ce9407844 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1487031 +Signed-off-by: Karel Zak +--- + libfdisk/src/gpt.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 51 insertions(+), 8 deletions(-) + +diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c +index 612ce0971..de30b3dcb 100644 +--- a/libfdisk/src/gpt.c ++++ b/libfdisk/src/gpt.c +@@ -157,27 +157,53 @@ static struct fdisk_parttype gpt_parttypes[] = + DEF_GUID("C12A7328-F81F-11D2-BA4B-00A0C93EC93B", N_("EFI System")), + + DEF_GUID("024DEE41-33E7-11D3-9D69-0008C781F39F", N_("MBR partition scheme")), ++ DEF_GUID("D3BFE2DE-3DAF-11DF-BA40-E3A556D89593", N_("Intel Fast Flash")), ++ + /* Hah!IdontneedEFI */ +- DEF_GUID("21686148-6449-6E6F-744E-656564454649", N_("BIOS boot partition")), ++ DEF_GUID("21686148-6449-6E6F-744E-656564454649", N_("BIOS boot")), ++ ++ /* NIH syndrome */ ++ DEF_GUID("F4019732-066E-4E12-8273-346C5641494F", N_("Sony boot partition")), ++ DEF_GUID("BFBFAFE7-A34F-448A-9A5B-6213EB736C22", N_("Lenovo boot partition")), ++ ++ /* PowerPC reference platform boot partition */ ++ DEF_GUID("9E1A2D38-C612-4316-AA26-8B49521E5A8B", N_("PowerPC PReP boot")), ++ ++ /* Open Network Install Environment */ ++ DEF_GUID("7412F7D5-A156-4B13-81DC-867174929325", N_("ONIE boot")), ++ DEF_GUID("D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149", N_("ONIE config")), + + /* Windows */ + DEF_GUID("E3C9E316-0B5C-4DB8-817D-F92DF00215AE", N_("Microsoft reserved")), + DEF_GUID("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", N_("Microsoft basic data")), + DEF_GUID("5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", N_("Microsoft LDM metadata")), + DEF_GUID("AF9B60A0-1431-4F62-BC68-3311714A69AD", N_("Microsoft LDM data")), +- DEF_GUID("DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", N_("Windows recovery evironmnet")), ++ DEF_GUID("DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", N_("Windows recovery environment")), + DEF_GUID("37AFFC90-EF7D-4E96-91C3-2D7AE055B174", N_("IBM General Parallel Fs")), ++ DEF_GUID("E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D", N_("Microsoft Storage Spaces")), + + /* HP-UX */ +- DEF_GUID("75894C1E-3AEB-11D3-B7C1-7B03A0000000", N_("HP-UX data partition")), +- DEF_GUID("E2A1E728-32E3-11D6-A682-7B03A0000000", N_("HP-UX service partition")), ++ DEF_GUID("75894C1E-3AEB-11D3-B7C1-7B03A0000000", N_("HP-UX data")), ++ DEF_GUID("E2A1E728-32E3-11D6-A682-7B03A0000000", N_("HP-UX service")), + +- /* Linux */ ++ /* Linux (http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec) */ ++ DEF_GUID("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", N_("Linux swap")), + DEF_GUID("0FC63DAF-8483-4772-8E79-3D69D8477DE4", N_("Linux filesystem")), ++ DEF_GUID("3B8F8425-20E0-4F3B-907F-1A25A76F98E8", N_("Linux server data")), ++ DEF_GUID("44479540-F297-41B2-9AF7-D131D5F0458A", N_("Linux root (x86)")), ++ DEF_GUID("69DAD710-2CE4-4E3C-B16C-21A1D49ABED3", N_("Linux root (ARM)")), ++ DEF_GUID("4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709", N_("Linux root (x86-64)")), ++ DEF_GUID("B921B045-1DF0-41C3-AF44-4C6F280D3FAE", N_("Linux root (ARM-64)")), ++ DEF_GUID("993D8D3D-F80E-4225-855A-9DAF8ED7EA97", N_("Linux root (IA-64)")), ++ DEF_GUID("8DA63339-0007-60C0-C436-083AC8230908", N_("Linux reserved")), ++ DEF_GUID("933AC7E1-2EB4-4F13-B844-0E14E2AEF915", N_("Linux home")), + DEF_GUID("A19D880F-05FC-4D3B-A006-743F0F84911E", N_("Linux RAID")), +- DEF_GUID("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", N_("Linux swap")), ++ DEF_GUID("BC13C2FF-59E6-4262-A352-B275FD6F7172", N_("Linux extended boot")), + DEF_GUID("E6D6D379-F507-44C2-A23C-238F2A3DF928", N_("Linux LVM")), +- DEF_GUID("8DA63339-0007-60C0-C436-083AC8230908", N_("Linux reserved")), ++ /* ... too crazy, ignore for now: ++ DEF_GUID("7FFEC5C9-2D00-49B7-8941-3EA10A5586B7", N_("Linux plain dm-crypt")), ++ DEF_GUID("CA7D7CCB-63ED-4C53-861C-1742536059CC", N_("Linux LUKS")), ++ */ + + /* FreeBSD */ + DEF_GUID("516E7CB4-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD data")), +@@ -230,9 +256,26 @@ static struct fdisk_parttype gpt_parttypes[] = + DEF_GUID("85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD data")), + DEF_GUID("85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD boot")), + DEF_GUID("85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD swap")), +- DEF_GUID("0394Ef8B-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD UFS")), ++ DEF_GUID("0394EF8B-237E-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD UFS")), + DEF_GUID("85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD ZFS")), + DEF_GUID("85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD Vinum")), ++ ++ /* Ceph */ ++ DEF_GUID("45B0969E-9B03-4F30-B4C6-B4B80CEFF106", N_("Ceph Journal")), ++ DEF_GUID("45B0969E-9B03-4F30-B4C6-5EC00CEFF106", N_("Ceph Encrypted Journal")), ++ DEF_GUID("4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D", N_("Ceph OSD")), ++ DEF_GUID("4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D", N_("Ceph crypt OSD")), ++ DEF_GUID("89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE", N_("Ceph disk in creation")), ++ DEF_GUID("89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE", N_("Ceph crypt disk in creation")), ++ ++ /* OpenBSD */ ++ DEF_GUID("824CC7A0-36A8-11E3-890A-952519AD3F61", N_("OpenBSD data")), ++ ++ /* QNX */ ++ DEF_GUID("CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1", N_("QNX6 file system")), ++ ++ /* Plan 9 */ ++ DEF_GUID("C91818F9-8025-47AF-89D2-F030D7000C2C", N_("Plan 9 partition")) + }; + + /* gpt_entry macros */ +-- +2.13.6 + diff --git a/SOURCES/0130-lscpu-cleanup-DMI-detection-return-codes.patch b/SOURCES/0130-lscpu-cleanup-DMI-detection-return-codes.patch new file mode 100644 index 0000000..d88f229 --- /dev/null +++ b/SOURCES/0130-lscpu-cleanup-DMI-detection-return-codes.patch @@ -0,0 +1,87 @@ +From 1b6deafbe0a671d4fd7b8b6e9cc23c8dfcd8683c Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 13 Jun 2017 12:15:11 +0200 +Subject: [PATCH 130/135] lscpu: cleanup DMI detection return codes + +Michal wrote: + There is weird mix of logic in lscpu-dmi.c which sometimes returns 0 and + sometimes -1 on error. Since most checks are if (rc) goto done; this + bails out early on error skipping some detection methods. Further, in + lscpu.c all following detections are guarder by if(hyper) so returning + -1 causes all following methods to be skipped. + +Upstream: http://github.com/karelzak/util-linux/commit/c972852b29391c35b1d5c7d3e1e6413e0cc86908 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1468646 +Reported-by: Michal Suchanek +Signed-off-by: Karel Zak +--- + sys-utils/lscpu-dmi.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/sys-utils/lscpu-dmi.c b/sys-utils/lscpu-dmi.c +index a8298ff74..e4afd0b92 100644 +--- a/sys-utils/lscpu-dmi.c ++++ b/sys-utils/lscpu-dmi.c +@@ -172,7 +172,7 @@ done: + static int hypervisor_decode_legacy(uint8_t *buf, const char *devmem) + { + if (!checksum(buf, 0x0F)) +- return HYPER_NONE; ++ return -1; + + return hypervisor_from_dmi_table(DWORD(buf + 0x08), WORD(buf + 0x06), + WORD(buf + 0x0C), +@@ -252,11 +252,15 @@ int read_hypervisor_dmi(void) + || sizeof(uint16_t) != 2 + || sizeof(uint32_t) != 4 + || '\0' != 0) +- return rc; ++ goto done; + ++ /* -1 : no DMI in /sys, ++ * 0 : DMI exist, nothing detected (HYPER_NONE) ++ * >0 : hypervisor detected ++ */ + rc = hypervisor_decode_sysfw(); +- if (rc >= 0) +- return rc; ++ if (rc >= HYPER_NONE) ++ goto done; + + /* First try EFI (ia64, Intel-based Mac) */ + switch (address_from_efi(&fp)) { +@@ -271,8 +275,9 @@ int read_hypervisor_dmi(void) + goto done; + + rc = hypervisor_decode_smbios(buf, _PATH_DEV_MEM); +- if (rc) ++ if (rc >= HYPER_NONE) + goto done; ++ + free(buf); + buf = NULL; + memory_scan: +@@ -285,17 +290,17 @@ memory_scan: + for (fp = 0; fp <= 0xFFF0; fp += 16) { + if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) { + rc = hypervisor_decode_smbios(buf + fp, _PATH_DEV_MEM); +- if (rc == -1) ++ if (rc < 0) + fp += 16; + + } else if (memcmp(buf + fp, "_DMI_", 5) == 0) + rc = hypervisor_decode_legacy(buf + fp, _PATH_DEV_MEM); + +- if (rc >= 0) ++ if (rc >= HYPER_NONE) + break; + } + #endif + done: + free(buf); +- return rc; ++ return rc < 0 ? HYPER_NONE : rc; + } +-- +2.13.6 + diff --git a/SOURCES/0131-flock-zero-timeout-is-valid.patch b/SOURCES/0131-flock-zero-timeout-is-valid.patch new file mode 100644 index 0000000..876da3a --- /dev/null +++ b/SOURCES/0131-flock-zero-timeout-is-valid.patch @@ -0,0 +1,50 @@ +From 31568ef6a91b0f441c64fe79f7fa94a32be4dc97 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 7 Oct 2014 12:12:39 +0200 +Subject: [PATCH 131/135] flock: zero timeout is valid + +This patch reverts Sami's "timeout cannot be zero", introduced +in commit 605325b23b36238c8f3ae165e37cab9064553cf7. + +The --timeout 0 has been originally interpreted as --nonblock. The +patch also add hint about this behavior to the man page. + +Upstream: http://github.com/karelzak/util-linux/commit/c4604c38b503c8c46e50fc2048ebbcbcfcad3802 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1455398 +Signed-off-by: Karel Zak +--- + sys-utils/flock.1 | 4 +++- + sys-utils/flock.c | 2 -- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sys-utils/flock.1 b/sys-utils/flock.1 +index b28526f69..d5e85e082 100644 +--- a/sys-utils/flock.1 ++++ b/sys-utils/flock.1 +@@ -83,7 +83,9 @@ Fail if the lock cannot be acquired within + Decimal fractional values are allowed. + See the + .I \-E +-option for the exit code used. ++option for the exit code used. The zero number of ++.IR seconds ++is interpreted as \fB\-\-nonblock\fR. + .TP + \fB\-o\fP, \fB\-\-close\fP + Close the file descriptor on which the lock is held before executing +diff --git a/sys-utils/flock.c b/sys-utils/flock.c +index 18625a029..7dad46af0 100644 +--- a/sys-utils/flock.c ++++ b/sys-utils/flock.c +@@ -175,8 +175,6 @@ int main(int argc, char *argv[]) + have_timeout = 1; + strtotimeval_or_err(optarg, &timeout.it_value, + _("invalid timeout value")); +- if (timeout.it_value.tv_sec + timeout.it_value.tv_usec == 0) +- errx(EX_USAGE, _("timeout cannot be zero")); + break; + case 'E': + conflict_exit_code = strtos32_or_err(optarg, +-- +2.13.6 + diff --git a/SOURCES/0132-logger-add-man-page-note-about-the-default-tag.patch b/SOURCES/0132-logger-add-man-page-note-about-the-default-tag.patch new file mode 100644 index 0000000..d1a5411 --- /dev/null +++ b/SOURCES/0132-logger-add-man-page-note-about-the-default-tag.patch @@ -0,0 +1,28 @@ +From b97b85baf6281745b7f720a35d9e4bcc26e9ddcb Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 16 May 2016 15:05:28 +0200 +Subject: [PATCH 132/135] logger: add man page note about the default --tag + +Upstream: http://github.com/karelzak/util-linux/commit/28b6c76f8a4ea1faa80fe779c2011bc433de28c6 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1336432 +Signed-off-by: Karel Zak +--- + misc-utils/logger.1 | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/misc-utils/logger.1 b/misc-utils/logger.1 +index 57ca0d55a..3b55c8d7d 100644 +--- a/misc-utils/logger.1 ++++ b/misc-utils/logger.1 +@@ -110,6 +110,8 @@ Output the message to standard error as well as to the system log. + \fB\-t\fR, \fB\-\-tag\fR \fItag\fR + Mark every line to be logged with the specified + .IR tag . ++The default tag is the name of the user logged in on the terminal (or a user ++name based on effective user ID). + .TP + \fB\-u\fR, \fB\-\-socket\fR \fIsocket\fR + Write to the specified +-- +2.13.6 + diff --git a/SOURCES/0133-script-use-all-io-to-write.patch b/SOURCES/0133-script-use-all-io-to-write.patch new file mode 100644 index 0000000..090aa9f --- /dev/null +++ b/SOURCES/0133-script-use-all-io-to-write.patch @@ -0,0 +1,61 @@ +From 214d0ef6ac63442c285dd5d9d54190c62faf50d7 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 16 Oct 2017 13:30:44 +0200 +Subject: [PATCH 133/135] script: use all-io to write + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1427500 +Signed-off-by: Karel Zak +--- + term-utils/script.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/term-utils/script.c b/term-utils/script.c +index 242b8154a..5840b600d 100644 +--- a/term-utils/script.c ++++ b/term-utils/script.c +@@ -62,6 +62,7 @@ + #include "closestream.h" + #include "nls.h" + #include "c.h" ++#include "all-io.h" + + #if defined(HAVE_LIBUTIL) && defined(HAVE_PTY_H) + # include +@@ -301,8 +302,7 @@ doinput(void) { + + while (die == 0) { + if ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) { +- ssize_t wrt = write(master, ibuf, cc); +- if (wrt < 0) { ++ if (write_all(master, ibuf, cc)) { + warn (_("write failed")); + fail(); + } +@@ -355,8 +355,6 @@ dooutput(FILE *timingfd) { + struct timeval tv; + double oldtime=time(NULL), newtime; + int flgs = 0; +- ssize_t wrt; +- ssize_t fwrt; + + close(STDIN_FILENO); + #ifdef HAVE_LIBUTIL +@@ -393,13 +391,11 @@ dooutput(FILE *timingfd) { + fprintf(timingfd, "%f %zd\n", newtime - oldtime, cc); + oldtime = newtime; + } +- wrt = write(STDOUT_FILENO, obuf, cc); +- if (wrt < 0) { ++ if (write_all(STDOUT_FILENO, obuf, cc)) { + warn (_("write failed")); + fail(); + } +- fwrt = fwrite(obuf, 1, cc, fscript); +- if (fwrt < cc) { ++ if (fwrite_all(obuf, 1, cc, fscript)) { + warn (_("cannot write script file")); + fail(); + } +-- +2.13.6 + diff --git a/SOURCES/0134-logger-do-not-rely-only-getlogin-3-telling-who-ran-t.patch b/SOURCES/0134-logger-do-not-rely-only-getlogin-3-telling-who-ran-t.patch new file mode 100644 index 0000000..c066d9a --- /dev/null +++ b/SOURCES/0134-logger-do-not-rely-only-getlogin-3-telling-who-ran-t.patch @@ -0,0 +1,79 @@ +From 70ed51ccc2e8e6c4976d422af960e4232210fb99 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 16 Oct 2017 13:31:47 +0200 +Subject: [PATCH 134/135] logger: do not rely only getlogin(3) telling who ran + the command + +The getlogin(3) is known not to always work, and when that happens it +is reasonable to try determine user of name by looking process owner +and passwd information. + +Upstream: http://github.com/karelzak/util-linux/commit/019b97024fde3f07eaf541eef990762483369a11 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1336432 +Signed-off-by: Karel Zak +--- + misc-utils/logger.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/misc-utils/logger.c b/misc-utils/logger.c +index dfda01866..c1cec45e8 100644 +--- a/misc-utils/logger.c ++++ b/misc-utils/logger.c +@@ -49,6 +49,8 @@ + #include + #include + #include ++#include ++#include + + #include "c.h" + #include "closestream.h" +@@ -183,9 +185,20 @@ inet_socket(const char *servername, const char *port, const int socket_type) + return fd; + } + ++static char const *xgetlogin(void) ++{ ++ char const *cp; ++ struct passwd *pw; ++ ++ if (!(cp = getlogin()) || !*cp) ++ cp = (pw = getpwuid(geteuid()))? pw->pw_name : ""; ++ return cp; ++} ++ + static void + mysyslog(int fd, int logflags, int pri, char *tag, char *msg) { +- char *buf, pid[30], *cp, *tp; ++ char *buf, pid[30], *tp; ++ const char *cp; + time_t now; + + if (fd > -1) { +@@ -193,13 +206,7 @@ mysyslog(int fd, int logflags, int pri, char *tag, char *msg) { + snprintf (pid, sizeof(pid), "[%d]", getpid()); + else + pid[0] = 0; +- if (tag) +- cp = tag; +- else { +- cp = getlogin(); +- if (!cp) +- cp = ""; +- } ++ cp = tag ? tag : xgetlogin(); + (void)time(&now); + tp = ctime(&now)+4; + +@@ -334,7 +341,7 @@ main(int argc, char **argv) { + else if (usock) + LogSock = unix_socket(usock, socket_type); + else +- openlog(tag ? tag : getlogin(), logflags, 0); ++ openlog(tag ? tag : xgetlogin(), logflags, 0); + + buf = xcalloc(1, max_message_size); + +-- +2.13.6 + diff --git a/SOURCES/0135-login-use-IPv4-on-IPv4-mapping-to-IPv6.patch b/SOURCES/0135-login-use-IPv4-on-IPv4-mapping-to-IPv6.patch new file mode 100644 index 0000000..8d1c955 --- /dev/null +++ b/SOURCES/0135-login-use-IPv4-on-IPv4-mapping-to-IPv6.patch @@ -0,0 +1,52 @@ +From 7a1a825c7b77785f256e05b1e3ac7676c7485a5c Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 4 Jul 2017 12:50:39 +0200 +Subject: [PATCH 135/135] login: use IPv4 on IPv4-mapping-to-IPv6 + +It seems that on some systems (e.g. RHEL7) the libc function +getaddrinfo() is not able to translate ::ffff: address to IPv4. The +result is 0.0.0.0 host address in the last(1) and utmpdump(1) output. + + /sbin/login -h "::ffff:192.168.1.7" + +utmpdump: + + [7] [03926] [1 ] [user1 ] [pts/1 ] [::ffff:192.168.1.7 ] [0.0.0.0 ] [Thu May 12 17:49:50 2016 ] + +Not sure if this is about order of the getaddrinfo() results, system +configuration or libc version. It's irrelevant for login(1). We have +to be robust enough to write usable address to log files everywhere. + +The solution is to detect IPv4-mapping-to-IPv6 and use IPv4 for utmp. + +Upstream: http://github.com/karelzak/util-linux/commit/1c8792f1ae7fa38cf1d4418ad99c207f65dfdb1a +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1296233 +Signed-off-by: Karel Zak +--- + login-utils/login.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/login-utils/login.c b/login-utils/login.c +index e0e960f88..5c36953ef 100644 +--- a/login-utils/login.c ++++ b/login-utils/login.c +@@ -1101,8 +1101,15 @@ static void init_remote_info(struct login_context *cxt, char *remotehost) + } else if (info->ai_family == AF_INET6) { + struct sockaddr_in6 *sa = + (struct sockaddr_in6 *) info->ai_addr; ++#ifdef IN6_IS_ADDR_V4MAPPED ++ if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr)) { ++ const uint8_t *bytes = sa->sin6_addr.s6_addr; ++ struct in_addr addr = { *(const in_addr_t *) (bytes + 12) }; + +- memcpy(cxt->hostaddress, &(sa->sin6_addr), sizeof(sa->sin6_addr)); ++ memcpy(cxt->hostaddress, &addr, sizeof(struct in_addr)); ++ } else ++#endif ++ memcpy(cxt->hostaddress, &(sa->sin6_addr), sizeof(sa->sin6_addr)); + } + freeaddrinfo(info); + } +-- +2.13.6 + diff --git a/SOURCES/0136-blkid-update-man-page-about-lsblk-and-ambivalent-pro.patch b/SOURCES/0136-blkid-update-man-page-about-lsblk-and-ambivalent-pro.patch new file mode 100644 index 0000000..342f5d9 --- /dev/null +++ b/SOURCES/0136-blkid-update-man-page-about-lsblk-and-ambivalent-pro.patch @@ -0,0 +1,85 @@ +From d7725fb45fe8d4fcb67cb9fbc117bc1cf66fcd56 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 17 Oct 2017 10:44:01 +0200 +Subject: [PATCH 136/141] blkid: update man page about lsblk and ambivalent + probing + +Upstream: http://github.com/karelzak/util-linux/commit/12786a901520d7b30ff75ee8727221bf8a3089cb +Upstream: http://github.com/karelzak/util-linux/commit/27fbfef33c1f23b5448b6cee856bcb3500b33c42 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1501953 +Signed-off-by: Karel Zak +--- + misc-utils/blkid.8 | 39 +++++++++++++++++++++++++++------------ + 1 file changed, 27 insertions(+), 12 deletions(-) + +diff --git a/misc-utils/blkid.8 b/misc-utils/blkid.8 +index a974b8e99..1f12d202a 100644 +--- a/misc-utils/blkid.8 ++++ b/misc-utils/blkid.8 +@@ -61,6 +61,23 @@ library. It can determine the type of content (e.g. filesystem or swap) + that a block device holds, and also the attributes (tokens, NAME=value pairs) + from the content metadata (e.g. LABEL or UUID fields). + .PP ++.B It is recommended to use ++.BR lsblk (8) ++.B command to get information about block devices, or lsblk --fs to get an overview of filesystems, or ++.BR findmnt (8) ++.B to search in already mounted filesystems. ++.PP ++.RS ++.BR lsblk (8) ++provides more information, better control on output formatting, easy to use in ++scripts and it does not require root permissions to get actual information. ++.B blkid ++reads information directly from devices and for non-root users ++it returns cached unverified information. ++.B blkid ++is mostly designed for system services and to test libblkid functionality. ++.RE ++.PP + When + .I device + is specified, tokens from only this device are displayed. +@@ -71,21 +88,19 @@ If none is given, all devices which appear in + .I /proc/partitions + are shown, if they are recognized. + .PP +-Note that +-.B blkid +-reads information directly from devices and for non-root users +-it returns cached unverified information. It is better to use +-.B lsblk --fs +-to get a user-friendly overview of filesystems and devices. +-.BR lsblk (8) +-is also easy to use in scripts. +-.B blkid +-is mostly designed for system services and to test libblkid functionality. +-.PP + .B blkid + has two main forms of operation: either searching for a device with a + specific NAME=value pair, or displaying NAME=value pairs for one or + more specified devices. ++.PP ++For security reasons ++.B blkid ++silently ignores all devices where the probing result is ambivalent (multiple ++colliding filesystems are detected). The low-level probing mode (\fB-p\fR) ++provides more information and extra return code in this case. ++It's recommended to use ++.BR wipefs (8) ++to get a detailed overview and to erase obsolete stuff (magic strings) from the device. + .SH OPTIONS + The \fIsize\fR and \fIoffset\fR arguments may be followed by the multiplicative + suffixes like KiB (=1024), MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB +@@ -264,7 +279,7 @@ identified, an exit code of 2 is returned. + + For usage or other errors, an exit code of 4 is returned. + +-If an ambivalent low-level probing result was detected, an exit code of 8 is ++If an ambivalent probing result was detected by low-level probing mode (\fB\-p\fR), an exit code of 8 is + returned. + .SH CONFIGURATION FILE + The standard location of the +-- +2.13.6 + diff --git a/SOURCES/0137-wipefs-fix-t-filter.patch b/SOURCES/0137-wipefs-fix-t-filter.patch new file mode 100644 index 0000000..84e8954 --- /dev/null +++ b/SOURCES/0137-wipefs-fix-t-filter.patch @@ -0,0 +1,69 @@ +From df6302339ae99535d3c075712db8cadeedbb6c00 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 17 Oct 2017 11:07:56 +0200 +Subject: [PATCH 137/141] wipefs: fix -t filter + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1486777 +Signed-off-by: Karel Zak +--- + misc-utils/wipefs.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c +index 0144c9ef8..a0852aa97 100644 +--- a/misc-utils/wipefs.c ++++ b/misc-utils/wipefs.c +@@ -162,13 +162,16 @@ clone_offset(struct wipe_desc *wp0) + } + + static struct wipe_desc * +-get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr) ++get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr, int *found) + { + const char *off, *type, *mag, *p, *usage = NULL; + size_t len; + loff_t offset; + int rc, ispt = 0; + ++ if (found) ++ *found = 0; ++ + /* superblocks */ + if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) == 0) { + rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL); +@@ -215,6 +218,8 @@ get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr) + if (blkid_probe_lookup_value(pr, "UUID", &p, NULL) == 0) + wp->uuid = xstrdup(p); + ++ if (found) ++ *found = 1; + return wp; + } + +@@ -266,7 +271,7 @@ read_offsets(struct wipe_desc *wp, const char *devname) + return NULL; + + while (blkid_do_probe(pr) == 0) { +- wp = get_desc_for_probe(wp, pr); ++ wp = get_desc_for_probe(wp, pr, NULL); + if (!wp) + break; + } +@@ -347,9 +352,13 @@ do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet + wp0 = clone_offset(wp); + + while (blkid_do_probe(pr) == 0) { +- wp = get_desc_for_probe(wp, pr); ++ int found = 0; ++ ++ wp = get_desc_for_probe(wp, pr, &found); + if (!wp) + break; ++ if (!found) ++ continue; + + /* Check if offset is in provided list */ + w = wp0; +-- +2.13.6 + diff --git a/SOURCES/0138-tests-backport-new-ts_scsi_debug_init.patch b/SOURCES/0138-tests-backport-new-ts_scsi_debug_init.patch new file mode 100644 index 0000000..e3eba23 --- /dev/null +++ b/SOURCES/0138-tests-backport-new-ts_scsi_debug_init.patch @@ -0,0 +1,105 @@ +From 84995ef8ff7b76cff1cce438fc448f0afa560e23 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 17 Oct 2017 12:16:27 +0200 +Subject: [PATCH 138/141] tests: backport new ts_scsi_debug_init + +Signed-off-by: Karel Zak +--- + tests/functions.sh | 76 +++++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 66 insertions(+), 10 deletions(-) + +diff --git a/tests/functions.sh b/tests/functions.sh +index 0d1c9c88a..b930dfe7e 100644 +--- a/tests/functions.sh ++++ b/tests/functions.sh +@@ -502,21 +502,77 @@ function ts_fdisk_clean { + } + + function ts_scsi_debug_init { ++ local devname ++ local t ++ TS_DEVICE="none" + +- modprobe --dry-run --quiet scsi_debug +- [ "$?" == 0 ] || ts_skip "missing scsi_debug module" ++ # dry run is not really reliable, real modprobe may still fail ++ modprobe --dry-run --quiet scsi_debug &>/dev/null \ ++ || ts_skip "missing scsi_debug module (dry-run)" + +- rmmod scsi_debug &> /dev/null +- modprobe scsi_debug $* +- [ "$?" == 0 ] || ts_die "Cannot init device" ++ # skip if still in use or removal of modules not supported at all ++ # We don't want a slow timeout here so we don't use ts_scsi_debug_rmmod! ++ modprobe -r scsi_debug &>/dev/null \ ++ || ts_skip "cannot remove scsi_debug module (rmmod)" + +- DEVNAME=$(grep --with-filename scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}') +- [ "x${DEVNAME}" == "x" ] && ts_die "Cannot find device" ++ modprobe -b scsi_debug "$@" &>/dev/null \ ++ || ts_skip "cannot load scsi_debug module (modprobe)" + +- DEVICE="/dev/${DEVNAME}" ++ # it might be still not loaded, modprobe.conf or whatever ++ lsmod 2>/dev/null | grep -q "^scsi_debug " \ ++ || ts_skip "scsi_debug module not loaded (lsmod)" + +- sleep 1 + udevadm settle + +- echo $DEVICE ++ # wait for device if udevadm settle does not work ++ for t in 0 0.02 0.05 0.1 1; do ++ sleep $t ++ devname=$(grep --with-filename scsi_debug /sys/block/*/device/model) && break ++ done ++ [ -n "${devname}" ] || ts_die "timeout waiting for scsi_debug device" ++ ++ devname=$(echo $devname | awk -F '/' '{print $4}') ++ TS_DEVICE="/dev/${devname}" ++ ++ # TODO validate that device is really up, for now just a warning on stderr ++ test -b $TS_DEVICE || echo "warning: scsi_debug device is still down" >&2 ++} ++ ++# automatically called once in ts_cleanup_on_exit() ++function ts_scsi_debug_rmmod { ++ local err=1 ++ local t ++ local lastmsg ++ ++ # Return early most importantly in case we are not root or the module does ++ # not exist at all. ++ [ $UID -eq 0 ] || return 0 ++ [ -n "$TS_DEVICE" ] || return 0 ++ lsmod 2>/dev/null | grep -q "^scsi_debug " || return 0 ++ ++ udevadm settle ++ ++ # wait for successful rmmod if udevadm settle does not work ++ for t in 0 0.02 0.05 0.1 1; do ++ sleep $t ++ lastmsg="$(modprobe -r scsi_debug 2>&1)" && err=0 && break ++ done ++ ++ if [ "$err" = "1" ]; then ++ ts_log "rmmod failed: '$lastmsg'" ++ ts_log "timeout removing scsi_debug module (rmmod)" ++ return 1 ++ fi ++ if lsmod | grep -q "^scsi_debug "; then ++ ts_log "BUG! scsi_debug still loaded" ++ return 1 ++ fi ++ ++ # TODO Do we need to validate that all devices are gone? ++ udevadm settle ++ test -b "$TS_DEVICE" && echo "warning: scsi_debug device is still up" >&2 ++ ++ # TODO unset TS_DEVICE, check that nobody uses it later, e.g. ts_fdisk_clean ++ ++ return 0 + } +-- +2.13.6 + diff --git a/SOURCES/0139-tests-ts_scsi_debug_init-must-not-run-in-a-subshell.patch b/SOURCES/0139-tests-ts_scsi_debug_init-must-not-run-in-a-subshell.patch new file mode 100644 index 0000000..a2356df --- /dev/null +++ b/SOURCES/0139-tests-ts_scsi_debug_init-must-not-run-in-a-subshell.patch @@ -0,0 +1,558 @@ +From 9e643d190c1c3b39423c4d00f1ddc89e2b4cc09e Mon Sep 17 00:00:00 2001 +From: Ruediger Meier +Date: Sun, 11 May 2014 08:50:28 +0200 +Subject: [PATCH 139/141] tests: ts_scsi_debug_init must not run in a subshell + +ts_skip and ts_die won't work from subshell. Now we simply use +TS_DEVICE which is globally set in that function. + +I've made sure that we never change TS_DEVICE variable after +we've got it. So we could use it again for cleanup on exit in +ts_{finalize,die,skip} functions. + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1454652 +Upstream: http://github.com/karelzak/util-linux/commit/f45df374ffc311220bd395da985b121eccfb4045 +Signed-off-by: Karel Zak +Signed-off-by: Ruediger Meier +--- + tests/ts/blkid/md-raid1-part | 25 +++++++++++++++------- + tests/ts/eject/umount | 39 ++++++++++++++++++----------------- + tests/ts/fdisk/align-512-4K | 9 ++++---- + tests/ts/fdisk/align-512-4K-63 | 9 ++++---- + tests/ts/fdisk/align-512-4K-md | 12 ++++++----- + tests/ts/fdisk/align-512-512-topology | 10 ++++----- + tests/ts/libmount/context | 9 ++++---- + tests/ts/libmount/context-utab | 9 ++++---- + tests/ts/libmount/tabfiles-tags | 15 +++++++------- + tests/ts/mount/umount-alltargets | 29 +++++++++++++------------- + tests/ts/mount/umount-recursive | 21 ++++++++++--------- + 11 files changed, 104 insertions(+), 83 deletions(-) + +diff --git a/tests/ts/blkid/md-raid1-part b/tests/ts/blkid/md-raid1-part +index 46bde0ec8..20612ec21 100755 +--- a/tests/ts/blkid/md-raid1-part ++++ b/tests/ts/blkid/md-raid1-part +@@ -23,10 +23,11 @@ TS_DESC="MD raid1 (last partition)" + ts_init "$*" + ts_skip_nonroot + +-DEVICE=$(ts_scsi_debug_init dev_size_mb=51 sector_size=512) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=51 sector_size=512 + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <> $TS_OUTPUT 2>&1 < /dev/null < /dev/null + /sbin/mdadm -q --create ${MD_DEVICE} --metadata=0.90 --chunk=64 --level=1 \ +- --raid-devices=2 ${DEVICE}1 ${DEVICE}2 >> $TS_OUTPUT 2>&1 ++ --raid-devices=2 ${TS_DEVICE}1 ${TS_DEVICE}2 >> $TS_OUTPUT 2>&1 + udevadm settle + + ts_log "Probe whole-disk" +-$TS_CMD_BLKID -p -o udev ${DEVICE} 2>&1 | sort >> $TS_OUTPUT ++$TS_CMD_BLKID -p -o udev ${TS_DEVICE} 2>&1 | sort >> $TS_OUTPUT + + ts_log "Probe first RAID member" +-$TS_CMD_BLKID -p -o udev ${DEVICE}1 2>&1 | sort >> $TS_OUTPUT ++$TS_CMD_BLKID -p -o udev ${TS_DEVICE}1 2>&1 | sort >> $TS_OUTPUT + + ts_log "Probe second RAID member" +-$TS_CMD_BLKID -p -o udev ${DEVICE}2 2>&1 | sort >> $TS_OUTPUT ++$TS_CMD_BLKID -p -o udev ${TS_DEVICE}2 2>&1 | sort >> $TS_OUTPUT + + /sbin/mdadm -q -S ${MD_DEVICE} >> $TS_OUTPUT 2>&1 + + udevadm settle + rmmod scsi_debug + +-ts_fdisk_clean $DEVICE ++ts_fdisk_clean $TS_DEVICE + # substitue UUIDs and major/minor number before comparison + sed -i \ + -e 's/^\(ID_FS_UUID\)=.*/\1=__ts_uuid__/' \ +diff --git a/tests/ts/eject/umount b/tests/ts/eject/umount +index 3c1f84edf..994ddb483 100755 +--- a/tests/ts/eject/umount ++++ b/tests/ts/eject/umount +@@ -12,6 +12,7 @@ ts_skip_nonroot + # not removable device. + # + ++# set global variable TS_DEVICE + function init_device { + ts_scsi_debug_init dev_size_mb=100 + } +@@ -47,50 +48,50 @@ function deinit_device { + + + ts_init_subtest "by-disk" +-DEVICE=$(init_device) +-$TS_CMD_EJECT --force $DEVICE && ts_log "Success" ++init_device ++$TS_CMD_EJECT --force $TS_DEVICE && ts_log "Success" + deinit_device + ts_finalize_subtest + + ts_init_subtest "by-disk-mounted" +-DEVICE=$(init_device) +-mkfs.ext2 -q -F $DEVICE ++init_device ++mkfs.ext2 -q -F $TS_DEVICE + udevadm settle + mkdir -p $TS_MOUNTPOINT +-mount $DEVICE $TS_MOUNTPOINT +-$TS_CMD_EJECT --force $DEVICE && ts_log "Success" ++mount $TS_DEVICE $TS_MOUNTPOINT ++$TS_CMD_EJECT --force $TS_DEVICE && ts_log "Success" + deinit_device + ts_finalize_subtest + + + ts_init_subtest "by-disk-mounted-partition" +-DEVICE=$(init_device) +-init_partitions $DEVICE ++init_device ++init_partitions $TS_DEVICE + mkdir -p ${TS_MOUNTPOINT}1 + mkdir -p ${TS_MOUNTPOINT}2 +-mount ${DEVICE}1 ${TS_MOUNTPOINT}1 +-mount ${DEVICE}2 ${TS_MOUNTPOINT}2 +-$TS_CMD_EJECT --force $DEVICE && ts_log "Success" ++mount ${TS_DEVICE}1 ${TS_MOUNTPOINT}1 ++mount ${TS_DEVICE}2 ${TS_MOUNTPOINT}2 ++$TS_CMD_EJECT --force $TS_DEVICE && ts_log "Success" + deinit_device + ts_finalize_subtest + + + ts_init_subtest "by-partition" +-DEVICE=$(init_device) +-init_partitions $DEVICE +-$TS_CMD_EJECT --force ${DEVICE}1 && ts_log "Success" ++init_device ++init_partitions $TS_DEVICE ++$TS_CMD_EJECT --force ${TS_DEVICE}1 && ts_log "Success" + deinit_device + ts_finalize_subtest + + + ts_init_subtest "by-partition-mounted" +-DEVICE=$(init_device) +-init_partitions $DEVICE ++init_device ++init_partitions $TS_DEVICE + mkdir -p ${TS_MOUNTPOINT}1 + mkdir -p ${TS_MOUNTPOINT}2 +-mount ${DEVICE}1 ${TS_MOUNTPOINT}1 +-mount ${DEVICE}2 ${TS_MOUNTPOINT}2 +-$TS_CMD_EJECT --force ${DEVICE}1 && ts_log "Success" ++mount ${TS_DEVICE}1 ${TS_MOUNTPOINT}1 ++mount ${TS_DEVICE}2 ${TS_MOUNTPOINT}2 ++$TS_CMD_EJECT --force ${TS_DEVICE}1 && ts_log "Success" + deinit_device + ts_finalize_subtest + +diff --git a/tests/ts/fdisk/align-512-4K b/tests/ts/fdisk/align-512-4K +index c5ea72e7a..5608b1b65 100755 +--- a/tests/ts/fdisk/align-512-4K ++++ b/tests/ts/fdisk/align-512-4K +@@ -27,11 +27,12 @@ TS_DESC="align 512/4K" + ts_init "$*" + ts_skip_nonroot + +-DEVICE=$(ts_scsi_debug_init dev_size_mb=50 sector_size=512 physblk_exp=3) +-DEVNAME=$(basename $DEVICE) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=50 sector_size=512 physblk_exp=3 ++DEVNAME=$(basename $TS_DEVICE) + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <> $TS_OUTPUT 2>&1 <> $TS_OUTP + + rmmod scsi_debug + +-ts_fdisk_clean $DEVICE ++ts_fdisk_clean $TS_DEVICE + + ts_finalize +diff --git a/tests/ts/fdisk/align-512-4K-63 b/tests/ts/fdisk/align-512-4K-63 +index 4ec81982f..8199cf7b3 100755 +--- a/tests/ts/fdisk/align-512-4K-63 ++++ b/tests/ts/fdisk/align-512-4K-63 +@@ -27,11 +27,12 @@ TS_DESC="align 512/4K +alignment_offset" + ts_init "$*" + ts_skip_nonroot + +-DEVICE=$(ts_scsi_debug_init dev_size_mb=50 sector_size=512 physblk_exp=3 lowest_aligned=7) +-DEVNAME=$(basename $DEVICE) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=50 sector_size=512 physblk_exp=3 lowest_aligned=7 ++DEVNAME=$(basename $TS_DEVICE) + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <> $TS_OUTPUT 2>&1 <> $TS_OUTP + + rmmod scsi_debug + +-ts_fdisk_clean $DEVICE ++ts_fdisk_clean $TS_DEVICE + + ts_finalize +diff --git a/tests/ts/fdisk/align-512-4K-md b/tests/ts/fdisk/align-512-4K-md +index 09947ff9e..ad662e0e8 100755 +--- a/tests/ts/fdisk/align-512-4K-md ++++ b/tests/ts/fdisk/align-512-4K-md +@@ -27,11 +27,12 @@ TS_DESC="align 512/4K +MD" + ts_init "$*" + ts_skip_nonroot + +-DEVICE=$(ts_scsi_debug_init dev_size_mb=50 sector_size=512 physblk_exp=3) +-DEVNAME=$(basename $DEVICE) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=50 sector_size=512 physblk_exp=3 ++DEVNAME=$(basename $TS_DEVICE) + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <> $TS_OUTPUT 2>&1 < /dev/null + /sbin/mdadm -q --create ${MD_DEVICE} --metadata=0.90 --chunk=64 \ +- --level=0 --raid-devices=2 ${DEVICE}1 ${DEVICE}2 >> $TS_OUTPUT 2>&1 ++ --level=0 --raid-devices=2 ${TS_DEVICE}1 ${TS_DEVICE}2 >> $TS_OUTPUT 2>&1 + + udevadm settle + ts_log "Create partitions (MD)" +@@ -85,6 +86,7 @@ cat /sys/block/${MD_DEVNAME}/${MD_DEVNAME}p{1,2}/alignment_offset >> $TS_OUTPUT + udevadm settle + rmmod scsi_debug + +-ts_fdisk_clean $DEVICE ++ts_fdisk_clean $TS_DEVICE ++ts_fdisk_clean $MD_DEVICE + + ts_finalize +diff --git a/tests/ts/fdisk/align-512-512-topology b/tests/ts/fdisk/align-512-512-topology +index 9354e45c7..65cb03f1d 100755 +--- a/tests/ts/fdisk/align-512-512-topology ++++ b/tests/ts/fdisk/align-512-512-topology +@@ -27,12 +27,12 @@ TS_DESC="align 512/512 +topology" + ts_init "$*" + ts_skip_nonroot + +- +-DEVICE=$(ts_scsi_debug_init dev_size_mb=50 sector_size=512) +-DEVNAME=$(basename $DEVICE) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=50 sector_size=512 ++DEVNAME=$(basename $TS_DEVICE) + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} >> $TS_OUTPUT 2>&1 <> $TS_OUTPUT 2>&1 <> $TS_OUTP + + rmmod scsi_debug + +-ts_fdisk_clean $DEVICE ++ts_fdisk_clean $TS_DEVICE + + ts_finalize +diff --git a/tests/ts/libmount/context b/tests/ts/libmount/context +index 0c3bce986..873890378 100755 +--- a/tests/ts/libmount/context ++++ b/tests/ts/libmount/context +@@ -21,11 +21,12 @@ TS_NOEXIST="$TS_OUTDIR/${TS_TESTNAME}-${TS_SUBNAME}-noex" + ts_log "Init device" + umount $MOUNTPOINT &> /dev/null + +-DEVICE=$(ts_scsi_debug_init dev_size_mb=100) +-DEVNAME=$(basename $DEVICE) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=100 ++DEVNAME=$(basename $TS_DEVICE) + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} &> /dev/null < /dev/null < /dev/null < /dev/null < /dev/null || ts_die "Cannot make ext3 on $DEVICE" $DEVICE ++mkfs.ext3 -F -L $LABEL $TS_DEVICE -U $UUID &> /dev/null || ts_die "Cannot make ext3 on $TS_DEVICE" $TS_DEVICE + udevadm settle + +-ts_device_has_uuid $DEVICE || ts_die "Cannot find UUID on $DEVICE" $DEVICE ++ts_device_has_uuid $TS_DEVICE || ts_die "Cannot find UUID on $TS_DEVICE" $TS_DEVICE + + FSTAB="$TS_OUTDIR/fstab" + +@@ -36,7 +37,7 @@ sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT + ts_finalize_subtest + + ts_init_subtest "fstab-label2dev" +-ts_valgrind $TESTPROG --find-forward $FSTAB source $DEVICE &> $TS_OUTPUT ++ts_valgrind $TESTPROG --find-forward $FSTAB source $TS_DEVICE &> $TS_OUTPUT + sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT + ts_finalize_subtest + +@@ -60,18 +61,18 @@ ts_finalize_subtest + + ts_init_subtest "fstab-dev2label" + # has to return /mnt/mountpoint +-ts_valgrind $TESTPROG --find-forward $FSTAB source $DEVICE &> $TS_OUTPUT ++ts_valgrind $TESTPROG --find-forward $FSTAB source $TS_DEVICE &> $TS_OUTPUT + sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT + ts_finalize_subtest + + # + # Add devname + # +-echo "$DEVICE /mnt/mountpoint3 auto defaults" >> $FSTAB ++echo "$TS_DEVICE /mnt/mountpoint3 auto defaults" >> $FSTAB + + ts_init_subtest "fstab-dev" + # has to return /mnt/mountpoint3 +-ts_valgrind $TESTPROG --find-forward $FSTAB source $DEVICE &> $TS_OUTPUT ++ts_valgrind $TESTPROG --find-forward $FSTAB source $TS_DEVICE &> $TS_OUTPUT + sed -i -e 's/fs: 0x.*/fs:/g' $TS_OUTPUT + sed -i -e 's/source: .*//g' $TS_OUTPUT # devname is generated, remove it + ts_finalize_subtest +diff --git a/tests/ts/mount/umount-alltargets b/tests/ts/mount/umount-alltargets +index 434ecab2d..ae35e320a 100755 +--- a/tests/ts/mount/umount-alltargets ++++ b/tests/ts/mount/umount-alltargets +@@ -12,10 +12,11 @@ ts_skip_nonroot + $TS_CMD_UMOUNT --help | grep -q all-targets + [ $? -eq 1 ] && ts_skip "all-targets unsupported" + +-DEVICE=$(ts_scsi_debug_init dev_size_mb=50) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=50 + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} &> /dev/null < /dev/null < /dev/null ++mkfs.ext2 ${TS_DEVICE}1 &> /dev/null + ts_log "Create filesystem B" +-mkfs.ext2 ${DEVICE}2 &> /dev/null ++mkfs.ext2 ${TS_DEVICE}2 &> /dev/null + ts_log "Create filesystem C" +-mkfs.ext2 ${DEVICE}3 &> /dev/null ++mkfs.ext2 ${TS_DEVICE}3 &> /dev/null + ts_log "Create filesystem D" +-mkfs.ext2 ${DEVICE}4 &> /dev/null ++mkfs.ext2 ${TS_DEVICE}4 &> /dev/null + + udevadm settle + +@@ -76,7 +77,7 @@ MOUNTPOINT=$TS_MOUNTPOINT + # The same device mounted on more places, umount all by mountpoint name + # + ts_init_subtest "all-targets-mnt" +-multi_mount ${DEVICE}1 $MOUNTPOINT ++multi_mount ${TS_DEVICE}1 $MOUNTPOINT + $TS_CMD_UMOUNT --all-targets ${MOUNTPOINT}1 >> $TS_OUTPUT 2>&1 + [ $? == 0 ] || ts_log "umount failed" + ts_finalize_subtest +@@ -85,8 +86,8 @@ ts_finalize_subtest + # The same device mounted on more places, umount all by device name + # + ts_init_subtest "all-targets-dev" +-multi_mount ${DEVICE}1 $MOUNTPOINT +-$TS_CMD_UMOUNT --all-targets ${DEVICE}1 >> $TS_OUTPUT 2>&1 ++multi_mount ${TS_DEVICE}1 $MOUNTPOINT ++$TS_CMD_UMOUNT --all-targets ${TS_DEVICE}1 >> $TS_OUTPUT 2>&1 + [ $? == 0 ] || ts_log "umount failed" + ts_finalize_subtest + +@@ -95,14 +96,14 @@ ts_finalize_subtest + # sub-mounts. Umount all by one umount all by top-level device name. + # + ts_init_subtest "all-targets-recursive" +-multi_mount ${DEVICE}1 $MOUNTPOINT ++multi_mount ${TS_DEVICE}1 $MOUNTPOINT + [ -d "${MOUNTPOINT}1/subA" ] || mkdir -p ${MOUNTPOINT}1/subA +-$TS_CMD_MOUNT ${DEVICE}2 ${MOUNTPOINT}1/subA ++$TS_CMD_MOUNT ${TS_DEVICE}2 ${MOUNTPOINT}1/subA + [ -d "${MOUNTPOINT}1/subA/subAB" ] || mkdir -p ${MOUNTPOINT}1/subA/subAB +-$TS_CMD_MOUNT ${DEVICE}3 ${MOUNTPOINT}1/subA/subAB ++$TS_CMD_MOUNT ${TS_DEVICE}3 ${MOUNTPOINT}1/subA/subAB + [ -d "${MOUNTPOINT}1/subB" ] || mkdir -p ${MOUNTPOINT}1/subB +-$TS_CMD_MOUNT ${DEVICE}4 ${MOUNTPOINT}1/subB +-$TS_CMD_UMOUNT --recursive --all-targets ${DEVICE}1 >> $TS_OUTPUT 2>&1 ++$TS_CMD_MOUNT ${TS_DEVICE}4 ${MOUNTPOINT}1/subB ++$TS_CMD_UMOUNT --recursive --all-targets ${TS_DEVICE}1 >> $TS_OUTPUT 2>&1 + [ $? == 0 ] || ts_log "umount failed" + ts_finalize_subtest + +diff --git a/tests/ts/mount/umount-recursive b/tests/ts/mount/umount-recursive +index 85e54df7a..9b9a7a1f1 100755 +--- a/tests/ts/mount/umount-recursive ++++ b/tests/ts/mount/umount-recursive +@@ -13,10 +13,11 @@ $TS_CMD_UMOUNT --help | grep -q recursive + [ $? -eq 1 ] && ts_skip "recursive unsupported" + + ts_log "Init device" +-DEVICE=$(ts_scsi_debug_init dev_size_mb=50) ++# set global variable TS_DEVICE ++ts_scsi_debug_init dev_size_mb=50 + + ts_log "Create partitions" +-$TS_CMD_FDISK ${DEVICE} &> /dev/null < /dev/null < /dev/null ++mkfs.ext2 ${TS_DEVICE}1 &> /dev/null + ts_log "Create filesystem B" +-mkfs.ext2 ${DEVICE}2 &> /dev/null ++mkfs.ext2 ${TS_DEVICE}2 &> /dev/null + ts_log "Create filesystem C" +-mkfs.ext2 ${DEVICE}3 &> /dev/null ++mkfs.ext2 ${TS_DEVICE}3 &> /dev/null + ts_log "Create filesystem D" +-mkfs.ext2 ${DEVICE}4 &> /dev/null ++mkfs.ext2 ${TS_DEVICE}4 &> /dev/null + + udevadm settle + +@@ -58,12 +59,12 @@ ts_log "Do tests..." + [ -d "$TS_MOUNTPOINT" ] || mkdir -p $TS_MOUNTPOINT + + ts_log "A) Mount root" +-$TS_CMD_MOUNT ${DEVICE}1 $TS_MOUNTPOINT >> $TS_OUTPUT 2>&1 ++$TS_CMD_MOUNT ${TS_DEVICE}1 $TS_MOUNTPOINT >> $TS_OUTPUT 2>&1 + $TS_CMD_MOUNT --make-shared $TS_MOUNTPOINT + + ts_log "B) Mount child" + mkdir -p $TS_MOUNTPOINT/mntB +-$TS_CMD_MOUNT ${DEVICE}2 $TS_MOUNTPOINT/mntB >> $TS_OUTPUT 2>&1 ++$TS_CMD_MOUNT ${TS_DEVICE}2 $TS_MOUNTPOINT/mntB >> $TS_OUTPUT 2>&1 + + ts_log "B2) Mount child-bind" + mkdir -p $TS_MOUNTPOINT/bindB +@@ -71,10 +72,10 @@ $TS_CMD_MOUNT --bind $TS_MOUNTPOINT/mntB $TS_MOUNTPOINT/bindB >> $TS_OUTPUT 2>&1 + + ts_log "C) Mount child/child" + mkdir -p $TS_MOUNTPOINT/mntB/mnt{C,D} +-$TS_CMD_MOUNT ${DEVICE}3 $TS_MOUNTPOINT/mntB/mntC >> $TS_OUTPUT 2>&1 ++$TS_CMD_MOUNT ${TS_DEVICE}3 $TS_MOUNTPOINT/mntB/mntC >> $TS_OUTPUT 2>&1 + + ts_log "D) Mount child/child" +-$TS_CMD_MOUNT ${DEVICE}4 $TS_MOUNTPOINT/mntB/mntD >> $TS_OUTPUT 2>&1 ++$TS_CMD_MOUNT ${TS_DEVICE}4 $TS_MOUNTPOINT/mntB/mntD >> $TS_OUTPUT 2>&1 + + ts_log "E) Mount child-bind" + mkdir -p $TS_MOUNTPOINT/bindC +-- +2.13.6 + diff --git a/SOURCES/0140-tests-cleanup-fdisk-outputs.patch b/SOURCES/0140-tests-cleanup-fdisk-outputs.patch new file mode 100644 index 0000000..37d23a7 --- /dev/null +++ b/SOURCES/0140-tests-cleanup-fdisk-outputs.patch @@ -0,0 +1,86 @@ +From 0c4c724109d160e336d38f0a50fd82c9f5184ddb Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 17 Oct 2017 12:35:31 +0200 +Subject: [PATCH 140/141] tests: cleanup fdisk outputs + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1454652 +Signed-off-by: Karel Zak +--- + tests/expected/fdisk/align-512-4K-md | 6 +++--- + tests/expected/fdisk/align-512-512 | 16 ++++++++-------- + tests/ts/fdisk/align-512-512 | 3 +-- + 3 files changed, 12 insertions(+), 13 deletions(-) + +diff --git a/tests/expected/fdisk/align-512-4K-md b/tests/expected/fdisk/align-512-4K-md +index e8f6ba161..336c9e019 100644 +--- a/tests/expected/fdisk/align-512-4K-md ++++ b/tests/expected/fdisk/align-512-4K-md +@@ -69,7 +69,7 @@ Select (default p): Partition number (2-4, default 2): First sector (22528-10009 + Last sector, +sectors or +size{K,M,G} (22528-100095, default 100095): Partition 2 of type Linux and of size 10 MiB is set + + Command (m for help): +-Disk /dev/md8: 51 MB, 51249152 bytes, 100096 sectors ++Disk /dev/...: 51 MB, 51249152 bytes, 100096 sectors + Units = sectors of 1 * 512 = 512 bytes + Sector size (logical/physical): 512 bytes / 4096 bytes + I/O size (minimum/optimal): 65536 bytes / bytes +@@ -77,8 +77,8 @@ Disk label type: dos + + + Device Boot Start End Blocks Id System +-/dev/md8p1 2048 22527 10240 83 Linux +-/dev/md8p2 22528 43007 10240 83 Linux ++/dev/...p1 2048 22527 10240 83 Linux ++/dev/...p2 22528 43007 10240 83 Linux + + Command (m for help): The partition table has been altered! + +diff --git a/tests/expected/fdisk/align-512-512 b/tests/expected/fdisk/align-512-512 +index 8e03d900d..f9cbb0e89 100644 +--- a/tests/expected/fdisk/align-512-512 ++++ b/tests/expected/fdisk/align-512-512 +@@ -50,7 +50,7 @@ Last sector, +sectors or +size{K,M,G} (90112-102399, default 102399): Using defa + Partition 7 of type Linux and of size 6 MiB is set + + Command (m for help): +-Disk /dev/loop0: 52 MB, 52428800 bytes, 102400 sectors ++Disk /dev/...: 52 MB, 52428800 bytes, 102400 sectors + Units = sectors of 1 * 512 = 512 bytes + Sector size (logical/physical): 512 bytes / 512 bytes + I/O size (minimum/optimal): 512 bytes / bytes +@@ -58,12 +58,12 @@ Disk label type: dos + + + Device Boot Start End Blocks Id System +-/dev/loop0p1 2048 22527 10240 83 Linux +-/dev/loop0p2 22528 43007 10240 83 Linux +-/dev/loop0p3 43008 63487 10240 83 Linux +-/dev/loop0p4 63488 102399 19456 5 Extended +-/dev/loop0p5 65536 75775 5120 83 Linux +-/dev/loop0p6 77824 88063 5120 83 Linux +-/dev/loop0p7 90112 102399 6144 83 Linux ++/dev/...p1 2048 22527 10240 83 Linux ++/dev/...p2 22528 43007 10240 83 Linux ++/dev/...p3 43008 63487 10240 83 Linux ++/dev/...p4 63488 102399 19456 5 Extended ++/dev/...p5 65536 75775 5120 83 Linux ++/dev/...p6 77824 88063 5120 83 Linux ++/dev/...p7 90112 102399 6144 83 Linux + + Command (m for help): +diff --git a/tests/ts/fdisk/align-512-512 b/tests/ts/fdisk/align-512-512 +index 82a6268cf..03133a6d1 100755 +--- a/tests/ts/fdisk/align-512-512 ++++ b/tests/ts/fdisk/align-512-512 +@@ -64,7 +64,6 @@ q + EOF + + ts_device_deinit $DEVICE +- +-ts_fdisk_clean ++ts_fdisk_clean $DEVICE + + ts_finalize +-- +2.13.6 + diff --git a/SOURCES/0141-tests-check-for-mdadm.patch b/SOURCES/0141-tests-check-for-mdadm.patch new file mode 100644 index 0000000..c2fc6c7 --- /dev/null +++ b/SOURCES/0141-tests-check-for-mdadm.patch @@ -0,0 +1,53 @@ +From 609177ec200592dce34bf0ee082c0d2ac8d01b8b Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 17 Oct 2017 12:35:31 +0200 +Subject: [PATCH 141/141] tests: check for mdadm + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1454652 +Signed-off-by: Karel Zak +--- + tests/ts/blkid/md-raid1-part | 1 + + tests/ts/eject/umount | 2 +- + tests/ts/fdisk/align-512-4K-md | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tests/ts/blkid/md-raid1-part b/tests/ts/blkid/md-raid1-part +index 20612ec21..de21bca9a 100755 +--- a/tests/ts/blkid/md-raid1-part ++++ b/tests/ts/blkid/md-raid1-part +@@ -22,6 +22,7 @@ TS_DESC="MD raid1 (last partition)" + . $TS_TOPDIR/functions.sh + ts_init "$*" + ts_skip_nonroot ++ts_check_prog "mdadm" + + # set global variable TS_DEVICE + ts_scsi_debug_init dev_size_mb=51 sector_size=512 +diff --git a/tests/ts/eject/umount b/tests/ts/eject/umount +index 994ddb483..e5cfe2b14 100755 +--- a/tests/ts/eject/umount ++++ b/tests/ts/eject/umount +@@ -43,7 +43,7 @@ EOF + + function deinit_device { + udevadm settle +- rmmod scsi_debug ++ ts_scsi_debug_rmmod + } + + +diff --git a/tests/ts/fdisk/align-512-4K-md b/tests/ts/fdisk/align-512-4K-md +index ad662e0e8..c45a0d43b 100755 +--- a/tests/ts/fdisk/align-512-4K-md ++++ b/tests/ts/fdisk/align-512-4K-md +@@ -26,6 +26,7 @@ TS_DESC="align 512/4K +MD" + . $TS_TOPDIR/functions.sh + ts_init "$*" + ts_skip_nonroot ++ts_check_prog "mdadm" + + # set global variable TS_DEVICE + ts_scsi_debug_init dev_size_mb=50 sector_size=512 physblk_exp=3 +-- +2.13.6 + diff --git a/SOURCES/0142-lsmem-chmem-backport-new-commands.patch b/SOURCES/0142-lsmem-chmem-backport-new-commands.patch new file mode 100644 index 0000000..c20edd1 --- /dev/null +++ b/SOURCES/0142-lsmem-chmem-backport-new-commands.patch @@ -0,0 +1,1608 @@ +From 4fde7a853f61fa025a9d42a7571161a69fdae162 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 23 Oct 2017 15:54:54 +0200 +Subject: [PATCH] lsmem, chmem: backport new commands + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1496421 +Signed-off-by: Karel Zak +--- + configure.ac | 19 ++ + include/c.h | 10 + + include/path.h | 5 +- + include/strutils.h | 1 + + lib/path.c | 36 ++- + lib/strutils.c | 17 +- + sys-utils/Makemodule.am | 14 + + sys-utils/chmem.8 | 114 ++++++++ + sys-utils/chmem.c | 447 +++++++++++++++++++++++++++++++ + sys-utils/lsmem.1 | 95 +++++++ + sys-utils/lsmem.c | 687 ++++++++++++++++++++++++++++++++++++++++++++++++ + 11 files changed, 1432 insertions(+), 13 deletions(-) + create mode 100644 sys-utils/chmem.8 + create mode 100644 sys-utils/chmem.c + create mode 100644 sys-utils/lsmem.1 + create mode 100644 sys-utils/lsmem.c + +diff --git a/configure.ac b/configure.ac +index 96c5838cf..d561e01d0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1138,6 +1138,25 @@ UL_REQUIRES_SYSCALL_CHECK([pivot_root], [UL_CHECK_SYSCALL([pivot_root])]) + AM_CONDITIONAL(BUILD_PIVOT_ROOT, test "x$build_pivot_root" = xyes) + + ++AC_ARG_ENABLE([lsmem], ++ AS_HELP_STRING([--disable-lsmem], [do not build lsmem]), ++ [], enable_lsmem=check ++) ++UL_BUILD_INIT([lsmem]) ++UL_REQUIRES_LINUX([lsmem]) ++UL_REQUIRES_BUILD([lsmem], [libsmartcols]) ++AM_CONDITIONAL([BUILD_LSMEM], [test "x$build_lsmem" = xyes]) ++ ++ ++AC_ARG_ENABLE([chmem], ++ AS_HELP_STRING([--disable-chmem], [do not build chmem]), ++ [], enable_chmem=check ++) ++UL_BUILD_INIT([chmem]) ++UL_REQUIRES_LINUX([chmem]) ++AM_CONDITIONAL([BUILD_CHMEM], [test "x$build_chmem" = xyes]) ++ ++ + AC_ARG_ENABLE([elvtune], + AS_HELP_STRING([--enable-elvtune], [build elvtune (only works with 2.2 and 2.4 kernels)]), + [], enable_elvtune=no +diff --git a/include/c.h b/include/c.h +index 8ff61b484..124035ea5 100644 +--- a/include/c.h ++++ b/include/c.h +@@ -302,6 +302,16 @@ static inline int usleep(useconds_t usec) + + #define UTIL_LINUX_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING + ++/* backported to RHEL */ ++#define USAGE_COLUMNS _("\nAvailable output columns:\n") ++#define USAGE_OPTSTR_HELP _("display this help") ++#define USAGE_OPTSTR_VERSION _("display version") ++#define USAGE_HELP_OPTIONS(marg_dsc) \ ++ "%-" #marg_dsc "s%s\n" \ ++ "%-" #marg_dsc "s%s\n" \ ++ , " -h, --help", USAGE_OPTSTR_HELP \ ++ , " -V, --version", USAGE_OPTSTR_VERSION ++ + /* + * scanf modifiers for "strings allocation" + */ +diff --git a/include/path.h b/include/path.h +index 45da692f8..1ab5724fc 100644 +--- a/include/path.h ++++ b/include/path.h +@@ -4,6 +4,10 @@ + #include + #include + ++extern int path_set_prefix(const char *); ++ ++extern const char *path_get(const char *path, ...); ++ + extern char *path_strdup(const char *path, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + extern FILE *path_fopen(const char *mode, int exit_on_err, const char *path, ...) +@@ -27,7 +31,6 @@ extern cpu_set_t *path_read_cpuset(int, const char *path, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + extern cpu_set_t *path_read_cpulist(int, const char *path, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +-extern void path_set_prefix(const char *); + #endif /* HAVE_CPU_SET_T */ + + #endif /* UTIL_LINUX_PATH_H */ +diff --git a/include/strutils.h b/include/strutils.h +index aa7b95f96..1f028e4ed 100644 +--- a/include/strutils.h ++++ b/include/strutils.h +@@ -25,6 +25,7 @@ extern uint32_t strtou32_or_err(const char *str, const char *errmesg); + + extern int64_t strtos64_or_err(const char *str, const char *errmesg); + extern uint64_t strtou64_or_err(const char *str, const char *errmesg); ++extern uint64_t strtox64_or_err(const char *str, const char *errmesg); + + extern double strtod_or_err(const char *str, const char *errmesg); + +diff --git a/lib/path.c b/lib/path.c +index e47d31418..49ca9b5e0 100644 +--- a/lib/path.c ++++ b/lib/path.c +@@ -38,6 +38,20 @@ + static size_t prefixlen; + static char pathbuf[PATH_MAX]; + ++int ++path_set_prefix(const char *prefix) ++{ ++ size_t len = strlen(prefix); ++ ++ if (len >= sizeof(pathbuf) - 1) { ++ errno = ENAMETOOLONG; ++ return -1; ++ } ++ prefixlen = len; ++ strcpy(pathbuf, prefix); ++ return 0; ++} ++ + static const char * + path_vcreate(const char *path, va_list ap) + { +@@ -49,6 +63,19 @@ path_vcreate(const char *path, va_list ap) + return pathbuf; + } + ++const char * ++path_get(const char *path, ...) ++{ ++ const char *p; ++ va_list ap; ++ ++ va_start(ap, path); ++ p = path_vcreate(path, ap); ++ va_end(ap); ++ ++ return p; ++} ++ + char * + path_strdup(const char *path, ...) + { +@@ -246,13 +273,6 @@ path_read_cpulist(int maxcpus, const char *path, ...) + + return set; + } +- + #endif /* HAVE_CPU_SET_T */ + +-void +-path_set_prefix(const char *prefix) +-{ +- prefixlen = strlen(prefix); +- strncpy(pathbuf, prefix, sizeof(pathbuf)); +- pathbuf[sizeof(pathbuf) - 1] = '\0'; +-} ++ +diff --git a/lib/strutils.c b/lib/strutils.c +index 4b8a8130d..2458a2c2f 100644 +--- a/lib/strutils.c ++++ b/lib/strutils.c +@@ -237,27 +237,36 @@ err: + errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str); + } + +-uint64_t strtou64_or_err(const char *str, const char *errmesg) ++static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base) + { + uintmax_t num; + char *end = NULL; + ++ errno = 0; + if (str == NULL || *str == '\0') + goto err; +- errno = 0; +- num = strtoumax(str, &end, 10); ++ num = strtoumax(str, &end, base); + + if (errno || str == end || (end && *end)) + goto err; + + return num; + err: +- if (errno) ++ if (errno == ERANGE) + err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str); + + errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str); + } + ++uint64_t strtou64_or_err(const char *str, const char *errmesg) ++{ ++ return _strtou64_or_err(str, errmesg, 10); ++} ++ ++uint64_t strtox64_or_err(const char *str, const char *errmesg) ++{ ++ return _strtou64_or_err(str, errmesg, 16); ++} + + double strtod_or_err(const char *str, const char *errmesg) + { +diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am +index 0496b84e3..21585ce80 100644 +--- a/sys-utils/Makemodule.am ++++ b/sys-utils/Makemodule.am +@@ -1,3 +1,17 @@ ++if BUILD_LSMEM ++usrbin_exec_PROGRAMS += lsmem ++dist_man_MANS += sys-utils/lsmem.1 ++lsmem_SOURCES = sys-utils/lsmem.c ++lsmem_LDADD = $(LDADD) libcommon.la libsmartcols.la ++lsmem_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) ++endif ++ ++if BUILD_CHMEM ++usrbin_exec_PROGRAMS += chmem ++dist_man_MANS += sys-utils/chmem.8 ++chmem_SOURCES = sys-utils/chmem.c ++chmem_LDADD = $(LDADD) libcommon.la ++endif + + usrbin_exec_PROGRAMS += flock + dist_man_MANS += sys-utils/flock.1 +diff --git a/sys-utils/chmem.8 b/sys-utils/chmem.8 +new file mode 100644 +index 000000000..dae7413d4 +--- /dev/null ++++ b/sys-utils/chmem.8 +@@ -0,0 +1,114 @@ ++.TH CHMEM 8 "October 2016" "util-linux" "System Administration" ++.SH NAME ++chmem \- configure memory ++.SH SYNOPSIS ++.B chmem ++.RB [ \-h "] [" \-V "] [" \-v "] [" \-e | \-d "]" ++[\fISIZE\fP|\fIRANGE\fP|\fB\-b\fP \fIBLOCKRANGE\fP] ++[-z ZONE] ++.SH DESCRIPTION ++The chmem command sets a particular size or range of memory online or offline. ++. ++.IP "\(hy" 2 ++Specify \fISIZE\fP as [m|M|g|G]. With m or M, specifies the memory ++size in MiB (1024 x 1024 bytes). With g or G, specifies the memory size ++in GiB (1024 x 1024 x 1024 bytes). The default unit is MiB. ++. ++.IP "\(hy" 2 ++Specify \fIRANGE\fP in the form 0x-0x as shown in the output of the ++\fBlsmem\fP command. is the hexadecimal address of the first byte and ++is the hexadecimal address of the last byte in the memory range. ++. ++.IP "\(hy" 2 ++Specify \fIBLOCKRANGE\fP in the form - or as shown in the ++output of the \fBlsmem\fP command. is the number of the first memory block ++and is the number of the last memory block in the memory ++range. Alternatively a single block can be specified. \fIBLOCKRANGE\fP requires ++the \fB--blocks\fP option. ++. ++.IP "\(hy" 2 ++Specify \fIZONE\fP as the name of a memory zone, as shown in the output of the ++\fBlsmem -o +ZONES\fP command. The output shows one or more valid memory zones ++for each memory range. If multiple zones are shown, then the memory range ++currently belongs to the first zone. By default, chmem will set memory online ++to the zone Movable, if this is among the valid zones. This default can be ++changed by specifying the \fB--zone\fP option with another valid zone. ++For memory ballooning, it is recommended to select the zone Movable for memory ++online and offline, if possible. Memory in this zone is much more likely to be ++able to be offlined again, but it cannot be used for arbitrary kernel ++allocations, only for migratable pages (e.g. anonymous and page cache pages). ++Use the \fB\-\-help\fR option to see all available zones. ++. ++.PP ++\fISIZE\fP and \fIRANGE\fP must be aligned to the Linux memory block size, as ++shown in the output of the \fBlsmem\fP command. ++ ++Setting memory online can fail for various reasons. On virtualized systems it ++can fail if the hypervisor does not have enough memory left, for example ++because memory was overcommitted. Setting memory offline can fail if Linux ++cannot free the memory. If only part of the requested memory can be set online ++or offline, a message tells you how much memory was set online or offline ++instead of the requested amount. ++ ++When setting memory online \fBchmem\fP starts with the lowest memory block ++numbers. When setting memory offline \fBchmem\fP starts with the highest memory ++block numbers. ++.SH OPTIONS ++.TP ++.BR \-b ", " \-\-blocks ++Use a \fIBLOCKRANGE\fP parameter instead of \fIRANGE\fP or \fISIZE\fP for the ++\fB--enable\fP and \fB--disable\fP options. ++.TP ++.BR \-d ", " \-\-disable ++Set the specified \fIRANGE\fP, \fISIZE\fP, or \fIBLOCKRANGE\fP of memory offline. ++.TP ++.BR \-e ", " \-\-enable ++Set the specified \fIRANGE\fP, \fISIZE\fP, or \fIBLOCKRANGE\fP of memory online. ++.TP ++.BR \-z ", " \-\-zone ++Select the memory \fIZONE\fP where to set the specified \fIRANGE\fP, \fISIZE\fP, ++or \fIBLOCKRANGE\fP of memory online or offline. By default, memory will be set ++online to the zone Movable, if possible. ++.TP ++.BR \-h ", " \-\-help ++Print a short help text, then exit. ++.TP ++.BR \-v ", " \-\-verbose ++Verbose mode. Causes \fBchmem\fP to print debugging messages about it's ++progress. ++.TP ++.BR \-V ", " \-\-version ++Print the version number, then exit. ++.SH RETURN CODES ++.B chmem ++has the following return codes: ++.TP ++.BR 0 ++success ++.TP ++.BR 1 ++failure ++.TP ++.BR 64 ++partial success ++.SH EXAMPLES ++.TP ++.B chmem --enable 1024 ++This command requests 1024 MiB of memory to be set online. ++.TP ++.B chmem -e 2g ++This command requests 2 GiB of memory to be set online. ++.TP ++.B chmem --disable 0x00000000e4000000-0x00000000f3ffffff ++This command requests the memory range starting with 0x00000000e4000000 ++and ending with 0x00000000f3ffffff to be set offline. ++.TP ++.B chmem -b -d 10 ++This command requests the memory block number 10 to be set offline. ++.SH SEE ALSO ++.BR lsmem (1) ++.SH AVAILABILITY ++The \fBchmem\fP command is part of the util-linux package and is available from ++.UR https://\:www.kernel.org\:/pub\:/linux\:/utils\:/util-linux/ ++Linux Kernel Archive ++.UE . +diff --git a/sys-utils/chmem.c b/sys-utils/chmem.c +new file mode 100644 +index 000000000..0e5e84727 +--- /dev/null ++++ b/sys-utils/chmem.c +@@ -0,0 +1,447 @@ ++/* ++ * chmem - Memory configuration tool ++ * ++ * Copyright IBM Corp. 2016 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it would be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "c.h" ++#include "nls.h" ++#include "path.h" ++#include "strutils.h" ++#include "strv.h" ++#include "optutils.h" ++#include "closestream.h" ++#include "xalloc.h" ++ ++/* partial success, otherwise we return regular EXIT_{SUCCESS,FAILURE} */ ++#define CHMEM_EXIT_SOMEOK 64 ++ ++#define _PATH_SYS_MEMORY "/sys/devices/system/memory" ++#define _PATH_SYS_MEMORY_BLOCK_SIZE _PATH_SYS_MEMORY "/block_size_bytes" ++ ++struct chmem_desc { ++ struct dirent **dirs; ++ int ndirs; ++ uint64_t block_size; ++ uint64_t start; ++ uint64_t end; ++ uint64_t size; ++ unsigned int use_blocks : 1; ++ unsigned int is_size : 1; ++ unsigned int verbose : 1; ++ unsigned int have_zones : 1; ++}; ++ ++enum { ++ CMD_MEMORY_ENABLE = 0, ++ CMD_MEMORY_DISABLE, ++ CMD_NONE ++}; ++ ++enum zone_id { ++ ZONE_DMA = 0, ++ ZONE_DMA32, ++ ZONE_NORMAL, ++ ZONE_HIGHMEM, ++ ZONE_MOVABLE, ++ ZONE_DEVICE, ++}; ++ ++static char *zone_names[] = { ++ [ZONE_DMA] = "DMA", ++ [ZONE_DMA32] = "DMA32", ++ [ZONE_NORMAL] = "Normal", ++ [ZONE_HIGHMEM] = "Highmem", ++ [ZONE_MOVABLE] = "Movable", ++ [ZONE_DEVICE] = "Device", ++}; ++ ++/* ++ * name must be null-terminated ++ */ ++static int zone_name_to_id(const char *name) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(zone_names); i++) { ++ if (!strcasecmp(name, zone_names[i])) ++ return i; ++ } ++ return -1; ++} ++ ++static void idxtostr(struct chmem_desc *desc, uint64_t idx, char *buf, size_t bufsz) ++{ ++ uint64_t start, end; ++ ++ start = idx * desc->block_size; ++ end = start + desc->block_size - 1; ++ snprintf(buf, bufsz, ++ _("Memory Block %"PRIu64" (0x%016"PRIx64"-0x%016"PRIx64")"), ++ idx, start, end); ++} ++ ++static int chmem_size(struct chmem_desc *desc, int enable, int zone_id) ++{ ++ char *name, *onoff, line[BUFSIZ], str[BUFSIZ]; ++ uint64_t size, index; ++ const char *zn; ++ int i, rc; ++ ++ size = desc->size; ++ onoff = enable ? "online" : "offline"; ++ i = enable ? 0 : desc->ndirs - 1; ++ ++ if (enable && zone_id >= 0) { ++ if (zone_id == ZONE_MOVABLE) ++ onoff = "online_movable"; ++ else ++ onoff = "online_kernel"; ++ } ++ ++ for (; i >= 0 && i < desc->ndirs && size; i += enable ? 1 : -1) { ++ name = desc->dirs[i]->d_name; ++ index = strtou64_or_err(name + 6, _("Failed to parse index")); ++ path_read_str(line, sizeof(line), _PATH_SYS_MEMORY "/%s/state", name); ++ if (strncmp(onoff, line, 6) == 0) ++ continue; ++ ++ if (desc->have_zones) { ++ path_read_str(line, sizeof(line), ++ _PATH_SYS_MEMORY "/%s/valid_zones", name); ++ if (zone_id >= 0) { ++ zn = zone_names[zone_id]; ++ if (enable && !strcasestr(line, zn)) ++ continue; ++ if (!enable && strncasecmp(line, zn, strlen(zn))) ++ continue; ++ } else if (enable) { ++ /* By default, use zone Movable for online, if valid */ ++ if (strcasestr(line, zone_names[ZONE_MOVABLE])) ++ onoff = "online_movable"; ++ else ++ onoff = "online"; ++ } ++ } ++ ++ idxtostr(desc, index, str, sizeof(str)); ++ rc = path_write_str(onoff, _PATH_SYS_MEMORY"/%s/state", name); ++ if (rc == -1 && desc->verbose) { ++ if (enable) ++ fprintf(stdout, _("%s enable failed\n"), str); ++ else ++ fprintf(stdout, _("%s disable failed\n"), str); ++ } else if (rc == 0 && desc->verbose) { ++ if (enable) ++ fprintf(stdout, _("%s enabled\n"), str); ++ else ++ fprintf(stdout, _("%s disabled\n"), str); ++ } ++ if (rc == 0) ++ size--; ++ } ++ if (size) { ++ uint64_t bytes; ++ char *sizestr; ++ ++ bytes = (desc->size - size) * desc->block_size; ++ sizestr = size_to_human_string(SIZE_SUFFIX_1LETTER, bytes); ++ if (enable) ++ warnx(_("Could only enable %s of memory"), sizestr); ++ else ++ warnx(_("Could only disable %s of memory"), sizestr); ++ free(sizestr); ++ } ++ return size == 0 ? 0 : size == desc->size ? -1 : 1; ++} ++ ++static int chmem_range(struct chmem_desc *desc, int enable, int zone_id) ++{ ++ char *name, *onoff, line[BUFSIZ], str[BUFSIZ]; ++ uint64_t index, todo; ++ const char *zn; ++ int i, rc; ++ ++ todo = desc->end - desc->start + 1; ++ onoff = enable ? "online" : "offline"; ++ ++ if (enable && zone_id >= 0) { ++ if (zone_id == ZONE_MOVABLE) ++ onoff = "online_movable"; ++ else ++ onoff = "online_kernel"; ++ } ++ ++ for (i = 0; i < desc->ndirs; i++) { ++ name = desc->dirs[i]->d_name; ++ index = strtou64_or_err(name + 6, _("Failed to parse index")); ++ if (index < desc->start) ++ continue; ++ if (index > desc->end) ++ break; ++ idxtostr(desc, index, str, sizeof(str)); ++ path_read_str(line, sizeof(line), _PATH_SYS_MEMORY "/%s/state", name); ++ if (strncmp(onoff, line, 6) == 0) { ++ if (desc->verbose && enable) ++ fprintf(stdout, _("%s already enabled\n"), str); ++ else if (desc->verbose && !enable) ++ fprintf(stdout, _("%s already disabled\n"), str); ++ todo--; ++ continue; ++ } ++ ++ if (desc->have_zones) { ++ path_read_str(line, sizeof(line), ++ _PATH_SYS_MEMORY "/%s/valid_zones", name); ++ if (zone_id >= 0) { ++ zn = zone_names[zone_id]; ++ if (enable && !strcasestr(line, zn)) { ++ warnx(_("%s enable failed: Zone mismatch"), str); ++ continue; ++ } ++ if (!enable && strncasecmp(line, zn, strlen(zn))) { ++ warnx(_("%s disable failed: Zone mismatch"), str); ++ continue; ++ } ++ } else if (enable) { ++ /* By default, use zone Movable for online, if valid */ ++ if (strcasestr(line, zone_names[ZONE_MOVABLE])) ++ onoff = "online_movable"; ++ else ++ onoff = "online"; ++ } ++ } ++ ++ rc = path_write_str(onoff, _PATH_SYS_MEMORY"/%s/state", name); ++ if (rc == -1) { ++ if (enable) ++ warn(_("%s enable failed"), str); ++ else ++ warn(_("%s disable failed"), str); ++ } else if (desc->verbose) { ++ if (enable) ++ fprintf(stdout, _("%s enabled\n"), str); ++ else ++ fprintf(stdout, _("%s disabled\n"), str); ++ } ++ if (rc == 0) ++ todo--; ++ } ++ return todo == 0 ? 0 : todo == desc->end - desc->start + 1 ? -1 : 1; ++} ++ ++static int filter(const struct dirent *de) ++{ ++ if (strncmp("memory", de->d_name, 6)) ++ return 0; ++ return isdigit_string(de->d_name + 6); ++} ++ ++static void read_info(struct chmem_desc *desc) ++{ ++ char line[BUFSIZ]; ++ ++ desc->ndirs = scandir(_PATH_SYS_MEMORY, &desc->dirs, filter, versionsort); ++ if (desc->ndirs <= 0) ++ err(EXIT_FAILURE, _("Failed to read %s"), _PATH_SYS_MEMORY); ++ path_read_str(line, sizeof(line), _PATH_SYS_MEMORY_BLOCK_SIZE); ++ desc->block_size = strtoumax(line, NULL, 16); ++} ++ ++static void parse_single_param(struct chmem_desc *desc, char *str) ++{ ++ if (desc->use_blocks) { ++ desc->start = strtou64_or_err(str, _("Failed to parse block number")); ++ desc->end = desc->start; ++ return; ++ } ++ desc->is_size = 1; ++ desc->size = strtosize_or_err(str, _("Failed to parse size")); ++ if (isdigit(str[strlen(str) - 1])) ++ desc->size *= 1024*1024; ++ if (desc->size % desc->block_size) { ++ errx(EXIT_FAILURE, _("Size must be aligned to memory block size (%s)"), ++ size_to_human_string(SIZE_SUFFIX_1LETTER, desc->block_size)); ++ } ++ desc->size /= desc->block_size; ++} ++ ++static void parse_range_param(struct chmem_desc *desc, char *start, char *end) ++{ ++ if (desc->use_blocks) { ++ desc->start = strtou64_or_err(start, _("Failed to parse start")); ++ desc->end = strtou64_or_err(end, _("Failed to parse end")); ++ return; ++ } ++ if (strlen(start) < 2 || start[1] != 'x') ++ errx(EXIT_FAILURE, _("Invalid start address format: %s"), start); ++ if (strlen(end) < 2 || end[1] != 'x') ++ errx(EXIT_FAILURE, _("Invalid end address format: %s"), end); ++ desc->start = strtox64_or_err(start, _("Failed to parse start address")); ++ desc->end = strtox64_or_err(end, _("Failed to parse end address")); ++ if (desc->start % desc->block_size || (desc->end + 1) % desc->block_size) { ++ errx(EXIT_FAILURE, ++ _("Start address and (end address + 1) must be aligned to " ++ "memory block size (%s)"), ++ size_to_human_string(SIZE_SUFFIX_1LETTER, desc->block_size)); ++ } ++ desc->start /= desc->block_size; ++ desc->end /= desc->block_size; ++} ++ ++static void parse_parameter(struct chmem_desc *desc, char *param) ++{ ++ char **split; ++ ++ split = strv_split(param, "-"); ++ if (strv_length(split) > 2) ++ errx(EXIT_FAILURE, _("Invalid parameter: %s"), param); ++ if (strv_length(split) == 1) ++ parse_single_param(desc, split[0]); ++ else ++ parse_range_param(desc, split[0], split[1]); ++ strv_free(split); ++ if (desc->start > desc->end) ++ errx(EXIT_FAILURE, _("Invalid range: %s"), param); ++} ++ ++static void __attribute__((__noreturn__)) usage(void) ++{ ++ FILE *out = stdout; ++ size_t i; ++ ++ fputs(USAGE_HEADER, out); ++ fprintf(out, _(" %s [options] [SIZE|RANGE|BLOCKRANGE]\n"), program_invocation_short_name); ++ ++ fputs(USAGE_SEPARATOR, out); ++ fputs(_("Set a particular size or range of memory online or offline.\n"), out); ++ ++ fputs(USAGE_OPTIONS, out); ++ fputs(_(" -e, --enable enable memory\n"), out); ++ fputs(_(" -d, --disable disable memory\n"), out); ++ fputs(_(" -b, --blocks use memory blocks\n"), out); ++ fputs(_(" -z, --zone select memory zone (see below)\n"), out); ++ fputs(_(" -v, --verbose verbose output\n"), out); ++ printf(USAGE_HELP_OPTIONS(20)); ++ ++ fputs(_("\nSupported zones:\n"), out); ++ for (i = 0; i < ARRAY_SIZE(zone_names); i++) ++ fprintf(out, " %s\n", zone_names[i]); ++ ++ printf(USAGE_MAN_TAIL("chmem(8)")); ++ ++ exit(EXIT_SUCCESS); ++} ++ ++int main(int argc, char **argv) ++{ ++ struct chmem_desc _desc = { }, *desc = &_desc; ++ int cmd = CMD_NONE, zone_id = -1; ++ char *zone = NULL; ++ int c, rc; ++ ++ static const struct option longopts[] = { ++ {"block", no_argument, NULL, 'b'}, ++ {"disable", no_argument, NULL, 'd'}, ++ {"enable", no_argument, NULL, 'e'}, ++ {"help", no_argument, NULL, 'h'}, ++ {"verbose", no_argument, NULL, 'v'}, ++ {"version", no_argument, NULL, 'V'}, ++ {"zone", required_argument, NULL, 'z'}, ++ {NULL, 0, NULL, 0} ++ }; ++ ++ static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ ++ { 'd','e' }, ++ { 0 } ++ }; ++ int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; ++ ++ setlocale(LC_ALL, ""); ++ bindtextdomain(PACKAGE, LOCALEDIR); ++ textdomain(PACKAGE); ++ atexit(close_stdout); ++ ++ read_info(desc); ++ ++ while ((c = getopt_long(argc, argv, "bdehvVz:", longopts, NULL)) != -1) { ++ ++ err_exclusive_options(c, longopts, excl, excl_st); ++ ++ switch (c) { ++ case 'd': ++ cmd = CMD_MEMORY_DISABLE; ++ break; ++ case 'e': ++ cmd = CMD_MEMORY_ENABLE; ++ break; ++ case 'b': ++ desc->use_blocks = 1; ++ break; ++ case 'h': ++ usage(); ++ break; ++ case 'v': ++ desc->verbose = 1; ++ break; ++ case 'V': ++ printf(UTIL_LINUX_VERSION); ++ return EXIT_SUCCESS; ++ case 'z': ++ zone = xstrdup(optarg); ++ break; ++ default: ++ errtryhelp(EXIT_FAILURE); ++ } ++ } ++ ++ if ((argc == 1) || (argc != optind + 1) || (cmd == CMD_NONE)) { ++ warnx(_("bad usage")); ++ errtryhelp(EXIT_FAILURE); ++ } ++ ++ parse_parameter(desc, argv[optind]); ++ ++ /* The valid_zones sysfs attribute was introduced with kernel 3.18 */ ++ if (path_exist(_PATH_SYS_MEMORY "/memory0/valid_zones")) ++ desc->have_zones = 1; ++ else if (zone) ++ warnx(_("zone ignored, no valid_zones sysfs attribute present")); ++ ++ if (zone && desc->have_zones) { ++ zone_id = zone_name_to_id(zone); ++ if (zone_id == -1) { ++ warnx(_("unknown memory zone: %s"), zone); ++ errtryhelp(EXIT_FAILURE); ++ } ++ } ++ ++ if (desc->is_size) ++ rc = chmem_size(desc, cmd == CMD_MEMORY_ENABLE ? 1 : 0, zone_id); ++ else ++ rc = chmem_range(desc, cmd == CMD_MEMORY_ENABLE ? 1 : 0, zone_id); ++ ++ return rc == 0 ? EXIT_SUCCESS : ++ rc < 0 ? EXIT_FAILURE : CHMEM_EXIT_SOMEOK; ++} +diff --git a/sys-utils/lsmem.1 b/sys-utils/lsmem.1 +new file mode 100644 +index 000000000..3f5cd7d4b +--- /dev/null ++++ b/sys-utils/lsmem.1 +@@ -0,0 +1,95 @@ ++.TH LSMEM 1 "October 2016" "util-linux" "User Commands" ++.SH NAME ++lsmem \- list the ranges of available memory with their online status ++.SH SYNOPSIS ++.B lsmem ++[options] ++.SH DESCRIPTION ++The \fBlsmem\fP command lists the ranges of available memory with their online ++status. The listed memory blocks correspond to the memory block representation ++in sysfs. The command also shows the memory block size and the amount of memory ++in online and offline state. ++ ++The default output compatible with original implementation from s390-tools, but ++it's strongly recommended to avoid using default outputs in your scripts. ++Always explicitly define expected columns by using the \fB\-\-output\fR option ++together with a columns list in environments where a stable output is required. ++ ++The \fBlsmem\fP command lists a new memory range always when the current memory ++block distinguish from the previous block by STATE, REMOVABLE, NODE or ZONES ++attribute. This default behavior is possible to override by the ++\fB\-\-split\fR option (e.g. \fBlsmem \-\-split=STATE,ZONES\fR). The special ++word "none" may be used to ignore all differences between memory blocks and to ++create as large as possible continuous ranges. The opposite semantic is ++\fB\-\-all\fR to list individual memory blocks. The default split policy is ++subject to change. Always explicitly use \fB\-\-split\fR in environments where ++a stable output is required. ++ ++Note that some output columns may provide inaccurate information if a split policy ++forces \fBlsmem\fP to ignore diffrences in some attributes. For example if you ++merge removable and non-removable memory blocks to the one range than all ++the range will be marked as non-removable on \fBlsmem\fP output. ++ ++Not all columns are supported on all systems. If an unsupported column is ++specified, \fBlsmem\fP prints the column but does not provide any data for it. ++ ++Use the \fB\-\-help\fR option to see the columns description. ++ ++.SH OPTIONS ++.TP ++.BR \-a ", " \-\-all ++List each individual memory block, instead of combining memory blocks with ++similar attributes. ++.TP ++.BR \-b , " \-\-bytes" ++Print the SIZE column in bytes rather than in a human-readable format. ++.TP ++.BR \-h ", " \-\-help ++Display help text and exit. ++.TP ++.BR \-n , " \-\-noheadings" ++Do not print a header line. ++.TP ++.BR \-o , " \-\-output " \fIlist\fP ++Specify which output columns to print. Use \fB\-\-help\fR ++to get a list of all supported columns. ++The default list of columns may be extended if \fIlist\fP is ++specified in the format \fB+\fIlist\fP (e.g. \fBlsmem \-o +NODE\fP). ++.TP ++.BR \-P , " \-\-pairs" ++Produce output in the form of key="value" pairs. ++All potentially unsafe characters are hex-escaped (\\x). ++.TP ++.BR \-r , " \-\-raw" ++Produce output in raw format. All potentially unsafe characters are hex-escaped ++(\\x). ++.TP ++.BR \-S , " \-\-split " \fIlist\fP ++Specify which columns (attributes) use to split memory blocks to ranges. The ++supported columns are STATE, REMOVABLE, NODE and ZONES, or "none". The another columns are ++silently ignored. For more details see DESCRIPTION above. ++.TP ++.BR \-s , " \-\-sysroot " \fIdirectory\fP ++Gather memory data for a Linux instance other than the instance from which the ++\fBlsmem\fP command is issued. The specified \fIdirectory\fP is the system ++root of the Linux instance to be inspected. ++.TP ++.BR \-V ", " \-\-version ++Display version information and exit. ++.TP ++\fB\-\-summary\fR[=\fIwhen\fR] ++This option controls summary lines output. The optional argument \fIwhen\fP can be ++\fBnever\fR, \fBalways\fR or \fBonly\fR. If the \fIwhen\fR argument is ++omitted, it defaults to \fB"only"\fR. The summary output is suppresed for ++\fB\-\-raw\fR and \fB\-\-pairs\fR. ++.SH AUTHOR ++.B lsmem ++was originally written by Gerald Schaefer for s390-tools in Perl. The C version ++for util-linux was written by Clemens von Mann, Heiko Carstens and Karel Zak. ++.SH SEE ALSO ++.BR chmem (8) ++.SH AVAILABILITY ++The \fBlsmem\fP command is part of the util-linux package and is available from ++.UR https://\:www.kernel.org\:/pub\:/linux\:/utils\:/util-linux/ ++Linux Kernel Archive ++.UE . +diff --git a/sys-utils/lsmem.c b/sys-utils/lsmem.c +new file mode 100644 +index 000000000..34a2847af +--- /dev/null ++++ b/sys-utils/lsmem.c +@@ -0,0 +1,687 @@ ++/* ++ * lsmem - Show memory configuration ++ * ++ * Copyright IBM Corp. 2016 ++ * Copyright (C) 2016 Karel Zak ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it would be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define _PATH_SYS_MEMORY "/sys/devices/system/memory" ++#define _PATH_SYS_MEMORY_BLOCK_SIZE _PATH_SYS_MEMORY "/block_size_bytes" ++ ++#define MEMORY_STATE_ONLINE 0 ++#define MEMORY_STATE_OFFLINE 1 ++#define MEMORY_STATE_GOING_OFFLINE 2 ++#define MEMORY_STATE_UNKNOWN 3 ++ ++enum zone_id { ++ ZONE_DMA = 0, ++ ZONE_DMA32, ++ ZONE_NORMAL, ++ ZONE_HIGHMEM, ++ ZONE_MOVABLE, ++ ZONE_DEVICE, ++ ZONE_NONE, ++ ZONE_UNKNOWN, ++ MAX_NR_ZONES, ++}; ++ ++struct memory_block { ++ uint64_t index; ++ uint64_t count; ++ int state; ++ int node; ++ int nr_zones; ++ int zones[MAX_NR_ZONES]; ++ unsigned int removable:1; ++}; ++ ++struct lsmem { ++ struct dirent **dirs; ++ int ndirs; ++ struct memory_block *blocks; ++ int nblocks; ++ uint64_t block_size; ++ uint64_t mem_online; ++ uint64_t mem_offline; ++ ++ struct libscols_table *table; ++ unsigned int have_nodes : 1, ++ raw : 1, ++ export : 1, ++ noheadings : 1, ++ summary : 1, ++ list_all : 1, ++ bytes : 1, ++ want_summary : 1, ++ want_table : 1, ++ split_by_node : 1, ++ split_by_state : 1, ++ split_by_removable : 1, ++ split_by_zones : 1, ++ have_zones : 1; ++}; ++ ++ ++enum { ++ COL_RANGE, ++ COL_SIZE, ++ COL_STATE, ++ COL_REMOVABLE, ++ COL_BLOCK, ++ COL_NODE, ++ COL_ZONES, ++}; ++ ++static char *zone_names[] = { ++ [ZONE_DMA] = "DMA", ++ [ZONE_DMA32] = "DMA32", ++ [ZONE_NORMAL] = "Normal", ++ [ZONE_HIGHMEM] = "Highmem", ++ [ZONE_MOVABLE] = "Movable", ++ [ZONE_DEVICE] = "Device", ++ [ZONE_NONE] = "None", /* block contains more than one zone, can't be offlined */ ++ [ZONE_UNKNOWN] = "Unknown", ++}; ++ ++/* column names */ ++struct coldesc { ++ const char *name; /* header */ ++ double whint; /* width hint (N < 1 is in percent of termwidth) */ ++ int flags; /* SCOLS_FL_* */ ++ const char *help; ++ ++ int sort_type; /* SORT_* */ ++}; ++ ++/* columns descriptions */ ++static struct coldesc coldescs[] = { ++ [COL_RANGE] = { "RANGE", 0, 0, N_("start and end address of the memory range")}, ++ [COL_SIZE] = { "SIZE", 5, SCOLS_FL_RIGHT, N_("size of the memory range")}, ++ [COL_STATE] = { "STATE", 0, SCOLS_FL_RIGHT, N_("online status of the memory range")}, ++ [COL_REMOVABLE] = { "REMOVABLE", 0, SCOLS_FL_RIGHT, N_("memory is removable")}, ++ [COL_BLOCK] = { "BLOCK", 0, SCOLS_FL_RIGHT, N_("memory block number or blocks range")}, ++ [COL_NODE] = { "NODE", 0, SCOLS_FL_RIGHT, N_("numa node of memory")}, ++ [COL_ZONES] = { "ZONES", 0, SCOLS_FL_RIGHT, N_("valid zones for the memory range")}, ++}; ++ ++/* columns[] array specifies all currently wanted output column. The columns ++ * are defined by coldescs[] array and you can specify (on command line) each ++ * column twice. That's enough, dynamically allocated array of the columns is ++ * unnecessary overkill and over-engineering in this case */ ++static int columns[ARRAY_SIZE(coldescs) * 2]; ++static size_t ncolumns; ++ ++static inline size_t err_columns_index(size_t arysz, size_t idx) ++{ ++ if (idx >= arysz) ++ errx(EXIT_FAILURE, _("too many columns specified, " ++ "the limit is %zu columns"), ++ arysz - 1); ++ return idx; ++} ++ ++/* ++ * name must be null-terminated ++ */ ++static int zone_name_to_id(const char *name) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(zone_names); i++) { ++ if (!strcasecmp(name, zone_names[i])) ++ return i; ++ } ++ return ZONE_UNKNOWN; ++} ++ ++#define add_column(ary, n, id) \ ++ ((ary)[ err_columns_index(ARRAY_SIZE(ary), (n)) ] = (id)) ++ ++static int column_name_to_id(const char *name, size_t namesz) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(coldescs); i++) { ++ const char *cn = coldescs[i].name; ++ ++ if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) ++ return i; ++ } ++ warnx(_("unknown column: %s"), name); ++ return -1; ++} ++ ++static inline int get_column_id(int num) ++{ ++ assert(num >= 0); ++ assert((size_t) num < ncolumns); ++ assert(columns[num] < (int) ARRAY_SIZE(coldescs)); ++ ++ return columns[num]; ++} ++ ++static inline struct coldesc *get_column_desc(int num) ++{ ++ return &coldescs[ get_column_id(num) ]; ++} ++ ++static inline void reset_split_policy(struct lsmem *l, int enable) ++{ ++ l->split_by_state = enable; ++ l->split_by_node = enable; ++ l->split_by_removable = enable; ++ l->split_by_zones = enable; ++} ++ ++static void add_scols_line(struct lsmem *lsmem, struct memory_block *blk) ++{ ++ size_t i; ++ struct libscols_line *line; ++ ++ line = scols_table_new_line(lsmem->table, NULL); ++ if (!line) ++ err_oom(); ++ ++ for (i = 0; i < ncolumns; i++) { ++ char *str = NULL; ++ ++ switch (get_column_id(i)) { ++ case COL_RANGE: ++ { ++ uint64_t start = blk->index * lsmem->block_size; ++ uint64_t size = blk->count * lsmem->block_size; ++ xasprintf(&str, "0x%016"PRIx64"-0x%016"PRIx64, start, start + size - 1); ++ break; ++ } ++ case COL_SIZE: ++ if (lsmem->bytes) ++ xasprintf(&str, "%"PRId64, (uint64_t) blk->count * lsmem->block_size); ++ else ++ str = size_to_human_string(SIZE_SUFFIX_1LETTER, ++ (uint64_t) blk->count * lsmem->block_size); ++ break; ++ case COL_STATE: ++ str = xstrdup( ++ blk->state == MEMORY_STATE_ONLINE ? _("online") : ++ blk->state == MEMORY_STATE_OFFLINE ? _("offline") : ++ blk->state == MEMORY_STATE_GOING_OFFLINE ? _("on->off") : ++ "?"); ++ break; ++ case COL_REMOVABLE: ++ if (blk->state == MEMORY_STATE_ONLINE) ++ str = xstrdup(blk->removable ? _("yes") : _("no")); ++ else ++ str = xstrdup("-"); ++ break; ++ case COL_BLOCK: ++ if (blk->count == 1) ++ xasprintf(&str, "%"PRId64, blk->index); ++ else ++ xasprintf(&str, "%"PRId64"-%"PRId64, ++ blk->index, blk->index + blk->count - 1); ++ break; ++ case COL_NODE: ++ if (lsmem->have_nodes) ++ xasprintf(&str, "%d", blk->node); ++ else ++ str = xstrdup("-"); ++ break; ++ case COL_ZONES: ++ if (lsmem->have_zones) { ++ char valid_zones[BUFSIZ]; ++ int j, zone_id; ++ ++ valid_zones[0] = '\0'; ++ for (j = 0; j < blk->nr_zones; j++) { ++ zone_id = blk->zones[j]; ++ if (strlen(valid_zones) + ++ strlen(zone_names[zone_id]) > BUFSIZ - 2) ++ break; ++ strcat(valid_zones, zone_names[zone_id]); ++ if (j + 1 < blk->nr_zones) ++ strcat(valid_zones, "/"); ++ } ++ str = xstrdup(valid_zones); ++ } else ++ str = xstrdup("-"); ++ break; ++ } ++ ++ if (str && scols_line_refer_data(line, i, str) != 0) ++ err_oom(); ++ } ++} ++ ++static void fill_scols_table(struct lsmem *lsmem) ++{ ++ int i; ++ ++ for (i = 0; i < lsmem->nblocks; i++) ++ add_scols_line(lsmem, &lsmem->blocks[i]); ++} ++ ++static void print_summary(struct lsmem *lsmem) ++{ ++ if (lsmem->bytes) { ++ printf("%-23s %15"PRId64"\n",_("Memory block size:"), lsmem->block_size); ++ printf("%-23s %15"PRId64"\n",_("Total online memory:"), lsmem->mem_online); ++ printf("%-23s %15"PRId64"\n",_("Total offline memory:"), lsmem->mem_offline); ++ } else { ++ printf("%-23s %5s\n",_("Memory block size:"), ++ size_to_human_string(SIZE_SUFFIX_1LETTER, lsmem->block_size)); ++ printf("%-23s %5s\n",_("Total online memory:"), ++ size_to_human_string(SIZE_SUFFIX_1LETTER, lsmem->mem_online)); ++ printf("%-23s %5s\n",_("Total offline memory:"), ++ size_to_human_string(SIZE_SUFFIX_1LETTER, lsmem->mem_offline)); ++ } ++} ++ ++static int memory_block_get_node(char *name) ++{ ++ struct dirent *de; ++ const char *path; ++ DIR *dir; ++ int node; ++ ++ path = path_get(_PATH_SYS_MEMORY"/%s", name); ++ if (!path || !(dir= opendir(path))) ++ err(EXIT_FAILURE, _("Failed to open %s"), path ? path : name); ++ ++ node = -1; ++ while ((de = readdir(dir)) != NULL) { ++ if (strncmp("node", de->d_name, 4)) ++ continue; ++ if (!isdigit_string(de->d_name + 4)) ++ continue; ++ node = strtol(de->d_name + 4, NULL, 10); ++ break; ++ } ++ closedir(dir); ++ return node; ++} ++ ++static void memory_block_read_attrs(struct lsmem *lsmem, char *name, ++ struct memory_block *blk) ++{ ++ char *token = NULL; ++ char line[BUFSIZ]; ++ int i; ++ ++ blk->count = 1; ++ blk->index = strtoumax(name + 6, NULL, 10); /* get of "memory" */ ++ blk->removable = path_read_u64(_PATH_SYS_MEMORY"/%s/removable", name); ++ blk->state = MEMORY_STATE_UNKNOWN; ++ ++ path_read_str(line, sizeof(line), _PATH_SYS_MEMORY"/%s/state", name); ++ if (strcmp(line, "offline") == 0) ++ blk->state = MEMORY_STATE_OFFLINE; ++ else if (strcmp(line, "online") == 0) ++ blk->state = MEMORY_STATE_ONLINE; ++ else if (strcmp(line, "going-offline") == 0) ++ blk->state = MEMORY_STATE_GOING_OFFLINE; ++ ++ if (lsmem->have_nodes) ++ blk->node = memory_block_get_node(name); ++ ++ blk->nr_zones = 0; ++ if (lsmem->have_zones) { ++ path_read_str(line, sizeof(line), _PATH_SYS_MEMORY"/%s/valid_zones", name); ++ token = strtok(line, " "); ++ } ++ for (i = 0; i < MAX_NR_ZONES; i++) { ++ if (token) { ++ blk->zones[i] = zone_name_to_id(token); ++ blk->nr_zones++; ++ token = strtok(NULL, " "); ++ } ++ } ++} ++ ++static int is_mergeable(struct lsmem *lsmem, struct memory_block *blk) ++{ ++ struct memory_block *curr; ++ int i; ++ ++ if (!lsmem->nblocks) ++ return 0; ++ curr = &lsmem->blocks[lsmem->nblocks - 1]; ++ if (lsmem->list_all) ++ return 0; ++ if (curr->index + curr->count != blk->index) ++ return 0; ++ if (lsmem->split_by_state && curr->state != blk->state) ++ return 0; ++ if (lsmem->split_by_removable && curr->removable != blk->removable) ++ return 0; ++ if (lsmem->split_by_node && lsmem->have_nodes) { ++ if (curr->node != blk->node) ++ return 0; ++ } ++ if (lsmem->split_by_zones && lsmem->have_zones) { ++ if (curr->nr_zones != blk->nr_zones) ++ return 0; ++ for (i = 0; i < curr->nr_zones; i++) { ++ if (curr->zones[i] == ZONE_UNKNOWN || ++ curr->zones[i] != blk->zones[i]) ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++static void read_info(struct lsmem *lsmem) ++{ ++ struct memory_block blk; ++ char line[BUFSIZ]; ++ int i; ++ ++ path_read_str(line, sizeof(line), _PATH_SYS_MEMORY_BLOCK_SIZE); ++ lsmem->block_size = strtoumax(line, NULL, 16); ++ ++ for (i = 0; i < lsmem->ndirs; i++) { ++ memory_block_read_attrs(lsmem, lsmem->dirs[i]->d_name, &blk); ++ if (is_mergeable(lsmem, &blk)) { ++ lsmem->blocks[lsmem->nblocks - 1].count++; ++ continue; ++ } ++ lsmem->nblocks++; ++ lsmem->blocks = xrealloc(lsmem->blocks, lsmem->nblocks * sizeof(blk)); ++ *&lsmem->blocks[lsmem->nblocks - 1] = blk; ++ } ++ for (i = 0; i < lsmem->nblocks; i++) { ++ if (lsmem->blocks[i].state == MEMORY_STATE_ONLINE) ++ lsmem->mem_online += lsmem->block_size * lsmem->blocks[i].count; ++ else ++ lsmem->mem_offline += lsmem->block_size * lsmem->blocks[i].count; ++ } ++} ++ ++static int memory_block_filter(const struct dirent *de) ++{ ++ if (strncmp("memory", de->d_name, 6)) ++ return 0; ++ return isdigit_string(de->d_name + 6); ++} ++ ++static void read_basic_info(struct lsmem *lsmem) ++{ ++ const char *dir; ++ ++ if (!path_exist(_PATH_SYS_MEMORY_BLOCK_SIZE)) ++ errx(EXIT_FAILURE, _("This system does not support memory blocks")); ++ ++ dir = path_get(_PATH_SYS_MEMORY); ++ if (!dir) ++ err(EXIT_FAILURE, _("Failed to read %s"), _PATH_SYS_MEMORY); ++ ++ lsmem->ndirs = scandir(dir, &lsmem->dirs, memory_block_filter, versionsort); ++ if (lsmem->ndirs <= 0) ++ err(EXIT_FAILURE, _("Failed to read %s"), _PATH_SYS_MEMORY); ++ ++ if (memory_block_get_node(lsmem->dirs[0]->d_name) != -1) ++ lsmem->have_nodes = 1; ++ ++ /* The valid_zones sysfs attribute was introduced with kernel 3.18 */ ++ if (path_exist(_PATH_SYS_MEMORY "/memory0/valid_zones")) ++ lsmem->have_zones = 1; ++} ++ ++static void __attribute__((__noreturn__)) usage(void) ++{ ++ FILE *out = stdout; ++ size_t i; ++ ++ fputs(USAGE_HEADER, out); ++ fprintf(out, _(" %s [options]\n"), program_invocation_short_name); ++ ++ fputs(USAGE_SEPARATOR, out); ++ fputs(_("List the ranges of available memory with their online status.\n"), out); ++ ++ fputs(USAGE_OPTIONS, out); ++ fputs(_(" -P, --pairs use key=\"value\" output format\n"), out); ++ fputs(_(" -a, --all list each individual memory block\n"), out); ++ fputs(_(" -b, --bytes print SIZE in bytes rather than in human readable format\n"), out); ++ fputs(_(" -n, --noheadings don't print headings\n"), out); ++ fputs(_(" -o, --output output columns\n"), out); ++ fputs(_(" -r, --raw use raw output format\n"), out); ++ fputs(_(" -S, --split split ranges by specified columns\n"), out); ++ fputs(_(" -s, --sysroot use the specified directory as system root\n"), out); ++ fputs(_(" --summary[=when] print summary information (never,always or only)\n"), out); ++ ++ fputs(USAGE_SEPARATOR, out); ++ printf(USAGE_HELP_OPTIONS(22)); ++ ++ fputs(USAGE_COLUMNS, out); ++ for (i = 0; i < ARRAY_SIZE(coldescs); i++) ++ fprintf(out, " %10s %s\n", coldescs[i].name, _(coldescs[i].help)); ++ ++ printf(USAGE_MAN_TAIL("lsmem(1)")); ++ ++ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); ++} ++ ++int main(int argc, char **argv) ++{ ++ struct lsmem _lsmem = { ++ .want_table = 1, ++ .want_summary = 1 ++ }, *lsmem = &_lsmem; ++ ++ const char *outarg = NULL, *splitarg = NULL; ++ int c; ++ size_t i; ++ ++ enum { ++ LSMEM_OPT_SUMARRY = CHAR_MAX + 1 ++ }; ++ ++ static const struct option longopts[] = { ++ {"all", no_argument, NULL, 'a'}, ++ {"bytes", no_argument, NULL, 'b'}, ++ {"help", no_argument, NULL, 'h'}, ++ {"noheadings", no_argument, NULL, 'n'}, ++ {"output", required_argument, NULL, 'o'}, ++ {"pairs", no_argument, NULL, 'P'}, ++ {"raw", no_argument, NULL, 'r'}, ++ {"sysroot", required_argument, NULL, 's'}, ++ {"split", required_argument, NULL, 'S'}, ++ {"version", no_argument, NULL, 'V'}, ++ {"summary", optional_argument, NULL, LSMEM_OPT_SUMARRY }, ++ {NULL, 0, NULL, 0} ++ }; ++ static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ ++ { 'J', 'P', 'r' }, ++ { 'S', 'a' }, ++ { 0 } ++ }; ++ int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; ++ ++ setlocale(LC_ALL, ""); ++ bindtextdomain(PACKAGE, LOCALEDIR); ++ textdomain(PACKAGE); ++ atexit(close_stdout); ++ ++ while ((c = getopt_long(argc, argv, "abhJno:PrS:s:V", longopts, NULL)) != -1) { ++ ++ err_exclusive_options(c, longopts, excl, excl_st); ++ ++ switch (c) { ++ case 'a': ++ lsmem->list_all = 1; ++ break; ++ case 'b': ++ lsmem->bytes = 1; ++ break; ++ case 'h': ++ usage(); ++ break; ++ case 'n': ++ lsmem->noheadings = 1; ++ break; ++ case 'o': ++ outarg = optarg; ++ break; ++ case 'P': ++ lsmem->export = 1; ++ lsmem->want_summary = 0; ++ break; ++ case 'r': ++ lsmem->raw = 1; ++ lsmem->want_summary = 0; ++ break; ++ case 's': ++ if(path_set_prefix(optarg)) ++ err(EXIT_FAILURE, _("invalid argument to %s"), "--sysroot"); ++ break; ++ case 'S': ++ splitarg = optarg; ++ break; ++ case 'V': ++ printf(UTIL_LINUX_VERSION); ++ return 0; ++ case LSMEM_OPT_SUMARRY: ++ if (optarg) { ++ if (strcmp(optarg, "never") == 0) ++ lsmem->want_summary = 0; ++ else if (strcmp(optarg, "only") == 0) ++ lsmem->want_table = 0; ++ else if (strcmp(optarg, "always") == 0) ++ lsmem->want_summary = 1; ++ else ++ errx(EXIT_FAILURE, _("unsupported --summary argument")); ++ } else ++ lsmem->want_table = 0; ++ break; ++ default: ++ errtryhelp(EXIT_FAILURE); ++ } ++ } ++ ++ if (argc != optind) { ++ warnx(_("bad usage")); ++ errtryhelp(EXIT_FAILURE); ++ } ++ ++ if (lsmem->want_table + lsmem->want_summary == 0) ++ errx(EXIT_FAILURE, _("options --{raw,pairs} and --summary=only are mutually exclusive")); ++ ++ /* Shortcut to avoid scols machinery on --summary=only */ ++ if (lsmem->want_table == 0 && lsmem->want_summary) { ++ read_basic_info(lsmem); ++ read_info(lsmem); ++ print_summary(lsmem); ++ return EXIT_SUCCESS; ++ } ++ ++ /* ++ * Default columns ++ */ ++ if (!ncolumns) { ++ add_column(columns, ncolumns++, COL_RANGE); ++ add_column(columns, ncolumns++, COL_SIZE); ++ add_column(columns, ncolumns++, COL_STATE); ++ add_column(columns, ncolumns++, COL_REMOVABLE); ++ add_column(columns, ncolumns++, COL_BLOCK); ++ } ++ ++ if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns), ++ (int *) &ncolumns, column_name_to_id) < 0) ++ return EXIT_FAILURE; ++ ++ /* ++ * Initialize output ++ */ ++ scols_init_debug(0); ++ ++ if (!(lsmem->table = scols_new_table())) ++ errx(EXIT_FAILURE, _("failed to initialize output table")); ++ scols_table_enable_raw(lsmem->table, lsmem->raw); ++ scols_table_enable_export(lsmem->table, lsmem->export); ++ scols_table_enable_noheadings(lsmem->table, lsmem->noheadings); ++ ++ for (i = 0; i < ncolumns; i++) { ++ struct coldesc *ci = get_column_desc(i); ++ if (!scols_table_new_column(lsmem->table, ci->name, ci->whint, ci->flags)) ++ err(EXIT_FAILURE, _("Failed to initialize output column")); ++ } ++ ++ if (splitarg) { ++ int split[ARRAY_SIZE(coldescs)] = { 0 }; ++ static size_t nsplits = 0; ++ ++ reset_split_policy(lsmem, 0); /* disable all */ ++ ++ if (strcasecmp(splitarg, "none") == 0) ++ ; ++ else if (string_add_to_idarray(splitarg, split, ARRAY_SIZE(split), ++ (int *) &nsplits, column_name_to_id) < 0) ++ return EXIT_FAILURE; ++ ++ for (i = 0; i < nsplits; i++) { ++ switch (split[i]) { ++ case COL_STATE: ++ lsmem->split_by_state = 1; ++ break; ++ case COL_NODE: ++ lsmem->split_by_node = 1; ++ break; ++ case COL_REMOVABLE: ++ lsmem->split_by_removable = 1; ++ break; ++ case COL_ZONES: ++ lsmem->split_by_zones = 1; ++ break; ++ } ++ } ++ } else ++ reset_split_policy(lsmem, 1); /* enable all */ ++ ++ /* ++ * Read data and print output ++ */ ++ read_basic_info(lsmem); ++ read_info(lsmem); ++ ++ if (lsmem->want_table) { ++ fill_scols_table(lsmem); ++ scols_print_table(lsmem->table); ++ ++ if (lsmem->want_summary) ++ fputc('\n', stdout); ++ } ++ ++ if (lsmem->want_summary) ++ print_summary(lsmem); ++ ++ scols_unref_table(lsmem->table); ++ return 0; ++} +-- +2.13.6 + diff --git a/SOURCES/0143-lsmem-make-split-optional-follow-output-by-default.patch b/SOURCES/0143-lsmem-make-split-optional-follow-output-by-default.patch new file mode 100644 index 0000000..ec94d77 --- /dev/null +++ b/SOURCES/0143-lsmem-make-split-optional-follow-output-by-default.patch @@ -0,0 +1,119 @@ +From 66d819dc82080e9dba609b3bfff45c14d7c3ba3c Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Fri, 3 Nov 2017 10:58:33 +0100 +Subject: [PATCH] lsmem: make --split optional, follow output by default + +Let's keep lsmem backwardly compatible (<=v2.30) and create ranges +according to the output columns by default. This default behavior may +be modified by --split command line option. + +Upstream: http://github.com/karelzak/util-linux/commit/96cbe362c034305e5f12a912b4247b3321420ee7 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1496421 +Signed-off-by: Karel Zak +--- + sys-utils/lsmem.1 | 14 ++++++-------- + sys-utils/lsmem.c | 49 ++++++++++++++++++++++++++++++------------------- + 2 files changed, 36 insertions(+), 27 deletions(-) + +diff --git a/sys-utils/lsmem.1 b/sys-utils/lsmem.1 +index 3f5cd7d4b..bfe312bfc 100644 +--- a/sys-utils/lsmem.1 ++++ b/sys-utils/lsmem.1 +@@ -16,14 +16,12 @@ Always explicitly define expected columns by using the \fB\-\-output\fR option + together with a columns list in environments where a stable output is required. + + The \fBlsmem\fP command lists a new memory range always when the current memory +-block distinguish from the previous block by STATE, REMOVABLE, NODE or ZONES +-attribute. This default behavior is possible to override by the +-\fB\-\-split\fR option (e.g. \fBlsmem \-\-split=STATE,ZONES\fR). The special +-word "none" may be used to ignore all differences between memory blocks and to +-create as large as possible continuous ranges. The opposite semantic is +-\fB\-\-all\fR to list individual memory blocks. The default split policy is +-subject to change. Always explicitly use \fB\-\-split\fR in environments where +-a stable output is required. ++block distinguish from the previous block by some output column. This default ++behavior is possible to override by the \fB\-\-split\fR option (e.g. \fBlsmem ++\-\-split=ZONES\fR). The special word "none" may be used to ignore all ++differences between memory blocks and to create as large as possible continuous ++ranges. The opposite semantic is \fB\-\-all\fR to list individual memory ++blocks. + + Note that some output columns may provide inaccurate information if a split policy + forces \fBlsmem\fP to ignore diffrences in some attributes. For example if you +diff --git a/sys-utils/lsmem.c b/sys-utils/lsmem.c +index 34a2847af..aaf7374fc 100644 +--- a/sys-utils/lsmem.c ++++ b/sys-utils/lsmem.c +@@ -202,6 +202,32 @@ static inline void reset_split_policy(struct lsmem *l, int enable) + l->split_by_zones = enable; + } + ++static void set_split_policy(struct lsmem *l, int cols[], size_t ncols) ++{ ++ size_t i; ++ ++ reset_split_policy(l, 0); ++ ++ for (i = 0; i < ncols; i++) { ++ switch (cols[i]) { ++ case COL_STATE: ++ l->split_by_state = 1; ++ break; ++ case COL_NODE: ++ l->split_by_node = 1; ++ break; ++ case COL_REMOVABLE: ++ l->split_by_removable = 1; ++ break; ++ case COL_ZONES: ++ l->split_by_zones = 1; ++ break; ++ default: ++ break; ++ } ++ } ++} ++ + static void add_scols_line(struct lsmem *lsmem, struct memory_block *blk) + { + size_t i; +@@ -638,32 +664,17 @@ int main(int argc, char **argv) + int split[ARRAY_SIZE(coldescs)] = { 0 }; + static size_t nsplits = 0; + +- reset_split_policy(lsmem, 0); /* disable all */ +- + if (strcasecmp(splitarg, "none") == 0) + ; + else if (string_add_to_idarray(splitarg, split, ARRAY_SIZE(split), + (int *) &nsplits, column_name_to_id) < 0) + return EXIT_FAILURE; + +- for (i = 0; i < nsplits; i++) { +- switch (split[i]) { +- case COL_STATE: +- lsmem->split_by_state = 1; +- break; +- case COL_NODE: +- lsmem->split_by_node = 1; +- break; +- case COL_REMOVABLE: +- lsmem->split_by_removable = 1; +- break; +- case COL_ZONES: +- lsmem->split_by_zones = 1; +- break; +- } +- } ++ set_split_policy(lsmem, split, nsplits); ++ + } else +- reset_split_policy(lsmem, 1); /* enable all */ ++ /* follow output columns */ ++ set_split_policy(lsmem, columns, ncolumns); + + /* + * Read data and print output +-- +2.13.6 + diff --git a/SOURCES/0144-libmount-fix-access-utab-write-test.patch b/SOURCES/0144-libmount-fix-access-utab-write-test.patch new file mode 100644 index 0000000..50dccbd --- /dev/null +++ b/SOURCES/0144-libmount-fix-access-utab-write-test.patch @@ -0,0 +1,226 @@ +From 5d238002ff22241a7d04608102a2182aa74d2b69 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Wed, 8 Nov 2017 16:47:40 +0100 +Subject: [PATCH] libmount: fix access() utab write test + +The commit c08396c7691e1e6a04b6b45892e7e4612ceed8d7 replaces +open(O_CREATE) with ecaccess(). Unfortunately, another code depends on +the original behavior. + +* let's make utab when really necessary rather than in the try_write() test + +* __mnt_new_table_from_file() returns NULL if tab-file does not + exists. This is incorrect for tab_update.c stuff. We need empty table + in this case. + +* we can check /run/mount/ directory for write access if + eaccess(filename) return ENOENT (because file does not exist) + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1499760 +Upstream: http://github.com/karelzak/util-linux/commit/06ff935ec3ad2290025b555ff32b590680af565f +Signed-off-by: Karel Zak +--- + libmount/src/mountP.h | 2 +- + libmount/src/tab_parse.c | 11 +++++++---- + libmount/src/tab_update.c | 9 +++++---- + libmount/src/utils.c | 42 +++++++++++++++++++++++++++++++----------- + 4 files changed, 44 insertions(+), 20 deletions(-) + +diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h +index 6cabcedeb..8b3f92e17 100644 +--- a/libmount/src/mountP.h ++++ b/libmount/src/mountP.h +@@ -278,7 +278,7 @@ struct libmnt_table { + struct list_head ents; /* list of entries (libmnt_fs) */ + }; + +-extern struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt); ++extern struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt, int empty_for_enoent); + + /* + * Tab file format +diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c +index 987e671fa..c629c67ad 100644 +--- a/libmount/src/tab_parse.c ++++ b/libmount/src/tab_parse.c +@@ -714,7 +714,7 @@ int mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) + return __mnt_table_parse_dir(tb, dirname); + } + +-struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) ++struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt, int empty_for_enoent) + { + struct libmnt_table *tb; + struct stat st; +@@ -723,7 +723,8 @@ struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) + if (!filename) + return NULL; + if (stat(filename, &st)) +- return NULL; ++ return empty_for_enoent ? mnt_new_table() : NULL; ++ + tb = mnt_new_table(); + if (tb) { + tb->fmt = fmt; +@@ -748,8 +749,10 @@ struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) + */ + struct libmnt_table *mnt_new_table_from_file(const char *filename) + { +- assert(filename); +- return __mnt_new_table_from_file(filename, MNT_FMT_GUESS); ++ if (!filename) ++ return NULL; ++ ++ return __mnt_new_table_from_file(filename, MNT_FMT_GUESS, 0); + } + + /** +diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c +index 1e7f32be0..5f503cad7 100644 +--- a/libmount/src/tab_update.c ++++ b/libmount/src/tab_update.c +@@ -567,6 +567,7 @@ leave: + + unlink(uq); /* be paranoid */ + free(uq); ++ DBG(UPDATE, mnt_debug_h(upd, "%s: done [rc=%d]", upd->filename, rc)); + return rc; + } + +@@ -600,7 +601,7 @@ static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc) + return rc; + + tb = __mnt_new_table_from_file(upd->filename, +- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); ++ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); + if (tb) + rc = add_file_entry(tb, upd); + if (lc) +@@ -626,7 +627,7 @@ static int update_remove_entry(struct libmnt_update *upd, struct libmnt_lock *lc + return rc; + + tb = __mnt_new_table_from_file(upd->filename, +- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); ++ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); + if (tb) { + struct libmnt_fs *rem = mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD); + if (rem) { +@@ -656,7 +657,7 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l + return rc; + + tb = __mnt_new_table_from_file(upd->filename, +- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); ++ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); + if (tb) { + struct libmnt_fs *cur = mnt_table_find_target(tb, + mnt_fs_get_srcpath(upd->fs), MNT_ITER_BACKWARD); +@@ -693,7 +694,7 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock * + return rc; + + tb = __mnt_new_table_from_file(upd->filename, +- upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); ++ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); + if (tb) { + struct libmnt_fs *cur = mnt_table_find_target(tb, + mnt_fs_get_target(fs), +diff --git a/libmount/src/utils.c b/libmount/src/utils.c +index a275d0a0e..fa33bd9a1 100644 +--- a/libmount/src/utils.c ++++ b/libmount/src/utils.c +@@ -651,18 +651,37 @@ done: + return rc; + } + +-static int try_write(const char *filename) ++static int try_write(const char *filename, const char *directory) + { + int rc = 0; + + if (!filename) + return -EINVAL; + ++ DBG(UTILS, mnt_debug("try write %s dir: %s", filename, directory)); ++ + #ifdef HAVE_EACCESS +- if (eaccess(filename, R_OK|W_OK) != 0) +- rc = -errno; +-#else ++ /* Try eaccess() first, because open() is overkill, may be monitored by ++ * audit and we don't want to fill logs by our checks... ++ */ ++ if (eaccess(filename, R_OK|W_OK) == 0) { ++ DBG(UTILS, mnt_debug(" access OK")); ++ return 0; ++ } else if (errno != ENOENT) { ++ DBG(UTILS, mnt_debug(" access FAILED")); ++ return -errno; ++ } else if (directory) { ++ /* file does not exist; try if directory is writable */ ++ if (eaccess(directory, R_OK|W_OK) != 0) ++ rc = -errno; ++ ++ DBG(UTILS, mnt_debug(" access %s [%s]", rc ? "FAILED" : "OK", directory)); ++ return rc; ++ } else ++#endif + { ++ DBG(UTILS, mnt_debug(" doing open-write test")); ++ + int fd = open(filename, O_RDWR|O_CREAT|O_CLOEXEC, + S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); + if (fd < 0) +@@ -670,7 +689,6 @@ static int try_write(const char *filename) + else + close(fd); + } +-#endif + return rc; + } + +@@ -704,7 +722,7 @@ int mnt_has_regular_mtab(const char **mtab, int *writable) + /* file exist */ + if (S_ISREG(st.st_mode)) { + if (writable) +- *writable = !try_write(filename); ++ *writable = !try_write(filename, NULL); + return 1; + } + goto done; +@@ -712,7 +730,7 @@ int mnt_has_regular_mtab(const char **mtab, int *writable) + + /* try to create the file */ + if (writable) { +- *writable = !try_write(filename); ++ *writable = !try_write(filename, NULL); + if (*writable) + return 1; + } +@@ -750,7 +768,7 @@ int mnt_has_regular_utab(const char **utab, int *writable) + /* file exist */ + if (S_ISREG(st.st_mode)) { + if (writable) +- *writable = !try_write(filename); ++ *writable = !try_write(filename, NULL); + return 1; + } + goto done; /* it's not regular file */ +@@ -767,11 +785,13 @@ int mnt_has_regular_utab(const char **utab, int *writable) + rc = mkdir(dirname, S_IWUSR| + S_IRUSR|S_IRGRP|S_IROTH| + S_IXUSR|S_IXGRP|S_IXOTH); +- free(dirname); +- if (rc && errno != EEXIST) ++ if (rc && errno != EEXIST) { ++ free(dirname); + goto done; /* probably EACCES */ ++ } + +- *writable = !try_write(filename); ++ *writable = !try_write(filename, dirname); ++ free(dirname); + if (*writable) + return 1; + } +-- +2.13.6 + diff --git a/SOURCES/0145-login-add-LOGIN_PLAIN_PROMPT-to-login.defs.patch b/SOURCES/0145-login-add-LOGIN_PLAIN_PROMPT-to-login.defs.patch new file mode 100644 index 0000000..58c0242 --- /dev/null +++ b/SOURCES/0145-login-add-LOGIN_PLAIN_PROMPT-to-login.defs.patch @@ -0,0 +1,86 @@ +From a8427f41c91ac12f0b208fe7eaf4e535b8a56464 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 4 Dec 2017 12:31:29 +0100 +Subject: [PATCH 145/146] login: add LOGIN_PLAIN_PROMPT to login.defs + +We have command line option -H to disable hostname in login prompt. +Unfortunately, in same cases (e.g. telnetd) it's impossible to specify +login(1) command line options due to hardcoded execl()... + +This patch introduces LOGIN_PLAIN_PROMPT boolean for /etc/login.defs +to suppress hostname in the prompt. + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1520906 +Upstream: http://github.com/karelzak/util-linux/commit/e6b32e7d1adf2a0c09743d71dfdbe2742c5884ac +Signed-off-by: Karel Zak +--- + login-utils/login.1 | 12 ++++++++++++ + login-utils/login.c | 12 +++++++++--- + 2 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/login-utils/login.1 b/login-utils/login.1 +index 216645ebe..ec636fd74 100644 +--- a/login-utils/login.1 ++++ b/login-utils/login.1 +@@ -130,6 +130,9 @@ Used by other servers (i.e., + to tell + .B login + that printing the hostname should be suppressed in the login: prompt. ++See also LOGIN_PLAIN_PROMPT below if your server does not allow to configure ++.B login ++command line. + .TP + .B \-V + Print version and exit. +@@ -157,6 +160,15 @@ by + PAM module. + .RE + .PP ++.B LOGIN_PLAIN_PROMPT ++(boolean) ++.RS 4 ++Tell login that printing the hostname should be suppressed in the login: ++prompt. This is alternative to the \fB\-H\fR command line option. The default ++value is ++.IR no . ++.RE ++.PP + .B LOGIN_TIMEOUT + (number) + .RS 4 +diff --git a/login-utils/login.c b/login-utils/login.c +index 5c36953ef..eee3f7bd1 100644 +--- a/login-utils/login.c ++++ b/login-utils/login.c +@@ -709,7 +709,8 @@ static void loginpam_err(pam_handle_t *pamh, int retcode) + } + + /* +- * Composes " login: " string; or returns "login: " is -H is given ++ * Composes " login: " string; or returns "login: " if -H is given or ++ * LOGIN_PLAIN_PROMPT=yes configured. + */ + static const char *loginpam_get_prompt(struct login_context *cxt) + { +@@ -717,11 +718,16 @@ static const char *loginpam_get_prompt(struct login_context *cxt) + char *prompt, *dflt_prompt = _("login: "); + size_t sz; + +- if (cxt->nohost || !(host = get_thishost(cxt, NULL))) ++ if (cxt->nohost) ++ return dflt_prompt; /* -H on command line */ ++ ++ if (getlogindefs_bool("LOGIN_PLAIN_PROMPT", 0) == 1) + return dflt_prompt; + +- sz = strlen(host) + 1 + strlen(dflt_prompt) + 1; ++ if (!(host = get_thishost(cxt, NULL))) ++ return dflt_prompt; + ++ sz = strlen(host) + 1 + strlen(dflt_prompt) + 1; + prompt = xmalloc(sz); + snprintf(prompt, sz, "%s %s", host, dflt_prompt); + +-- +2.13.6 + diff --git a/SOURCES/0146-libblkid-Add-VDO-superblock-information-into-blkid.patch b/SOURCES/0146-libblkid-Add-VDO-superblock-information-into-blkid.patch new file mode 100644 index 0000000..22ee16c --- /dev/null +++ b/SOURCES/0146-libblkid-Add-VDO-superblock-information-into-blkid.patch @@ -0,0 +1,114 @@ +From e8c8b5f97c864f0fd65378ccde0c45526e6916c9 Mon Sep 17 00:00:00 2001 +From: Sweet Tea Dorminy +Date: Wed, 6 Dec 2017 18:26:59 -0500 +Subject: [PATCH 146/146] libblkid: Add VDO superblock information into blkid + +[kzak@redhat.com: - add tests/expected/blkid/low-probe-vdo + - enlarge the image (must be > 1024)] + +[RHEL7: exclude vdo regression test doe to binary stuff in the patch] + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1521163 +Upstream: http://github.com/karelzak/util-linux/commit/6418cba457a701d44294d934c2bc4b766bbcfa2b +Signed-off-by: Karel Zak +--- + libblkid/src/Makemodule.am | 1 + + libblkid/src/superblocks/superblocks.c | 1 + + libblkid/src/superblocks/superblocks.h | 1 + + libblkid/src/superblocks/vdo.c | 48 +++++++++++++++++++++++++++++++++ + 4 files changed, 55 insertions(+) + create mode 100644 libblkid/src/superblocks/vdo.c + +diff --git a/libblkid/src/Makemodule.am b/libblkid/src/Makemodule.am +index 15639768a..791d7cbe8 100644 +--- a/libblkid/src/Makemodule.am ++++ b/libblkid/src/Makemodule.am +@@ -88,6 +88,7 @@ libblkid_la_SOURCES = \ + libblkid/src/superblocks/ubifs.c \ + libblkid/src/superblocks/udf.c \ + libblkid/src/superblocks/ufs.c \ ++ libblkid/src/superblocks/vdo.c \ + libblkid/src/superblocks/vfat.c \ + libblkid/src/superblocks/via_raid.c \ + libblkid/src/superblocks/vmfs.c \ +diff --git a/libblkid/src/superblocks/superblocks.c b/libblkid/src/superblocks/superblocks.c +index 3721544ff..8210fc17b 100644 +--- a/libblkid/src/superblocks/superblocks.c ++++ b/libblkid/src/superblocks/superblocks.c +@@ -109,6 +109,7 @@ static const struct blkid_idinfo *idinfos[] = + &verity_hash_idinfo, + &luks_idinfo, + &vmfs_volume_idinfo, ++ &vdo_idinfo, + + /* Filesystems */ + &vfat_idinfo, +diff --git a/libblkid/src/superblocks/superblocks.h b/libblkid/src/superblocks/superblocks.h +index 90847151b..487fe38c2 100644 +--- a/libblkid/src/superblocks/superblocks.h ++++ b/libblkid/src/superblocks/superblocks.h +@@ -72,6 +72,7 @@ extern const struct blkid_idinfo befs_idinfo; + extern const struct blkid_idinfo nilfs2_idinfo; + extern const struct blkid_idinfo exfat_idinfo; + extern const struct blkid_idinfo f2fs_idinfo; ++extern const struct blkid_idinfo vdo_idinfo; + + /* + * superblock functions +diff --git a/libblkid/src/superblocks/vdo.c b/libblkid/src/superblocks/vdo.c +new file mode 100644 +index 000000000..bec686f4f +--- /dev/null ++++ b/libblkid/src/superblocks/vdo.c +@@ -0,0 +1,48 @@ ++/* ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "superblocks.h" ++ ++struct vdo_super_block { ++ char magic[8]; /* magic number 'dmvdo001'*/ ++ char unused[32]; /* 32 bytes of unimportant space */ ++ unsigned char sb_uuid[16]; /* vdo unique id */ ++ ++ /* this is not all... but enough for libblkid */ ++} __attribute__((packed)); ++ ++static int probe_vdo(blkid_probe pr, const struct blkid_idmag *mag) ++{ ++ struct vdo_super_block *vsb; ++ ++ vsb = blkid_probe_get_sb(pr, mag, struct vdo_super_block); ++ if (!vsb) ++ return errno ? -errno : 1; ++ ++ blkid_probe_set_uuid(pr, vsb->sb_uuid); ++ return 0; ++} ++ ++const struct blkid_idinfo vdo_idinfo = ++{ ++ .name = "vdo", ++ .usage = BLKID_USAGE_OTHER, ++ .probefunc = probe_vdo, ++ .magics = ++ { ++ { .magic = "dmvdo001", .len = 8 }, ++ { NULL } ++ } ++}; +-- +2.13.6 + diff --git a/SOURCES/0147-include-debug-don-t-print-pointer-address-for-SUID-p.patch b/SOURCES/0147-include-debug-don-t-print-pointer-address-for-SUID-p.patch new file mode 100644 index 0000000..296753c --- /dev/null +++ b/SOURCES/0147-include-debug-don-t-print-pointer-address-for-SUID-p.patch @@ -0,0 +1,406 @@ +From 3fcd52706b6818e785a104ed6c4f2b46e5d1ab2f Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Fri, 12 Jan 2018 11:01:26 +0100 +Subject: [PATCH] include/debug: don't print pointer address for SUID programs + +* introduce new flag __UL_DEBUG_FL_NOADDR to suppress pointer address printing + (and MNT_DEBUG_FL_NOADDR for libmount) + +* use __UL_DEBUG_FL_NOADDR when SUID + +* move ul_debugobj() to debugobj.h, and require UL_DEBUG_CURRENT_MASK + to provide access to the current mask from ul_debugobj(). It's better + than modify all ul_debugobj() calls and use the global mask as + argument. + +* remove never used UL_DEBUG_DEFINE_FLAG + +* remove %p from another libmount and libblkid debug messages + +Upstream: http://github.com/karelzak/util-linux/commit/6d00cfb2330cb47d00d350eedfbffbbf5991a743 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1534893 +Reported-by: halfdog +Signed-off-by: Karel Zak +--- + include/Makemodule.am | 2 ++ + include/debug.h | 29 +++++++++++------------------ + include/debugobj.h | 22 ++++++++++++++++++++++ + lib/loopdev.c | 2 +- + libblkid/src/partitions/partitions.c | 20 ++++++++++---------- + libblkid/src/probe.c | 21 ++++++++++----------- + libmount/src/fs.c | 2 +- + libmount/src/init.c | 5 +++++ + libmount/src/mountP.h | 4 +++- + libmount/src/tab_diff.c | 6 +++--- + libmount/src/tab_update.c | 4 ++-- + libsmartcols/src/smartcolsP.h | 3 +++ + sys-utils/lsns.c | 3 +++ + 13 files changed, 76 insertions(+), 47 deletions(-) + create mode 100644 include/debugobj.h + +diff --git a/include/Makemodule.am b/include/Makemodule.am +index 168029683..bd4aa8cea 100644 +--- a/include/Makemodule.am ++++ b/include/Makemodule.am +@@ -11,6 +11,8 @@ dist_noinst_HEADERS += \ + include/colors.h \ + include/cpuset.h \ + include/crc32.h \ ++ include/debug.h \ ++ include/debugobj.h \ + include/env.h \ + include/exec_shell.h \ + include/exitcodes.h \ +diff --git a/include/debug.h b/include/debug.h +index 848e47456..1c7ed8037 100644 +--- a/include/debug.h ++++ b/include/debug.h +@@ -13,12 +13,15 @@ + struct dbg_mask { char *mname; int val; }; + #define UL_DEBUG_EMPTY_MASKNAMES {{ NULL, 0 }} + +-#define UL_DEBUG_DEFINE_MASK(m) int m ## _debug_mask ++#define UL_DEBUG_MASK(m) m ## _debug_mask ++#define UL_DEBUG_DEFINE_MASK(m) int UL_DEBUG_MASK(m) + #define UL_DEBUG_DECLARE_MASK(m) extern UL_DEBUG_DEFINE_MASK(m) + #define UL_DEBUG_DEFINE_MASKNAMES(m) static const struct dbg_mask m ## _masknames[] + +-/* p - flag prefix, m - flag postfix */ +-#define UL_DEBUG_DEFINE_FLAG(p, m) p ## m ++/* ++ * Internal mask flags (above 0xffffff) ++ */ ++#define __UL_DEBUG_FL_NOADDR (1 << 24) /* Don't print object address */ + + /* l - library name, p - flag prefix, m - flag postfix, x - function */ + #define __UL_DBG(l, p, m, x) \ +@@ -55,6 +58,10 @@ struct dbg_mask { char *mname; int val; }; + lib ## _debug_mask = parse_envmask(lib ## _masknames, str); \ + } else \ + lib ## _debug_mask = mask; \ ++ if (lib ## _debug_mask) { \ ++ if (getuid() != geteuid() || getgid() != getegid()) \ ++ lib ## _debug_mask |= __UL_DEBUG_FL_NOADDR; \ ++ } \ + lib ## _debug_mask |= pref ## INIT; \ + if (lib ## _debug_mask != pref ## INIT) { \ + __UL_DBG(lib, pref, INIT, ul_debug("library debug mask: 0x%04x", \ +@@ -72,21 +79,7 @@ ul_debug(const char *mesg, ...) + va_end(ap); + fputc('\n', stderr); + } +- +-static inline void __attribute__ ((__format__ (__printf__, 2, 3))) +-ul_debugobj(void *handler, const char *mesg, ...) +-{ +- va_list ap; +- +- if (handler) +- fprintf(stderr, "[%p]: ", handler); +- va_start(ap, mesg); +- vfprintf(stderr, mesg, ap); +- va_end(ap); +- fputc('\n', stderr); +-} +- +-static inline int parse_envmask(const struct dbg_mask const flagnames[], ++static inline int parse_envmask(const struct dbg_mask flagnames[], + const char *mask) + { + int res; +diff --git a/include/debugobj.h b/include/debugobj.h +new file mode 100644 +index 000000000..73b70b8df +--- /dev/null ++++ b/include/debugobj.h +@@ -0,0 +1,22 @@ ++#ifndef UTIL_LINUX_DEBUGOBJ_H ++#define UTIL_LINUX_DEBUGOBJ_H ++ ++/* ++ * Include *after* debug.h and after UL_DEBUG_CURRENT_MASK define. ++ */ ++ ++static inline void __attribute__ ((__format__ (__printf__, 2, 3))) ++ul_debugobj(const void *handler, const char *mesg, ...) ++{ ++ va_list ap; ++ ++ if (handler && !(UL_DEBUG_CURRENT_MASK & __UL_DEBUG_FL_NOADDR)) ++ fprintf(stderr, "[%p]: ", handler); ++ ++ va_start(ap, mesg); ++ vfprintf(stderr, mesg, ap); ++ va_end(ap); ++ fputc('\n', stderr); ++} ++ ++#endif /* UTIL_LINUX_DEBUGOBJ_H */ +diff --git a/lib/loopdev.c b/lib/loopdev.c +index db5463698..daf0a81e8 100644 +--- a/lib/loopdev.c ++++ b/lib/loopdev.c +@@ -50,7 +50,7 @@ + + # define DBG(l,x) do { \ + if ((l)->debug) {\ +- fprintf(stderr, "loopdev: [%p]: ", (l)); \ ++ fprintf(stderr, "loopdev: "); \ + x; \ + } \ + } while(0) +diff --git a/libblkid/src/partitions/partitions.c b/libblkid/src/partitions/partitions.c +index 9d846ff85..2d0d70d81 100644 +--- a/libblkid/src/partitions/partitions.c ++++ b/libblkid/src/partitions/partitions.c +@@ -381,8 +381,8 @@ static blkid_partlist partitions_init_data(struct blkid_chain *chn) + + reset_partlist(ls); + +- DBG(LOWPROBE, blkid_debug("parts: initialized partitions list (%p, size=%d)", +- ls, ls->nparts_max)); ++ DBG(LOWPROBE, blkid_debug("parts: initialized partitions list (size=%d)", ++ ls->nparts_max)); + return ls; + } + +@@ -417,7 +417,7 @@ blkid_parttable blkid_partlist_new_parttable(blkid_partlist ls, + list_add_tail(&tab->t_tabs, &ls->l_tabs); + + DBG(LOWPROBE, blkid_debug("parts: create a new partition table " +- "(%p, type=%s, offset=%"PRId64")", tab, type, offset)); ++ "(type=%s, offset=%"PRId64")", type, offset)); + return tab; + } + +@@ -458,9 +458,9 @@ blkid_partition blkid_partlist_add_partition(blkid_partlist ls, + par->start = start; + par->size = size; + +- DBG(LOWPROBE, blkid_debug("parts: add partition (%p start=%" +- PRId64 ", size=%" PRId64 ", table=%p)", +- par, par->start, par->size, tab)); ++ DBG(LOWPROBE, blkid_debug("parts: add partition (start=%" ++ PRId64 ", size=%" PRId64 ")", ++ par->start, par->size)); + return par; + } + +@@ -662,8 +662,8 @@ int blkid_partitions_do_subprobe(blkid_probe pr, blkid_partition parent, + blkid_loff_t sz, off; + + DBG(LOWPROBE, blkid_debug( +- "parts: ----> %s subprobe requested (parent=%p)", +- id->name, parent)); ++ "parts: ----> %s subprobe requested)", ++ id->name)); + + if (!pr || !parent || !parent->size) + return -EINVAL; +@@ -709,8 +709,8 @@ int blkid_partitions_do_subprobe(blkid_probe pr, blkid_partition parent, + blkid_free_probe(prc); /* free cloned prober */ + + DBG(LOWPROBE, blkid_debug( +- "parts: <---- %s subprobe done (parent=%p, rc=%d)", +- id->name, parent, rc)); ++ "parts: <---- %s subprobe done (rc=%d)", ++ id->name, rc)); + + return rc; + } +diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c +index 9cf099ae4..07b08441f 100644 +--- a/libblkid/src/probe.c ++++ b/libblkid/src/probe.c +@@ -145,7 +145,7 @@ blkid_probe blkid_new_probe(void) + if (!pr) + return NULL; + +- DBG(LOWPROBE, blkid_debug("allocate a new probe %p", pr)); ++ DBG(LOWPROBE, blkid_debug("allocate a new probe")); + + /* initialize chains */ + for (i = 0; i < BLKID_NCHAINS; i++) { +@@ -260,7 +260,7 @@ void blkid_free_probe(blkid_probe pr) + blkid_probe_reset_buffer(pr); + blkid_free_probe(pr->disk_probe); + +- DBG(LOWPROBE, blkid_debug("free probe %p", pr)); ++ DBG(LOWPROBE, blkid_debug("free probe")); + free(pr); + } + +@@ -552,8 +552,8 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, + list_entry(p, struct blkid_bufinfo, bufs); + + if (x->off <= off && off + len <= x->off + x->len) { +- DBG(LOWPROBE, blkid_debug("\treuse buffer: off=%jd len=%jd pr=%p", +- x->off, x->len, pr)); ++ DBG(LOWPROBE, blkid_debug("\treuse buffer: off=%jd len=%jd", ++ x->off, x->len)); + bf = x; + break; + } +@@ -584,8 +584,8 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, + bf->off = off; + INIT_LIST_HEAD(&bf->bufs); + +- DBG(LOWPROBE, blkid_debug("\tbuffer read: off=%jd len=%jd pr=%p", +- off, len, pr)); ++ DBG(LOWPROBE, blkid_debug("\tbuffer read: off=%jd len=%jd", ++ off, len)); + + ret = read(pr->fd, bf->data, len); + if (ret != (ssize_t) len) { +@@ -609,7 +609,7 @@ static void blkid_probe_reset_buffer(blkid_probe pr) + if (!pr || list_empty(&pr->buffers)) + return; + +- DBG(LOWPROBE, blkid_debug("reseting probing buffers pr=%p", pr)); ++ DBG(LOWPROBE, blkid_debug("reseting probing buffers")); + + while (!list_empty(&pr->buffers)) { + struct blkid_bufinfo *bf = list_entry(pr->buffers.next, +@@ -766,9 +766,8 @@ int blkid_probe_set_dimension(blkid_probe pr, + return -1; + + DBG(LOWPROBE, blkid_debug( +- "changing probing area pr=%p: size=%llu, off=%llu " ++ "changing probing area: size=%llu, off=%llu " + "-to-> size=%llu, off=%llu", +- pr, + (unsigned long long) pr->size, + (unsigned long long) pr->off, + (unsigned long long) size, +@@ -840,7 +839,7 @@ int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id, + static inline void blkid_probe_start(blkid_probe pr) + { + if (pr) { +- DBG(LOWPROBE, blkid_debug("%p: start probe", pr)); ++ DBG(LOWPROBE, blkid_debug("start probe")); + pr->cur_chain = NULL; + pr->prob_flags = 0; + blkid_probe_set_wiper(pr, 0, 0); +@@ -850,7 +849,7 @@ static inline void blkid_probe_start(blkid_probe pr) + static inline void blkid_probe_end(blkid_probe pr) + { + if (pr) { +- DBG(LOWPROBE, blkid_debug("%p: end probe", pr)); ++ DBG(LOWPROBE, blkid_debug("end probe")); + pr->cur_chain = NULL; + pr->prob_flags = 0; + blkid_probe_set_wiper(pr, 0, 0); +diff --git a/libmount/src/fs.c b/libmount/src/fs.c +index 75e3bbb26..e46ee0c0e 100644 +--- a/libmount/src/fs.c ++++ b/libmount/src/fs.c +@@ -1451,7 +1451,7 @@ int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file) + { + if (!fs || !file) + return -EINVAL; +- fprintf(file, "------ fs: %p\n", fs); ++ fprintf(file, "------ fs\n"); + fprintf(file, "source: %s\n", mnt_fs_get_source(fs)); + fprintf(file, "target: %s\n", mnt_fs_get_target(fs)); + fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs)); +diff --git a/libmount/src/init.c b/libmount/src/init.c +index 4e5f489c4..e5e6925f5 100644 +--- a/libmount/src/init.c ++++ b/libmount/src/init.c +@@ -38,6 +38,11 @@ void mnt_init_debug(int mask) + } else + libmount_debug_mask = mask; + ++ if (libmount_debug_mask) { ++ if (getuid() != geteuid() || getgid() != getegid()) ++ libmount_debug_mask |= MNT_DEBUG_FL_NOADDR; ++ } ++ + libmount_debug_mask |= MNT_DEBUG_INIT; + + if (libmount_debug_mask && libmount_debug_mask != MNT_DEBUG_INIT) { +diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h +index 8b3f92e17..dc3ed3f49 100644 +--- a/libmount/src/mountP.h ++++ b/libmount/src/mountP.h +@@ -51,6 +51,8 @@ + #define MNT_DEBUG_DIFF (1 << 11) + #define MNT_DEBUG_ALL 0xFFFF + ++#define MNT_DEBUG_FL_NOADDR (1 << 24) ++ + #ifdef CONFIG_LIBMOUNT_DEBUG + # include + # include +@@ -91,7 +93,7 @@ mnt_debug_h(void *handler, const char *mesg, ...) + { + va_list ap; + +- if (handler) ++ if (handler && !(libmount_debug_mask & MNT_DEBUG_FL_NOADDR)) + fprintf(stderr, "[%p]: ", handler); + va_start(ap, mesg); + vfprintf(stderr, mesg, ap); +diff --git a/libmount/src/tab_diff.c b/libmount/src/tab_diff.c +index f01f889f8..0a69f402c 100644 +--- a/libmount/src/tab_diff.c ++++ b/libmount/src/tab_diff.c +@@ -229,9 +229,9 @@ int mnt_diff_tables(struct libmnt_tabdiff *df, struct libmnt_table *old_tab, + if (!no && !nn) /* both tables are empty */ + return 0; + +- DBG(DIFF, mnt_debug_h(df, "analyze new=%p (%d entries), " +- "old=%p (%d entries)", +- new_tab, nn, old_tab, no)); ++ DBG(DIFF, mnt_debug_h(df, "analyze new (%d entries), " ++ "old (%d entries)", ++ nn, no)); + + mnt_reset_iter(&itr, MNT_ITER_FORWARD); + +diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c +index 5f503cad7..b45c4a92c 100644 +--- a/libmount/src/tab_update.c ++++ b/libmount/src/tab_update.c +@@ -173,8 +173,8 @@ int mnt_update_set_fs(struct libmnt_update *upd, unsigned long mountflags, + return -EINVAL; + + DBG(UPDATE, mnt_debug_h(upd, +- "resetting FS [fs=0x%p, target=%s, flags=0x%08lx]", +- fs, target, mountflags)); ++ "resetting FS [target=%s, flags=0x%08lx]", ++ target, mountflags)); + if (fs) { + DBG(UPDATE, mnt_debug_h(upd, "FS template:")); + DBG(UPDATE, mnt_fs_print_debug(fs, stderr)); +diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h +index 28246c14f..cea4f3101 100644 +--- a/libsmartcols/src/smartcolsP.h ++++ b/libsmartcols/src/smartcolsP.h +@@ -43,6 +43,9 @@ UL_DEBUG_DECLARE_MASK(libsmartcols); + #define ON_DBG(m, x) __UL_DBG_CALL(libsmartcols, SCOLS_DEBUG_, m, x) + #define DBG_FLUSH __UL_DBG_FLUSH(libsmartcols, SCOLS_DEBUG_) + ++#define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(libsmartcols) ++#include "debugobj.h" ++ + /* + * Generic iterator + */ +diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c +index 5ee298172..fb53a16a4 100644 +--- a/sys-utils/lsns.c ++++ b/sys-utils/lsns.c +@@ -55,6 +55,9 @@ UL_DEBUG_DEFINE_MASKNAMES(lsns) = UL_DEBUG_EMPTY_MASKNAMES; + #define DBG(m, x) __UL_DBG(lsns, LSNS_DEBUG_, m, x) + #define ON_DBG(m, x) __UL_DBG_CALL(lsns, LSNS_DEBUG_, m, x) + ++#define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(lsns) ++#include "debugobj.h" ++ + struct idcache *uid_cache = NULL; + + /* column IDs */ +-- +2.13.6 + diff --git a/SOURCES/0148-mkswap-tolerate-ENOTSUP-when-failing-to-relabel.patch b/SOURCES/0148-mkswap-tolerate-ENOTSUP-when-failing-to-relabel.patch new file mode 100644 index 0000000..d1f36df --- /dev/null +++ b/SOURCES/0148-mkswap-tolerate-ENOTSUP-when-failing-to-relabel.patch @@ -0,0 +1,34 @@ +From a656eda4cf268f555563d45808df4bb1df54c95f Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Mon, 18 Apr 2016 09:01:23 +0200 +Subject: [PATCH] mkswap: tolerate ENOTSUP when failing to relabel + +It might be that the underlying filesystem just doesn't support SELinux +labeling. This fixes creating swap on vfat live media: + + # livecd-iso-to-disk.sh --msdos --swap-size-mb 666 ... + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1538545 +Upstream: http://github.com/karelzak/util-linux/commit/d97dc0ee2505e80c8e9fca89aa2001b2ec2c3695 +Signed-off-by: Lubomir Rintel +Signed-off-by: Karel Zak +--- + disk-utils/mkswap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c +index ec6fc5f99..ff47f2038 100644 +--- a/disk-utils/mkswap.c ++++ b/disk-utils/mkswap.c +@@ -656,7 +656,7 @@ main(int argc, char **argv) { + context_string = context_str(newcontext); + + if (strcmp(context_string, oldcontext)!=0) { +- if (fsetfilecon(DEV, context_string)) ++ if (fsetfilecon(DEV, context_string) && errno != ENOTSUP) + err(EXIT_FAILURE, _("unable to relabel %s to %s"), + device_name, context_string); + } +-- +2.13.6 + diff --git a/SOURCES/0149-libmount-fix-debug-message.patch b/SOURCES/0149-libmount-fix-debug-message.patch new file mode 100644 index 0000000..c3e2be7 --- /dev/null +++ b/SOURCES/0149-libmount-fix-debug-message.patch @@ -0,0 +1,28 @@ +From c817652429d4326bb43a8d975611927170447805 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 1 Feb 2018 16:52:14 +0100 +Subject: [PATCH] libmount: fix debug message + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1534893 +Upstream: http://github.com/karelzak/util-linux/commit/b058f473d175450c48a65031f1abc8d8b90b2b7b +Signed-off-by: Karel Zak +--- + libmount/src/fs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmount/src/fs.c b/libmount/src/fs.c +index e46ee0c0e..e5c38c1b6 100644 +--- a/libmount/src/fs.c ++++ b/libmount/src/fs.c +@@ -1451,7 +1451,7 @@ int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file) + { + if (!fs || !file) + return -EINVAL; +- fprintf(file, "------ fs\n"); ++ fprintf(file, "------ fs:\n"); + fprintf(file, "source: %s\n", mnt_fs_get_source(fs)); + fprintf(file, "target: %s\n", mnt_fs_get_target(fs)); + fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs)); +-- +2.14.3 + diff --git a/SPECS/util-linux.spec b/SPECS/util-linux.spec index 7ddf276..48100e4 100644 --- a/SPECS/util-linux.spec +++ b/SPECS/util-linux.spec @@ -2,7 +2,7 @@ Summary: A collection of basic system utilities Name: util-linux Version: 2.23.2 -Release: 43%{?dist}.2 +Release: 52%{?dist} License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain Group: System Environment/Base URL: http://en.wikipedia.org/wiki/Util-linux @@ -57,6 +57,9 @@ Conflicts: e2fsprogs < 1.41.8-5 Obsoletes: util-linux-ng < 2.19 Provides: util-linux-ng = %{version}-%{release} Conflicts: filesystem < 3 +# lsmem and chmem from s390utils +Conflicts: s390utils-base < 2:1.23.0-33 + Provides: /bin/dmesg Provides: /bin/kill Provides: /bin/more @@ -335,10 +338,53 @@ Patch124: 0124-lscpu-use-sysfs-for-table-access-if-available.patch # 1457744 - lscpu -e get crashed after offline one host cpu on amd machine Patch125: 0125-lscpu-improve-for-offline-CPUs-on-AMD.patch -# RHEL7.4.Z +# +# RHEL7.5 +# # 1499760 - gvfs-udisks2-volume-monitor generates huge amount of audit log with access denied messages Patch126: 0126-libmount-use-eacess-rather-than-open-to-check-mtab-u.patch -Patch127: 0127-libmount-fix-access-utab-write-test.patch +# 1498462 - agetty not parsing /etc/os-release correctly when processing /etc/issue +Patch127: 0127-agetty-fix-etc-os-release-parsing.patch +# 1490984 - Please update fdisk's manual page +Patch128: 0128-fdisk-remove-obsolete-info-about-GPT-from-man-page.patch +# 1487031 - [GSS][RFE]The Ceph disk type is unknown then we run the command "fdisk -l" +Patch129: 0129-libfdisk-gpt-sync-type-UUIDs-with-upstream.patch +# 1468646 - lscpu output missing Hypervisor +Patch130: 0130-lscpu-cleanup-DMI-detection-return-codes.patch +# 1455398 - flock --timeout=0 doesn't work on RHEL7 +Patch131: 0131-flock-zero-timeout-is-valid.patch +# 1336432 - journald: SYSLOG_IDENTIFIER is invalid when running logger +Patch132: 0132-logger-add-man-page-note-about-the-default-tag.patch +# 1427500 - util-linux: script does not retry on EINTR when logging command output +Patch133: 0133-script-use-all-io-to-write.patch +# 1336432 - journald: SYSLOG_IDENTIFIER is invalid when running logger +Patch134: 0134-logger-do-not-rely-only-getlogin-3-telling-who-ran-t.patch +# 1296233 - login(1) writes 0.0.0.0 IP address to wtmp when executed with "-h " hostname +Patch135: 0135-login-use-IPv4-on-IPv4-mapping-to-IPv6.patch +# 1501953 - blkid shows wrong return code on failure with ambivalent results +Patch136: 0136-blkid-update-man-page-about-lsblk-and-ambivalent-pro.patch +# 1486777 - wipefs printing duplicate gpt clear messages +Patch137: 0137-wipefs-fix-t-filter.patch +# 1454652 - fix test suite +Patch138: 0138-tests-backport-new-ts_scsi_debug_init.patch +Patch139: 0139-tests-ts_scsi_debug_init-must-not-run-in-a-subshell.patch +Patch140: 0140-tests-cleanup-fdisk-outputs.patch +Patch141: 0141-tests-check-for-mdadm.patch +# 1496421 - [Pegas1.1 FEAT] z Systems: Move lsmem and chmem to util-linux (through rebase >= 2.30) +Patch142: 0142-lsmem-chmem-backport-new-commands.patch +Patch143: 0143-lsmem-make-split-optional-follow-output-by-default.patch +# 1499760 - gvfs-udisks2-volume-monitor generates huge amount of audit log with access denied messages +Patch144: 0144-libmount-fix-access-utab-write-test.patch +# 1520906 - make hostname in login(1) prompt optional [rhel-7.5] +Patch145: 0145-login-add-LOGIN_PLAIN_PROMPT-to-login.defs.patch +# 1521163 - [RFE] blkid can identify magic number and UUID of VDO volume +Patch146: 0146-libblkid-Add-VDO-superblock-information-into-blkid.patch +# 1534893 - RHEL7: util-linux: mount/unmount ASLR bypass via environment variable in libmount +Patch147: 0147-include-debug-don-t-print-pointer-address-for-SUID-p.patch +# 1538545 - SELinux error creating swap file +Patch148: 0148-mkswap-tolerate-ENOTSUP-when-failing-to-relabel.patch +# 1534893 - RHEL7: util-linux: mount/unmount ASLR bypass via environment variable in libmount +Patch149: 0149-libmount-fix-debug-message.patch %description The util-linux package contains a large variety of low-level system @@ -595,8 +641,7 @@ chmod 644 misc-utils/getopt-*.{bash,tcsh} rm -f ${RPM_BUILD_ROOT}%{_datadir}/getopt/* rmdir ${RPM_BUILD_ROOT}%{_datadir}/getopt -ln -sf /proc/mounts %{buildroot}/etc/mtab - +ln -sf ../proc/self/mounts %{buildroot}/etc/mtab # remove static libs rm -f $RPM_BUILD_ROOT%{_libdir}/lib{uuid,blkid,mount}.a @@ -634,7 +679,7 @@ if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then fi fi if [ ! -L /etc/mtab ]; then - ln -fs /proc/mounts /etc/mtab + ln -sf ../proc/self/mounts /etc/mtab || : fi %post -n libblkid @@ -719,6 +764,7 @@ fi %{_bindir}/colcrt %{_bindir}/colrm %{_bindir}/column +%{_bindir}/chmem %{_bindir}/dmesg %{_bindir}/eject %{_bindir}/fallocate @@ -734,6 +780,7 @@ fi %{_bindir}/kill %{_bindir}/lsipc %{_bindir}/lsns +%{_bindir}/lsmem %{_bindir}/logger %{_bindir}/look %{_bindir}/lsblk @@ -788,6 +835,7 @@ fi %{_mandir}/man1/look.1* %{_mandir}/man1/lscpu.1* %{_mandir}/man1/lslogins.1* +%{_mandir}/man1/lsmem.1* %{_mandir}/man1/lsipc.1* %{_mandir}/man1/mcookie.1* %{_mandir}/man1/more.1* @@ -820,6 +868,7 @@ fi %{_mandir}/man8/blkid.8* %{_mandir}/man8/blockdev.8* %{_mandir}/man8/chcpu.8* +%{_mandir}/man8/chmem.8* %{_mandir}/man8/ctrlaltdel.8* %{_mandir}/man8/delpart.8* %{_mandir}/man8/fdisk.8* @@ -1069,11 +1118,45 @@ fi %{_libdir}/pkgconfig/uuid.pc %changelog -* Thu Nov 09 2017 Karel Zak 2.23.2-43.el7_4.2 -- improve libmount eaccess test (bug #1499760) +* Fri Feb 02 2018 Karel Zak 2.23.2-52 +- fix #1534893 - RHEL7: util-linux: mount/unmount ASLR bypass via environment variable in libmount + +* Wed Jan 31 2018 Karel Zak 2.23.2-51 +- fix #1538545 - SELinux error creating swap file + +* Tue Jan 23 2018 Karel Zak 2.23.2-50 +- fix #1534893 - RHEL7: util-linux: mount/unmount ASLR bypass via environment variable in libmount + +* Mon Dec 11 2017 Karel Zak 2.23.2-49 +- fix #1520906 - make hostname in login(1) prompt optional +- fix #1521163 - [RFE] blkid can identify magic number and UUID of VDO volume + +* Thu Nov 09 2017 Karel Zak 2.23.2-48 +- improve libmount eaccess test (#1499760) + +* Wed Nov 08 2017 Karel Zak 2.23.2-47 +- improve lsmem (#1496421) + +* Mon Oct 23 2017 Karel Zak 2.23.2-46 +- fix #1496421 - Move lsmem and chmem to util-linux + +* Tue Oct 17 2017 Karel Zak 2.23.2-45 +- fix #1501953 - blkid shows wrong return code on failure with ambivalent results +- fix #1486777 - wipefs printing duplicate gpt clear messages +- fix #1454652 - fix test suite -* Mon Oct 30 2017 Karel Zak 2.23.2-43.el7_4.1 +* Mon Oct 16 2017 Karel Zak 2.23.2-44 +- fix #1478002 - systemd read-only container produces errors - fix #1499760 - gvfs-udisks2-volume-monitor generates huge amount of audit log with access denied messages +- fix #1498462 - agetty not parsing /etc/os-release correctly when processing /etc/issue +- fix #1490984 - Please update fdisk's manual page +- fix #1487031 - [GSS][RFE]The Ceph disk type is unknown then we run the command "fdisk -l" +- fix #1468646 - lscpu output missing Hypervisor +- fix #1455398 - flock --timeout=0 doesn't work on RHEL7 +- fix #1336432 - journald: SYSLOG_IDENTIFIER is invalid when running logger +- fix #1427500 - util-linux: script does not retry on EINTR when logging command output +- fix #1336432 - journald: SYSLOG_IDENTIFIER is invalid when running logger +- fix #1296233 - login(1) writes 0.0.0.0 IP address to wtmp when executed with "-h " hostname * Thu Jun 01 2017 Karel Zak 2.23.2-43 - fix #1457744 - lscpu -e get crashed after offline one host cpu on amd machine