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

ostid_set_{seq,id}() badness

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • Minor
    • None
    • None
    • 3
    • 9223372036854775807

    Description

      Reviewing https://review.whamcloud.com/#/c/30376/ I noticed several issues with ostid_set_seq() and ostid_set_id(). The normal use of these functions looks like:

      struct ost_id oi;
      ...
      ostid_set_seq(&oi, ...);
      rc = ostid_set_id(&oi, ...);
      ...
      
      

      1. In ostid_set_seq() we (sometimes) make decisions based on oi_fid.f_oid and oi_fid.f_ver which may be uninitialized:

      static inline void ostid_set_seq(struct ost_id *oi, __u64 seq)
      {
              if (fid_seq_is_mdt0(seq) || fid_seq_is_default(seq)) {
                      oi->oi.oi_seq = seq;
              } else {
                      oi->oi_fid.f_seq = seq;
                      /*
                       * Note: if f_oid + f_ver is zero, we need init it
                       * to be 1, otherwise, ostid_seq will treat this
                       * as old ostid (oi_seq == 0)
                       */
                      if (!oi->oi_fid.f_oid && !oi->oi_fid.f_ver)
                              oi->oi_fid.f_oid = LUSTRE_FID_INIT_OID;
              }
      }
      
      

      2. In ostid_set_id() we make decisions based on fid_is_idif(&oi->oi_fid) === fid_seq_is_idif(oi->oi_fid.f_seq) which may not have been initialized by ostid_set_seq():

      static inline int ostid_set_id(struct ost_id *oi, __u64 oid)
      {
              if (fid_seq_is_mdt0(oi->oi.oi_seq)) {
                      if (oid >= IDIF_MAX_OID)
                              return -E2BIG;
                      oi->oi.oi_id = oid;
              } else if (fid_is_idif(&oi->oi_fid)) {
                      if (oid >= IDIF_MAX_OID)
                              return -E2BIG;
                      oi->oi_fid.f_seq = fid_idif_seq(oid,
                                                      fid_idif_ost_idx(&oi->oi_fid));
                      oi->oi_fid.f_oid = oid;
                      oi->oi_fid.f_ver = oid >> 48;
              } else {
                      if (oid >= OBIF_MAX_OID)
                              return -E2BIG;
                      oi->oi_fid.f_oid = oid;
              }
              return 0;
      }
      
      

      3. In the IDIF case, setting f_ver = oid >> 48 seems broken. We have already rejected OIDs greater than or equal to IDIF_MAX_OID === 1UL << 48. So we must have oid < (1UL << 48) and therefore oid >> 48 is always zero.

      Perhaps it would be safer (and clearer) to have a single function that takes seq and oid and initializes the ostid completely.

      Attachments

        Issue Links

          Activity

            People

              wc-triage WC Triage
              jhammond John Hammond
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated: