Uploaded image for project: 'Lustre'
  1. Lustre
  2. LU-6174

do_div() silently truncates divisor to uint32_t

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • Major
    • Lustre 2.16.0
    • None
    • None
    • 3
    • 17275

    Description

      The Linux do_div() silently truncates divisor to uint32_t, even on x86_64:

       
      25 # define do_div(n,base) ({                                      \
      26         uint32_t __base = (base);
      

      Any code that uses 64-bit divisor will end up with incorrect result whenever the higher 32 bits aren't all zero. And when the lower 32 bits are all zero, it will end up with a division by zero error.

      It happens on both x86_64 and i686. I've verified it on a x86_64 VM.

      So any code that looks like the following is BAD:

       
      uint64_t foo, bar;
      ......
      if (bar != 0)
          do_div(foo, bar);
      

      There seemed to be plenty of such code in Lustre, e.g.:

       
      void fld_cache_fini(struct fld_cache *cache)
              __u64 pct;
      ......
              if (cache->fci_stat.fst_count > 0) {
                      pct = cache->fci_stat.fst_cache * 100;
                      do_div(pct, cache->fci_stat.fst_count);
      

      I'd suggest to go through and verify all callers of do_div(). In addition, it'd be good to add a warning on do_div() in our patch checker script.

      Attachments

        Issue Links

          Activity

            People

              simmonsja James A Simmons
              isaac Isaac Huang (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: