Re: [PATCH v10 06/26] RDMA/rtrs: client: main functionality

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

 



On Fri, Mar 13, 2020 at 01:18:23PM +0100, Danil Kipnis wrote:
> > > > calling rcu list iteration without holding rcu_lock is wrong
> > > This function (add_path) along with the corresponding
> > > remove_path_from_arr() are the only functions modifying the
> > > paths_list. In both functions paths_mutex is taken so that they are
> > > serialized. Since the modification of the paths_list is protected by
> > > the mutex, the rcu_read_lock is superfluous here.
> >
> > Then don't use the _rcu functions.
> We need to traverse rcu list in the update-side of the code. According
> to the whatisRCU.rst "if list_for_each_entry_rcu() instance might be
> used by update-side code...then an additional lockdep expression can
> be added to its list of arguments..." The would be our case since we
> always hold a lock when doing this, but I don't see a corresponding
> API. We can just surround the statement with
> rcu_readlock/rcu_readunlock to avoid the warning.

The only case where you can avoid RCU is if the code is already
holding a lock preventing writes to the list, in which case you use
the normal list iterator.

> > > > > +     /*
> > > > > +      * @pcpu paths can still point to the path which is going to be
> > > > > +      * removed, so change the pointer manually.
> > > > > +      */
> > > > > +     for_each_possible_cpu(cpu) {
> > > > > +             struct rtrs_clt_sess __rcu **ppcpu_path;
> > > > > +
> > > > > +             ppcpu_path = per_cpu_ptr(clt->pcpu_path, cpu);
> > > > > +             if (rcu_dereference(*ppcpu_path) != sess)
> > > >
> > > > calling rcu_dereference without holding rcu_lock is wrong.
> > > We only need a READ_ONCE semantic here. ppcpu_path is pointing to the
> > > last path used for an IO and is used for the round robin multipath
> > > policy. I guess the call can be changed to rcu_dereference_raw to
> > > avoid rcu_lockdep warning. The round-robin algorithm has been reviewed
> > > by Paul E. McKenney, he wrote a litmus test for it:
> > > https://lkml.org/lkml/2018/5/28/2080.
> >
> > You can't call rcu expecting functions without holding the rcu lock -
> > use READ_ONCE/etc if that is what is really going on

> Look's people are using rcu_dereference_protected when dereferencing
> rcu pointer in update-side and have an explicit lock to protect it, as
> we do. Will dig into it next week.

Yes, that is right too

> > > > > +static void rtrs_clt_add_path_to_arr(struct rtrs_clt_sess *sess,
> > > > > +                                   struct rtrs_addr *addr)
> > > > > +{
> > > > > +     struct rtrs_clt *clt = sess->clt;
> > > > > +
> > > > > +     mutex_lock(&clt->paths_mutex);
> > > > > +     clt->paths_num++;
> > > > > +
> > > > > +     /*
> > > > > +      * Firstly increase paths_num, wait for GP and then
> > > > > +      * add path to the list.  Why?  Since we add path with
> > > > > +      * !CONNECTED state explanation is similar to what has
> > > > > +      * been written in rtrs_clt_remove_path_from_arr().
> > > > > +      */
> > > > > +     synchronize_rcu();
> > > >
> > > > This makes no sense to me. RCU readers cannot observe the element in
> > > > the list without also observing paths_num++
> > > Paths_num is only used to make sure a reader doesn't look for a
> > > CONNECTED path in the list for ever - instead he makes at most
> > > paths_num attempts. The reader can in fact observe paths_num++ without
> > > observing new element in the paths_list, but this is OK. When adding a
> > > new path we first increase the paths_num and them add the element to
> > > the list to make sure the reader will also iterate over it. When
> > > removing the path - the logic is opposite: we first remove element
> > > from the list and only then decrement the paths_num.
> >
> > I don't understand how this explains why synchronize_rcu would be need
> > here.
> It is needed here so that readers who read the old (smaller) value of
> paths_num and are iterating over the list of paths will have a chance
> to reach the new path we are about to insert. Basically it is here to
> be symmetrical with the removal procedure: remove path,
> syncronize_rcu, path_num--.

How do readers see the paths_num before it is inserted into the list?

Jason



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux