Re: [PATCH 1/3] libmultipath: merge_mptable(): sort table by wwid

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2022-08-23 at 15:48 -0500, Benjamin Marzinski wrote:
> On Thu, Aug 18, 2022 at 11:06:28PM +0200, mwilck@xxxxxxxx wrote:
> > From: Martin Wilck <mwilck@xxxxxxxx>
> > 
> > If the mptable is very large (for example, in a configuration with
> > lots of maps assigned individual aliases), merge_mptable may get
> > very slow because it needs to make O(n^2) string comparisons (with
> > n being the number of mptable entries). WWID strings often differ
> > only in the last few bytes, causing a lot of CPU time spent in
> > strcmp().
> > 
> > merge_mptable is executed whenever multipath or multipathd is
> > started, that
> > is, also for "multipath -u" and "multipath -U" invocations from
> > udev rules.
> > Optimize it by sorting the mptable before merging. This way we
> > don't need
> > to iterate towards the end of the vector searching for duplicates.
> > 
> > Signed-off-by: Martin Wilck <mwilck@xxxxxxxx>
> > ---
> >  libmultipath/config.c | 15 +++++++++++++--
> >  libmultipath/vector.c |  8 ++++++++
> >  libmultipath/vector.h |  1 +
> >  3 files changed, 22 insertions(+), 2 deletions(-)
> > 
> > diff --git a/libmultipath/config.c b/libmultipath/config.c
> > index ab8b26e..a2c79a4 100644
> > --- a/libmultipath/config.c
> > +++ b/libmultipath/config.c
> > @@ -520,6 +520,14 @@ merge_mpe(struct mpentry *dst, struct mpentry
> > *src)
> >         merge_num(mode);
> >  }
> >  
> > +static int wwid_compar(const void *p1, const void *p2)
> > +{
> > +       const char *wwid1 = (*(struct mpentry * const *)p1)->wwid;
> > +       const char *wwid2 = (*(struct mpentry * const *)p2)->wwid;
> > +
> > +       return strcmp(wwid1, wwid2);
> > +}
> > +
> >  void merge_mptable(vector mptable)
> >  {
> >         struct mpentry *mp1, *mp2;
> > @@ -533,10 +541,13 @@ void merge_mptable(vector mptable)
> >                         free_mpe(mp1);
> >                         continue;
> >                 }
> > +       }
> > +       vector_sort(mptable, wwid_compar);
> > +       vector_foreach_slot(mptable, mp1, i) {
> >                 j = i + 1;
> >                 vector_foreach_slot_after(mptable, mp2, j) {
> > -                       if (!mp2->wwid || strcmp(mp1->wwid, mp2-
> > >wwid))
> > -                               continue;
> > +                       if (strcmp(mp1->wwid, mp2->wwid))
> > +                               break;
> >                         condlog(1, "%s: duplicate multipath config
> > section for %s",
> >                                 __func__, mp1->wwid);
> >                         merge_mpe(mp2, mp1);
> 
> The way merge_mpe() works, values are only copied from mp1's
> variables
> if the corresponding variable is unset in mp2. This requires the
> original order of mp1 and mp2 to be unchanged by the sorting
> algorithm,
> but according to the qsort() man page "If two members compare as
> equal,
> their order in the sorted array is undefined."
> 
> One quick and dirty way we could fix this is to add a variable to
> struct
> mptable called config_idx, which is its index in the config file.  If
> the wwids are equal, you compare that.

Thanks for pointing this out. I believe it's easier than that: as we're
passed the offsets into the array (aka struct mpentry **), we can
simply compare p1 and p2 if the strings are equal.

Agree?

Martin

--
dm-devel mailing list
dm-devel@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/dm-devel





[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux