Whamcloud - gitweb
LU-12501 utils: fix 'lfs df' printing loop 56/35456/3
authorAndreas Dilger <adilger@whamcloud.com>
Wed, 10 Jul 2019 16:53:59 +0000 (10:53 -0600)
committerOleg Drokin <green@whamcloud.com>
Sat, 20 Jul 2019 18:38:13 +0000 (18:38 +0000)
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")
Change-Id: Ib62e949ca56d691c4699d5f2d9439c42643ebbe5
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/35456
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/utils/lfs.c

index 339714c..bec3191 100644 (file)
@@ -126,9 +126,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 */
index 33d09d8..8babfb4 100644 (file)
@@ -4965,27 +4965,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)
@@ -5059,16 +5059,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);
                        }
                }