From 2734b902c296f3f6cbc1522a579f23bd86d1be45 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Wed, 10 Jul 2019 10:53:59 -0600 Subject: [PATCH] LU-12501 utils: fix 'lfs df' printing loop If the OS_STATE_NONROT flag is set for a device, the showdf() state printing loop will spin endlessly because this bit is not printed, so it is never cleared from the loop's state mask. Declaring the obd_statfs_state_names[] array indexed by OS_STATE_* flags also is problematic because the array will double in size as new binary flags are added (already OS_STATE_NONROT results in an array size of 0x200 = 512 entries). Instead, declare a struct that is indexed linearly and stores the OS_STATE_* flag in a field, along with the name and whether the flag indicates a problem state. The flag printing loop can iterate over the array of flags instead of the os_state bits, which clarifies the for-loop iteration and is equally efficient. This also allows printing informational flags with "lfs df -v" so that OS_STATE_NONROT and similar flags can be visible to users. Fixes: 68635c3d9b3 ("LU-11963 osd: Add nonrotational flag to statfs") Lustre-change: https://review.whamcloud.com/35456 Lustre-commit: e4d92a8a08acbdca6634decd4deb9fe5678ad7ba Change-Id: Ib62e949ca56d691c4699d5f2d9439c42643ebbe5 Signed-off-by: Andreas Dilger Reviewed-by: James Simmons Reviewed-by: Patrick Farrell Signed-off-by: Minh Diep Reviewed-on: https://review.whamcloud.com/35662 Tested-by: jenkins Tested-by: Maloo --- lustre/include/uapi/linux/lustre/lustre_user.h | 8 +++-- lustre/utils/lfs.c | 48 ++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index 4ddb902..f864afc 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -125,9 +125,11 @@ typedef struct stat lstat_t; #define LUSTRE_FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_DEVICE_ORDER) enum obd_statfs_state { - OS_STATE_DEGRADED = 0x00000001, /**< RAID degraded/rebuilding */ - OS_STATE_READONLY = 0x00000002, /**< filesystem is read-only */ - OS_STATE_NOPRECREATE = 0x00000004, /**< no object precreation */ + OS_STATE_DEGRADED = 0x00000001, /**< RAID degraded/rebuilding */ + OS_STATE_READONLY = 0x00000002, /**< filesystem is read-only */ + OS_STATE_NOPRECREATE = 0x00000004, /**< no object precreation */ + OS_STATE_UNUSED1 = 0x00000008, /**< obsolete 1.6, was EROFS=30 */ + OS_STATE_UNUSED2 = 0x00000010, /**< obsolete 1.6, was EROFS=30 */ OS_STATE_ENOSPC = 0x00000020, /**< not enough free space */ OS_STATE_ENOINO = 0x00000040, /**< not enough inodes */ OS_STATE_SUM = 0x00000100, /**< aggregated for all tagrets */ diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 7f53af5..872f3a2 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -4628,27 +4628,27 @@ static inline int obd_statfs_ratio(const struct obd_statfs *st, bool inodes) return (ratio - (int)ratio) > 0 ? (int)(ratio + 1) : (int)ratio; } -/* This is only used to reflect various problem states for lfs df, so we only - * translate the flags reflecting those states. +/* This is to identify various problem states for "lfs df" if .osn_err = true, + * so only show flags reflecting those states by default. Informational states + * are only shown with "-v" and use lower-case names to distinguish them. + * UNUSED[12] were for "EROFS = 30" until 1.6 but are now available for use. */ -static char obd_statfs_state_names[] = { - [OS_STATE_DEGRADED] = 'D', - [OS_STATE_READONLY] = 'R', - [OS_STATE_NOPRECREATE] = 'N', - [OS_STATE_ENOSPC] = 'S', - [OS_STATE_ENOINO] = 'I', +static struct obd_statfs_state_names { + enum obd_statfs_state osn_state; + const char osn_name; + bool osn_err; +} oss_names[] = { + { .osn_state = OS_STATE_DEGRADED, .osn_name = 'D', .osn_err = true }, + { .osn_state = OS_STATE_READONLY, .osn_name = 'R', .osn_err = true }, + { .osn_state = OS_STATE_NOPRECREATE, .osn_name = 'N', .osn_err = true }, + { .osn_state = OS_STATE_UNUSED1, .osn_name = '?', .osn_err = true }, + { .osn_state = OS_STATE_UNUSED2, .osn_name = '?', .osn_err = true }, + { .osn_state = OS_STATE_ENOSPC, .osn_name = 'S', .osn_err = true }, + { .osn_state = OS_STATE_ENOINO, .osn_name = 'I', .osn_err = true }, + { .osn_state = OS_STATE_SUM, .osn_name = 'a', /* aggregate */ }, + { .osn_state = OS_STATE_NONROT, .osn_name = 'f', /* flash */ }, }; -static char obd_statfs_state2char(int s) -{ - /* Unknown name */ - if (s > ARRAY_SIZE(obd_statfs_state_names)/sizeof(char) || - obd_statfs_state_names[s] == 0) - return '?'; - - return obd_statfs_state_names[s]; -} - static int showdf(char *mntdir, struct obd_statfs *stat, char *uuid, enum mntdf_flags flags, char *type, int index, int rc) @@ -4722,16 +4722,14 @@ static int showdf(char *mntdir, struct obd_statfs *stat, printf("[%s:%d]", type, index); if (stat->os_state) { - uint32_t state; uint32_t i; printf(" "); - for (i = 0, state = stat->os_state; state != 0; i++) { - uint32_t mask = 1 << i; - if (!(state & mask) || mask == OS_STATE_NONROT) - continue; - printf("%c", obd_statfs_state2char(mask)); - state &= ~mask; + for (i = 0; i < ARRAY_SIZE(oss_names); i++) { + if (oss_names[i].osn_state & stat->os_state && + (oss_names[i].osn_err || + flags & MNTDF_VERBOSE)) + printf("%c", oss_names[i].osn_name); } } -- 1.8.3.1