Tarantool development patches archive
 help / color / mirror / Atom feed
From: Nikita Pettik <korablev@tarantool.org>
To: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH 2/2] vinyl: drop wasted runs in case range recovery fails
Date: Thu, 7 May 2020 13:02:56 +0000	[thread overview]
Message-ID: <20200507130256.GB11724@tarantool.org> (raw)
In-Reply-To: <959a3f72-6b95-30b1-c838-3b9e2bebc04c@tarantool.org>

On 03 May 21:21, Vladislav Shpilevoy wrote:
> Thanks for the patch!
> 
> On 30/04/2020 21:27, Nikita Pettik wrote:
> > If recovery process fails during range restoration, range itself is
> > deleted and recovery is assumed to be finished as failed (in case of
> > casual i.e. not forced recovery). During recovery of particular range,
> > runs to be restored are reffed twice: once when they are created at
> > vy_run_new() and once when they are attached to slice. This fact is
> > taken into consideration and after all ranges are recovered all runs of
> > lsm tree are unreffed so that slices own run resources. However, if
> 
> Nit: 'unreffed' -> 'unrefed'. Since this is a shortcut for
> 'unreferenced', where number of 'f' is 1.
> 
> The same for 'reffed'.

Fixed.
 
> > range recovery fails, it is dropped alongside with slices which in turn
> > results in unreffing runs - this is not accounted. In this case, once
> > again unreffing such runs would lead to their destruction. On the other
> > hand, iteration over runs may turn out to be unsafe, so we should use
> > rlist_foreach_entry_safe(). Moreover, we should explicitly unaccount
> > these runs calling vy_lsm_remove_run().
> 
> Sorry, I didn't understand almost everything from the message :D
> But I did from the code. You may want to rephrase/restruct the text
> if you think it may help.

A bit reworked commit message and provided a brief schema in pseudocode.
Hope this will help:

    vinyl: drop wasted runs in case range recovery fails
    
    If recovery process fails during range restoration, range itself is
    deleted and recovery is assumed to be finished as failed (in case of
    casual i.e. not forced recovery). During recovery of particular range,
    runs to be restored are refed twice: once when they are created at
    vy_run_new() and once when they are attached to slice. This fact is
    taken into consideration and after all ranges are recovered: all runs of
    lsm tree are unrefed so that slices own run resources (as a result, when
    slice is to be deleted its runs unrefed and deleted as well). However, if
    range recovery fails, range is dropped alongside with already recovered
    slices. This leads to unrefing runs - this is not accounted. To sum up
    recovery process below is a brief schema:
    
    foreach range in lsm.ranges {
      vy_lsm_recover_range(range) {
        foreach slice in range.slices {
          // inside recover_slice() each run is refed twice
          if vy_lsm_recover_slice() != 0 {
            // here all already restored slices are deleted and
            // corresponding runs are unrefed, so now they have 1 ref.
            range_delete()
          }
        }
      }
    }
    foreach run in lsm.runs {
      assert(run->refs > 1)
      vy_run_unref(run)
    }
    
    In this case, unrefing such runs one more time would lead to their
    destruction. On the other hand, iteration over runs may turn out to
    be unsafe, so we should use rlist_foreach_entry_safe(). Moreover, we
    should explicitly clean-up these runs calling vy_lsm_remove_run().
    
    Closes #4805


> > diff --git a/src/box/vy_lsm.c b/src/box/vy_lsm.c
> > index 3d3f41b7a..81b011c69 100644
> > --- a/src/box/vy_lsm.c
> > +++ b/src/box/vy_lsm.c
> > @@ -604,9 +604,17 @@ vy_lsm_recover(struct vy_lsm *lsm, struct vy_recovery *recovery,
> >  	 * of each recovered run. We need to drop the extra
> >  	 * references once we are done.
> >  	 */
> > -	struct vy_run *run;
> > -	rlist_foreach_entry(run, &lsm->runs, in_lsm) {
> > -		assert(run->refs > 1);
> > +	struct vy_run *run, *next_run;
> > +	rlist_foreach_entry_safe(run, &lsm->runs, in_lsm, next_run) {
> > +		/*
> > +		 * In case vy_lsm_recover_range() failed, slices
> > +		 * are already deleted and runs are unreffed. So
> > +		 * we have nothing to do but finish run clean-up.
> > +		 */
> > +		if (run->refs == 1) {
> 
> Reference counter looks like not a good information channel.
> Could you use run->fd to check whether the run was really recovered?
> vy_run_recover() leaves it -1, when fails.
> 
> Otherwise this won't work the second when we will ref the run anywhere
> else.

Firstly, lsm at this point is not restored, ergo it is not functional
and run can't be refed somewehere else - it's life span is clearly
defined. Secondly, the problem is not in the last run (which failed to
recover) but in those which are already recovered at the moment.
Recovered runs feature valid fds. Finally, slice recover may fail
not only in vy_run_recover(), but also due to oom, broken vylog etc.
All these scenarios lead to the same situation.

  reply	other threads:[~2020-05-07 13:02 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-30 19:27 [Tarantool-patches] [PATCH 0/2] Fix crash in case of lack of FDs during recovery Nikita Pettik
2020-04-30 19:27 ` [Tarantool-patches] [PATCH 1/2] errinj: introduce delayed injection Nikita Pettik
2020-04-30 20:15   ` Konstantin Osipov
2020-04-30 20:55     ` Nikita Pettik
2020-05-01 19:15       ` Konstantin Osipov
2020-05-03 19:20   ` Vladislav Shpilevoy
2020-05-07 13:50     ` Nikita Pettik
2020-05-07 21:47       ` Vladislav Shpilevoy
2020-05-07 22:41         ` Nikita Pettik
2020-04-30 19:27 ` [Tarantool-patches] [PATCH 2/2] vinyl: drop wasted runs in case range recovery fails Nikita Pettik
2020-05-03 19:21   ` Vladislav Shpilevoy
2020-05-07 13:02     ` Nikita Pettik [this message]
2020-05-07 14:16       ` Konstantin Osipov
2020-05-07 21:47         ` Vladislav Shpilevoy
2020-05-07 22:37           ` Nikita Pettik
2020-05-07 21:47       ` Vladislav Shpilevoy
2020-05-07 22:36         ` Nikita Pettik
2020-05-10 19:59           ` Vladislav Shpilevoy
2020-05-12  1:16             ` Nikita Pettik
2020-05-03 19:20 ` [Tarantool-patches] [PATCH 0/2] Fix crash in case of lack of FDs during recovery Vladislav Shpilevoy
2020-05-07 14:11   ` Nikita Pettik
2020-05-12 20:53 ` Vladislav Shpilevoy
2020-05-12 20:56   ` Vladislav Shpilevoy
2020-05-12 22:45     ` Nikita Pettik
2020-05-13 20:19       ` Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200507130256.GB11724@tarantool.org \
    --to=korablev@tarantool.org \
    --cc=tarantool-patches@dev.tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH 2/2] vinyl: drop wasted runs in case range recovery fails' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox