The sbitmap_word.cleared member was added by kernel commit ea86ea2cdced
("sbitmap: ammortize cost of clearing bits") at Linux 5.0.  Without the
patch, on earlier kernels the "sbitmapq" command fails with the
following error:

   crash> sbitmapq ffff8f1a3611cf10

   sbitmapq: invalid structure member offset: sbitmap_word_cleared
             FILE: sbitmap.c  LINE: 92  FUNCTION: __sbitmap_weight()

Signed-off-by: Kazuhito Hagio <[email protected]>
---
  sbitmap.c | 26 ++++++++++++++++++--------
  1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/sbitmap.c b/sbitmap.c
index 37db21d15219..c8c9f2b6d003 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -89,7 +89,6 @@ static unsigned int __sbitmap_weight(const struct 
sbitmap_context *sc, bool set)
  {
        const ulong sbitmap_word_size = SIZE(sbitmap_word);
        const ulong w_word_off = OFFSET(sbitmap_word_word);
-       const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
  
        unsigned int weight = 0;
        ulong addr = sc->map_addr;
@@ -111,7 +110,10 @@ static unsigned int __sbitmap_weight(const struct 
sbitmap_context *sc, bool set)
                        word = ULONG(sbitmap_word_buf + w_word_off);
                        weight += bitmap_weight(word, depth);
                } else {
-                       cleared = ULONG(sbitmap_word_buf + w_cleared_off);
+                       if (VALID_MEMBER(sbitmap_word_cleared))
+                               cleared = ULONG(sbitmap_word_buf + 
OFFSET(sbitmap_word_cleared));
+                       else
+                               cleared = 0;
                        weight += bitmap_weight(cleared, depth);
                }
  
@@ -130,7 +132,10 @@ static unsigned int sbitmap_weight(const struct 
sbitmap_context *sc)
  
  static unsigned int sbitmap_cleared(const struct sbitmap_context *sc)
  {
-       return __sbitmap_weight(sc, false);
+       if (VALID_MEMBER(sbitmap_word_cleared)) /* 5.0 and later */
+               return __sbitmap_weight(sc, false);
+       else
+               return 0;
  }
  
  static void sbitmap_emit_byte(unsigned int offset, uint8_t byte)
@@ -149,7 +154,6 @@ static void sbitmap_bitmap_show(const struct 
sbitmap_context *sc)
  {
        const ulong sbitmap_word_size = SIZE(sbitmap_word);
        const ulong w_word_off = OFFSET(sbitmap_word_word);
-       const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
  
        uint8_t byte = 0;
        unsigned int byte_bits = 0;
@@ -169,7 +173,10 @@ static void sbitmap_bitmap_show(const struct 
sbitmap_context *sc)
                }
  
                word = ULONG(sbitmap_word_buf + w_word_off);
-               cleared = ULONG(sbitmap_word_buf + w_cleared_off);
+               if (VALID_MEMBER(sbitmap_word_cleared))
+                       cleared = ULONG(sbitmap_word_buf + 
OFFSET(sbitmap_word_cleared));
+               else
+                       cleared = 0;
                word_bits = __map_depth(sc, i);
  
                word &= ~cleared;
@@ -219,7 +226,6 @@ static void __sbitmap_for_each_set(const struct 
sbitmap_context *sc,
  {
        const ulong sbitmap_word_size = SIZE(sbitmap_word);
        const ulong w_word_off = OFFSET(sbitmap_word_word);
-       const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
  
        unsigned int index;
        unsigned int nr;
@@ -245,7 +251,10 @@ static void __sbitmap_for_each_set(const struct 
sbitmap_context *sc,
                }
  
                w_word = ULONG(sbitmap_word_buf + w_word_off);
-               w_cleared = ULONG(sbitmap_word_buf + w_cleared_off);
+               if (VALID_MEMBER(sbitmap_word_cleared))
+                       w_cleared = ULONG(sbitmap_word_buf + 
OFFSET(sbitmap_word_cleared));
+               else
+                       w_cleared = 0;
  
                depth = min(__map_depth(sc, index) - nr, sc->depth - scanned);
  
@@ -297,7 +306,8 @@ static void sbitmap_queue_show(const struct 
sbitmap_queue_context *sqc,
  
        fprintf(fp, "depth = %u\n", sc->depth);
        fprintf(fp, "busy = %u\n", sbitmap_weight(sc) - sbitmap_cleared(sc));
-       fprintf(fp, "cleared = %u\n", sbitmap_cleared(sc));
+       if (VALID_MEMBER(sbitmap_word_cleared)) /* 5.0 and later */
+               fprintf(fp, "cleared = %u\n", sbitmap_cleared(sc));
        fprintf(fp, "bits_per_word = %u\n", 1U << sc->shift);
        fprintf(fp, "map_nr = %u\n", sc->map_nr);
  
-- 
2.27.0
--
Crash-utility mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to