From 378c18e5f024ac5a8aef4cb40d7c9aa9633d144c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 16:30:35 +0200 Subject: Adding upstream version 2.38.1. Signed-off-by: Daniel Baumann --- sys-utils/Makemodule.am | 568 +++++++ sys-utils/adjtime_config.5 | 88 ++ sys-utils/adjtime_config.5.adoc | 65 + sys-utils/blkdiscard.8 | 105 ++ sys-utils/blkdiscard.8.adoc | 68 + sys-utils/blkdiscard.c | 327 ++++ sys-utils/blkzone.8 | 250 +++ sys-utils/blkzone.8.adoc | 118 ++ sys-utils/blkzone.c | 506 ++++++ sys-utils/chcpu.8 | 129 ++ sys-utils/chcpu.8.adoc | 86 + sys-utils/chcpu.c | 391 +++++ sys-utils/chmem.8 | 173 ++ sys-utils/chmem.8.adoc | 91 ++ sys-utils/chmem.c | 459 ++++++ sys-utils/choom.1 | 88 ++ sys-utils/choom.1.adoc | 61 + sys-utils/choom.c | 159 ++ sys-utils/ctrlaltdel.8 | 80 + sys-utils/ctrlaltdel.8.adoc | 58 + sys-utils/ctrlaltdel.c | 113 ++ sys-utils/dmesg.1 | 312 ++++ sys-utils/dmesg.1.adoc | 194 +++ sys-utils/dmesg.c | 1683 ++++++++++++++++++++ sys-utils/eject.1 | 185 +++ sys-utils/eject.1.adoc | 130 ++ sys-utils/eject.c | 1056 +++++++++++++ sys-utils/fallocate.1 | 141 ++ sys-utils/fallocate.1.adoc | 98 ++ sys-utils/fallocate.c | 443 ++++++ sys-utils/flock.1 | 166 ++ sys-utils/flock.1.adoc | 141 ++ sys-utils/flock.c | 385 +++++ sys-utils/fsfreeze.8 | 88 ++ sys-utils/fsfreeze.8.adoc | 63 + sys-utils/fsfreeze.c | 150 ++ sys-utils/fstab.5 | 144 ++ sys-utils/fstab.5.adoc | 149 ++ sys-utils/fstrim.8 | 146 ++ sys-utils/fstrim.8.adoc | 94 ++ sys-utils/fstrim.c | 586 +++++++ sys-utils/fstrim.service.in | 16 + sys-utils/fstrim.timer | 14 + sys-utils/hwclock-cmos.c | 387 +++++ sys-utils/hwclock-parse-date.c | 3292 +++++++++++++++++++++++++++++++++++++++ sys-utils/hwclock-parse-date.y | 1629 +++++++++++++++++++ sys-utils/hwclock-rtc.c | 599 +++++++ sys-utils/hwclock.8 | 597 +++++++ sys-utils/hwclock.8.adoc | 393 +++++ sys-utils/hwclock.c | 1692 ++++++++++++++++++++ sys-utils/hwclock.h | 96 ++ sys-utils/ipcmk.1 | 88 ++ sys-utils/ipcmk.1.adoc | 61 + sys-utils/ipcmk.c | 171 ++ sys-utils/ipcrm.1 | 119 ++ sys-utils/ipcrm.1.adoc | 88 ++ sys-utils/ipcrm.c | 424 +++++ sys-utils/ipcs.1 | 150 ++ sys-utils/ipcs.1.adoc | 107 ++ sys-utils/ipcs.c | 681 ++++++++ sys-utils/ipcutils.c | 536 +++++++ sys-utils/ipcutils.h | 187 +++ sys-utils/irq-common.c | 554 +++++++ sys-utils/irq-common.h | 72 + sys-utils/irqtop.1 | 114 ++ sys-utils/irqtop.1.adoc | 71 + sys-utils/irqtop.c | 398 +++++ sys-utils/ldattach.8 | 198 +++ sys-utils/ldattach.8.adoc | 129 ++ sys-utils/ldattach.c | 489 ++++++ sys-utils/losetup.8 | 230 +++ sys-utils/losetup.8.adoc | 164 ++ sys-utils/losetup.c | 926 +++++++++++ sys-utils/lscpu-arm.c | 371 +++++ sys-utils/lscpu-cpu.c | 90 ++ sys-utils/lscpu-cputype.c | 911 +++++++++++ sys-utils/lscpu-dmi.c | 159 ++ sys-utils/lscpu-topology.c | 661 ++++++++ sys-utils/lscpu-virt.c | 686 ++++++++ sys-utils/lscpu.1 | 157 ++ sys-utils/lscpu.1.adoc | 113 ++ sys-utils/lscpu.c | 1437 +++++++++++++++++ sys-utils/lscpu.h | 334 ++++ sys-utils/lsipc.1 | 188 +++ sys-utils/lsipc.1.adoc | 125 ++ sys-utils/lsipc.c | 1357 ++++++++++++++++ sys-utils/lsirq.1 | 93 ++ sys-utils/lsirq.1.adoc | 57 + sys-utils/lsirq.c | 152 ++ sys-utils/lsmem.1 | 133 ++ sys-utils/lsmem.1.adoc | 82 + sys-utils/lsmem.c | 774 +++++++++ sys-utils/lsns.8 | 130 ++ sys-utils/lsns.8.adoc | 90 ++ sys-utils/lsns.c | 1436 +++++++++++++++++ sys-utils/meson.build | 233 +++ sys-utils/mount.8 | 2418 ++++++++++++++++++++++++++++ sys-utils/mount.8.adoc | 1594 +++++++++++++++++++ sys-utils/mount.c | 1049 +++++++++++++ sys-utils/mountpoint.1 | 111 ++ sys-utils/mountpoint.1.adoc | 75 + sys-utils/mountpoint.c | 219 +++ sys-utils/nsenter.1 | 251 +++ sys-utils/nsenter.1.adoc | 149 ++ sys-utils/nsenter.c | 530 +++++++ sys-utils/pivot_root.8 | 112 ++ sys-utils/pivot_root.8.adoc | 77 + sys-utils/pivot_root.c | 79 + sys-utils/prlimit.1 | 251 +++ sys-utils/prlimit.1.adoc | 146 ++ sys-utils/prlimit.c | 664 ++++++++ sys-utils/readprofile.8 | 190 +++ sys-utils/readprofile.8.adoc | 121 ++ sys-utils/readprofile.c | 415 +++++ sys-utils/renice.1 | 103 ++ sys-utils/renice.1.adoc | 107 ++ sys-utils/renice.c | 194 +++ sys-utils/rfkill.8 | 148 ++ sys-utils/rfkill.8.adoc | 90 ++ sys-utils/rfkill.c | 818 ++++++++++ sys-utils/rtcwake.8 | 257 +++ sys-utils/rtcwake.8.adoc | 142 ++ sys-utils/rtcwake.c | 688 ++++++++ sys-utils/setarch.8 | 155 ++ sys-utils/setarch.8.adoc | 101 ++ sys-utils/setarch.c | 479 ++++++ sys-utils/setpriv.1 | 205 +++ sys-utils/setpriv.1.adoc | 127 ++ sys-utils/setpriv.c | 1061 +++++++++++++ sys-utils/setsid.1 | 77 + sys-utils/setsid.1.adoc | 54 + sys-utils/setsid.c | 123 ++ sys-utils/swapoff.8 | 1 + sys-utils/swapoff.c | 281 ++++ sys-utils/swapon-common.c | 117 ++ sys-utils/swapon-common.h | 25 + sys-utils/swapon.8 | 252 +++ sys-utils/swapon.8.adoc | 181 +++ sys-utils/swapon.c | 1029 ++++++++++++ sys-utils/switch_root.8 | 85 + sys-utils/switch_root.8.adoc | 60 + sys-utils/switch_root.c | 283 ++++ sys-utils/tunelp.8 | 111 ++ sys-utils/tunelp.8.adoc | 76 + sys-utils/tunelp.c | 319 ++++ sys-utils/umount.8 | 232 +++ sys-utils/umount.8.adoc | 189 +++ sys-utils/umount.c | 650 ++++++++ sys-utils/unshare.1 | 400 +++++ sys-utils/unshare.1.adoc | 277 ++++ sys-utils/unshare.c | 1111 +++++++++++++ sys-utils/wdctl.8 | 127 ++ sys-utils/wdctl.8.adoc | 79 + sys-utils/wdctl.c | 851 ++++++++++ sys-utils/zramctl.8 | 158 ++ sys-utils/zramctl.8.adoc | 110 ++ sys-utils/zramctl.c | 771 +++++++++ 157 files changed, 55933 insertions(+) create mode 100644 sys-utils/Makemodule.am create mode 100644 sys-utils/adjtime_config.5 create mode 100644 sys-utils/adjtime_config.5.adoc create mode 100644 sys-utils/blkdiscard.8 create mode 100644 sys-utils/blkdiscard.8.adoc create mode 100644 sys-utils/blkdiscard.c create mode 100644 sys-utils/blkzone.8 create mode 100644 sys-utils/blkzone.8.adoc create mode 100644 sys-utils/blkzone.c create mode 100644 sys-utils/chcpu.8 create mode 100644 sys-utils/chcpu.8.adoc create mode 100644 sys-utils/chcpu.c create mode 100644 sys-utils/chmem.8 create mode 100644 sys-utils/chmem.8.adoc create mode 100644 sys-utils/chmem.c create mode 100644 sys-utils/choom.1 create mode 100644 sys-utils/choom.1.adoc create mode 100644 sys-utils/choom.c create mode 100644 sys-utils/ctrlaltdel.8 create mode 100644 sys-utils/ctrlaltdel.8.adoc create mode 100644 sys-utils/ctrlaltdel.c create mode 100644 sys-utils/dmesg.1 create mode 100644 sys-utils/dmesg.1.adoc create mode 100644 sys-utils/dmesg.c create mode 100644 sys-utils/eject.1 create mode 100644 sys-utils/eject.1.adoc create mode 100644 sys-utils/eject.c create mode 100644 sys-utils/fallocate.1 create mode 100644 sys-utils/fallocate.1.adoc create mode 100644 sys-utils/fallocate.c create mode 100644 sys-utils/flock.1 create mode 100644 sys-utils/flock.1.adoc create mode 100644 sys-utils/flock.c create mode 100644 sys-utils/fsfreeze.8 create mode 100644 sys-utils/fsfreeze.8.adoc create mode 100644 sys-utils/fsfreeze.c create mode 100644 sys-utils/fstab.5 create mode 100644 sys-utils/fstab.5.adoc create mode 100644 sys-utils/fstrim.8 create mode 100644 sys-utils/fstrim.8.adoc create mode 100644 sys-utils/fstrim.c create mode 100644 sys-utils/fstrim.service.in create mode 100644 sys-utils/fstrim.timer create mode 100644 sys-utils/hwclock-cmos.c create mode 100644 sys-utils/hwclock-parse-date.c create mode 100644 sys-utils/hwclock-parse-date.y create mode 100644 sys-utils/hwclock-rtc.c create mode 100644 sys-utils/hwclock.8 create mode 100644 sys-utils/hwclock.8.adoc create mode 100644 sys-utils/hwclock.c create mode 100644 sys-utils/hwclock.h create mode 100644 sys-utils/ipcmk.1 create mode 100644 sys-utils/ipcmk.1.adoc create mode 100644 sys-utils/ipcmk.c create mode 100644 sys-utils/ipcrm.1 create mode 100644 sys-utils/ipcrm.1.adoc create mode 100644 sys-utils/ipcrm.c create mode 100644 sys-utils/ipcs.1 create mode 100644 sys-utils/ipcs.1.adoc create mode 100644 sys-utils/ipcs.c create mode 100644 sys-utils/ipcutils.c create mode 100644 sys-utils/ipcutils.h create mode 100644 sys-utils/irq-common.c create mode 100644 sys-utils/irq-common.h create mode 100644 sys-utils/irqtop.1 create mode 100644 sys-utils/irqtop.1.adoc create mode 100644 sys-utils/irqtop.c create mode 100644 sys-utils/ldattach.8 create mode 100644 sys-utils/ldattach.8.adoc create mode 100644 sys-utils/ldattach.c create mode 100644 sys-utils/losetup.8 create mode 100644 sys-utils/losetup.8.adoc create mode 100644 sys-utils/losetup.c create mode 100644 sys-utils/lscpu-arm.c create mode 100644 sys-utils/lscpu-cpu.c create mode 100644 sys-utils/lscpu-cputype.c create mode 100644 sys-utils/lscpu-dmi.c create mode 100644 sys-utils/lscpu-topology.c create mode 100644 sys-utils/lscpu-virt.c create mode 100644 sys-utils/lscpu.1 create mode 100644 sys-utils/lscpu.1.adoc create mode 100644 sys-utils/lscpu.c create mode 100644 sys-utils/lscpu.h create mode 100644 sys-utils/lsipc.1 create mode 100644 sys-utils/lsipc.1.adoc create mode 100644 sys-utils/lsipc.c create mode 100644 sys-utils/lsirq.1 create mode 100644 sys-utils/lsirq.1.adoc create mode 100644 sys-utils/lsirq.c create mode 100644 sys-utils/lsmem.1 create mode 100644 sys-utils/lsmem.1.adoc create mode 100644 sys-utils/lsmem.c create mode 100644 sys-utils/lsns.8 create mode 100644 sys-utils/lsns.8.adoc create mode 100644 sys-utils/lsns.c create mode 100644 sys-utils/meson.build create mode 100644 sys-utils/mount.8 create mode 100644 sys-utils/mount.8.adoc create mode 100644 sys-utils/mount.c create mode 100644 sys-utils/mountpoint.1 create mode 100644 sys-utils/mountpoint.1.adoc create mode 100644 sys-utils/mountpoint.c create mode 100644 sys-utils/nsenter.1 create mode 100644 sys-utils/nsenter.1.adoc create mode 100644 sys-utils/nsenter.c create mode 100644 sys-utils/pivot_root.8 create mode 100644 sys-utils/pivot_root.8.adoc create mode 100644 sys-utils/pivot_root.c create mode 100644 sys-utils/prlimit.1 create mode 100644 sys-utils/prlimit.1.adoc create mode 100644 sys-utils/prlimit.c create mode 100644 sys-utils/readprofile.8 create mode 100644 sys-utils/readprofile.8.adoc create mode 100644 sys-utils/readprofile.c create mode 100644 sys-utils/renice.1 create mode 100644 sys-utils/renice.1.adoc create mode 100644 sys-utils/renice.c create mode 100644 sys-utils/rfkill.8 create mode 100644 sys-utils/rfkill.8.adoc create mode 100644 sys-utils/rfkill.c create mode 100644 sys-utils/rtcwake.8 create mode 100644 sys-utils/rtcwake.8.adoc create mode 100644 sys-utils/rtcwake.c create mode 100644 sys-utils/setarch.8 create mode 100644 sys-utils/setarch.8.adoc create mode 100644 sys-utils/setarch.c create mode 100644 sys-utils/setpriv.1 create mode 100644 sys-utils/setpriv.1.adoc create mode 100644 sys-utils/setpriv.c create mode 100644 sys-utils/setsid.1 create mode 100644 sys-utils/setsid.1.adoc create mode 100644 sys-utils/setsid.c create mode 100644 sys-utils/swapoff.8 create mode 100644 sys-utils/swapoff.c create mode 100644 sys-utils/swapon-common.c create mode 100644 sys-utils/swapon-common.h create mode 100644 sys-utils/swapon.8 create mode 100644 sys-utils/swapon.8.adoc create mode 100644 sys-utils/swapon.c create mode 100644 sys-utils/switch_root.8 create mode 100644 sys-utils/switch_root.8.adoc create mode 100644 sys-utils/switch_root.c create mode 100644 sys-utils/tunelp.8 create mode 100644 sys-utils/tunelp.8.adoc create mode 100644 sys-utils/tunelp.c create mode 100644 sys-utils/umount.8 create mode 100644 sys-utils/umount.8.adoc create mode 100644 sys-utils/umount.c create mode 100644 sys-utils/unshare.1 create mode 100644 sys-utils/unshare.1.adoc create mode 100644 sys-utils/unshare.c create mode 100644 sys-utils/wdctl.8 create mode 100644 sys-utils/wdctl.8.adoc create mode 100644 sys-utils/wdctl.c create mode 100644 sys-utils/zramctl.8 create mode 100644 sys-utils/zramctl.8.adoc create mode 100644 sys-utils/zramctl.c (limited to 'sys-utils') diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am new file mode 100644 index 0000000..e553634 --- /dev/null +++ b/sys-utils/Makemodule.am @@ -0,0 +1,568 @@ +if BUILD_LSMEM +usrbin_exec_PROGRAMS += lsmem +MANPAGES += sys-utils/lsmem.1 +dist_noinst_DATA += sys-utils/lsmem.1.adoc +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 +MANPAGES += sys-utils/chmem.8 +dist_noinst_DATA += sys-utils/chmem.8.adoc +chmem_SOURCES = sys-utils/chmem.c +chmem_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_FLOCK +usrbin_exec_PROGRAMS += flock +MANPAGES += sys-utils/flock.1 +dist_noinst_DATA += sys-utils/flock.1.adoc +flock_SOURCES = sys-utils/flock.c lib/monotonic.c lib/timer.c +flock_LDADD = $(LDADD) libcommon.la $(REALTIME_LIBS) +endif + +if BUILD_CHOOM +usrbin_exec_PROGRAMS += choom +MANPAGES += sys-utils/choom.1 +dist_noinst_DATA += sys-utils/choom.1.adoc +choom_SOURCES = sys-utils/choom.c +choom_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_IPCMK +usrbin_exec_PROGRAMS += ipcmk +MANPAGES += sys-utils/ipcmk.1 +dist_noinst_DATA += sys-utils/ipcmk.1.adoc +ipcmk_SOURCES = sys-utils/ipcmk.c +ipcmk_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_IPCRM +usrbin_exec_PROGRAMS += ipcrm +MANPAGES += sys-utils/ipcrm.1 +dist_noinst_DATA += sys-utils/ipcrm.1.adoc +ipcrm_SOURCES = sys-utils/ipcrm.c +ipcrm_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_IPCS +usrbin_exec_PROGRAMS += ipcs +MANPAGES += sys-utils/ipcs.1 +dist_noinst_DATA += sys-utils/ipcs.1.adoc +ipcs_SOURCES = sys-utils/ipcs.c \ + sys-utils/ipcutils.c \ + sys-utils/ipcutils.h +ipcs_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_IRQTOP +usrbin_exec_PROGRAMS += irqtop +MANPAGES += sys-utils/irqtop.1 +dist_noinst_DATA += sys-utils/irqtop.1.adoc +irqtop_SOURCES = sys-utils/irqtop.c \ + sys-utils/irq-common.c \ + sys-utils/irq-common.h \ + lib/monotonic.c +irqtop_LDADD = $(LDADD) libcommon.la $(REALTIME_LIBS) libsmartcols.la +irqtop_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +if HAVE_SLANG +irqtop_LDADD += -lslang +else +irqtop_CFLAGS += $(NCURSES_CFLAGS) +irqtop_LDADD += $(NCURSES_LIBS) +endif +endif + +if BUILD_LSIRQ +usrbin_exec_PROGRAMS += lsirq +MANPAGES += sys-utils/lsirq.1 +dist_noinst_DATA += sys-utils/lsirq.1.adoc +lsirq_SOURCES = sys-utils/lsirq.c \ + sys-utils/irq-common.c \ + sys-utils/irq-common.h +lsirq_LDADD = $(LDADD) libcommon.la libsmartcols.la +lsirq_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif + +if BUILD_LSIPC +usrbin_exec_PROGRAMS += lsipc +MANPAGES += sys-utils/lsipc.1 +dist_noinst_DATA += sys-utils/lsipc.1.adoc +lsipc_SOURCES = sys-utils/lsipc.c \ + sys-utils/ipcutils.c \ + sys-utils/ipcutils.h +lsipc_LDADD = $(LDADD) libcommon.la libsmartcols.la +lsipc_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif + +if BUILD_RENICE +usrbin_exec_PROGRAMS += renice +MANPAGES += sys-utils/renice.1 +dist_noinst_DATA += sys-utils/renice.1.adoc +renice_SOURCES = sys-utils/renice.c +endif + +if BUILD_RFKILL +usrsbin_exec_PROGRAMS += rfkill +MANPAGES += sys-utils/rfkill.8 +dist_noinst_DATA += sys-utils/rfkill.8.adoc +rfkill_SOURCES = sys-utils/rfkill.c +rfkill_LDADD = $(LDADD) libcommon.la libsmartcols.la +rfkill_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif + +if BUILD_SETSID +usrbin_exec_PROGRAMS += setsid +MANPAGES += sys-utils/setsid.1 +dist_noinst_DATA += sys-utils/setsid.1.adoc +setsid_SOURCES = sys-utils/setsid.c +endif + +if BUILD_READPROFILE +usrsbin_exec_PROGRAMS += readprofile +MANPAGES += sys-utils/readprofile.8 +dist_noinst_DATA += sys-utils/readprofile.8.adoc +readprofile_SOURCES = sys-utils/readprofile.c +readprofile_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_TUNELP +usrsbin_exec_PROGRAMS += tunelp +MANPAGES += sys-utils/tunelp.8 +dist_noinst_DATA += sys-utils/tunelp.8.adoc +tunelp_SOURCES = sys-utils/tunelp.c +tunelp_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_FSTRIM +sbin_PROGRAMS += fstrim +MANPAGES += sys-utils/fstrim.8 +dist_noinst_DATA += sys-utils/fstrim.8.adoc +fstrim_SOURCES = sys-utils/fstrim.c +fstrim_LDADD = $(LDADD) libcommon.la libmount.la +fstrim_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +if HAVE_SYSTEMD +systemdsystemunit_DATA += \ + sys-utils/fstrim.service \ + sys-utils/fstrim.timer +endif +endif # BUILD_FSTRIM + +PATHFILES += sys-utils/fstrim.service +EXTRA_DIST += sys-utils/fstrim.timer + +if BUILD_DMESG +bin_PROGRAMS += dmesg +MANPAGES += sys-utils/dmesg.1 +dist_noinst_DATA += sys-utils/dmesg.1.adoc +dmesg_SOURCES = sys-utils/dmesg.c lib/monotonic.c +dmesg_LDADD = $(LDADD) libcommon.la libtcolors.la $(REALTIME_LIBS) +dmesg_CFLAGS = $(AM_CFLAGS) +check_PROGRAMS += test_dmesg +test_dmesg_SOURCES = $(dmesg_SOURCES) +test_dmesg_LDADD = $(dmesg_LDADD) +test_dmesg_CFLAGS = -DTEST_DMESG $(dmesg_CFLAGS) +endif + +if BUILD_CTRLALTDEL +sbin_PROGRAMS += ctrlaltdel +MANPAGES += sys-utils/ctrlaltdel.8 +dist_noinst_DATA += sys-utils/ctrlaltdel.8.adoc +ctrlaltdel_SOURCES = sys-utils/ctrlaltdel.c +ctrlaltdel_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_FSFREEZE +sbin_PROGRAMS += fsfreeze +MANPAGES += sys-utils/fsfreeze.8 +dist_noinst_DATA += sys-utils/fsfreeze.8.adoc +fsfreeze_SOURCES = sys-utils/fsfreeze.c +endif + +if BUILD_BLKDISCARD +sbin_PROGRAMS += blkdiscard +MANPAGES += sys-utils/blkdiscard.8 +dist_noinst_DATA += sys-utils/blkdiscard.8.adoc +blkdiscard_SOURCES = sys-utils/blkdiscard.c lib/monotonic.c +blkdiscard_LDADD = $(LDADD) libcommon.la $(REALTIME_LIBS) +blkdiscard_CFLAGS = $(AM_CFLAGS) +if BUILD_LIBBLKID +blkdiscard_LDADD += libblkid.la +blkdiscard_CFLAGS += -I$(ul_libblkid_incdir) +endif +endif + +if BUILD_BLKZONE +sbin_PROGRAMS += blkzone +MANPAGES += sys-utils/blkzone.8 +dist_noinst_DATA += sys-utils/blkzone.8.adoc +blkzone_SOURCES = sys-utils/blkzone.c +blkzone_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_LDATTACH +usrsbin_exec_PROGRAMS += ldattach +MANPAGES += sys-utils/ldattach.8 +dist_noinst_DATA += sys-utils/ldattach.8.adoc +ldattach_SOURCES = sys-utils/ldattach.c +ldattach_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_RTCWAKE +usrsbin_exec_PROGRAMS += rtcwake +MANPAGES += sys-utils/rtcwake.8 +dist_noinst_DATA += sys-utils/rtcwake.8.adoc +rtcwake_SOURCES = sys-utils/rtcwake.c +rtcwake_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_SETARCH +usrbin_exec_PROGRAMS += setarch +MANPAGES += sys-utils/setarch.8 +dist_noinst_DATA += sys-utils/setarch.8.adoc +setarch_SOURCES = sys-utils/setarch.c + +SETARCH_LINKS = uname26 linux32 linux64 + +if ARCH_S390 +SETARCH_LINKS += s390 s390x +endif +if ARCH_I86 +SETARCH_LINKS += i386 +endif +if ARCH_86_64 +SETARCH_LINKS += i386 x86_64 +endif +if ARCH_PPC +SETARCH_LINKS += ppc ppc64 ppc32 +endif +if ARCH_SPARC +SETARCH_LINKS += sparc sparc64 sparc32 sparc32bash +endif +if ARCH_MIPS +SETARCH_LINKS += mips mips64 mips32 +endif +if ARCH_IA64 +SETARCH_LINKS += i386 ia64 +endif +if ARCH_HPPA +SETARCH_LINKS += parisc parisc64 parisc32 +endif + +if ENABLE_ASCIIDOC +SETARCH_MAN_LINKS = $(addprefix sys-utils/,$(SETARCH_LINKS:=.8)) +endif + +man_MANS += $(SETARCH_MAN_LINKS) +CLEANFILES += $(SETARCH_MAN_LINKS) + +$(SETARCH_MAN_LINKS): + $(AM_V_at) $(MKDIR_P) sys-utils + $(AM_V_GEN)echo ".so man8/setarch.8" > $@ + +install-exec-hook-setarch: + for I in $(SETARCH_LINKS); do \ + cd $(DESTDIR)$(usrbin_execdir) && ln -sf setarch $$I ; \ + done + +uninstall-hook-setarch: + for I in $(SETARCH_LINKS); do \ + rm -f $(DESTDIR)$(usrbin_execdir)/$$I ; \ + done + +INSTALL_EXEC_HOOKS += install-exec-hook-setarch +UNINSTALL_HOOKS += uninstall-hook-setarch + +endif # BUILD_SETARCH + + +if BUILD_EJECT +usrbin_exec_PROGRAMS += eject +MANPAGES += sys-utils/eject.1 +dist_noinst_DATA += sys-utils/eject.1.adoc +eject_SOURCES = sys-utils/eject.c lib/monotonic.c +eject_LDADD = $(LDADD) libmount.la libcommon.la $(REALTIME_LIBS) +eject_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +endif + + +if BUILD_LOSETUP +sbin_PROGRAMS += losetup +MANPAGES += sys-utils/losetup.8 +dist_noinst_DATA += sys-utils/losetup.8.adoc +losetup_SOURCES = sys-utils/losetup.c +losetup_LDADD = $(LDADD) libcommon.la libsmartcols.la +losetup_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) + +if HAVE_STATIC_LOSETUP +bin_PROGRAMS += losetup.static +losetup_static_SOURCES = $(losetup_SOURCES) +losetup_static_LDFLAGS = -all-static +losetup_static_LDADD = $(losetup_LDADD) +losetup_static_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif +endif # BUILD_LOSETUP + + +if BUILD_ZRAMCTL +sbin_PROGRAMS += zramctl +MANPAGES += sys-utils/zramctl.8 +dist_noinst_DATA += sys-utils/zramctl.8.adoc +zramctl_SOURCES = sys-utils/zramctl.c \ + lib/ismounted.c +zramctl_LDADD = $(LDADD) libcommon.la libsmartcols.la +zramctl_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif + + +if BUILD_PRLIMIT +usrbin_exec_PROGRAMS += prlimit +MANPAGES += sys-utils/prlimit.1 +dist_noinst_DATA += sys-utils/prlimit.1.adoc +prlimit_SOURCES = sys-utils/prlimit.c +prlimit_LDADD = $(LDADD) libcommon.la libsmartcols.la +prlimit_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif + + +if BUILD_LSNS +usrbin_exec_PROGRAMS += lsns +MANPAGES += sys-utils/lsns.8 +dist_noinst_DATA += sys-utils/lsns.8.adoc +lsns_SOURCES = sys-utils/lsns.c +lsns_LDADD = $(LDADD) libcommon.la libsmartcols.la libmount.la +lsns_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) -I$(ul_libmount_incdir) +endif + + +if BUILD_MOUNT +bin_PROGRAMS += mount umount +MANPAGES += \ + sys-utils/mount.8 \ + sys-utils/fstab.5 \ + sys-utils/umount.8 +dist_noinst_DATA += \ + sys-utils/mount.8.adoc \ + sys-utils/fstab.5.adoc \ + sys-utils/umount.8.adoc +mount_SOURCES = sys-utils/mount.c +mount_LDADD = $(LDADD) libcommon.la libmount.la $(SELINUX_LIBS) +mount_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS) -I$(ul_libmount_incdir) +mount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) + +umount_SOURCES = sys-utils/umount.c +umount_LDADD = $(LDADD) libcommon.la libmount.la +umount_CFLAGS = $(AM_CFLAGS) $(SUID_CFLAGS) -I$(ul_libmount_incdir) +umount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) + +if HAVE_STATIC_MOUNT +bin_PROGRAMS += mount.static +mount_static_SOURCES = $(mount_SOURCES) +mount_static_CFLAGS = $(mount_CFLAGS) +mount_static_LDFLAGS = $(mount_LDFLAGS) -all-static +mount_static_LDADD = $(mount_LDADD) $(SELINUX_LIBS_STATIC) +endif + +if HAVE_STATIC_UMOUNT +bin_PROGRAMS += umount.static +umount_static_SOURCES = $(umount_SOURCES) +umount_static_CFLAGS = $(umount_CFLAGS) +umount_static_LDFLAGS = $(umount_LDFLAGS) -all-static +umount_static_LDADD = $(umount_LDADD) +endif + +install-exec-hook-mount: +if MAKEINSTALL_DO_CHOWN + chown root:root $(DESTDIR)$(bindir)/mount +endif +if MAKEINSTALL_DO_SETUID + chmod 4755 $(DESTDIR)$(bindir)/mount +endif +if MAKEINSTALL_DO_CHOWN + chown root:root $(DESTDIR)$(bindir)/umount +endif +if MAKEINSTALL_DO_SETUID + chmod 4755 $(DESTDIR)$(bindir)/umount +endif + +INSTALL_EXEC_HOOKS += install-exec-hook-mount +endif # BUILD_MOUNT + + +if BUILD_SWAPON +sbin_PROGRAMS += swapon swapoff +MANPAGES += sys-utils/swapon.8 +dist_noinst_DATA += sys-utils/swapon.8.adoc +MANLINKS += sys-utils/swapoff.8 + +swapon_SOURCES = \ + sys-utils/swapon.c \ + sys-utils/swapon-common.c \ + sys-utils/swapon-common.h \ + lib/swapprober.c \ + include/swapprober.h +swapon_CFLAGS = $(AM_CFLAGS) \ + -I$(ul_libblkid_incdir) \ + -I$(ul_libmount_incdir) \ + -I$(ul_libsmartcols_incdir) +swapon_LDADD = $(LDADD) \ + libblkid.la \ + libcommon.la \ + libmount.la \ + libsmartcols.la + +swapoff_SOURCES = \ + sys-utils/swapoff.c \ + sys-utils/swapon-common.c \ + sys-utils/swapon-common.h \ + lib/swapprober.c \ + include/swapprober.h +swapoff_CFLAGS = $(AM_CFLAGS) \ + -I$(ul_libblkid_incdir) \ + -I$(ul_libmount_incdir) +swapoff_LDADD = $(LDADD) \ + libmount.la \ + libblkid.la \ + libcommon.la +endif + +if BUILD_LSCPU +usrbin_exec_PROGRAMS += lscpu +MANPAGES += sys-utils/lscpu.1 +dist_noinst_DATA += sys-utils/lscpu.1.adoc +lscpu_SOURCES = sys-utils/lscpu.c \ + sys-utils/lscpu-cputype.c \ + sys-utils/lscpu-cpu.c \ + sys-utils/lscpu-topology.c \ + sys-utils/lscpu-virt.c \ + sys-utils/lscpu-arm.c \ + sys-utils/lscpu-dmi.c \ + sys-utils/lscpu.h +lscpu_LDADD = $(LDADD) libcommon.la libsmartcols.la $(RTAS_LIBS) +lscpu_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif + +if BUILD_CHCPU +sbin_PROGRAMS += chcpu +MANPAGES += sys-utils/chcpu.8 +dist_noinst_DATA += sys-utils/chcpu.8.adoc +chcpu_SOURCES = sys-utils/chcpu.c +chcpu_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_WDCTL +bin_PROGRAMS += wdctl +MANPAGES += sys-utils/wdctl.8 +dist_noinst_DATA += sys-utils/wdctl.8.adoc +wdctl_SOURCES = sys-utils/wdctl.c +wdctl_LDADD = $(LDADD) libcommon.la libsmartcols.la +wdctl_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) +endif + +if BUILD_MOUNTPOINT +bin_PROGRAMS += mountpoint +MANPAGES += sys-utils/mountpoint.1 +dist_noinst_DATA += sys-utils/mountpoint.1.adoc +mountpoint_LDADD = $(LDADD) libmount.la +mountpoint_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) +mountpoint_SOURCES = sys-utils/mountpoint.c +endif + +if BUILD_FALLOCATE +usrbin_exec_PROGRAMS += fallocate +MANPAGES += sys-utils/fallocate.1 +dist_noinst_DATA += sys-utils/fallocate.1.adoc +fallocate_SOURCES = sys-utils/fallocate.c +fallocate_LDADD = $(LDADD) libcommon.la +endif + +if BUILD_PIVOT_ROOT +sbin_PROGRAMS += pivot_root +MANPAGES += sys-utils/pivot_root.8 +dist_noinst_DATA += sys-utils/pivot_root.8.adoc +pivot_root_SOURCES = sys-utils/pivot_root.c +endif + +if BUILD_SWITCH_ROOT +sbin_PROGRAMS += switch_root +MANPAGES += sys-utils/switch_root.8 +dist_noinst_DATA += sys-utils/switch_root.8.adoc +switch_root_SOURCES = sys-utils/switch_root.c +endif + +if BUILD_UNSHARE +usrbin_exec_PROGRAMS += unshare +MANPAGES += sys-utils/unshare.1 +dist_noinst_DATA += sys-utils/unshare.1.adoc +unshare_SOURCES = sys-utils/unshare.c \ + lib/caputils.c \ + lib/exec_shell.c +unshare_LDADD = $(LDADD) libcommon.la +unshare_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) + +if HAVE_STATIC_UNSHARE +usrbin_exec_PROGRAMS += unshare.static +unshare_static_SOURCES = $(unshare_SOURCES) +unshare_static_LDFLAGS = -all-static +unshare_static_LDADD = $(unshare_LDADD) +unshare_static_CFLAGS = $(unshare_CFLAGS) +endif +endif + +if BUILD_NSENTER +usrbin_exec_PROGRAMS += nsenter +MANPAGES += sys-utils/nsenter.1 +dist_noinst_DATA += sys-utils/nsenter.1.adoc +nsenter_SOURCES = sys-utils/nsenter.c lib/exec_shell.c +nsenter_LDADD = $(LDADD) libcommon.la $(SELINUX_LIBS) + +if HAVE_STATIC_NSENTER +usrbin_exec_PROGRAMS += nsenter.static +nsenter_static_SOURCES = $(nsenter_SOURCES) +nsenter_static_LDFLAGS = -all-static +nsenter_static_LDADD = $(nsenter_LDADD) +endif +endif + +if BUILD_HWCLOCK +sbin_PROGRAMS += hwclock +MANPAGES += \ + sys-utils/hwclock.8 \ + sys-utils/adjtime_config.5 +dist_noinst_DATA += \ + sys-utils/hwclock.8.adoc \ + sys-utils/adjtime_config.5.adoc +hwclock_SOURCES = \ + sys-utils/hwclock.c \ + sys-utils/hwclock.h +if USE_HWCLOCK_GPLv3_DATETIME +hwclock_SOURCES += \ + sys-utils/hwclock-parse-date.y +endif +hwclock_LDADD = $(LDADD) libcommon.la -lm +hwclock_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/sys-utils +if USE_HWCLOCK_CMOS +hwclock_SOURCES += \ + sys-utils/hwclock-cmos.c +endif +if LINUX +hwclock_SOURCES += \ + sys-utils/hwclock-rtc.c \ + lib/monotonic.c +hwclock_LDADD += $(REALTIME_LIBS) +endif +if HAVE_AUDIT +hwclock_LDADD += -laudit +endif +endif # BUILD_HWCLOCK + +if BUILD_SETPRIV +usrbin_exec_PROGRAMS += setpriv +MANPAGES += sys-utils/setpriv.1 +dist_noinst_DATA += sys-utils/setpriv.1.adoc +setpriv_SOURCES = sys-utils/setpriv.c \ + lib/caputils.c +setpriv_LDADD = $(LDADD) -lcap-ng libcommon.la +endif diff --git a/sys-utils/adjtime_config.5 b/sys-utils/adjtime_config.5 new file mode 100644 index 0000000..a794876 --- /dev/null +++ b/sys-utils/adjtime_config.5 @@ -0,0 +1,88 @@ +'\" t +.\" Title: adjtime_config +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: File formats +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "ADJTIME_CONFIG" "5" "2022-05-11" "util\-linux 2.38.1" "File formats" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +adjtime_config \- information about hardware clock setting and drift factor +.SH "SYNOPSIS" +.sp +\fI/etc/adjtime\fP +.SH "DESCRIPTION" +.sp +The file \fI/etc/adjtime\fP contains descriptive information about the hardware mode clock setting and clock drift factor. The file is read and write by \fBhwclock\fP(8); and read by programs like rtcwake to get RTC time mode. +.sp +The file is usually located in \fI/etc\fP, but tools like \fBhwclock\fP(8) or \fBrtcwake\fP(8) can use alternative location by command line options if write access to \fI/etc\fP is unwanted. The default clock mode is "UTC" if the file is missing. +.sp +The Hardware Clock is usually not very accurate. However, much of its inaccuracy is completely predictable \- it gains or loses the same amount of time every day. This is called systematic drift. The util \fBhwclock\fP(8) keeps the file \fI/etc/adjtime\fP, that keeps some historical information. For more details see "\fBThe Adjust Function\fP" and "\fBThe Adjtime File\fP" sections from \fBhwclock\fP(8) man page. +.sp +The \fIadjtime\fP file is formatted in ASCII. +.SS "First line" +.sp +Three numbers, separated by blanks: +.sp +\fBdrift factor\fP +.RS 4 +the systematic drift rate in seconds per day (floating point decimal) +.RE +.sp +\fBlast adjust time\fP +.RS 4 +the resulting number of seconds since 1969 UTC of most recent adjustment or calibration (decimal integer) +.RE +.sp +\fBadjustment status\fP +.RS 4 +zero (for compatibility with \fBclock\fP(8)) as a floating point decimal +.RE +.SS "Second line" +.sp +\fBlast calibration time\fP +.RS 4 +The resulting number of seconds since 1969 UTC of most recent calibration. Zero if there has been no calibration yet or it is known that any previous calibration is moot (for example, because the Hardware Clock has been found, since that calibration, not to contain a valid time). This is a decimal integer. +.RE +.SS "Third line" +.sp +\fBclock mode\fP +.RS 4 +Supported values are \fBUTC\fP or \fBLOCAL\fP. Tells whether the Hardware Clock is set to Coordinated Universal Time or local time. You can always override this value with options on the \fBhwclock\fP(8) command line. +.RE +.SH "FILES" +.sp +\fI/etc/adjtime\fP +.SH "SEE ALSO" +.sp +\fBhwclock\fP(8), +\fBrtcwake\fP(8) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +\fBadjtime_config\fP is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/adjtime_config.5.adoc b/sys-utils/adjtime_config.5.adoc new file mode 100644 index 0000000..ee7d8ec --- /dev/null +++ b/sys-utils/adjtime_config.5.adoc @@ -0,0 +1,65 @@ +//po4a: entry man manual += adjtime_config(5) +:doctype: manpage +:man manual: File formats +:man source: util-linux {release-version} +:page-layout: base +:configfile: adjtime_config + +== NAME + +adjtime_config - information about hardware clock setting and drift factor + +== SYNOPSIS + +_/etc/adjtime_ + +== DESCRIPTION + +The file _/etc/adjtime_ contains descriptive information about the hardware mode clock setting and clock drift factor. The file is read and write by *hwclock*(8); and read by programs like rtcwake to get RTC time mode. + +The file is usually located in _/etc_, but tools like *hwclock*(8) or *rtcwake*(8) can use alternative location by command line options if write access to _/etc_ is unwanted. The default clock mode is "UTC" if the file is missing. + +The Hardware Clock is usually not very accurate. However, much of its inaccuracy is completely predictable - it gains or loses the same amount of time every day. This is called systematic drift. The util *hwclock*(8) keeps the file _/etc/adjtime_, that keeps some historical information. For more details see "*The Adjust Function*" and "*The Adjtime File*" sections from *hwclock*(8) man page. + +The _adjtime_ file is formatted in ASCII. + +=== First line + +Three numbers, separated by blanks: + +*drift factor*:: +the systematic drift rate in seconds per day (floating point decimal) + +*last adjust time*:: +the resulting number of seconds since 1969 UTC of most recent adjustment or calibration (decimal integer) + +*adjustment status*:: +zero (for compatibility with *clock*(8)) as a floating point decimal + +=== Second line + +*last calibration time*:: +The resulting number of seconds since 1969 UTC of most recent calibration. Zero if there has been no calibration yet or it is known that any previous calibration is moot (for example, because the Hardware Clock has been found, since that calibration, not to contain a valid time). This is a decimal integer. + +=== Third line + +*clock mode*:: +Supported values are *UTC* or *LOCAL*. Tells whether the Hardware Clock is set to Coordinated Universal Time or local time. You can always override this value with options on the *hwclock*(8) command line. + +== FILES + +_/etc/adjtime_ + +== SEE ALSO + +*hwclock*(8), +*rtcwake*(8) + +include::man-common/bugreports.adoc[] + +include::man-common/footer-config.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/blkdiscard.8 b/sys-utils/blkdiscard.8 new file mode 100644 index 0000000..fe167a8 --- /dev/null +++ b/sys-utils/blkdiscard.8 @@ -0,0 +1,105 @@ +'\" t +.\" Title: blkdiscard +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: System Administration +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "BLKDISCARD" "8" "2022-05-11" "util\-linux 2.38.1" "System Administration" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +blkdiscard \- discard sectors on a device +.SH "SYNOPSIS" +.sp +\fBblkdiscard\fP [options] [\fB\-o\fP \fIoffset\fP] [\fB\-l\fP \fIlength\fP] \fIdevice\fP +.SH "DESCRIPTION" +.sp +\fBblkdiscard\fP is used to discard device sectors. This is useful for solid\-state drivers (SSDs) and thinly\-provisioned storage. Unlike \fBfstrim\fP(8), this command is used directly on the block device. +.sp +By default, \fBblkdiscard\fP will discard all blocks on the device. Options may be used to modify this behavior based on range or size, as explained below. +.sp +The \fIdevice\fP argument is the pathname of the block device. +.sp +\fBWARNING: All data in the discarded region on the device will be lost!\fP +.SH "OPTIONS" +.sp +The \fIoffset\fP and \fIlength\fP arguments may be followed by the multiplicative suffixes KiB (=1024), MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB" is optional, e.g., "K" has the same meaning as "KiB") or the suffixes KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB. +.sp +\fB\-f\fP, \fB\-\-force\fP +.RS 4 +Disable all checking. Since v2.36 the block device is open in exclusive mode (\fBO_EXCL\fP) by default to avoid collision with mounted filesystem or another kernel subsystem. The \fB\-\-force\fP option disables the exclusive access mode. +.RE +.sp +\fB\-o\fP, \fB\-\-offset\fP \fIoffset\fP +.RS 4 +Byte offset into the device from which to start discarding. The provided value must be aligned to the device sector size. The default value is zero. +.RE +.sp +\fB\-l\fP, \fB\-\-length\fP \fIlength\fP +.RS 4 +The number of bytes to discard (counting from the starting point). The provided value must be aligned to the device sector size. If the specified value extends past the end of the device, \fBblkdiscard\fP will stop at the device size boundary. The default value extends to the end of the device. +.RE +.sp +\fB\-p\fP, \fB\-\-step\fP \fIlength\fP +.RS 4 +The number of bytes to discard within one iteration. The default is to discard all by one ioctl call. +.RE +.sp +\fB\-s\fP, \fB\-\-secure\fP +.RS 4 +Perform a secure discard. A secure discard is the same as a regular discard except that all copies of the discarded blocks that were possibly created by garbage collection must also be erased. This requires support from the device. +.RE +.sp +\fB\-z\fP, \fB\-\-zeroout\fP +.RS 4 +Zero\-fill rather than discard. +.RE +.sp +\fB\-v\fP, \fB\-\-verbose\fP +.RS 4 +Display the aligned values of \fIoffset\fP and \fIlength\fP. If the \fB\-\-step\fP option is specified, it prints the discard progress every second. +.RE +.sp +\fB\-h\fP, \fB\-\-help\fP +.RS 4 +Display help text and exit. +.RE +.sp +\fB\-V\fP, \fB\-\-version\fP +.RS 4 +Print version and exit. +.RE +.SH "AUTHORS" +.sp +.MTO "lczerner\(atredhat.com" "Lukas Czerner" "" +.SH "SEE ALSO" +.sp +\fBfstrim\fP(8) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +The \fBblkdiscard\fP command is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/blkdiscard.8.adoc b/sys-utils/blkdiscard.8.adoc new file mode 100644 index 0000000..8368743 --- /dev/null +++ b/sys-utils/blkdiscard.8.adoc @@ -0,0 +1,68 @@ +//po4a: entry man manual += blkdiscard(8) +:doctype: manpage +:man manual: System Administration +:man source: util-linux {release-version} +:page-layout: base +:command: blkdiscard + +== NAME + +blkdiscard - discard sectors on a device + +== SYNOPSIS + +*blkdiscard* [options] [*-o* _offset_] [*-l* _length_] _device_ + +== DESCRIPTION + +*blkdiscard* is used to discard device sectors. This is useful for solid-state drivers (SSDs) and thinly-provisioned storage. Unlike *fstrim*(8), this command is used directly on the block device. + +By default, *blkdiscard* will discard all blocks on the device. Options may be used to modify this behavior based on range or size, as explained below. + +The _device_ argument is the pathname of the block device. + +*WARNING: All data in the discarded region on the device will be lost!* + +== OPTIONS + +The _offset_ and _length_ arguments may be followed by the multiplicative suffixes KiB (=1024), MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB" is optional, e.g., "K" has the same meaning as "KiB") or the suffixes KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB. + +*-f*, *--force*:: +Disable all checking. Since v2.36 the block device is open in exclusive mode (*O_EXCL*) by default to avoid collision with mounted filesystem or another kernel subsystem. The *--force* option disables the exclusive access mode. + +*-o*, *--offset* _offset_:: +Byte offset into the device from which to start discarding. The provided value must be aligned to the device sector size. The default value is zero. + +*-l*, *--length* _length_:: +The number of bytes to discard (counting from the starting point). The provided value must be aligned to the device sector size. If the specified value extends past the end of the device, *blkdiscard* will stop at the device size boundary. The default value extends to the end of the device. + +*-p*, *--step* _length_:: +The number of bytes to discard within one iteration. The default is to discard all by one ioctl call. + +*-s*, *--secure*:: +Perform a secure discard. A secure discard is the same as a regular discard except that all copies of the discarded blocks that were possibly created by garbage collection must also be erased. This requires support from the device. + +*-z*, *--zeroout*:: +Zero-fill rather than discard. + +*-v*, *--verbose*:: +Display the aligned values of _offset_ and _length_. If the *--step* option is specified, it prints the discard progress every second. + +include::man-common/help-version.adoc[] + +== AUTHORS + +mailto:lczerner@redhat.com[Lukas Czerner] + +== SEE ALSO + +*fstrim*(8) + +include::man-common/bugreports.adoc[] + +include::man-common/footer.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/blkdiscard.c b/sys-utils/blkdiscard.c new file mode 100644 index 0000000..38240e8 --- /dev/null +++ b/sys-utils/blkdiscard.c @@ -0,0 +1,327 @@ +/* + * blkdiscard.c -- discard the part (or whole) of the block device. + * + * Copyright (C) 2012 Red Hat, Inc. All rights reserved. + * Written by Lukas Czerner + * + * 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 will 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, see . + * + * This program uses BLKDISCARD ioctl to discard part or the whole block + * device if the device supports it. You can specify range (start and + * length) to be discarded, or simply discard the whole device. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef HAVE_LIBBLKID +# include +#endif + +#include "nls.h" +#include "strutils.h" +#include "c.h" +#include "closestream.h" +#include "monotonic.h" + +#ifndef BLKDISCARD +# define BLKDISCARD _IO(0x12,119) +#endif + +#ifndef BLKSECDISCARD +# define BLKSECDISCARD _IO(0x12,125) +#endif + +#ifndef BLKZEROOUT +# define BLKZEROOUT _IO(0x12,127) +#endif + +enum { + ACT_DISCARD = 0, /* default */ + ACT_ZEROOUT, + ACT_SECURE +}; + +static void print_stats(int act, char *path, uint64_t stats[]) +{ + switch (act) { + case ACT_ZEROOUT: + printf(_("%s: Zero-filled %" PRIu64 " bytes from the offset %" PRIu64"\n"), \ + path, stats[1], stats[0]); + break; + case ACT_SECURE: + case ACT_DISCARD: + printf(_("%s: Discarded %" PRIu64 " bytes from the offset %" PRIu64"\n"), \ + path, stats[1], stats[0]); + break; + } +} + +static void __attribute__((__noreturn__)) usage(void) +{ + FILE *out = stdout; + fputs(USAGE_HEADER, out); + fprintf(out, + _(" %s [options] \n"), program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fputs(_("Discard the content of sectors on a device.\n"), out); + + fputs(USAGE_OPTIONS, out); + fputs(_(" -f, --force disable all checking\n"), out); + fputs(_(" -o, --offset offset in bytes to discard from\n"), out); + fputs(_(" -l, --length length of bytes to discard from the offset\n"), out); + fputs(_(" -p, --step size of the discard iterations within the offset\n"), out); + fputs(_(" -s, --secure perform secure discard\n"), out); + fputs(_(" -z, --zeroout zero-fill rather than discard\n"), out); + fputs(_(" -v, --verbose print aligned length and offset\n"), out); + + fputs(USAGE_SEPARATOR, out); + printf(USAGE_HELP_OPTIONS(21)); + + fputs(USAGE_ARGUMENTS, out); + printf(USAGE_ARG_SIZE(_(""))); + + printf(USAGE_MAN_TAIL("blkdiscard(8)")); + exit(EXIT_SUCCESS); +} + +#ifdef HAVE_LIBBLKID +/* + * Check existing signature on the open fd + * Returns 0 signature found + * 1 no signature + * <0 error + */ +static int probe_device(int fd, char *path) +{ + const char *type; + blkid_probe pr = NULL; + int ret = -1; + + pr = blkid_new_probe(); + if (!pr || blkid_probe_set_device(pr, fd, 0, 0)) + return ret; + + blkid_probe_enable_superblocks(pr, TRUE); + blkid_probe_enable_partitions(pr, TRUE); + + ret = blkid_do_fullprobe(pr); + if (ret) + goto out; + + if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) { + warnx("%s contains existing file system (%s).",path ,type); + } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) { + warnx("%s contains existing partition (%s).",path ,type); + } else { + warnx("%s contains existing signature.", path); + } + +out: + blkid_free_probe(pr); + return ret; +} +#endif /* HAVE_LIBBLKID */ + +int main(int argc, char **argv) +{ + char *path; + int c, fd, verbose = 0, secsize, force = 0; + uint64_t end, blksize, step, range[2], stats[2]; + struct stat sb; + struct timeval now = { 0 }, last = { 0 }; + int act = ACT_DISCARD; + + static const struct option longopts[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "offset", required_argument, NULL, 'o' }, + { "force", no_argument, NULL, 'f' }, + { "length", required_argument, NULL, 'l' }, + { "step", required_argument, NULL, 'p' }, + { "secure", no_argument, NULL, 's' }, + { "verbose", no_argument, NULL, 'v' }, + { "zeroout", no_argument, NULL, 'z' }, + { NULL, 0, NULL, 0 } + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + close_stdout_atexit(); + + range[0] = 0; + range[1] = ULLONG_MAX; + step = 0; + + while ((c = getopt_long(argc, argv, "hfVsvo:l:p:z", longopts, NULL)) != -1) { + switch(c) { + case 'f': + force = 1; + break; + case 'l': + range[1] = strtosize_or_err(optarg, + _("failed to parse length")); + break; + case 'o': + range[0] = strtosize_or_err(optarg, + _("failed to parse offset")); + break; + case 'p': + step = strtosize_or_err(optarg, + _("failed to parse step")); + break; + case 's': + act = ACT_SECURE; + break; + case 'v': + verbose = 1; + break; + case 'z': + act = ACT_ZEROOUT; + break; + + case 'h': + usage(); + case 'V': + print_version(EXIT_SUCCESS); + default: + errtryhelp(EXIT_FAILURE); + } + } + + if (optind == argc) + errx(EXIT_FAILURE, _("no device specified")); + + path = argv[optind++]; + + if (optind != argc) { + warnx(_("unexpected number of arguments")); + errtryhelp(EXIT_FAILURE); + } + + fd = open(path, O_RDWR | (force ? 0 : O_EXCL)); + if (fd < 0) + err(EXIT_FAILURE, _("cannot open %s"), path); + + if (fstat(fd, &sb) == -1) + err(EXIT_FAILURE, _("stat of %s failed"), path); + if (!S_ISBLK(sb.st_mode)) + errx(EXIT_FAILURE, _("%s: not a block device"), path); + + if (ioctl(fd, BLKGETSIZE64, &blksize)) + err(EXIT_FAILURE, _("%s: BLKGETSIZE64 ioctl failed"), path); + if (ioctl(fd, BLKSSZGET, &secsize)) + err(EXIT_FAILURE, _("%s: BLKSSZGET ioctl failed"), path); + + /* check offset alignment to the sector size */ + if (range[0] % secsize) + errx(EXIT_FAILURE, _("%s: offset %" PRIu64 " is not aligned " + "to sector size %i"), path, range[0], secsize); + + /* is the range end behind the end of the device ?*/ + if (range[0] > blksize) + errx(EXIT_FAILURE, _("%s: offset is greater than device size"), path); + end = range[0] + range[1]; + if (end < range[0] || end > blksize) + end = blksize; + + range[1] = (step > 0) ? step : end - range[0]; + + /* check length alignment to the sector size */ + if (range[1] % secsize) + errx(EXIT_FAILURE, _("%s: length %" PRIu64 " is not aligned " + "to sector size %i"), path, range[1], secsize); +#ifdef HAVE_LIBBLKID + if (force) + warnx(_("Operation forced, data will be lost!")); + else { + /* Check for existing signatures on the device */ + switch(probe_device(fd, path)) { + case 0: /* signature detected */ + /* + * Only require force in interactive mode to avoid + * breaking existing scripts + */ + if (isatty(STDIN_FILENO)) { + errx(EXIT_FAILURE, + _("This is destructive operation, data will " \ + "be lost! Use the -f option to override.")); + } + break; + case 1: /* no signature */ + break; + default: /* error */ + err(EXIT_FAILURE, _("failed to probe the device")); + break; + } + } +#endif /* HAVE_LIBBLKID */ + + stats[0] = range[0], stats[1] = 0; + gettime_monotonic(&last); + + for (/* nothing */; range[0] < end; range[0] += range[1]) { + if (range[0] + range[1] > end) + range[1] = end - range[0]; + + switch (act) { + case ACT_ZEROOUT: + if (ioctl(fd, BLKZEROOUT, &range)) + err(EXIT_FAILURE, _("%s: BLKZEROOUT ioctl failed"), path); + break; + case ACT_SECURE: + if (ioctl(fd, BLKSECDISCARD, &range)) + err(EXIT_FAILURE, _("%s: BLKSECDISCARD ioctl failed"), path); + break; + case ACT_DISCARD: + if (ioctl(fd, BLKDISCARD, &range)) + err(EXIT_FAILURE, _("%s: BLKDISCARD ioctl failed"), path); + break; + } + + stats[1] += range[1]; + + /* reporting progress at most once per second */ + if (verbose && step) { + gettime_monotonic(&now); + if (now.tv_sec > last.tv_sec && + (now.tv_usec >= last.tv_usec || now.tv_sec > last.tv_sec + 1)) { + print_stats(act, path, stats); + stats[0] += stats[1], stats[1] = 0; + last = now; + } + } + } + + if (verbose && stats[1]) + print_stats(act, path, stats); + + close(fd); + return EXIT_SUCCESS; +} diff --git a/sys-utils/blkzone.8 b/sys-utils/blkzone.8 new file mode 100644 index 0000000..45e8c3e --- /dev/null +++ b/sys-utils/blkzone.8 @@ -0,0 +1,250 @@ +'\" t +.\" Title: blkzone +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: System Administration +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "BLKZONE" "8" "2022-05-11" "util\-linux 2.38.1" "System Administration" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +blkzone \- run zone command on a device +.SH "SYNOPSIS" +.sp +\fBblkzone\fP \fIcommand\fP [options] \fIdevice\fP +.SH "DESCRIPTION" +.sp +\fBblkzone\fP is used to run zone command on device that support the Zoned Block Commands (ZBC) or Zoned\-device ATA Commands (ZAC). The zones to operate on can be specified using the offset, count and length options. +.sp +The \fIdevice\fP argument is the pathname of the block device. +.SH "COMMANDS" +.SS "report" +.sp +The command \fBblkzone report\fP is used to report device zone information. +.sp +By default, the command will report all zones from the start of the block device. Options may be used to modify this behavior, changing the starting zone or the size of the report, as explained below. +.sp +Report output: +.TS +allbox tab(:); +lt lt. +T{ +.sp +start +T}:T{ +.sp +Zone start sector +T} +T{ +.sp +len +T}:T{ +.sp +Zone length in number of sectors +T} +T{ +.sp +cap +T}:T{ +.sp +Zone capacity in number of sectors +T} +T{ +.sp +wptr +T}:T{ +.sp +Zone write pointer position +T} +T{ +.sp +reset +T}:T{ +.sp +Reset write pointer recommended +T} +T{ +.sp +non\-seq +T}:T{ +.sp +Non\-sequential write resources active +T} +T{ +.sp +cond +T}:T{ +.sp +Zone condition +T} +T{ +.sp +type +T}:T{ +.sp +Zone type +T} +.TE +.sp +.sp +Zone conditions: +.TS +allbox tab(:); +lt lt. +T{ +.sp +cl +T}:T{ +.sp +Closed +T} +T{ +.sp +nw +T}:T{ +.sp +Not write pointer +T} +T{ +.sp +em +T}:T{ +.sp +Empty +T} +T{ +.sp +fu +T}:T{ +.sp +Full +T} +T{ +.sp +oe +T}:T{ +.sp +Explicitly opened +T} +T{ +.sp +oi +T}:T{ +.sp +Implicitly opened +T} +T{ +.sp +ol +T}:T{ +.sp +Offline +T} +T{ +.sp +ro +T}:T{ +.sp +Read only +T} +T{ +.sp +x? +T}:T{ +.sp +Reserved conditions (should not be reported) +T} +.TE +.sp +.SS "capacity" +.sp +The command \fBblkzone capacity\fP is used to report device capacity information. +.sp +By default, the command will report the sum, in number of sectors, of all zone capacities on the device. Options may be used to modify this behavior, changing the starting zone or the size of the report, as explained below. +.SS "reset" +.sp +The command \fBblkzone reset\fP is used to reset one or more zones. Unlike \fBsg_reset_wp\fP(8), this command operates from the block layer and can reset a range of zones. +.SS "open" +.sp +The command \fBblkzone open\fP is used to explicitly open one or more zones. Unlike \fBsg_zone\fP(8), open action, this command operates from the block layer and can open a range of zones. +.SS "close" +.sp +The command \fBblkzone close\fP is used to close one or more zones. Unlike \fBsg_zone\fP(8), close action, this command operates from the block layer and can close a range of zones. +.SS "finish" +.sp +The command \fBblkzone finish\fP is used to finish (transition to full condition) one or more zones. Unlike \fBsg_zone\fP(8), finish action, this command operates from the block layer and can finish a range of zones. +.sp +By default, the \fBreset\fP, \fBopen\fP, \fBclose\fP and \fBfinish\fP commands will operate from the zone at device sector 0 and operate on all zones. Options may be used to modify this behavior as explained below. +.SH "OPTIONS" +.sp +The \fIoffset\fP and \fIlength\fP option arguments may be followed by the multiplicative suffixes KiB (=1024), MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB" is optional, e.g., "K" has the same meaning as "KiB") or the suffixes KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB. Additionally, the 0x prefix can be used to specify \fIoffset\fP and \fIlength\fP in hex. +.sp +\fB\-o\fP, \fB\-\-offset\fP \fIsector\fP +.RS 4 +The starting zone specified as a sector offset. The provided offset in sector units (512 bytes) should match the start of a zone. The default value is zero. +.RE +.sp +\fB\-l\fP, \fB\-\-length\fP \fIsectors\fP +.RS 4 +The maximum number of sectors the command should operate on. The default value is the number of sectors remaining after \fIoffset\fP. This option cannot be used together with the option \fB\-\-count\fP. +.RE +.sp +\fB\-c\fP, \fB\-\-count\fP \fIcount\fP +.RS 4 +The maximum number of zones the command should operate on. The default value is the number of zones starting from \fIoffset\fP. This option cannot be used together with the option \fB\-\-length\fP. +.RE +.sp +\fB\-f\fP, \fB\-\-force\fP +.RS 4 +Enforce commands to change zone status on block devices used by the system. +.RE +.sp +\fB\-v\fP, \fB\-\-verbose\fP +.RS 4 +Display the number of zones returned in the report or the range of sectors reset. +.RE +.sp +\fB\-h\fP, \fB\-\-help\fP +.RS 4 +Display help text and exit. +.RE +.sp +\fB\-V\fP, \fB\-\-version\fP +.RS 4 +Print version and exit. +.RE +.SH "AUTHORS" +.sp +.MTO "shaun\(attancheff.com" "Shaun Tancheff" "," +.MTO "kzak\(atredhat.com" "Karel Zak" "" +.SH "SEE ALSO" +.sp +\fBsg_rep_zones\fP(8) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +The \fBblkzone\fP command is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/blkzone.8.adoc b/sys-utils/blkzone.8.adoc new file mode 100644 index 0000000..8456b5e --- /dev/null +++ b/sys-utils/blkzone.8.adoc @@ -0,0 +1,118 @@ +//po4a: entry man manual += blkzone(8) +:doctype: manpage +:man manual: System Administration +:man source: util-linux {release-version} +:page-layout: base +:command: blkzone + +== NAME + +blkzone - run zone command on a device + +== SYNOPSIS + +*blkzone* _command_ [options] _device_ + +== DESCRIPTION + +*blkzone* is used to run zone command on device that support the Zoned Block Commands (ZBC) or Zoned-device ATA Commands (ZAC). The zones to operate on can be specified using the offset, count and length options. + +The _device_ argument is the pathname of the block device. + +== COMMANDS + +=== report + +The command *blkzone report* is used to report device zone information. + +By default, the command will report all zones from the start of the block device. Options may be used to modify this behavior, changing the starting zone or the size of the report, as explained below. + +Report output: +[cols=",",] +|=== +|start |Zone start sector +|len |Zone length in number of sectors +|cap |Zone capacity in number of sectors +|wptr |Zone write pointer position +|reset |Reset write pointer recommended +|non-seq |Non-sequential write resources active +|cond |Zone condition +|type |Zone type +|=== + +Zone conditions: +[cols=",",] +|=== +|cl |Closed +|nw |Not write pointer +|em |Empty +|fu |Full +|oe |Explicitly opened +|oi |Implicitly opened +|ol |Offline +|ro |Read only +|x? |Reserved conditions (should not be reported) +|=== + +=== capacity + +The command *blkzone capacity* is used to report device capacity information. + +By default, the command will report the sum, in number of sectors, of all zone capacities on the device. Options may be used to modify this behavior, changing the starting zone or the size of the report, as explained below. + +=== reset + +The command *blkzone reset* is used to reset one or more zones. Unlike *sg_reset_wp*(8), this command operates from the block layer and can reset a range of zones. + +=== open + +The command *blkzone open* is used to explicitly open one or more zones. Unlike *sg_zone*(8), open action, this command operates from the block layer and can open a range of zones. + +=== close + +The command *blkzone close* is used to close one or more zones. Unlike *sg_zone*(8), close action, this command operates from the block layer and can close a range of zones. + +=== finish + +The command *blkzone finish* is used to finish (transition to full condition) one or more zones. Unlike *sg_zone*(8), finish action, this command operates from the block layer and can finish a range of zones. + +By default, the *reset*, *open*, *close* and *finish* commands will operate from the zone at device sector 0 and operate on all zones. Options may be used to modify this behavior as explained below. + +== OPTIONS + +The _offset_ and _length_ option arguments may be followed by the multiplicative suffixes KiB (=1024), MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB" is optional, e.g., "K" has the same meaning as "KiB") or the suffixes KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB. Additionally, the 0x prefix can be used to specify _offset_ and _length_ in hex. + +*-o*, *--offset* _sector_:: +The starting zone specified as a sector offset. The provided offset in sector units (512 bytes) should match the start of a zone. The default value is zero. + +*-l*, *--length* _sectors_:: +The maximum number of sectors the command should operate on. The default value is the number of sectors remaining after _offset_. This option cannot be used together with the option *--count*. + +*-c*, *--count* _count_:: +The maximum number of zones the command should operate on. The default value is the number of zones starting from _offset_. This option cannot be used together with the option *--length*. + +*-f*, *--force*:: +Enforce commands to change zone status on block devices used by the system. + +*-v*, *--verbose*:: +Display the number of zones returned in the report or the range of sectors reset. + +include::man-common/help-version.adoc[] + +== AUTHORS + +mailto:shaun@tancheff.com[Shaun Tancheff], +mailto:kzak@redhat.com[Karel Zak] + +== SEE ALSO + +*sg_rep_zones*(8) + +include::man-common/bugreports.adoc[] + +include::man-common/footer.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/blkzone.c b/sys-utils/blkzone.c new file mode 100644 index 0000000..04e2660 --- /dev/null +++ b/sys-utils/blkzone.c @@ -0,0 +1,506 @@ +/* + * blkzone.c -- the block device zone commands + * + * Copyright (C) 2015,2016 Seagate Technology PLC + * Written by Shaun Tancheff + * + * Copyright (C) 2017 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 will 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, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "nls.h" +#include "strutils.h" +#include "xalloc.h" +#include "c.h" +#include "closestream.h" +#include "blkdev.h" +#include "sysfs.h" +#include "optutils.h" + +/* + * These ioctls are defined in linux/blkzoned.h starting with kernel 5.5. + */ +#ifndef BLKOPENZONE +#define BLKOPENZONE _IOW(0x12, 134, struct blk_zone_range) +#endif +#ifndef BLKCLOSEZONE +#define BLKCLOSEZONE _IOW(0x12, 135, struct blk_zone_range) +#endif +#ifndef BLKFINISHZONE +#define BLKFINISHZONE _IOW(0x12, 136, struct blk_zone_range) +#endif + +struct blkzone_control; + +static int blkzone_report(struct blkzone_control *ctl); +static int blkzone_action(struct blkzone_control *ctl); + +struct blkzone_command { + const char *name; + int (*handler)(struct blkzone_control *); + unsigned long ioctl_cmd; + const char *ioctl_name; + const char *help; +}; + +struct blkzone_control { + const char *devname; + const struct blkzone_command *command; + + uint64_t total_sectors; + int secsize; + + uint64_t offset; + uint64_t length; + uint32_t count; + + unsigned int force : 1; + unsigned int verbose : 1; +}; + +static const struct blkzone_command commands[] = { + { + .name = "report", + .handler = blkzone_report, + .help = N_("Report zone information about the given device") + },{ + .name = "capacity", + .handler = blkzone_report, + .help = N_("Report sum of zone capacities for the given device") + },{ + .name = "reset", + .handler = blkzone_action, + .ioctl_cmd = BLKRESETZONE, + .ioctl_name = "BLKRESETZONE", + .help = N_("Reset a range of zones.") + },{ + .name = "open", + .handler = blkzone_action, + .ioctl_cmd = BLKOPENZONE, + .ioctl_name = "BLKOPENZONE", + .help = N_("Open a range of zones.") + },{ + .name = "close", + .handler = blkzone_action, + .ioctl_cmd = BLKCLOSEZONE, + .ioctl_name = "BLKCLOSEZONE", + .help = N_("Close a range of zones.") + },{ + .name = "finish", + .handler = blkzone_action, + .ioctl_cmd = BLKFINISHZONE, + .ioctl_name = "BLKFINISHZONE", + .help = N_("Set a range of zones to Full.") + } +}; + +static const struct blkzone_command *name_to_command(const char *name) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(commands); i++) { + if (strcmp(commands[i].name, name) == 0) + return &commands[i]; + } + + return NULL; +} + +static int init_device(struct blkzone_control *ctl, int mode) +{ + struct stat sb; + int fd; + + fd = open(ctl->devname, mode); + if (fd < 0) + err(EXIT_FAILURE, _("cannot open %s"), ctl->devname); + + if (fstat(fd, &sb) == -1) + err(EXIT_FAILURE, _("stat of %s failed"), ctl->devname); + if (!S_ISBLK(sb.st_mode)) + errx(EXIT_FAILURE, _("%s: not a block device"), ctl->devname); + + if (blkdev_get_sectors(fd, (unsigned long long *) &ctl->total_sectors)) + err(EXIT_FAILURE, _("%s: blkdev_get_sectors ioctl failed"), ctl->devname); + + if (blkdev_get_sector_size(fd, &ctl->secsize)) + err(EXIT_FAILURE, _("%s: BLKSSZGET ioctl failed"), ctl->devname); + + return fd; +} + +/* + * Get the device zone size indicated by chunk sectors). + */ +static unsigned long blkdev_chunk_sectors(const char *dname) +{ + struct path_cxt *pc = NULL; + dev_t devno = sysfs_devname_to_devno(dname); + dev_t disk; + uint64_t sz = 0; + int rc; + + /* + * Mapping /dev/sdXn -> /sys/block/sdX to read the chunk_size entry. + * This method masks off the partition specified by the minor device + * component. + */ + pc = ul_new_sysfs_path(devno, NULL, NULL); + if (!pc) + return 0; + + rc = sysfs_blkdev_get_wholedisk(pc, NULL, 0, &disk); + if (rc != 0) + goto done; + + /* if @pc is not while-disk device, switch to disk */ + if (devno != disk) { + rc = sysfs_blkdev_init_path(pc, disk, NULL); + if (rc != 0) + goto done; + } + + rc = ul_path_read_u64(pc, &sz, "queue/chunk_sectors"); +done: + ul_unref_path(pc); + return rc == 0 ? sz : 0; +} + +#if HAVE_DECL_BLK_ZONE_REP_CAPACITY +#define has_zone_capacity(zi) ((zi)->flags & BLK_ZONE_REP_CAPACITY) +#define zone_capacity(z) (z)->capacity +#else +#define has_zone_capacity(zi) (false) +#define zone_capacity(z) (z)->len +#endif + +/* + * blkzone report + */ +#define DEF_REPORT_LEN (1U << 12) /* 4k zones per report (256k kzalloc) */ + +static const char *type_text[] = { + "RESERVED", + "CONVENTIONAL", + "SEQ_WRITE_REQUIRED", + "SEQ_WRITE_PREFERRED", +}; + +static const char *condition_str[] = { + "nw", /* Not write pointer */ + "em", /* Empty */ + "oi", /* Implicitly opened */ + "oe", /* Explicitly opened */ + "cl", /* Closed */ + "x5", "x6", "x7", "x8", "x9", "xA", "xB", "xC", /* xN: reserved */ + "ro", /* Read only */ + "fu", /* Full */ + "of" /* Offline */ +}; + +static int blkzone_report(struct blkzone_control *ctl) +{ + bool only_capacity_sum = !strcmp(ctl->command->name, "capacity"); + uint64_t capacity_sum = 0; + struct blk_zone_report *zi; + unsigned long zonesize; + uint32_t i, nr_zones; + int fd; + + fd = init_device(ctl, O_RDONLY); + + if (ctl->offset >= ctl->total_sectors) + errx(EXIT_FAILURE, + _("%s: offset is greater than or equal to device size"), ctl->devname); + + zonesize = blkdev_chunk_sectors(ctl->devname); + if (!zonesize) + errx(EXIT_FAILURE, _("%s: unable to determine zone size"), ctl->devname); + + if (ctl->count) + nr_zones = ctl->count; + else if (ctl->length) + nr_zones = (ctl->length + zonesize - 1) / zonesize; + else + nr_zones = 1 + (ctl->total_sectors - ctl->offset) / zonesize; + + zi = xmalloc(sizeof(struct blk_zone_report) + + (DEF_REPORT_LEN * sizeof(struct blk_zone))); + + while (nr_zones && ctl->offset < ctl->total_sectors) { + + zi->nr_zones = min(nr_zones, DEF_REPORT_LEN); + zi->sector = ctl->offset; + + if (ioctl(fd, BLKREPORTZONE, zi) == -1) + err(EXIT_FAILURE, _("%s: BLKREPORTZONE ioctl failed"), ctl->devname); + + if (ctl->verbose) + printf(_("Found %d zones from 0x%"PRIx64"\n"), + zi->nr_zones, ctl->offset); + + if (!zi->nr_zones) + break; + + for (i = 0; i < zi->nr_zones; i++) { +/* + * blk_zone_report hasn't been packed since https://github.com/torvalds/linux/commit/b3e7e7d2d668de0102264302a4d10dd9d4438a42 + * was merged. See https://github.com/util-linux/util-linux/issues/1083 + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" + const struct blk_zone *entry = &zi->zones[i]; +#pragma GCC diagnostic pop + unsigned int type = entry->type; + uint64_t start = entry->start; + uint64_t wp = entry->wp; + uint8_t cond = entry->cond; + uint64_t len = entry->len; + uint64_t cap; + + if (!len) { + nr_zones = 0; + break; + } + + if (has_zone_capacity(zi)) + cap = zone_capacity(entry); + else + cap = entry->len; + + if (only_capacity_sum) { + capacity_sum += cap; + } else if (has_zone_capacity(zi)) { + printf(_(" start: 0x%09"PRIx64", len 0x%06"PRIx64 + ", cap 0x%06"PRIx64", wptr 0x%06"PRIx64 + " reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"), + start, len, cap, (type == 0x1) ? 0 : wp - start, + entry->reset, entry->non_seq, + cond, condition_str[cond & (ARRAY_SIZE(condition_str) - 1)], + type, type_text[type]); + } else { + printf(_(" start: 0x%09"PRIx64", len 0x%06"PRIx64 + ", wptr 0x%06"PRIx64 + " reset:%u non-seq:%u, zcond:%2u(%s) [type: %u(%s)]\n"), + start, len, (type == 0x1) ? 0 : wp - start, + entry->reset, entry->non_seq, + cond, condition_str[cond & (ARRAY_SIZE(condition_str) - 1)], + type, type_text[type]); + } + + nr_zones--; + ctl->offset = start + len; + } + + } + + if (only_capacity_sum) + printf(_("0x%09"PRIx64"\n"), capacity_sum); + + free(zi); + close(fd); + + return 0; +} + +/* + * blkzone reset, open, close, and finish. + */ +static int blkzone_action(struct blkzone_control *ctl) +{ + struct blk_zone_range za = { .sector = 0 }; + unsigned long zonesize; + uint64_t zlen; + int fd; + + zonesize = blkdev_chunk_sectors(ctl->devname); + if (!zonesize) + errx(EXIT_FAILURE, _("%s: unable to determine zone size"), ctl->devname); + + fd = init_device(ctl, O_WRONLY | (ctl->force ? 0 : O_EXCL)); + + if (ctl->offset & (zonesize - 1)) + errx(EXIT_FAILURE, _("%s: offset %" PRIu64 " is not aligned " + "to zone size %lu"), + ctl->devname, ctl->offset, zonesize); + + if (ctl->offset > ctl->total_sectors) + errx(EXIT_FAILURE, _("%s: offset is greater than device size"), ctl->devname); + + if (ctl->count) + zlen = ctl->count * zonesize; + else if (ctl->length) + zlen = ctl->length; + else + zlen = ctl->total_sectors; + if (ctl->offset + zlen > ctl->total_sectors) + zlen = ctl->total_sectors - ctl->offset; + + if (ctl->length && + (zlen & (zonesize - 1)) && + ctl->offset + zlen != ctl->total_sectors) + errx(EXIT_FAILURE, _("%s: number of sectors %" PRIu64 " is not aligned " + "to zone size %lu"), + ctl->devname, ctl->length, zonesize); + + za.sector = ctl->offset; + za.nr_sectors = zlen; + + if (ioctl(fd, ctl->command->ioctl_cmd, &za) == -1) + err(EXIT_FAILURE, _("%s: %s ioctl failed"), + ctl->devname, ctl->command->ioctl_name); + else if (ctl->verbose) + printf(_("%s: successful %s of zones in range from %" PRIu64 ", to %" PRIu64), + ctl->devname, + ctl->command->name, + ctl->offset, + ctl->offset + zlen); + close(fd); + return 0; +} + +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(_("Run zone command on the given block device.\n"), out); + + fputs(USAGE_COMMANDS, out); + for (i = 0; i < ARRAY_SIZE(commands); i++) + fprintf(out, " %-11s %s\n", commands[i].name, _(commands[i].help)); + + fputs(USAGE_OPTIONS, out); + fputs(_(" -o, --offset start sector of zone to act (in 512-byte sectors)\n"), out); + fputs(_(" -l, --length maximum sectors to act (in 512-byte sectors)\n"), out); + fputs(_(" -c, --count maximum number of zones\n"), out); + fputs(_(" -f, --force enforce on block devices used by the system\n"), out); + fputs(_(" -v, --verbose display more details\n"), out); + fputs(USAGE_SEPARATOR, out); + printf(USAGE_HELP_OPTIONS(24)); + + fputs(USAGE_ARGUMENTS, out); + printf(USAGE_ARG_SIZE(_(" and "))); + + printf(USAGE_MAN_TAIL("blkzone(8)")); + exit(EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + int c; + struct blkzone_control ctl = { + .devname = NULL + }; + + static const struct option longopts[] = { + { "help", no_argument, NULL, 'h' }, + { "count", required_argument, NULL, 'c' }, /* max #of zones to operate on */ + { "length", required_argument, NULL, 'l' }, /* max of sectors to operate on */ + { "offset", required_argument, NULL, 'o' }, /* starting LBA */ + { "force", no_argument, NULL, 'f' }, + { "verbose", no_argument, NULL, 'v' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } + }; + static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ + { 'c', 'l' }, + { 0 } + }; + int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; + + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + close_stdout_atexit(); + + if (argc >= 2 && *argv[1] != '-') { + ctl.command = name_to_command(argv[1]); + if (!ctl.command) + errx(EXIT_FAILURE, _("%s is not valid command name"), argv[1]); + argv++; + argc--; + } + + while ((c = getopt_long(argc, argv, "hc:l:o:fvV", longopts, NULL)) != -1) { + + err_exclusive_options(c, longopts, excl, excl_st); + + switch (c) { + case 'c': + ctl.count = strtou32_or_err(optarg, + _("failed to parse number of zones")); + break; + case 'l': + ctl.length = strtosize_or_err(optarg, + _("failed to parse number of sectors")); + break; + case 'o': + ctl.offset = strtosize_or_err(optarg, + _("failed to parse zone offset")); + break; + case 'f': + ctl.force = 1; + break; + case 'v': + ctl.verbose = 1; + break; + + case 'h': + usage(); + case 'V': + print_version(EXIT_SUCCESS); + default: + errtryhelp(EXIT_FAILURE); + } + } + + if (!ctl.command) + errx(EXIT_FAILURE, _("no command specified")); + + if (optind == argc) + errx(EXIT_FAILURE, _("no device specified")); + ctl.devname = argv[optind++]; + + if (optind != argc) + errx(EXIT_FAILURE,_("unexpected number of arguments")); + + if (ctl.command->handler(&ctl) < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; + +} diff --git a/sys-utils/chcpu.8 b/sys-utils/chcpu.8 new file mode 100644 index 0000000..0a2c1dc --- /dev/null +++ b/sys-utils/chcpu.8 @@ -0,0 +1,129 @@ +'\" t +.\" Title: chcpu +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: System Administration +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "CHCPU" "8" "2022-05-11" "util\-linux 2.38.1" "System Administration" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +chcpu \- configure CPUs +.SH "SYNOPSIS" +.sp +\fBchcpu\fP \fB\-c\fP|\fB\-d\fP|\fB\-e\fP|\fB\-g\fP \fIcpu\-list\fP +.sp +\fBchcpu\fP \fB\-p\fP \fImode\fP +.sp +\fBchcpu\fP \fB\-r\fP|\fB\-h\fP|\fB\-V\fP +.SH "DESCRIPTION" +.sp +\fBchcpu\fP can modify the state of CPUs. It can enable or disable CPUs, scan for new CPUs, change the CPU dispatching \fImode\fP of the underlying hypervisor, and request CPUs from the hypervisor (configure) or return CPUs to the hypervisor (deconfigure). +.sp +Some options have a \fIcpu\-list\fP argument. Use this argument to specify a comma\-separated list of CPUs. The list can contain individual CPU addresses or ranges of addresses. For example, \fB0,5,7,9\-11\fP makes the command applicable to the CPUs with the addresses 0, 5, 7, 9, 10, and 11. +.SH "OPTIONS" +.sp +\fB\-c\fP, \fB\-\-configure\fP \fIcpu\-list\fP +.RS 4 +Configure the specified CPUs. Configuring a CPU means that the hypervisor takes a CPU from the CPU pool and assigns it to the virtual hardware on which your kernel runs. +.RE +.sp +\fB\-d\fP, \fB\-\-disable\fP \fIcpu\-list\fP +.RS 4 +Disable the specified CPUs. Disabling a CPU means that the kernel sets it offline. +.RE +.sp +\fB\-e\fP, \fB\-\-enable\fP \fIcpu\-list\fP +.RS 4 +Enable the specified CPUs. Enabling a CPU means that the kernel sets it online. A CPU must be configured, see \fB\-c\fP, before it can be enabled. +.RE +.sp +\fB\-g\fP, \fB\-\-deconfigure\fP \fIcpu\-list\fP +.RS 4 +Deconfigure the specified CPUs. Deconfiguring a CPU means that the hypervisor removes the CPU from the virtual hardware on which the Linux instance runs and returns it to the CPU pool. A CPU must be offline, see \fB\-d\fP, before it can be deconfigured. +.RE +.sp +\fB\-p\fP, \fB\-\-dispatch\fP \fImode\fP +.RS 4 +Set the CPU dispatching \fImode\fP (polarization). This option has an effect only if your hardware architecture and hypervisor support CPU polarization. Available \fImodes\fP are: +.sp +\fBhorizontal\fP +.RS 4 +The workload is spread across all available CPUs. +.RE +.sp +\fBvertical\fP +.RS 4 +The workload is concentrated on few CPUs. +.RE +.RE +.sp +\fB\-r\fP, \fB\-\-rescan\fP +.RS 4 +Trigger a rescan of CPUs. After a rescan, the Linux kernel recognizes the new CPUs. Use this option on systems that do not automatically detect newly attached CPUs. +.RE +.sp +\fB\-h\fP, \fB\-\-help\fP +.RS 4 +Display help text and exit. +.RE +.sp +\fB\-V\fP, \fB\-\-version\fP +.RS 4 +Print version and exit. +.RE +.SH "EXIT STATUS" +.sp +\fBchcpu\fP has the following exit status values: +.sp +\fB0\fP +.RS 4 +success +.RE +.sp +\fB1\fP +.RS 4 +failure +.RE +.sp +\fB64\fP +.RS 4 +partial success +.RE +.SH "AUTHORS" +.sp +.MTO "heiko.carstens\(atde.ibm.com" "Heiko Carstens" "" +.SH "COPYRIGHT" +.sp +Copyright IBM Corp. 2011 +.SH "SEE ALSO" +.sp +\fBlscpu\fP(1) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +The \fBchcpu\fP command is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/chcpu.8.adoc b/sys-utils/chcpu.8.adoc new file mode 100644 index 0000000..c5797df --- /dev/null +++ b/sys-utils/chcpu.8.adoc @@ -0,0 +1,86 @@ +//po4a: entry man manual += chcpu(8) +:doctype: manpage +:man manual: System Administration +:man source: util-linux {release-version} +:page-layout: base +:command: chcpu + +== NAME + +chcpu - configure CPUs + +== SYNOPSIS + +*chcpu* *-c*|*-d*|*-e*|*-g* _cpu-list_ + +*chcpu* *-p* _mode_ + +*chcpu* *-r*|*-h*|*-V* + +== DESCRIPTION + +*chcpu* can modify the state of CPUs. It can enable or disable CPUs, scan for new CPUs, change the CPU dispatching _mode_ of the underlying hypervisor, and request CPUs from the hypervisor (configure) or return CPUs to the hypervisor (deconfigure). + +Some options have a _cpu-list_ argument. Use this argument to specify a comma-separated list of CPUs. The list can contain individual CPU addresses or ranges of addresses. For example, *0,5,7,9-11* makes the command applicable to the CPUs with the addresses 0, 5, 7, 9, 10, and 11. + +== OPTIONS + +*-c*, *--configure* _cpu-list_:: +Configure the specified CPUs. Configuring a CPU means that the hypervisor takes a CPU from the CPU pool and assigns it to the virtual hardware on which your kernel runs. + +*-d*, *--disable* _cpu-list_:: +Disable the specified CPUs. Disabling a CPU means that the kernel sets it offline. + +*-e*, *--enable* _cpu-list_:: +Enable the specified CPUs. Enabling a CPU means that the kernel sets it online. A CPU must be configured, see *-c*, before it can be enabled. + +*-g*, *--deconfigure* _cpu-list_:: +Deconfigure the specified CPUs. Deconfiguring a CPU means that the hypervisor removes the CPU from the virtual hardware on which the Linux instance runs and returns it to the CPU pool. A CPU must be offline, see *-d*, before it can be deconfigured. + +*-p*, *--dispatch* _mode_:: +Set the CPU dispatching _mode_ (polarization). This option has an effect only if your hardware architecture and hypervisor support CPU polarization. Available _modes_ are: + +*horizontal*;; +The workload is spread across all available CPUs. + +*vertical*;; +The workload is concentrated on few CPUs. + +*-r*, *--rescan*:: +Trigger a rescan of CPUs. After a rescan, the Linux kernel recognizes the new CPUs. Use this option on systems that do not automatically detect newly attached CPUs. + +include::man-common/help-version.adoc[] + +== EXIT STATUS + +*chcpu* has the following exit status values: + +*0*:: +success + +*1*:: +failure + +*64*:: +partial success + +== AUTHORS + +mailto:heiko.carstens@de.ibm.com[Heiko Carstens] + +== COPYRIGHT + +Copyright IBM Corp. 2011 + +== SEE ALSO + +*lscpu*(1) + +include::man-common/bugreports.adoc[] + +include::man-common/footer.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c new file mode 100644 index 0000000..527bce5 --- /dev/null +++ b/sys-utils/chcpu.c @@ -0,0 +1,391 @@ +/* + * chcpu - CPU configuration tool + * + * Copyright IBM Corp. 2011 + * Author(s): Heiko Carstens , + * + * 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 "cpuset.h" +#include "nls.h" +#include "xalloc.h" +#include "c.h" +#include "strutils.h" +#include "bitops.h" +#include "path.h" +#include "closestream.h" +#include "optutils.h" + +#define EXCL_ERROR "--{configure,deconfigure,disable,dispatch,enable}" + +/* partial success, otherwise we return regular EXIT_{SUCCESS,FAILURE} */ +#define CHCPU_EXIT_SOMEOK 64 + +#define _PATH_SYS_CPU "/sys/devices/system/cpu" + +static cpu_set_t *onlinecpus; +static int maxcpus; + +#define is_cpu_online(cpu) (CPU_ISSET_S((cpu), CPU_ALLOC_SIZE(maxcpus), onlinecpus)) +#define num_online_cpus() (CPU_COUNT_S(CPU_ALLOC_SIZE(maxcpus), onlinecpus)) + +enum { + CMD_CPU_ENABLE = 0, + CMD_CPU_DISABLE, + CMD_CPU_CONFIGURE, + CMD_CPU_DECONFIGURE, + CMD_CPU_RESCAN, + CMD_CPU_DISPATCH_HORIZONTAL, + CMD_CPU_DISPATCH_VERTICAL, +}; + +/* returns: 0 = success + * < 0 = failure + * > 0 = partial success + */ +static int cpu_enable(struct path_cxt *sys, cpu_set_t *cpu_set, size_t setsize, int enable) +{ + int cpu; + int online, rc; + int configured = -1; + int fails = 0; + + for (cpu = 0; cpu < maxcpus; cpu++) { + if (!CPU_ISSET_S(cpu, setsize, cpu_set)) + continue; + if (ul_path_accessf(sys, F_OK, "cpu%d", cpu) != 0) { + warnx(_("CPU %u does not exist"), cpu); + fails++; + continue; + } + if (ul_path_accessf(sys, F_OK, "cpu%d/online", cpu) != 0) { + warnx(_("CPU %u is not hot pluggable"), cpu); + fails++; + continue; + } + if (ul_path_readf_s32(sys, &online, "cpu%d/online", cpu) == 0 + && online == 1 + && enable == 1) { + printf(_("CPU %u is already enabled\n"), cpu); + continue; + } + if (online == 0 && enable == 0) { + printf(_("CPU %u is already disabled\n"), cpu); + continue; + } + if (ul_path_accessf(sys, F_OK, "cpu%d/configure", cpu) == 0) + ul_path_readf_s32(sys, &configured, "cpu%d/configure", cpu); + if (enable) { + rc = ul_path_writef_string(sys, "1", "cpu%d/online", cpu); + if (rc != 0 && configured == 0) { + warn(_("CPU %u enable failed (CPU is deconfigured)"), cpu); + fails++; + } else if (rc != 0) { + warn(_("CPU %u enable failed"), cpu); + fails++; + } else + printf(_("CPU %u enabled\n"), cpu); + } else { + if (onlinecpus && num_online_cpus() == 1) { + warnx(_("CPU %u disable failed (last enabled CPU)"), cpu); + fails++; + continue; + } + rc = ul_path_writef_string(sys, "0", "cpu%d/online", cpu); + if (rc != 0) { + warn(_("CPU %u disable failed"), cpu); + fails++; + } else { + printf(_("CPU %u disabled\n"), cpu); + if (onlinecpus) + CPU_CLR_S(cpu, setsize, onlinecpus); + } + } + } + + return fails == 0 ? 0 : fails == maxcpus ? -1 : 1; +} + +static int cpu_rescan(struct path_cxt *sys) +{ + if (ul_path_access(sys, F_OK, "rescan") != 0) + errx(EXIT_FAILURE, _("This system does not support rescanning of CPUs")); + + if (ul_path_write_string(sys, "1", "rescan") != 0) + err(EXIT_FAILURE, _("Failed to trigger rescan of CPUs")); + + printf(_("Triggered rescan of CPUs\n")); + return 0; +} + +static int cpu_set_dispatch(struct path_cxt *sys, int mode) +{ + if (ul_path_access(sys, F_OK, "dispatching") != 0) + errx(EXIT_FAILURE, _("This system does not support setting " + "the dispatching mode of CPUs")); + if (mode == 0) { + if (ul_path_write_string(sys, "0", "dispatching") != 0) + err(EXIT_FAILURE, _("Failed to set horizontal dispatch mode")); + + printf(_("Successfully set horizontal dispatching mode\n")); + } else { + if (ul_path_write_string(sys, "1", "dispatching") != 0) + err(EXIT_FAILURE, _("Failed to set vertical dispatch mode")); + + printf(_("Successfully set vertical dispatching mode\n")); + } + return 0; +} + +/* returns: 0 = success + * < 0 = failure + * > 0 = partial success + */ +static int cpu_configure(struct path_cxt *sys, cpu_set_t *cpu_set, size_t setsize, int configure) +{ + int cpu; + int rc, current; + int fails = 0; + + for (cpu = 0; cpu < maxcpus; cpu++) { + if (!CPU_ISSET_S(cpu, setsize, cpu_set)) + continue; + if (ul_path_accessf(sys, F_OK, "cpu%d", cpu) != 0) { + warnx(_("CPU %u does not exist"), cpu); + fails++; + continue; + } + if (ul_path_accessf(sys, F_OK, "cpu%d/configure", cpu) != 0) { + warnx(_("CPU %u is not configurable"), cpu); + fails++; + continue; + } + ul_path_readf_s32(sys, ¤t, "cpu%d/configure", cpu); + if (current == 1 && configure == 1) { + printf(_("CPU %u is already configured\n"), cpu); + continue; + } + if (current == 0 && configure == 0) { + printf(_("CPU %u is already deconfigured\n"), cpu); + continue; + } + if (current == 1 && configure == 0 && onlinecpus && + is_cpu_online(cpu)) { + warnx(_("CPU %u deconfigure failed (CPU is enabled)"), cpu); + fails++; + continue; + } + if (configure) { + rc = ul_path_writef_string(sys, "1", "cpu%d/configure", cpu); + if (rc != 0) { + warn(_("CPU %u configure failed"), cpu); + fails++; + } else + printf(_("CPU %u configured\n"), cpu); + } else { + rc = ul_path_writef_string(sys, "0", "cpu%d/configure", cpu); + if (rc != 0) { + warn(_("CPU %u deconfigure failed"), cpu); + fails++; + } else + printf(_("CPU %u deconfigured\n"), cpu); + } + } + + return fails == 0 ? 0 : fails == maxcpus ? -1 : 1; +} + +static void cpu_parse(char *cpu_string, cpu_set_t *cpu_set, size_t setsize) +{ + int rc; + + rc = cpulist_parse(cpu_string, cpu_set, setsize, 1); + if (rc == 0) + return; + if (rc == 2) + errx(EXIT_FAILURE, _("invalid CPU number in CPU list: %s"), cpu_string); + errx(EXIT_FAILURE, _("failed to parse CPU list: %s"), cpu_string); +} + +static void __attribute__((__noreturn__)) usage(void) +{ + FILE *out = stdout; + fprintf(out, _( + "\nUsage:\n" + " %s [options]\n"), program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fputs(_("Configure CPUs in a multi-processor system.\n"), out); + + fputs(USAGE_OPTIONS, stdout); + fputs(_( + " -e, --enable enable cpus\n" + " -d, --disable disable cpus\n" + " -c, --configure configure cpus\n" + " -g, --deconfigure deconfigure cpus\n" + " -p, --dispatch set dispatching mode\n" + " -r, --rescan trigger rescan of cpus\n" + ), stdout); + printf(USAGE_HELP_OPTIONS(31)); + + printf(USAGE_MAN_TAIL("chcpu(8)")); + exit(EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) +{ + struct path_cxt *sys = NULL; /* _PATH_SYS_CPU handler */ + cpu_set_t *cpu_set = NULL; + size_t setsize; + int cmd = -1; + int c, rc; + + static const struct option longopts[] = { + { "configure", required_argument, NULL, 'c' }, + { "deconfigure",required_argument, NULL, 'g' }, + { "disable", required_argument, NULL, 'd' }, + { "dispatch", required_argument, NULL, 'p' }, + { "enable", required_argument, NULL, 'e' }, + { "help", no_argument, NULL, 'h' }, + { "rescan", no_argument, NULL, 'r' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } + }; + + static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ + { 'c','d','e','g','p' }, + { 0 } + }; + int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + close_stdout_atexit(); + + ul_path_init_debug(); + sys = ul_new_path(_PATH_SYS_CPU); + if (!sys) + err(EXIT_FAILURE, _("failed to initialize sysfs handler")); + + maxcpus = get_max_number_of_cpus(); + if (maxcpus < 1) + errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting")); + + if (ul_path_access(sys, F_OK, "online") == 0) + ul_path_readf_cpulist(sys, &cpu_set, maxcpus, "online"); + else + cpu_set = CPU_ALLOC(maxcpus); + if (!cpu_set) + err(EXIT_FAILURE, _("cpuset_alloc failed")); + + setsize = CPU_ALLOC_SIZE(maxcpus); + + while ((c = getopt_long(argc, argv, "c:d:e:g:hp:rV", longopts, NULL)) != -1) { + + err_exclusive_options(c, longopts, excl, excl_st); + + switch (c) { + case 'c': + cmd = CMD_CPU_CONFIGURE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'd': + cmd = CMD_CPU_DISABLE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'e': + cmd = CMD_CPU_ENABLE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'g': + cmd = CMD_CPU_DECONFIGURE; + cpu_parse(argv[optind - 1], cpu_set, setsize); + break; + case 'p': + if (strcmp("horizontal", argv[optind - 1]) == 0) + cmd = CMD_CPU_DISPATCH_HORIZONTAL; + else if (strcmp("vertical", argv[optind - 1]) == 0) + cmd = CMD_CPU_DISPATCH_VERTICAL; + else + errx(EXIT_FAILURE, _("unsupported argument: %s"), + argv[optind -1 ]); + break; + case 'r': + cmd = CMD_CPU_RESCAN; + break; + + case 'h': + usage(); + case 'V': + print_version(EXIT_SUCCESS); + default: + errtryhelp(EXIT_FAILURE); + } + } + + if ((argc == 1) || (argc != optind)) { + warnx(_("bad usage")); + errtryhelp(EXIT_FAILURE); + } + + switch (cmd) { + case CMD_CPU_ENABLE: + rc = cpu_enable(sys, cpu_set, maxcpus, 1); + break; + case CMD_CPU_DISABLE: + rc = cpu_enable(sys, cpu_set, maxcpus, 0); + break; + case CMD_CPU_CONFIGURE: + rc = cpu_configure(sys, cpu_set, maxcpus, 1); + break; + case CMD_CPU_DECONFIGURE: + rc = cpu_configure(sys, cpu_set, maxcpus, 0); + break; + case CMD_CPU_RESCAN: + rc = cpu_rescan(sys); + break; + case CMD_CPU_DISPATCH_HORIZONTAL: + rc = cpu_set_dispatch(sys, 0); + break; + case CMD_CPU_DISPATCH_VERTICAL: + rc = cpu_set_dispatch(sys, 1); + break; + default: + rc = -EINVAL; + break; + } + + CPU_FREE(cpu_set); + ul_unref_path(sys); + + return rc == 0 ? EXIT_SUCCESS : + rc < 0 ? EXIT_FAILURE : CHCPU_EXIT_SOMEOK; +} diff --git a/sys-utils/chmem.8 b/sys-utils/chmem.8 new file mode 100644 index 0000000..d152567 --- /dev/null +++ b/sys-utils/chmem.8 @@ -0,0 +1,173 @@ +'\" t +.\" Title: chmem +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: System Administration +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "CHMEM" "8" "2022-05-11" "util\-linux 2.38.1" "System Administration" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +chmem \- configure memory +.SH "SYNOPSIS" +.sp +\fBchmem\fP [\fB\-h] [\fP\-V*] [\fB\-v\fP] [\fB\-e\fP|\fB\-d\fP] [\fISIZE\fP|\fIRANGE\fP \fB\-b\fP \fIBLOCKRANGE\fP] [\fB\-z\fP \fIZONE\fP] +.SH "DESCRIPTION" +.sp +The chmem command sets a particular size or range of memory online or offline. +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +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. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +Specify \fIRANGE\fP in the form 0x\-0x as shown in the output of the \fBlsmem\fP(1) command. is the hexadecimal address of the first byte and is the hexadecimal address of the last byte in the memory range. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +Specify \fIBLOCKRANGE\fP in the form \- or as shown in the output of the \fBlsmem\fP(1) 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. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +. sp -1 +. IP \(bu 2.3 +.\} +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, \fBchmem\fP 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\fP option to see all available zones. +.RE +.sp +\fISIZE\fP and \fIRANGE\fP must be aligned to the Linux memory block size, as shown in the output of the \fBlsmem\fP(1) command. +.sp +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. +.sp +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" +.sp +\fB\-b\fP, \fB\-\-blocks\fP +.RS 4 +Use a \fIBLOCKRANGE\fP parameter instead of \fIRANGE\fP or \fISIZE\fP for the \fB\-\-enable\fP and \fB\-\-disable\fP options. +.RE +.sp +\fB\-d\fP, \fB\-\-disable\fP +.RS 4 +Set the specified \fIRANGE\fP, \fISIZE\fP, or \fIBLOCKRANGE\fP of memory offline. +.RE +.sp +\fB\-e\fP, \fB\-\-enable\fP +.RS 4 +Set the specified \fIRANGE\fP, \fISIZE\fP, or \fIBLOCKRANGE\fP of memory online. +.RE +.sp +\fB\-z\fP, \fB\-\-zone\fP +.RS 4 +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. +.RE +.sp +\fB\-v\fP, \fB\-\-verbose\fP +.RS 4 +Verbose mode. Causes \fBchmem\fP to print debugging messages about it\(cqs progress. +.RE +.sp +\fB\-h\fP, \fB\-\-help\fP +.RS 4 +Display help text and exit. +.RE +.sp +\fB\-V\fP, \fB\-\-version\fP +.RS 4 +Print version and exit. +.RE +.SH "EXIT STATUS" +.sp +\fBchmem\fP has the following exit status values: +.sp +\fB0\fP +.RS 4 +success +.RE +.sp +\fB1\fP +.RS 4 +failure +.RE +.sp +\fB64\fP +.RS 4 +partial success +.RE +.SH "EXAMPLE" +.sp +\fBchmem \-\-enable 1024\fP +.RS 4 +This command requests 1024 MiB of memory to be set online. +.RE +.sp +\fBchmem \-e 2g\fP +.RS 4 +This command requests 2 GiB of memory to be set online. +.RE +.sp +\fBchmem \-\-disable 0x00000000e4000000\-0x00000000f3ffffff\fP +.RS 4 +This command requests the memory range starting with 0x00000000e4000000 and ending with 0x00000000f3ffffff to be set offline. +.RE +.sp +\fBchmem \-b \-d 10\fP +.RS 4 +This command requests the memory block number 10 to be set offline. +.RE +.SH "SEE ALSO" +.sp +\fBlsmem\fP(1) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +The \fBchmem\fP command is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/chmem.8.adoc b/sys-utils/chmem.8.adoc new file mode 100644 index 0000000..de628aa --- /dev/null +++ b/sys-utils/chmem.8.adoc @@ -0,0 +1,91 @@ +//po4a: entry man manual += chmem(8) +:doctype: manpage +:man manual: System Administration +:man source: util-linux {release-version} +:page-layout: base +:command: chmem + +== NAME + +chmem - configure memory + +== SYNOPSIS + +*chmem* [*-h] [*-V*] [*-v*] [*-e*|*-d*] [_SIZE_|_RANGE_ *-b* _BLOCKRANGE_] [*-z* _ZONE_] + +== DESCRIPTION + +The chmem command sets a particular size or range of memory online or offline. + +* Specify _SIZE_ 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. + +* Specify _RANGE_ in the form 0x-0x as shown in the output of the *lsmem*(1) command. is the hexadecimal address of the first byte and is the hexadecimal address of the last byte in the memory range. + +* Specify _BLOCKRANGE_ in the form - or as shown in the output of the *lsmem*(1) 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. _BLOCKRANGE_ requires the *--blocks* option. + +* Specify _ZONE_ as the name of a memory zone, as shown in the output of the *lsmem -o +ZONES* 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 *--zone* 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 *--help* option to see all available zones. + +_SIZE_ and _RANGE_ must be aligned to the Linux memory block size, as shown in the output of the *lsmem*(1) 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 *chmem* starts with the lowest memory block numbers. When setting memory offline *chmem* starts with the highest memory block numbers. + +== OPTIONS + +*-b*, *--blocks*:: +Use a _BLOCKRANGE_ parameter instead of _RANGE_ or _SIZE_ for the *--enable* and *--disable* options. + +*-d*, *--disable*:: +Set the specified _RANGE_, _SIZE_, or _BLOCKRANGE_ of memory offline. + +*-e*, *--enable*:: +Set the specified _RANGE_, _SIZE_, or _BLOCKRANGE_ of memory online. + +*-z*, *--zone*:: +Select the memory _ZONE_ where to set the specified _RANGE_, _SIZE_, or _BLOCKRANGE_ of memory online or offline. By default, memory will be set online to the zone Movable, if possible. + +*-v*, *--verbose*:: +Verbose mode. Causes *chmem* to print debugging messages about it's progress. + +include::man-common/help-version.adoc[] + +== EXIT STATUS + +*chmem* has the following exit status values: + +*0*:: +success + +*1*:: +failure + +*64*:: +partial success + +== EXAMPLE + +*chmem --enable 1024*:: +This command requests 1024 MiB of memory to be set online. + +*chmem -e 2g*:: +This command requests 2 GiB of memory to be set online. + +*chmem --disable 0x00000000e4000000-0x00000000f3ffffff*:: +This command requests the memory range starting with 0x00000000e4000000 and ending with 0x00000000f3ffffff to be set offline. + +*chmem -b -d 10*:: +This command requests the memory block number 10 to be set offline. + +== SEE ALSO + +*lsmem*(1) + +include::man-common/bugreports.adoc[] + +include::man-common/footer.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/chmem.c b/sys-utils/chmem.c new file mode 100644 index 0000000..09d0af6 --- /dev/null +++ b/sys-utils/chmem.c @@ -0,0 +1,459 @@ +/* + * 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 "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" + +struct chmem_desc { + struct path_cxt *sysmem; /* _PATH_SYS_MEMORY handler */ + 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")); + + if (ul_path_readf_buffer(desc->sysmem, line, sizeof(line), "%s/state", name) > 0 + && strncmp(onoff, line, 6) == 0) + continue; + + if (desc->have_zones) { + ul_path_readf_buffer(desc->sysmem, line, sizeof(line), "%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)) != 0) + 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 = ul_path_writef_string(desc->sysmem, onoff, "%s/state", name); + if (rc != 0 && 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)); + if (ul_path_readf_buffer(desc->sysmem, line, sizeof(line), "%s/state", name) > 0 + && 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) { + ul_path_readf_buffer(desc->sysmem, line, sizeof(line), "%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)) != 0) { + 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 = ul_path_writef_string(desc->sysmem, onoff, "%s/state", name); + if (rc != 0) { + 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) != 0) + return 0; + return isdigit_string(de->d_name + 6); +} + +static void read_info(struct chmem_desc *desc) +{ + char line[128]; + + desc->ndirs = scandir(_PATH_SYS_MEMORY, &desc->dirs, filter, versionsort); + if (desc->ndirs <= 0) + goto fail; + ul_path_read_buffer(desc->sysmem, line, sizeof(line), "block_size_bytes"); + + errno = 0; + desc->block_size = strtoumax(line, NULL, 16); + if (errno) + goto fail; + return; +fail: + err(EXIT_FAILURE, _("Failed to read %s"), _PATH_SYS_MEMORY); +} + +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 = { 0 }, *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); + close_stdout_atexit(); + + ul_path_init_debug(); + desc->sysmem = ul_new_path(_PATH_SYS_MEMORY); + if (!desc->sysmem) + err(EXIT_FAILURE, _("failed to initialize %s handler"), _PATH_SYS_MEMORY); + + 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 'v': + desc->verbose = 1; + break; + case 'z': + zone = xstrdup(optarg); + break; + + case 'h': + usage(); + case 'V': + print_version(EXIT_SUCCESS); + 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 (ul_path_access(desc->sysmem, F_OK, "memory0/valid_zones") == 0) + 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); + + ul_unref_path(desc->sysmem); + + return rc == 0 ? EXIT_SUCCESS : + rc < 0 ? EXIT_FAILURE : CHMEM_EXIT_SOMEOK; +} diff --git a/sys-utils/choom.1 b/sys-utils/choom.1 new file mode 100644 index 0000000..e55b915 --- /dev/null +++ b/sys-utils/choom.1 @@ -0,0 +1,88 @@ +'\" t +.\" Title: choom +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: User Commands +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "CHOOM" "1" "2022-05-11" "util\-linux 2.38.1" "User Commands" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +choom \- display and adjust OOM\-killer score. +.sp +\fBchoom\fP \fB\-p\fP \fIPID\fP +.sp +\fBchoom\fP \fB\-p\fP \fIPID\fP \fB\-n\fP \fInumber\fP +.sp +\fBchoom\fP \fB\-n\fP \fInumber\fP [\-\-] \fIcommand\fP [\fIargument\fP ...] +.SH "DESCRIPTION" +.sp +The \fBchoom\fP command displays and adjusts Out\-Of\-Memory killer score setting. +.SH "OPTIONS" +.sp +\fB\-p\fP, \fB\-\-pid\fP \fIpid\fP +.RS 4 +Specifies process ID. +.RE +.sp +\fB\-n\fP, \fB\-\-adjust\fP \fIvalue\fP +.RS 4 +Specify the adjust score value. +.RE +.sp +\fB\-h\fP, \fB\-\-help\fP +.RS 4 +Display help text and exit. +.RE +.sp +\fB\-V\fP, \fB\-\-version\fP +.RS 4 +Print version and exit. +.RE +.SH "NOTES" +.sp +Linux kernel uses the badness heuristic to select which process gets killed in out of memory conditions. +.sp +The badness heuristic assigns a value to each candidate task ranging from 0 (never kill) to 1000 (always kill) to determine which process is targeted. The units are roughly a proportion along that range of allowed memory the process may allocate from based on an estimation of its current memory and swap use. For example, if a task is using all allowed memory, its badness score will be 1000. If it is using half of its allowed memory, its score will be 500. +.sp +There is an additional factor included in the badness score: the current memory and swap usage is discounted by 3% for root processes. +.sp +The amount of "allowed" memory depends on the context in which the oom killer was called. If it is due to the memory assigned to the allocating task\(cqs cpuset being exhausted, the allowed memory represents the set of mems assigned to that cpuset. If it is due to a mempolicy\(cqs node(s) being exhausted, the allowed memory represents the set of mempolicy nodes. If it is due to a memory limit (or swap limit) being reached, the allowed memory is that configured limit. Finally, if it is due to the entire system being out of memory, the allowed memory represents all allocatable resources. +.sp +The adjust score value is added to the badness score before it is used to determine which task to kill. Acceptable values range from \-1000 to +1000. This allows userspace to polarize the preference for oom killing either by always preferring a certain task or completely disabling it. The lowest possible value, \-1000, is equivalent to disabling oom killing entirely for that task since it will always report a badness score of 0. +.sp +Setting an adjust score value of +500, for example, is roughly equivalent to allowing the remainder of tasks sharing the same system, cpuset, mempolicy, or memory controller resources to use at least 50% more memory. A value of \-500, on the other hand, would be roughly equivalent to discounting 50% of the task\(cqs allowed memory from being considered as scoring against the task. +.SH "AUTHORS" +.sp +.MTO "kzak\(atredhat.com" "Karel Zak" "" +.SH "SEE ALSO" +.sp +\fBproc\fP(5) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +The \fBchoom\fP command is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/choom.1.adoc b/sys-utils/choom.1.adoc new file mode 100644 index 0000000..51d43e7 --- /dev/null +++ b/sys-utils/choom.1.adoc @@ -0,0 +1,61 @@ +//po4a: entry man manual += choom(1) +:doctype: manpage +:man manual: User Commands +:man source: util-linux {release-version} +:page-layout: base +:command: choom + +== NAME + +choom - display and adjust OOM-killer score. + +*choom* *-p* _PID_ + +*choom* *-p* _PID_ *-n* _number_ + +*choom* *-n* _number_ [--] _command_ [_argument_ ...] + +== DESCRIPTION + +The *choom* command displays and adjusts Out-Of-Memory killer score setting. + +== OPTIONS + +*-p*, *--pid* _pid_:: +Specifies process ID. + +*-n*, *--adjust* _value_:: +Specify the adjust score value. + +include::man-common/help-version.adoc[] + +== NOTES + +Linux kernel uses the badness heuristic to select which process gets killed in out of memory conditions. + +The badness heuristic assigns a value to each candidate task ranging from 0 (never kill) to 1000 (always kill) to determine which process is targeted. The units are roughly a proportion along that range of allowed memory the process may allocate from based on an estimation of its current memory and swap use. For example, if a task is using all allowed memory, its badness score will be 1000. If it is using half of its allowed memory, its score will be 500. + +There is an additional factor included in the badness score: the current memory and swap usage is discounted by 3% for root processes. + +The amount of "allowed" memory depends on the context in which the oom killer was called. If it is due to the memory assigned to the allocating task's cpuset being exhausted, the allowed memory represents the set of mems assigned to that cpuset. If it is due to a mempolicy's node(s) being exhausted, the allowed memory represents the set of mempolicy nodes. If it is due to a memory limit (or swap limit) being reached, the allowed memory is that configured limit. Finally, if it is due to the entire system being out of memory, the allowed memory represents all allocatable resources. + +The adjust score value is added to the badness score before it is used to determine which task to kill. Acceptable values range from -1000 to +1000. This allows userspace to polarize the preference for oom killing either by always preferring a certain task or completely disabling it. The lowest possible value, -1000, is equivalent to disabling oom killing entirely for that task since it will always report a badness score of 0. + +Setting an adjust score value of +500, for example, is roughly equivalent to allowing the remainder of tasks sharing the same system, cpuset, mempolicy, or memory controller resources to use at least 50% more memory. A value of -500, on the other hand, would be roughly equivalent to discounting 50% of the task's allowed memory from being considered as scoring against the task. + +== AUTHORS + +mailto:kzak@redhat.com[Karel Zak] + +== SEE ALSO + +*proc*(5) + +include::man-common/bugreports.adoc[] + +include::man-common/footer.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/choom.c b/sys-utils/choom.c new file mode 100644 index 0000000..b3d3e4d --- /dev/null +++ b/sys-utils/choom.c @@ -0,0 +1,159 @@ +/* + * choom - Change OOM score setting + * + * Copyright (C) 2018 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 "nls.h" +#include "c.h" +#include "path.h" +#include "strutils.h" +#include "closestream.h" + +static void __attribute__((__noreturn__)) usage(void) +{ + FILE *out = stdout; + fputs(USAGE_HEADER, out); + fprintf(out, + _(" %1$s [options] -p pid\n" + " %1$s [options] -n number -p pid\n" + " %1$s [options] -n number [--] command [args...]]\n"), + program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fputs(_("Display and adjust OOM-killer score.\n"), out); + + fputs(USAGE_OPTIONS, out); + fputs(_(" -n, --adjust specify the adjust score value\n"), out); + fputs(_(" -p, --pid process ID\n"), out); + fputs(USAGE_SEPARATOR, out); + printf(USAGE_HELP_OPTIONS(24)); + printf(USAGE_MAN_TAIL("choom(1)")); + exit(EXIT_SUCCESS); +} + +static int get_score(struct path_cxt *pc) +{ + int ret; + + if (ul_path_read_s32(pc, &ret, "oom_score") != 0) + err(EXIT_FAILURE, _("failed to read OOM score value")); + + return ret; +} + +static int get_score_adj(struct path_cxt *pc) +{ + int ret; + + if (ul_path_read_s32(pc, &ret, "oom_score_adj") != 0) + err(EXIT_FAILURE, _("failed to read OOM score adjust value")); + + return ret; +} + +static int set_score_adj(struct path_cxt *pc, int adj) +{ + return ul_path_write_s64(pc, adj, "oom_score_adj"); +} + +int main(int argc, char **argv) +{ + pid_t pid = 0; + int c, adj = 0, has_adj = 0; + struct path_cxt *pc = NULL; + + static const struct option longopts[] = { + { "adjust", required_argument, NULL, 'n' }, + { "pid", required_argument, NULL, 'p' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + close_stdout_atexit(); + + while ((c = getopt_long(argc, argv, "hn:p:V", longopts, NULL)) != -1) { + switch (c) { + case 'p': + pid = strtos32_or_err(optarg, _("invalid PID argument")); + break; + case 'n': + adj = strtos32_or_err(optarg, _("invalid adjust argument")); + has_adj = 1; + break; + + case 'V': + print_version(EXIT_SUCCESS); + case 'h': + usage(); + default: + errtryhelp(EXIT_FAILURE); + } + } + + if (optind < argc && pid) { + warnx(_("invalid argument: %s"), argv[optind]); + errtryhelp(EXIT_FAILURE); + } + if (!pid && argc - optind < 1) { + warnx(_("no PID or COMMAND specified")); + errtryhelp(EXIT_FAILURE); + } + if (optind < argc && !has_adj) { + warnx(_("no OOM score adjust value specified")); + errtryhelp(EXIT_FAILURE); + } + + pc = ul_new_path("/proc/%d", (int) (pid ? pid : getpid())); + + /* Show */ + if (!has_adj) { + printf(_("pid %d's current OOM score: %d\n"), pid, get_score(pc)); + printf(_("pid %d's current OOM score adjust value: %d\n"), pid, get_score_adj(pc)); + + /* Change */ + } else if (pid) { + int old = get_score_adj(pc); + + if (set_score_adj(pc, adj)) + err(EXIT_FAILURE, _("failed to set score adjust value")); + + printf(_("pid %d's OOM score adjust value changed from %d to %d\n"), pid, old, adj); + + /* Start new process */ + } else { + if (set_score_adj(pc, adj)) + err(EXIT_FAILURE, _("failed to set score adjust value")); + ul_unref_path(pc); + argv += optind; + execvp(argv[0], argv); + errexec(argv[0]); + } + + ul_unref_path(pc); + return EXIT_SUCCESS; +} diff --git a/sys-utils/ctrlaltdel.8 b/sys-utils/ctrlaltdel.8 new file mode 100644 index 0000000..e7ffa38 --- /dev/null +++ b/sys-utils/ctrlaltdel.8 @@ -0,0 +1,80 @@ +'\" t +.\" Title: ctrlaltdel +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: System Administration +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "CTRLALTDEL" "8" "2022-05-11" "util\-linux 2.38.1" "System Administration" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +ctrlaltdel \- set the function of the Ctrl\-Alt\-Del combination +.SH "SYNOPSIS" +.sp +\fBctrlaltdel\fP \fBhard\fP|\fBsoft\fP +.SH "DESCRIPTION" +.sp +Based on examination of the \fIlinux/kernel/reboot.c\fP code, it is clear that there are two supported functions that the sequence can perform. +.sp +\fBhard\fP +.RS 4 +Immediately reboot the computer without calling \fBsync\fP(2) and without any other preparation. This is the default. +.RE +.sp +\fBsoft\fP +.RS 4 +Make the kernel send the \fBSIGINT\fP (interrupt) signal to the \fBinit\fP process (this is always the process with PID 1). If this option is used, the \fBinit\fP(8) program must support this feature. Since there are now several \fBinit\fP(8) programs in the Linux community, please consult the documentation for the version that you are currently using. +.RE +.sp +When the command is run without any argument, it will display the current setting. +.sp +The function of \fBctrlaltdel\fP is usually set in the \fI/etc/rc.local\fP file. +.SH "OPTIONS" +.sp +\fB\-h\fP, \fB\-\-help\fP +.RS 4 +Display help text and exit. +.RE +.sp +\fB\-V\fP, \fB\-\-version\fP +.RS 4 +Print version and exit. +.RE +.SH "FILES" +.sp +\fI/etc/rc.local\fP +.SH "AUTHORS" +.sp +.MTO "poe\(atdaimi.aau.dk" "Peter Orbaek" "" +.SH "SEE ALSO" +.sp +\fBinit\fP(8), +\fBsystemd\fP(1) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +The \fBctrlaltdel\fP command is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/ctrlaltdel.8.adoc b/sys-utils/ctrlaltdel.8.adoc new file mode 100644 index 0000000..5784240 --- /dev/null +++ b/sys-utils/ctrlaltdel.8.adoc @@ -0,0 +1,58 @@ +//po4a: entry man manual +//// +Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) +May be distributed under the GNU General Public License +//// += ctrlaltdel(8) +:doctype: manpage +:man manual: System Administration +:man source: util-linux {release-version} +:page-layout: base +:command: ctrlaltdel + +== NAME + +ctrlaltdel - set the function of the Ctrl-Alt-Del combination + +== SYNOPSIS + +*ctrlaltdel* *hard*|*soft* + +== DESCRIPTION + +Based on examination of the _linux/kernel/reboot.c_ code, it is clear that there are two supported functions that the sequence can perform. + +*hard*:: +Immediately reboot the computer without calling *sync*(2) and without any other preparation. This is the default. + +*soft*:: +Make the kernel send the *SIGINT* (interrupt) signal to the *init* process (this is always the process with PID 1). If this option is used, the *init*(8) program must support this feature. Since there are now several *init*(8) programs in the Linux community, please consult the documentation for the version that you are currently using. + +When the command is run without any argument, it will display the current setting. + +The function of *ctrlaltdel* is usually set in the _/etc/rc.local_ file. + +== OPTIONS + +include::man-common/help-version.adoc[] + +== FILES + +_/etc/rc.local_ + +== AUTHORS + +mailto:poe@daimi.aau.dk[Peter Orbaek] + +== SEE ALSO + +*init*(8), +*systemd*(1) + +include::man-common/bugreports.adoc[] + +include::man-common/footer.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/ctrlaltdel.c b/sys-utils/ctrlaltdel.c new file mode 100644 index 0000000..303d2dc --- /dev/null +++ b/sys-utils/ctrlaltdel.c @@ -0,0 +1,113 @@ +/* + * ctrlaltdel.c - Set the function of the Ctrl-Alt-Del combination + * Created 4-Jul-92 by Peter Orbaek + * 1999-02-22 Arkadiusz MiÅ›kiewicz + * - added Native Language Support + */ + +#include +#include +#include +#include +#include +#include +#include +#include "nls.h" +#include "c.h" +#include "closestream.h" +#include "pathnames.h" +#include "path.h" + +#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF +#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000 + +static void __attribute__((__noreturn__)) usage(void) +{ + FILE *out = stdout; + fputs(USAGE_HEADER, out); + fprintf(out, _(" %s hard|soft\n"), program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fprintf(out, _("Set the function of the Ctrl-Alt-Del combination.\n")); + + fputs(USAGE_OPTIONS, out); + printf(USAGE_HELP_OPTIONS(16)); + printf(USAGE_MAN_TAIL("ctrlaltdel(8)")); + exit(EXIT_SUCCESS); +} + +static int get_cad(void) +{ + uint64_t val; + + if (ul_path_read_u64(NULL, &val, _PATH_PROC_CTRL_ALT_DEL) != 0) + err(EXIT_FAILURE, _("cannot read %s"), _PATH_PROC_CTRL_ALT_DEL); + + switch (val) { + case 0: + fputs("soft\n", stdout); + break; + case 1: + fputs("hard\n", stdout); + break; + default: + printf("%s hard\n", _("implicit")); + warnx(_("unexpected value in %s: %ju"), _PATH_PROC_CTRL_ALT_DEL, val); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +static int set_cad(const char *arg) +{ + unsigned int cmd; + + if (geteuid()) { + warnx(_("You must be root to set the Ctrl-Alt-Del behavior")); + return EXIT_FAILURE; + } + if (!strcmp("hard", arg)) + cmd = LINUX_REBOOT_CMD_CAD_ON; + else if (!strcmp("soft", arg)) + cmd = LINUX_REBOOT_CMD_CAD_OFF; + else { + warnx(_("unknown argument: %s"), arg); + return EXIT_FAILURE; + } + if (reboot(cmd) < 0) { + warn("reboot"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int main(int argc, char **argv) +{ + int ch, ret; + static const struct option longopts[] = { + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + close_stdout_atexit(); + + while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) + switch (ch) { + case 'V': + print_version(EXIT_SUCCESS); + case 'h': + usage(); + default: + errtryhelp(EXIT_FAILURE); + } + + if (argc < 2) + ret = get_cad(); + else + ret = set_cad(argv[1]); + return ret; +} diff --git a/sys-utils/dmesg.1 b/sys-utils/dmesg.1 new file mode 100644 index 0000000..a7f62d6 --- /dev/null +++ b/sys-utils/dmesg.1 @@ -0,0 +1,312 @@ +'\" t +.\" Title: dmesg +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.15 +.\" Date: 2022-05-11 +.\" Manual: User Commands +.\" Source: util-linux 2.38.1 +.\" Language: English +.\" +.TH "DMESG" "1" "2022-05-11" "util\-linux 2.38.1" "User Commands" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +dmesg \- print or control the kernel ring buffer +.SH "SYNOPSIS" +.sp +\fBdmesg\fP [options] +.sp +\fBdmesg\fP \fB\-\-clear\fP +.sp +\fBdmesg\fP \fB\-\-read\-clear\fP [options] +.sp +\fBdmesg\fP \fB\-\-console\-level\fP \fIlevel\fP +.sp +\fBdmesg\fP \fB\-\-console\-on\fP +.sp +\fBdmesg\fP \fB\-\-console\-off\fP +.SH "DESCRIPTION" +.sp +\fBdmesg\fP is used to examine or control the kernel ring buffer. +.sp +The default action is to display all messages from the kernel ring buffer. +.SH "OPTIONS" +.sp +The \fB\-\-clear\fP, \fB\-\-read\-clear\fP, \fB\-\-console\-on\fP, \fB\-\-console\-off\fP, and \fB\-\-console\-level\fP options are mutually exclusive. +.sp +\fB\-C\fP, \fB\-\-clear\fP +.RS 4 +Clear the ring buffer. +.RE +.sp +\fB\-c\fP, \fB\-\-read\-clear\fP +.RS 4 +Clear the ring buffer after first printing its contents. +.RE +.sp +\fB\-D\fP, \fB\-\-console\-off\fP +.RS 4 +Disable the printing of messages to the console. +.RE +.sp +\fB\-d\fP, \fB\-\-show\-delta\fP +.RS 4 +Display the timestamp and the time delta spent between messages. If used together with \fB\-\-notime\fP then only the time delta without the timestamp is printed. +.RE +.sp +\fB\-E\fP, \fB\-\-console\-on\fP +.RS 4 +Enable printing messages to the console. +.RE +.sp +\fB\-e\fP, \fB\-\-reltime\fP +.RS 4 +Display the local time and the delta in human\-readable format. Be aware that conversion to the local time could be inaccurate (see \fB\-T\fP for more details). +.RE +.sp +\fB\-F\fP, \fB\-\-file\fP \fIfile\fP +.RS 4 +Read the syslog messages from the given \fIfile\fP. Note that \fB\-F\fP does not support messages in kmsg format. The old syslog format is supported only. +.RE +.sp +\fB\-f\fP, \fB\-\-facility\fP \fIlist\fP +.RS 4 +Restrict output to the given (comma\-separated) \fIlist\fP of facilities. For example: +.sp +\fBdmesg \-\-facility=daemon\fP +.sp +will print messages from system daemons only. For all supported facilities see the \fB\-\-help\fP output. +.RE +.sp +\fB\-H\fP, \fB\-\-human\fP +.RS 4 +Enable human\-readable output. See also \fB\-\-color\fP, \fB\-\-reltime\fP and \fB\-\-nopager\fP. +.RE +.sp +\fB\-J\fP, \fB\-\-json\fP +.RS 4 +Use JSON output format. The time output format is in "sec.usec" format only, log priority level is not decoded by default (use \fB\-\-decode\fP to split into facility and priority), the other options to control the output format or time format are silently ignored. +.RE +.sp +\fB\-k\fP, \fB\-\-kernel\fP +.RS 4 +Print kernel messages. +.RE +.sp +\fB\-L\fP, \fB\-\-color\fP[=\fIwhen\fP] +.RS 4 +Colorize the output. The optional argument \fIwhen\fP can be \fBauto\fP, \fBnever\fP or \fBalways\fP. If the \fIwhen\fP argument is omitted, it defaults to \fBauto\fP. The colors can be disabled; for the current built\-in default see the \fB\-\-help\fP output. See also the \fBCOLORS\fP section below. +.RE +.sp +\fB\-l\fP, \fB\-\-level\fP \fIlist\fP +.RS 4 +Restrict output to the given (comma\-separated) \fIlist\fP of levels. For example: +.sp +\fBdmesg \-\-level=err,warn\fP +.sp +will print error and warning messages only. For all supported levels see the \fB\-\-help\fP output. +.RE +.sp +\fB\-n\fP, \fB\-\-console\-level\fP \fIlevel\fP +.RS 4 +Set the \fIlevel\fP at which printing of messages is done to the console. The \fIlevel\fP is a level number or abbreviation of the level name. For all supported levels see the \fB\-\-help\fP output. +.sp +For example, \fB\-n 1\fP or \fB\-n emerg\fP prevents all messages, except emergency (panic) messages, from appearing on the console. All levels of messages are still written to \fI/proc/kmsg\fP, so \fBsyslogd\fP(8) can still be used to control exactly where kernel messages appear. When the \fB\-n\fP option is used, \fBdmesg\fP will \fInot\fP print or clear the kernel ring buffer. +.RE +.sp +\fB\-\-noescape\fP +.RS 4 +The unprintable and potentially unsafe characters (e.g., broken multi\-byte sequences, terminal controlling chars, etc.) are escaped in format \(rsx for security reason by default. This option disables this feature at all. It\(cqs usable for example for debugging purpose together with \fB\-\-raw\fP. Be careful and don\(cqt use it by default. +.RE +.sp +\fB\-P\fP, \fB\-\-nopager\fP +.RS 4 +Do not pipe output into a pager. A pager is enabled by default for \fB\-\-human\fP output. +.RE +.sp +\fB\-p\fP, \fB\-\-force\-prefix\fP +.RS 4 +Add facility, level or timestamp information to each line of a multi\-line message. +.RE +.sp +\fB\-r\fP, \fB\-\-raw\fP +.RS 4 +Print the raw message buffer, i.e., do not strip the log\-level prefixes, but all unprintable characters are still escaped (see also \fB\-\-noescape\fP). +.sp +Note that the real raw format depends on the method how \fBdmesg\fP reads kernel messages. The \fI/dev/kmsg\fP device uses a different format than \fBsyslog\fP(2). For backward compatibility, \fBdmesg\fP returns data always in the \fBsyslog\fP(2) format. It is possible to read the real raw data from \fI/dev/kmsg\fP by, for example, the command \(aqdd if=/dev/kmsg iflag=nonblock\(aq. +.RE +.sp +\fB\-S\fP, \fB\-\-syslog\fP +.RS 4 +Force \fBdmesg\fP to use the \fBsyslog\fP(2) kernel interface to read kernel messages. The default is to use \fI/dev/kmsg\fP rather than \fBsyslog\fP(2) since kernel 3.5.0. +.RE +.sp +\fB\-s\fP, \fB\-\-buffer\-size\fP \fIsize\fP +.RS 4 +Use a buffer of \fIsize\fP to query the kernel ring buffer. This is 16392 by default. (The default kernel syslog buffer size was 4096 at first, 8192 since 1.3.54, 16384 since 2.1.113.) If you have set the kernel buffer to be larger than the default, then this option can be used to view the entire buffer. +.RE +.sp +\fB\-T\fP, \fB\-\-ctime\fP +.RS 4 +Print human\-readable timestamps. +.sp +\fBBe aware that the timestamp could be inaccurate!\fP The \fBtime\fP source used for the logs is \fBnot updated after\fP system \fBSUSPEND\fP/\fBRESUME\fP. Timestamps are adjusted according to current delta between boottime and monotonic clocks, this works only for messages printed after last resume. +.RE +.sp +\fB\-\-since\fP \fItime\fP +.RS 4 +Display record since the specified time. The time is possible to specify in absolute way as well as by relative notation (e.g. \(aq1 hour ago\(aq). Be aware that the timestamp could be inaccurate and see \fB\-\-ctime\fP for more details. +.RE +.sp +\fB\-\-until\fP \fItime\fP +.RS 4 +Display record until the specified time. The time is possible to specify in absolute way as well as by relative notation (e.g. \(aq1 hour ago\(aq). Be aware that the timestamp could be inaccurate and see \fB\-\-ctime\fP for more details. +.RE +.sp +\fB\-t\fP, \fB\-\-notime\fP +.RS 4 +Do not print kernel\(cqs timestamps. +.RE +.sp +\fB\-\-time\-format\fP \fIformat\fP +.RS 4 +Print timestamps using the given \fIformat\fP, which can be \fBctime\fP, \fBreltime\fP, \fBdelta\fP or \fBiso\fP. The first three formats are aliases of the time\-format\-specific options. The \fBiso\fP format is a \fBdmesg\fP implementation of the ISO\-8601 timestamp format. The purpose of this format is to make the comparing of timestamps between two systems, and any other parsing, easy. The definition of the \fBiso\fP timestamp is: YYYY\-MM\-DDHH:MM:SS,\(<-+>. +.sp +The \fBiso\fP format has the same issue as \fBctime\fP: the time may be inaccurate when a system is suspended and resumed. +.RE +.sp +\fB\-u\fP, \fB\-\-userspace\fP +.RS 4 +Print userspace messages. +.RE +.sp +\fB\-w\fP, \fB\-\-follow\fP +.RS 4 +Wait for new messages. This feature is supported only on systems with a readable \fI/dev/kmsg\fP (since kernel 3.5.0). +.RE +.sp +\fB\-W\fP, \fB\-\-follow\-new\fP +.RS 4 +Wait and print only new messages. +.RE +.sp +\fB\-x\fP, \fB\-\-decode\fP +.RS 4 +Decode facility and level (priority) numbers to human\-readable prefixes. +.RE +.sp +\fB\-h\fP, \fB\-\-help\fP +.RS 4 +Display help text and exit. +.RE +.sp +\fB\-V\fP, \fB\-\-version\fP +.RS 4 +Print version and exit. +.RE +.SH "COLORS" +.sp +The output colorization is implemented by \fBterminal\-colors.d\fP(5) functionality. +Implicit coloring can be disabled by an empty file +.RS 3 +.ll -.6i +.sp +\fI/etc/terminal\-colors.d/dmesg.disable\fP +.br +.RE +.ll +.sp +for the \fBdmesg\fP command or for all tools by +.RS 3 +.ll -.6i +.sp +\fI/etc/terminal\-colors.d/disable\fP +.br +.RE +.ll +.sp +The user\-specific \fI$XDG_CONFIG_HOME/terminal\-colors.d\fP +or \fI$HOME/.config/terminal\-colors.d\fP overrides the global setting. +.sp +Note that the output colorization may be enabled by default, and in this case +\fIterminal\-colors.d\fP directories do not have to exist yet. +.sp +The logical color names supported by \fBdmesg\fP are: +.sp +\fBsubsys\fP +.RS 4 +The message sub\-system prefix (e.g., "ACPI:"). +.RE +.sp +\fBtime\fP +.RS 4 +The message timestamp. +.RE +.sp +\fBtimebreak\fP +.RS 4 +The message timestamp in short ctime format in \fB\-\-reltime\fP or \fB\-\-human\fP output. +.RE +.sp +\fBalert\fP +.RS 4 +The text of the message with the alert log priority. +.RE +.sp +\fBcrit\fP +.RS 4 +The text of the message with the critical log priority. +.RE +.sp +\fBerr\fP +.RS 4 +The text of the message with the error log priority. +.RE +.sp +\fBwarn\fP +.RS 4 +The text of the message with the warning log priority. +.RE +.sp +\fBsegfault\fP +.RS 4 +The text of the message that inform about segmentation fault. +.RE +.SH "EXIT STATUS" +.sp +\fBdmesg\fP can fail reporting permission denied error. This is usually caused by \fBdmesg_restrict\fP kernel setting, please see \fBsyslog\fP(2) for more details. +.SH "AUTHORS" +.sp +.MTO "kzak\(atredhat.com" "Karel Zak" "" +.sp +\fBdmesg\fP was originally written by \c +.MTO "tytso\(atathena.mit.edu" "Theodore Ts\(cqo" "." +.SH "SEE ALSO" +.sp +\fBterminal\-colors.d\fP(5), +\fBsyslogd\fP(8) +.SH "REPORTING BUGS" +.sp +For bug reports, use the issue tracker at \c +.URL "https://github.com/util\-linux/util\-linux/issues" "" "." +.SH "AVAILABILITY" +.sp +The \fBdmesg\fP command is part of the util\-linux package which can be downloaded from \c +.URL "https://www.kernel.org/pub/linux/utils/util\-linux/" "Linux Kernel Archive" "." \ No newline at end of file diff --git a/sys-utils/dmesg.1.adoc b/sys-utils/dmesg.1.adoc new file mode 100644 index 0000000..9072f22 --- /dev/null +++ b/sys-utils/dmesg.1.adoc @@ -0,0 +1,194 @@ +//po4a: entry man manual +//// +Copyright 1993 Rickard E. Faith (faith@cs.unc.edu) +May be distributed under the GNU General Public License +//// += dmesg(1) +:doctype: manpage +:man manual: User Commands +:man source: util-linux {release-version} +:page-layout: base +:command: dmesg + +== NAME + +dmesg - print or control the kernel ring buffer + +== SYNOPSIS + +*dmesg* [options] + +*dmesg* *--clear* + +*dmesg* *--read-clear* [options] + +*dmesg* *--console-level* _level_ + +*dmesg* *--console-on* + +*dmesg* *--console-off* + +== DESCRIPTION + +*dmesg* is used to examine or control the kernel ring buffer. + +The default action is to display all messages from the kernel ring buffer. + +== OPTIONS + +The *--clear*, *--read-clear*, *--console-on*, *--console-off*, and *--console-level* options are mutually exclusive. + +*-C*, *--clear*:: +Clear the ring buffer. + +*-c*, *--read-clear*:: +Clear the ring buffer after first printing its contents. + +*-D*, *--console-off*:: +Disable the printing of messages to the console. + +*-d*, *--show-delta*:: +Display the timestamp and the time delta spent between messages. If used together with *--notime* then only the time delta without the timestamp is printed. + +*-E*, *--console-on*:: +Enable printing messages to the console. + +*-e*, *--reltime*:: +Display the local time and the delta in human-readable format. Be aware that conversion to the local time could be inaccurate (see *-T* for more details). + +*-F*, *--file* _file_:: +Read the syslog messages from the given _file_. Note that *-F* does not support messages in kmsg format. The old syslog format is supported only. + +*-f*, *--facility* _list_:: +Restrict output to the given (comma-separated) _list_ of facilities. For example: ++ +*dmesg --facility=daemon* ++ +will print messages from system daemons only. For all supported facilities see the *--help* output. + +*-H*, *--human*:: +Enable human-readable output. See also *--color*, *--reltime* and *--nopager*. + +*-J*, *--json*:: +Use JSON output format. The time output format is in "sec.usec" format only, log priority level is not decoded by default (use *--decode* to split into facility and priority), the other options to control the output format or time format are silently ignored. + +*-k*, *--kernel*:: +Print kernel messages. + +*-L*, *--color*[=_when_]:: +Colorize the output. The optional argument _when_ can be *auto*, *never* or *always*. If the _when_ argument is omitted, it defaults to *auto*. The colors can be disabled; for the current built-in default see the *--help* output. See also the *COLORS* section below. + +*-l*, *--level* _list_:: +Restrict output to the given (comma-separated) _list_ of levels. For example: ++ +*dmesg --level=err,warn* ++ +will print error and warning messages only. For all supported levels see the *--help* output. + +*-n*, *--console-level* _level_:: +Set the _level_ at which printing of messages is done to the console. The _level_ is a level number or abbreviation of the level name. For all supported levels see the *--help* output. ++ +For example, *-n 1* or *-n emerg* prevents all messages, except emergency (panic) messages, from appearing on the console. All levels of messages are still written to _/proc/kmsg_, so *syslogd*(8) can still be used to control exactly where kernel messages appear. When the *-n* option is used, *dmesg* will _not_ print or clear the kernel ring buffer. + +*--noescape*:: +The unprintable and potentially unsafe characters (e.g., broken multi-byte sequences, terminal controlling chars, etc.) are escaped in format \x for security reason by default. This option disables this feature at all. It's usable for example for debugging purpose together with *--raw*. Be careful and don't use it by default. + +*-P*, *--nopager*:: +Do not pipe output into a pager. A pager is enabled by default for *--human* output. + +*-p*, *--force-prefix*:: +Add facility, level or timestamp information to each line of a multi-line message. + +*-r*, *--raw*:: +Print the raw message buffer, i.e., do not strip the log-level prefixes, but all unprintable characters are still escaped (see also *--noescape*). ++ +Note that the real raw format depends on the method how *dmesg* reads kernel messages. The _/dev/kmsg_ device uses a different format than *syslog*(2). For backward compatibility, *dmesg* returns data always in the *syslog*(2) format. It is possible to read the real raw data from _/dev/kmsg_ by, for example, the command 'dd if=/dev/kmsg iflag=nonblock'. + +*-S*, *--syslog*:: +Force *dmesg* to use the *syslog*(2) kernel interface to read kernel messages. The default is to use _/dev/kmsg_ rather than *syslog*(2) since kernel 3.5.0. + +*-s*, *--buffer-size* _size_:: +Use a buffer of _size_ to query the kernel ring buffer. This is 16392 by default. (The default kernel syslog buffer size was 4096 at first, 8192 since 1.3.54, 16384 since 2.1.113.) If you have set the kernel buffer to be larger than the default, then this option can be used to view the entire buffer. + +*-T*, *--ctime*:: +Print human-readable timestamps. ++ +*Be aware that the timestamp could be inaccurate!* The *time* source used for the logs is *not updated after* system *SUSPEND*/*RESUME*. Timestamps are adjusted according to current delta between boottime and monotonic clocks, this works only for messages printed after last resume. + +*--since* _time_:: +Display record since the specified time. The time is possible to specify in absolute way as well as by relative notation (e.g. '1 hour ago'). Be aware that the timestamp could be inaccurate and see *--ctime* for more details. + +*--until* _time_:: +Display record until the specified time. The time is possible to specify in absolute way as well as by relative notation (e.g. '1 hour ago'). Be aware that the timestamp could be inaccurate and see *--ctime* for more details. + +*-t*, *--notime*:: +Do not print kernel's timestamps. + +*--time-format* _format_:: +Print timestamps using the given _format_, which can be *ctime*, *reltime*, *delta* or *iso*. The first three formats are aliases of the time-format-specific options. The *iso* format is a *dmesg* implementation of the ISO-8601 timestamp format. The purpose of this format is to make the comparing of timestamps between two systems, and any other parsing, easy. The definition of the *iso* timestamp is: YYYY-MM-DDHH:MM:SS,<-+>. ++ +The *iso* format has the same issue as *ctime*: the time may be inaccurate when a system is suspended and resumed. + +*-u*, *--userspace*:: +Print userspace messages. + +*-w*, *--follow*:: +Wait for new messages. This feature is supported only on systems with a readable _/dev/kmsg_ (since kernel 3.5.0). + +*-W*, *--follow-new*:: +Wait and print only new messages. + +*-x*, *--decode*:: +Decode facility and level (priority) numbers to human-readable prefixes. + +include::man-common/help-version.adoc[] + +include::man-common/colors.adoc[] +The logical color names supported by *dmesg* are: + +*subsys*:: +The message sub-system prefix (e.g., "ACPI:"). + +*time*:: +The message timestamp. + +*timebreak*:: +The message timestamp in short ctime format in *--reltime* or *--human* output. + +*alert*:: +The text of the message with the alert log priority. + +*crit*:: +The text of the message with the critical log priority. + +*err*:: +The text of the message with the error log priority. + +*warn*:: +The text of the message with the warning log priority. + +*segfault*:: +The text of the message that inform about segmentation fault. + +== EXIT STATUS + +*dmesg* can fail reporting permission denied error. This is usually caused by *dmesg_restrict* kernel setting, please see *syslog*(2) for more details. + +== AUTHORS + +mailto:kzak@redhat.com[Karel Zak] + +*dmesg* was originally written by mailto:tytso@athena.mit.edu[Theodore Ts'o]. + +== SEE ALSO + +*terminal-colors.d*(5), +*syslogd*(8) + +include::man-common/bugreports.adoc[] + +include::man-common/footer.adoc[] + +ifdef::translation[] +include::man-common/translation.adoc[] +endif::[] diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c new file mode 100644 index 0000000..0179362 --- /dev/null +++ b/sys-utils/dmesg.c @@ -0,0 +1,1683 @@ +/* + * dmesg.c -- Print out the contents of the kernel ring buffer + * + * Copyright (C) 1993 Theodore Ts'o + * Copyright (C) 2011 Karel Zak + * + * This program comes with ABSOLUTELY NO WARRANTY. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "c.h" +#include "colors.h" +#include "nls.h" +#include "strutils.h" +#include "xalloc.h" +#include "widechar.h" +#include "all-io.h" +#include "bitops.h" +#include "closestream.h" +#include "optutils.h" +#include "timeutils.h" +#include "monotonic.h" +#include "mangle.h" +#include "pager.h" +#include "jsonwrt.h" + +/* Close the log. Currently a NOP. */ +#define SYSLOG_ACTION_CLOSE 0 +/* Open the log. Currently a NOP. */ +#define SYSLOG_ACTION_OPEN 1 +/* Read from the log. */ +#define SYSLOG_ACTION_READ 2 +/* Read all messages remaining in the ring buffer. (allowed for non-root) */ +#define SYSLOG_ACTION_READ_ALL 3 +/* Read and clear all messages remaining in the ring buffer */ +#define SYSLOG_ACTION_READ_CLEAR 4 +/* Clear ring buffer. */ +#define SYSLOG_ACTION_CLEAR 5 +/* Disable printk's to console */ +#define SYSLOG_ACTION_CONSOLE_OFF 6 +/* Enable printk's to console */ +#define SYSLOG_ACTION_CONSOLE_ON 7 +/* Set level of messages printed to console */ +#define SYSLOG_ACTION_CONSOLE_LEVEL 8 +/* Return number of unread characters in the log buffer */ +#define SYSLOG_ACTION_SIZE_UNREAD 9 +/* Return size of the log buffer */ +#define SYSLOG_ACTION_SIZE_BUFFER 10 + +/* + * Color scheme + */ +struct dmesg_color { + const char *scheme; /* name used in termina-colors.d/dmesg.scheme */ + const char *dflt; /* default color ESC sequence */ +}; + +enum { + DMESG_COLOR_SUBSYS, + DMESG_COLOR_TIME, + DMESG_COLOR_TIMEBREAK, + DMESG_COLOR_ALERT, + DMESG_COLOR_CRIT, + DMESG_COLOR_ERR, + DMESG_COLOR_WARN, + DMESG_COLOR_SEGFAULT +}; + +static const struct dmesg_color colors[] = +{ + [DMESG_COLOR_SUBSYS] = { "subsys", UL_COLOR_BROWN }, + [DMESG_COLOR_TIME] = { "time", UL_COLOR_GREEN }, + [DMESG_COLOR_TIMEBREAK] = { "timebreak",UL_COLOR_GREEN UL_COLOR_BOLD }, + [DMESG_COLOR_ALERT] = { "alert", UL_COLOR_REVERSE UL_COLOR_RED }, + [DMESG_COLOR_CRIT] = { "crit", UL_COLOR_BOLD UL_COLOR_RED }, + [DMESG_COLOR_ERR] = { "err", UL_COLOR_RED }, + [DMESG_COLOR_WARN] = { "warn", UL_COLOR_BOLD }, + [DMESG_COLOR_SEGFAULT] = { "segfault", UL_COLOR_HALFBRIGHT UL_COLOR_RED } +}; + +#define dmesg_enable_color(_id) \ + color_scheme_enable(colors[_id].scheme, colors[_id].dflt); + +/* + * Priority and facility names + */ +struct dmesg_name { + const char *name; + const char *help; +}; + +/* + * Priority names -- based on sys/syslog.h + */ +static const struct dmesg_name level_names[] = +{ + [LOG_EMERG] = { "emerg", N_("system is unusable") }, + [LOG_ALERT] = { "alert", N_("action must be taken immediately") }, + [LOG_CRIT] = { "crit", N_("critical conditions") }, + [LOG_ERR] = { "err", N_("error conditions") }, + [LOG_WARNING] = { "warn", N_("warning conditions") }, + [LOG_NOTICE] = { "notice",N_("normal but significant condition") }, + [LOG_INFO] = { "info", N_("informational") }, + [LOG_DEBUG] = { "debug", N_("debug-level messages") } +}; + +/* + * sys/syslog.h uses (f << 3) for all facility codes. + * We want to use the codes as array indexes, so shift back... + * + * Note that libc LOG_FAC() macro returns the base codes, not the + * shifted code :-) + */ +#define FAC_BASE(f) ((f) >> 3) + +static const struct dmesg_name facility_names[] = +{ + [FAC_BASE(LOG_KERN)] = { "kern", N_("kernel messages") }, + [FAC_BASE(LOG_USER)] = { "user", N_("random user-level messages") }, + [FAC_BASE(LOG_MAIL)] = { "mail", N_("mail system") }, + [FAC_BASE(LOG_DAEMON)] = { "daemon", N_("system daemons") }, + [FAC_BASE(LOG_AUTH)] = { "auth", N_("security/authorization messages") }, + [FAC_BASE(LOG_SYSLOG)] = { "syslog", N_("messages generated internally by syslogd") }, + [FAC_BASE(LOG_LPR)] = { "lpr", N_("line printer subsystem") }, + [FAC_BASE(LOG_NEWS)] = { "news", N_("network news subsystem") }, + [FAC_BASE(LOG_UUCP)] = { "uucp", N_("UUCP subsystem") }, + [FAC_BASE(LOG_CRON)] = { "cron", N_("clock daemon") }, + [FAC_BASE(LOG_AUTHPRIV)] = { "authpriv", N_("security/authorization messages (private)") }, + [FAC_BASE(LOG_FTP)] = { "ftp", N_("FTP daemon") }, +}; + +/* supported methods to read message buffer + */ +enum { + DMESG_METHOD_KMSG, /* read messages from /dev/kmsg (default) */ + DMESG_METHOD_SYSLOG, /* klogctl() buffer */ + DMESG_METHOD_MMAP /* mmap file with records (see --file) */ +}; + +enum { + DMESG_TIMEFTM_NONE = 0, + DMESG_TIMEFTM_CTIME, /* [ctime] */ + DMESG_TIMEFTM_CTIME_DELTA, /* [ctime ] */ + DMESG_TIMEFTM_DELTA, /* [] */ + DMESG_TIMEFTM_RELTIME, /* [relative] */ + DMESG_TIMEFTM_TIME, /* [time] */ + DMESG_TIMEFTM_TIME_DELTA, /* [time ] */ + DMESG_TIMEFTM_ISO8601 /* 2013-06-13T22:11:00,123456+0100 */ +}; +#define is_timefmt(c, f) ((c)->time_fmt == (DMESG_TIMEFTM_ ##f)) + +struct dmesg_control { + /* bit arrays -- see include/bitops.h */ + char levels[ARRAY_SIZE(level_names) / NBBY + 1]; + char facilities[ARRAY_SIZE(facility_names) / NBBY + 1]; + + struct timeval lasttime; /* last printed timestamp */ + struct tm lasttm; /* last localtime */ + struct timeval boot_time; /* system boot time */ + time_t suspended_time; /* time spent in suspended state */ + + int action; /* SYSLOG_ACTION_* */ + int method; /* DMESG_METHOD_* */ + + size_t bufsize; /* size of syslog buffer */ + + int kmsg; /* /dev/kmsg file descriptor */ + ssize_t kmsg_first_read;/* initial read() return code */ + char kmsg_buf[BUFSIZ];/* buffer to read kmsg data */ + + time_t since; /* filter records by time */ + time_t until; /* filter records by time */ + + /* + * For the --file option we mmap whole file. The unnecessary (already + * printed) pages are always unmapped. The result is that we have in + * memory only the currently used page(s). + */ + char *filename; + char *mmap_buff; + size_t pagesize; + unsigned int time_fmt; /* time format */ + + struct ul_jsonwrt jfmt; /* -J formatting */ + + unsigned int follow:1, /* wait for new messages */ + end:1, /* seek to the of buffer */ + raw:1, /* raw mode */ + noesc:1, /* no escape */ + fltr_lev:1, /* filter out by levels[] */ + fltr_fac:1, /* filter out by facilities[] */ + decode:1, /* use "facility: level: " prefix */ + pager:1, /* pipe output into a pager */ + color:1, /* colorize messages */ + json:1, /* JSON output */ + force_prefix:1; /* force timestamp and decode prefix + on each line */ + int indent; /* due to timestamps if newline */ +}; + +struct dmesg_record { + const char *mesg; + size_t mesg_size; + + int level; + int facility; + struct timeval tv; + + const char *next; /* buffer with next unparsed record */ + size_t next_size; /* size of the next buffer */ +}; + +#define INIT_DMESG_RECORD(_r) do { \ + (_r)->mesg = NULL; \ + (_r)->mesg_size = 0; \ + (_r)->facility = -1; \ + (_r)->level = -1; \ + (_r)->tv.tv_sec = 0; \ + (_r)->tv.tv_usec = 0; \ + } while (0) + +static int read_kmsg(struct dmesg_control *ctl); + +static int set_level_color(int log_level, const char *mesg, size_t mesgsz) +{ + int id = -1; + + switch (log_level) { + case LOG_ALERT: + id = DMESG_COLOR_ALERT; + break; + case LOG_CRIT: + id = DMESG_COLOR_CRIT; + break; + case LOG_ERR: + id = DMESG_COLOR_ERR; + break; + case LOG_WARNING: + id = DMESG_COLOR_WARN; + break; + default: + break; + } + + /* well, sometimes the messages contains important keywords, but in + * non-warning/error messages + */ + if (id < 0 && memmem(mesg, mesgsz, "segfault at", 11)) + id = DMESG_COLOR_SEGFAULT; + + if (id >= 0) + dmesg_enable_color(id); + + return id >= 0 ? 0 : -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(_("Display or control the kernel ring buffer.\n"), out); + + fputs(USAGE_OPTIONS, out); + fputs(_(" -C, --clear clear the kernel ring buffer\n"), out); + fputs(_(" -c, --read-clear read and clear all messages\n"), out); + fputs(_(" -D, --console-off disable printing messages to console\n"), out); + fputs(_(" -E, --console-on enable printing messages to console\n"), out); + fputs(_(" -F, --file use the file instead of the kernel log buffer\n"), out); + fputs(_(" -f, --facility restrict output to defined facilities\n"), out); + fputs(_(" -H, --human human readable output\n"), out); + fputs(_(" -J, --json use JSON output format\n"), out); + fputs(_(" -k, --kernel display kernel messages\n"), out); + fprintf(out, + _(" -L, --color[=] colorize messages (%s, %s or %s)\n"), "auto", "always", "never"); + fprintf(out, + " %s\n", USAGE_COLORS_DEFAULT); + fputs(_(" -l, --level restrict output to defined levels\n"), out); + fputs(_(" -n, --console-level set level of messages printed to console\n"), out); + fputs(_(" -P, --nopager do not pipe output into a pager\n"), out); + fputs(_(" -p, --force-prefix force timestamp output on each line of multi-line messages\n"), out); + fputs(_(" -r, --raw print the raw message buffer\n"), out); + fputs(_(" --noescape don't escape unprintable character\n"), out); + fputs(_(" -S, --syslog force to use syslog(2) rather than /dev/kmsg\n"), out); + fputs(_(" -s, --buffer-size buffer size to query the kernel ring buffer\n"), out); + fputs(_(" -u, --userspace display userspace messages\n"), out); + fputs(_(" -w, --follow wait for new messages\n"), out); + fputs(_(" -W, --follow-new wait and print only new messages\n"), out); + fputs(_(" -x, --decode decode facility and level to readable string\n"), out); + fputs(_(" -d, --show-delta show time delta between printed messages\n"), out); + fputs(_(" -e, --reltime show local time and time delta in readable format\n"), out); + fputs(_(" -T, --ctime show human-readable timestamp (may be inaccurate!)\n"), out); + fputs(_(" -t, --notime don't show any timestamp with messages\n"), out); + fputs(_(" --time-format show timestamp using the given format:\n" + " [delta|reltime|ctime|notime|iso]\n" + "Suspending/resume will make ctime and iso timestamps inaccurate.\n"), out); + fputs(_(" --since