-
Notifications
You must be signed in to change notification settings - Fork 140
fsmonitor: don't fill bitmap with entries to be removed #372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Minor suggestions about the commit message:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Patch looks good ;-)
f58c8f4
to
ce9bf42
Compare
@dscho thanks for the feedback on the commit message, please let me know what you think of the updated commit message in my latest push. |
@wilbaker I think it is great! Hopefully the Git maintainer will agree (they usually insist on a more "imperative tone", i.e. pretending that the commit tells Git to do this or that)... |
/submit |
Submitted as [email protected] WARNING: wilbaker has no public email address set on GitHub |
On the Git mailing list, Johannes Schindelin wrote (reply to this):
|
On the Git mailing list, Junio C Hamano wrote (reply to this):
|
@@ -14,8 +14,13 @@ struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR); | |||
static void fsmonitor_ewah_callback(size_t pos, void *is) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Junio C Hamano wrote (reply to this):
"William Baker via GitGitGadget" <[email protected]> writes:
> create mode 100755 t/t7519/fsmonitor-env
> ...
> + if (pos >= istate->cache_nr)
> + BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" >= %"PRIuMAX")",
> + (uintmax_t)pos, (uintmax_t)istate->cache_nr);
This is how we show size_t values without using "%z" that we avoid,
but are "pos" and 'cache_nr" size_t or ssize_t? I thought they are
plain boring unsigned, so shouldn't we use the plain boring "%u"
without casting?
The same comment applies to other uses of uintmax_t cast in this
patch.
> void fill_fsmonitor_bitmap(struct index_state *istate)
> {
> - unsigned int i;
> + unsigned int i, skipped = 0;
> istate->fsmonitor_dirty = ewah_new();
> - for (i = 0; i < istate->cache_nr; i++)
> - if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
> - ewah_set(istate->fsmonitor_dirty, i);
> + for (i = 0; i < istate->cache_nr; i++) {
> + if (istate->cache[i]->ce_flags & CE_REMOVE)
> + skipped++;
> + else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID))
> + ewah_set(istate->fsmonitor_dirty, i - skipped);
> + }
> }
Matches the explanation in the proposed log message pretty well.
Good job.
> @@ -354,4 +354,16 @@ test_expect_success 'discard_index() also discards fsmonitor info' '
> test_cmp expect actual
> '
>
> +# Use test files that start with 'z' so that the entries being added
> +# and removed appear at the end of the index.
In other words, future developers are warned against adding entries
to and leaving them in the index that sort later than z100 in new
tests they add before this point. Is the above wording clear enough
to tell them that, I wonder?
> +test_expect_success 'status succeeds after staging/unstaging ' '
> + test_commit initial &&
> + removed=$(test_seq 1 100 | sed "s/^/z/") &&
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, William Baker wrote (reply to this):
On 10/3/19 4:36 PM, Junio C Hamano wrote:
>> + if (pos >= istate->cache_nr)
>> + BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" >= %"PRIuMAX")",
>> + (uintmax_t)pos, (uintmax_t)istate->cache_nr);
>
> This is how we show size_t values without using "%z" that we avoid,
> but are "pos" and 'cache_nr" size_t or ssize_t? I thought they are
> plain boring unsigned, so shouldn't we use the plain boring "%u"
> without casting?
>
> The same comment applies to other uses of uintmax_t cast in this
> patch.
>
Thanks for catching this. I will update these BUGs in the next
patch to avoid casting.
>> +# Use test files that start with 'z' so that the entries being added
>> +# and removed appear at the end of the index.
>
> In other words, future developers are warned against adding entries
> to and leaving them in the index that sort later than z100 in new
> tests they add before this point. Is the above wording clear enough
> to tell them that, I wonder?
>
You're understanding is correct, and I agree this comment could be
clearer. I will fix this up in v2.
Thanks for the feedback!
William
ce9bf42
to
08741d9
Compare
/submit |
Submitted as [email protected] WARNING: wilbaker has no public email address set on GitHub |
On the Git mailing list, Junio C Hamano wrote (reply to this):
|
@@ -14,8 +14,13 @@ struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR); | |||
static void fsmonitor_ewah_callback(size_t pos, void *is) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, SZEDER Gábor wrote (reply to this):
On Wed, Oct 09, 2019 at 02:00:12PM -0700, William Baker via GitGitGadget wrote:
> diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
> index 81a375fa0f..87042470ab 100755
> --- a/t/t7519-status-fsmonitor.sh
> +++ b/t/t7519-status-fsmonitor.sh
> @@ -354,4 +354,17 @@ test_expect_success 'discard_index() also discards fsmonitor info' '
> test_cmp expect actual
> '
>
> +# This test covers staging/unstaging files that appear at the end of the index.
> +# Test files with names beginning with 'z' are used under the assumption that
> +# earlier tests do not add/leave index entries that sort below them.
> +test_expect_success 'status succeeds after staging/unstaging ' '
> + test_commit initial &&
This is confusing: this is the 29th test case in this script and it
creates an "initial" commit?!
The first "setup" test case has already created an initial commit, so
this should rather be called "second".
OTOH, none of the later commands in this test case seem to have
anything to do with this second commit, and indeed the test case works
even without it (i.e. 'git status' still segfaults without the fix and
then succeeds with the fix applied), so instead of updating its
message perhaps it could simply be removed.
> + removed=$(test_seq 1 100 | sed "s/^/z/") &&
> + touch $removed &&
> + git add $removed &&
> + test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" &&
> + FSMONITOR_LIST="$removed" git restore -S $removed &&
> + FSMONITOR_LIST="$removed" git status
> +'
> +
> test_done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, SZEDER Gábor wrote (reply to this):
On Thu, Oct 10, 2019 at 01:07:32PM +0200, SZEDER Gábor wrote:
> On Wed, Oct 09, 2019 at 02:00:12PM -0700, William Baker via GitGitGadget wrote:
> > diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
> > index 81a375fa0f..87042470ab 100755
> > --- a/t/t7519-status-fsmonitor.sh
> > +++ b/t/t7519-status-fsmonitor.sh
> > @@ -354,4 +354,17 @@ test_expect_success 'discard_index() also discards fsmonitor info' '
> > test_cmp expect actual
> > '
> >
> > +# This test covers staging/unstaging files that appear at the end of the index.
> > +# Test files with names beginning with 'z' are used under the assumption that
> > +# earlier tests do not add/leave index entries that sort below them.
I just read through Junio's comments on the first version of this
patch, in particular his remarks about this comment.
If this new test case below were run in a dedicated repository, then
this comment wouldn't be necessary, and all my comments below about
that not-really-initial commit would be moot, too.
> > +test_expect_success 'status succeeds after staging/unstaging ' '
> > + test_commit initial &&
>
> This is confusing: this is the 29th test case in this script and it
> creates an "initial" commit?!
>
> The first "setup" test case has already created an initial commit, so
> this should rather be called "second".
>
> OTOH, none of the later commands in this test case seem to have
> anything to do with this second commit, and indeed the test case works
> even without it (i.e. 'git status' still segfaults without the fix and
> then succeeds with the fix applied), so instead of updating its
> message perhaps it could simply be removed.
>
> > + removed=$(test_seq 1 100 | sed "s/^/z/") &&
> > + touch $removed &&
> > + git add $removed &&
> > + test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" &&
> > + FSMONITOR_LIST="$removed" git restore -S $removed &&
> > + FSMONITOR_LIST="$removed" git status
> > +'
> > +
> > test_done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, William Baker wrote (reply to this):
On 10/10/19 4:22 AM, SZEDER Gábor wrote:
>>> +# This test covers staging/unstaging files that appear at the end of the index.
>>> +# Test files with names beginning with 'z' are used under the assumption that
>>> +# earlier tests do not add/leave index entries that sort below them.
>
> I just read through Junio's comments on the first version of this
> patch, in particular his remarks about this comment.
>
> If this new test case below were run in a dedicated repository, then
> this comment wouldn't be necessary, and all my comments below about
> that not-really-initial commit would be moot, too.
>
Thanks for this suggestion! I will submit a v3 version of the patch
with an update to the test script.
- William
This comment has been minimized.
This comment has been minimized.
This branch is now known as |
This patch series was integrated into pu via git@8e1573e. |
08741d9
to
a38b6f7
Compare
( | ||
cd fsmonitor-stage-unstage && | ||
test_commit initial && | ||
git update-index --fsmonitor && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interestingly, without this line:
git update-index --fsmonitor &&
This test would only catch the bug when run with --run=29
. If the entire script were run the issue did not repro (event with the new BUG
statements in this patch).
While doing some testing with fsmonitor enabled I found that git commands would segfault after staging and unstaging an untracked file. Looking at the crash it appeared that fsmonitor_ewah_callback was attempting to adjust bits beyond the bounds of the index cache. Digging into how this could happen it became clear that the fsmonitor extension must have been written with more bits than there were entries in the index. The root cause ended up being that fill_fsmonitor_bitmap was populating fsmonitor_dirty with bits for all entries in the index, even those that had been marked for removal. To solve this problem fill_fsmonitor_bitmap has been updated to skip entries with the the CE_REMOVE flag set. With this change the bits written for the fsmonitor extension will be consistent with the index entries written by do_write_index. Additionally, BUG checks have been added to detect if the number of bits in fsmonitor_dirty should ever exceed the number of entries in the index again. Another option that was considered was moving the call to fill_fsmonitor_bitmap closer to where the index is written (and where the fsmonitor extension itself is written). However, that did not work as the fsmonitor_dirty bitmap must be filled before the index is split during writing. Signed-off-by: William Baker <[email protected]>
a38b6f7
to
840972e
Compare
/submit |
Submitted as [email protected] WARNING: wilbaker has no public email address set on GitHub |
@@ -14,8 +14,13 @@ struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR); | |||
static void fsmonitor_ewah_callback(size_t pos, void *is) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Junio C Hamano wrote (reply to this):
"William Baker via GitGitGadget" <[email protected]> writes:
> +# Test staging/unstaging files that appear at the end of the index. Test
> +# file names begin with 'z' so that they are sorted to the end of the index.
Well, the test is now done in a freshly created repository, so the
z* files are the only thing you have in here---technically they are
at the end of the index, but so they are at the beginning, too.
Would it affect the effectiveness of the test that you do not have
any other paths in the working tree or in the index, unlike the test
in the previous rounds that did not use a newly created test
repository?
This is not a rhetorical question, but purely asking. "no, this
still tests what we want to test and shows breakage when the fix to
the code in the patch gets reverted" is perfectly a good answer, but
in that case, is "the end of" the most important trait of the
condition this test is checking? Wouldn't the bug be exposed as
long as we remove sufficiently large number of entries (like
"removing more paths than the paths still in the index at the end"
or something like that)?
Thanks.
> +test_expect_success 'status succeeds after staging/unstaging ' '
> + test_create_repo fsmonitor-stage-unstage &&
> + (
> + cd fsmonitor-stage-unstage &&
> + test_commit initial &&
> + git update-index --fsmonitor &&
> + removed=$(test_seq 1 100 | sed "s/^/z/") &&
> + touch $removed &&
> + git add $removed &&
> + git config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" &&
> + FSMONITOR_LIST="$removed" git restore -S $removed &&
> + FSMONITOR_LIST="$removed" git status
> + )
> +'
> +
> test_done
> diff --git a/t/t7519/fsmonitor-env b/t/t7519/fsmonitor-env
> new file mode 100755
> index 0000000000..8f1f7ab164
> --- /dev/null
> +++ b/t/t7519/fsmonitor-env
> @@ -0,0 +1,24 @@
> +#!/bin/sh
> +#
> +# An test hook script to integrate with git to test fsmonitor.
> +#
> +# The hook is passed a version (currently 1) and a time in nanoseconds
> +# formatted as a string and outputs to stdout all files that have been
> +# modified since the given time. Paths must be relative to the root of
> +# the working tree and separated by a single NUL.
> +#
> +#echo "$0 $*" >&2
> +
> +if test "$#" -ne 2
> +then
> + echo "$0: exactly 2 arguments expected" >&2
> + exit 2
> +fi
> +
> +if test "$1" != 1
> +then
> + echo "Unsupported core.fsmonitor hook version." >&2
> + exit 1
> +fi
> +
> +printf '%s\n' $FSMONITOR_LIST
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, William Baker wrote (reply to this):
On 10/11/19 6:26 PM, Junio C Hamano wrote:
> "William Baker via GitGitGadget" <[email protected]> writes:
>
>> +# Test staging/unstaging files that appear at the end of the index. Test
>> +# file names begin with 'z' so that they are sorted to the end of the index.
>
> Well, the test is now done in a freshly created repository, so the
> z* files are the only thing you have in here---technically they are
> at the end of the index, but so they are at the beginning, too.
>
There is one other file in the index created by 'test_commit', however,
the point still stands that there are almost no other entries in the
index now that the test is using its own repository.
> Would it affect the effectiveness of the test that you do not have
> any other paths in the working tree or in the index, unlike the test
> in the previous rounds that did not use a newly created test
> repository?
The test still validates the scenario that we're concerned about,
namely that the new index that's written has less entries than
the index of the last entry in the old index that's is not flagged
with CE_FSMONITOR_VALID but is flagged for removal (CE_REMOVE).
> This is not a rhetorical question, but purely asking. "no, this
> still tests what we want to test and shows breakage when the fix to
> the code in the patch gets reverted" is perfectly a good answer, but
> in that case, is "the end of" the most important trait of the
> condition this test is checking? Wouldn't the bug be exposed as
> long as we remove sufficiently large number of entries (like
> "removing more paths than the paths still in the index at the end"
> or something like that)?
This is exactly right. The most important trait is that the last
entry flagged with CE_REMOVE does not have CE_FSMONITOR_VALID set
and has an index >= the number of entries in the new index being
written.
I will send out a patch on top of 'wb/fsmonitor-bitmap-fix' with
an update to the comment for this test.
Thanks,
William
This patch series was integrated into pu via git@b71923d. |
This patch series was integrated into pu via git@03d2698. |
This patch series was integrated into next via git@1cc4091. |
This patch series was integrated into pu via git@3ff7190. |
This patch series was integrated into pu via git@6ced45a. |
This patch series was integrated into pu via git@41ca127. |
This patch series was integrated into pu via git@2ffa1fe. |
This patch series was integrated into pu via git@b53b87f. |
This patch series was integrated into pu via git@22dd22d. |
This patch series was integrated into next via git@22dd22d. |
This patch series was integrated into master via git@22dd22d. |
Closed via 22dd22d. |
This is the third iteration of changes to fix the segfault that I encountered while testing fsmonitor. This iteration includes the following updates for feedback I received on v2:
This latest v3 series has been reviewed by Dscho.
Thanks,
William
Cc: [email protected], [email protected], [email protected], [email protected]