Commit Graph

2192 Commits

Author SHA1 Message Date
Colin Walters a5eef45deb lib/remote: Box OstreeRemote if experimental-api
To avoid an introspection warning.  Otherwise, don't box it.

Closes: #858
Approved by: pwithnall
2017-05-16 08:28:47 +00:00
Colin Walters 05d0ee5cbe remount: Drop support for auto-tmpfs-on-var; use systemd.volatile=state
In current systemd, there is:
[systemd-volatile-root](https://www.freedesktop.org/software/systemd/man/systemd-volatile-root.service.html)
which was introduced by [this commit](91214a37ef).

I'd like to make further changes to how we handle `/var`, and I don't
want to reason about the interaction of our "tmpfs var" with too many
other things.

The comment about having "all /var handling in one place" was always inaccurate
given that we rely on systemd for mounting. And in general, I don't want to
duplicate too many things systemd does - it does them well, documents them, etc.

As far as I know, it was basically just Owen who was using this for the GNOME
hardware testing effort, and I'm sure he could easily switch over to
`systemd.volatile=state`.

Closes: #856
Approved by: owtaylor
2017-05-15 18:09:21 +00:00
Jonathan Lebon 23c60cda22 libglnx: bump and use new helper methods
Update submodule: libglnx

Closes: #857
Approved by: cgwalters
2017-05-12 21:02:16 +00:00
Colin Walters a195888b0f lib/checkout: Fix regression in subpath for regular files
This is what caused the merge of
https://github.com/projectatomic/rpm-ostree/pull/652
to blow up, since https://github.com/ostreedev/ostree/pull/848
landed right before we tried to merge it.

When I was writing that PR I remember having an uncertain feeling
since we were doing a `mkdirat` above, but at the time I thought
we'd have test suite coverage...turns out we didn't.

For backwards compatibility, we need to continue to do a `mkdirat` here of the
parent. However...I can't think of a reason anyone would *want* that behavior.
Hence, let's add a special trick - if the destination name is `.`, we skip
`mkdirat()`. That way rpm-ostree for example can open a dfd for `/etc` and avoid
the `mkdir`.

Fold the subpath tests into `test-basic.sh` since it's not worth a separate
file. Add a test case for checking out a file.

Closes: #854
Approved by: jlebon
2017-05-12 14:00:20 +00:00
Colin Walters b83d509e78 tree-wide: Switch tabs ⭾ in various files over to spaces ␠
As $DEITY intended.

I was reading the `prepare-root.c` code and the indentation damage was
distracting. Squash tabs that have leaked into various places in the code. I
didn't yet touch the `src/libostree` bits as that has higher potential for
conflict.

Closes: #852
Approved by: jlebon
2017-05-11 18:17:26 +00:00
Colin Walters ce4d21bc17 checkout: Plug a memleak of the state stringbuf
A struct without a cleanup macro is a struct likely to leak.

Closes: #850
Approved by: jlebon
2017-05-11 15:34:51 +00:00
Colin Walters 0177214982 lib/repo: Port more of GPG and summary functions to new code style
These ones were pretty easy, not sure why I didn't do them in an earlier pass.

Closes: #849
Approved by: jlebon
2017-05-11 15:26:49 +00:00
Colin Walters 964ca9d434 repo: Fix double close() in summary generation
Happened to notice this while doing a style port.

Closes: #849
Approved by: jlebon
2017-05-11 15:26:49 +00:00
Colin Walters e6f17b949d lib/checkout: Optimize checkout by avoiding OstreeRepoFile recusion
Looking at `perf record ostree checkout`, some things stand out; e.g.:

```
+   27.63%     0.07%  ostree   libgio-2.0.so.0.5000.3      [.] g_file_enumerator_iterate
+   22.74%     0.28%  ostree   libostree-1.so.1.0.0        [.] ostree_repo_file_tree_query_child
+   13.74%     0.08%  ostree   libostree-1.so.1.0.0        [.] ot_variant_bsearch_str
```

The GIO abstractions are already fairly heavyweight, and `OstreeRepoFile` mallocs
a lot too.

Make things more efficient here by dropping the GIO bits for reading ostree data -
we just read from the variants directly and iterate over them.  The end result
here is that according to perf we go from ~40% of our time in the kernel to
~70%, and things like `g_file_enumerator_iterate()` drop entirely out of the
hot set.

Closes: #848
Approved by: jlebon
2017-05-11 14:15:54 +00:00
Colin Walters 7896bcbe65 lib/checkout: Move special case for subpath of file to toplevel
Since we now have a cleaner separation of "toplevel checkout prep"
versus "recursive checkout", handle the special case of checking out
a single file at first rather than later.

Prep for future work in optimizing this function more.

Closes: #848
Approved by: jlebon
2017-05-11 14:15:54 +00:00
Colin Walters 986e05e3fd lib/prune: Complete porting to new code style
Only non-mechanical bit here was creating a local autoptr for a bit
where we'd previously done an unref for a struct member.

Closes: #847
Approved by: jlebon
2017-05-11 13:20:38 +00:00
Colin Walters 63497c65f3 checkout/commit: Use glnx_regfile_copy_bytes() if possible
Rather than `g_output_stream_splice()`, where the input is a regular
file.

See https://github.com/GNOME/libglnx/pull/44 for some more information.

I didn't try to measure the performance difference, but seeing the
read()/write() to/from userspace mixed in with the pointless `poll()` annoyed me
when reading strace.

As a bonus, we will again start using reflinks (if available) for `/etc`,
which is a regression from the https://github.com/ostreedev/ostree/pull/797
changes (which before used `glnx_file_copy_at()`).

Also, for the first time we'll use reflinks when doing commits from file-backed
content. This happens in `rpm-ostree compose tree` today for example.

Update submodule: libglnx

Closes: #817
Approved by: jlebon
2017-05-10 15:10:30 +00:00
Colin Walters 05fda71cb1 sysroot: More porting to new code style
This isn't all of this file yet, just doing another chunk.

Closes: #845
Approved by: jlebon
2017-05-10 14:09:42 +00:00
Colin Walters 18c5947c5f diff: Port some to new code style
Continuing to chip away at this.  Using `g_file_enumerator_iterate()`
here helps notably.

I started on the much bigger `ostree_diff_dirs_with_options()` but
it's a lot messier - for later.

Closes: #844
Approved by: jlebon
2017-05-09 18:33:12 +00:00
Colin Walters 86963334bd fsck: Check for refs missing corresponding commit
Just doing this one quickly since it was easy.

Closes: https://github.com/ostreedev/ostree/issues/831

Closes: #841
Approved by: jlebon
2017-05-09 14:05:46 +00:00
Colin Walters 052ba81c03 utils/checksum: Port to new code style
Just happened to be reading this code, it's an easy port.

Closes: #842
Approved by: jlebon
2017-05-09 13:51:12 +00:00
Philip Withnall 6eac575f21 libostree: Make OstreeRemote a public and internal API
Previously it was static to ostree-repo.c. Make it usable throughout
libostree so it can be used by an upcoming commit, but also expose the
typedef and reference counting functions so that opaque OstreeRemote
pointers can be used by user code, in anticipation of exposing more of
its API publicly in future.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #832
Approved by: cgwalters
2017-05-08 18:48:07 +00:00
Philip Withnall eeee5a0a1e libostree: Expose $OSTREE_FEATURES in the pkg-config file
This allows consumers of libostree to check at configure time whether it
supports the feature they want.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #832
Approved by: cgwalters
2017-05-08 18:48:07 +00:00
Philip Withnall c9244b1bb2 build: Add --enable-experimental-api configure option for unstable APIs
There are currently no unstable APIs, but some will be added in
following commits. They will be built and exposed in the libostree
global symbol list iff configured with --enable-experimental-api.

Distributions should not package OSTree with --enable-experimental-api.
This is designed for previewing new APIs on controlled platforms; any of
the APIs hidden behind this option may be changed or removed at any
point.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #832
Approved by: cgwalters
2017-05-08 18:48:07 +00:00
Dan Nicholson 4e13361c8e pull: Allow additional HTTP headers for summary fetch
Read the http-headers (a(ss)) option in
ostree_repo_remote_fetch_summary_with_options like
ostree_repo_pull_with_options and add the headers to the fetcher. This
allows things like providing additional authorization headers to the
HTTP requests.

Closes: #839
Approved by: cgwalters
2017-05-08 16:50:45 +00:00
Dan Nicholson 37b8dae2c4 commit: Mark ostree_repo_transaction_set_ref* checksums nullable
Allow GI bindings to delete refs through ostree_repo_transaction_set_ref
and ostree_repo_transaction_set_refspec by setting the checksum to NULL.

Closes: #834
Approved by: cgwalters
2017-05-08 16:35:09 +00:00
Philip Withnall c1290177a3 ostree: Use #defines for well-known metadata key names
Rather than hard-coding the names as strings. This makes the code a
little more maintainable.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #826
Approved by: cgwalters
2017-05-08 00:55:24 +00:00
Philip Withnall a946c3d423 ostree: Improve formatting for well-known summary metadata keys
If a summary metadata key is well-known, like ostree.static-deltas, or
ostree.summary.last-modified, format it a little more nicely.

This is especially important for timestamps like last-modified, since
otherwise they’re formatted as a big-endian uint64, which is basically
unusable for the user.

Non-formatted output can still be retrieved using the OSTREE_DUMP_RAW
flag, and the non-formatted key name is always printed for clarity.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #826
Approved by: cgwalters
2017-05-08 00:55:24 +00:00
Philip Withnall 8ea654251a ostree: Add --view mode to `ostree summary`
This allows a locally generated summary file to be viewed. It accepts
the same arguments as `ostree remote summary` (i.e. --raw).

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #826
Approved by: cgwalters
2017-05-08 00:55:24 +00:00
Philip Withnall 015ce7520b libostree: Document endianness of GVariant metadata types
Endianness strikes again.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #826
Approved by: cgwalters
2017-05-08 00:55:24 +00:00
Philip Withnall 9aa8d420cf libostree: Add some additional metadata to the summary file
• Commit timestamps, so it’s easy to work out whether a given commit is
   newer than the one we have locally
 • Summary file timestamp, so it’s easy to work out whether the summary
   file is more up to date than another summary file
 • Summary file expiry time, so clients can work out when they should
   expect the summary file to next be updated, and hence can query for
   it at roughly the right time

The expiry time requires input from the user, so is currently never set
automatically. Programs using libostree can set it if they wish.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #826
Approved by: cgwalters
2017-05-08 00:55:24 +00:00
Sjoerd Simons e6666fc2e5 repo/commit: Fix memory leak
While running the testsuite under valgrind a small memory leak showed up:

==16487== 65 bytes in 1 blocks are definitely lost in loss record 773 of 1,123
==16487==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==16487==    by 0x6048E08: g_malloc (gmem.c:94)
==16487==    by 0x6062EAE: g_strdup (gstrfuncs.c:363)
==16487==    by 0x54CE3E6: write_object (ostree-repo-commit.c:776)
==16487==    by 0x54CF2D4: ostree_repo_write_metadata (ostree-repo-commit.c:1528)
==16487==    by 0x54CF505: _ostree_repo_write_directory_meta (ostree-repo-commit.c:1712)
==16487==    by 0x54D0AB4: write_dfd_iter_to_mtree_internal (ostree-repo-commit.c:2650)
==16487==    by 0x54D0E2D: ostree_repo_write_dfd_to_mtree (ostree-repo-commit.c:2793)
==16487==    by 0x1190C4: ostree_builtin_commit (ot-builtin-commit.c:474)
==16487==    by 0x11F2EE: ostree_run (ot-main.c:200)
==16487==    by 0x116F32: main (main.c:78)

The reason for this is that ot_checksum_instream_get_string returns a chunk of newly allocated memory which never got freed.

Make actual_checksum something that gets autocleanend and own the memory
assigned to it in all cases.

Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>

Closes: #827
Approved by: pwithnall
2017-05-05 15:31:38 +00:00
Colin Walters 712bf21914 tree-wide: Convert to using autoptr(GString) vs g_string_free(...,TRUE)
If we're freeing the segment, it's basically always better to use
`autoptr()`.  Fewer lines, more reliable, etc.

Noticed an instance of this in the pull code while reviewing a different PR,
decided to do a grep for it and fix it tree wide.

Closes: #836
Approved by: pwithnall
2017-05-05 15:10:51 +00:00
Philip Withnall bf9772f231 libostree: Ensure progress keys are all always set
If one of the progress keys is set in a pull operation, a ::changed
signal is emitted on the progress object, and the callback for that
could query any of the progress keys — so they all need to be set,
otherwise we get an assertion failure in ostree_async_progress_get() due
to a named key not existing.

Spotted by Dan Nicholson in PR #819.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #835
Approved by: cgwalters
2017-05-05 14:58:03 +00:00
Philip Withnall f1da7ec300 libostree: Fix potential use of uninitialised memory in progress API
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #835
Approved by: cgwalters
2017-05-05 14:58:03 +00:00
Dan Nicholson 59897f2b84 pull: Fix crash specifying override URL in summary fetch
The summary URL override is looked up with "&s", which directly
exchanges the data to a pointer without allocation. This was causing a
segfault calling ostree_repo_remote_fetch_summary_with_options from
pygobject.

Closes: #829
Approved by: jlebon
2017-05-03 18:08:37 +00:00
Philip Withnall 4c731165bb libostree: Add missing checks for invalid timestamps
g_date_time_new_from_unix_utc() will not always return a valid GDateTime
— if the input timestamp is too big, GDateTime cannot represent it, and
the constructor returns NULL.

Add some missing checks for these situations. We don’t ever expect
timestamps to be this big, but they could be as a result of corruption
or a malicious repository.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #825
Approved by: cgwalters
2017-05-03 15:23:15 +00:00
Philip Withnall a1c866ed52 libostree: Fix a typo in docs for ostree_repo_pull_with_options()
Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #828
Approved by: cgwalters
2017-05-03 14:16:23 +00:00
Colin Walters 4f80548454 repo: Delete the last use of GFile tmp_dir
The keyring isn't large, so let's just fall back to copying it
rather than requiring `renameat()`.

Prep for `ostree_repo_open_at()`.

Closes: #821
Approved by: jlebon
2017-05-01 16:44:59 +00:00
Colin Walters 8d8f06f21b checkout: Dedup calls to memcache ref
Minor, but I realized `checkout_tree_at()` is a better place to
do common setup before checkout.  Prep for
https://github.com/ostreedev/ostree/pull/813

Closes: #823
Approved by: jlebon
2017-05-01 15:13:06 +00:00
Philip Withnall cbe3989b2b libostree: Get and set OstreeAsyncProgress:status atomically
Use the new well-known `status` key for OstreeAsyncProgress to get and
set the status atomically with other keys in an OstreeAsyncProgress
instance.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #819
Approved by: cgwalters
2017-04-29 11:50:15 +00:00
Philip Withnall ce83abb868 libostree: Allow OstreeAsyncProgress:status to be set atomically
Rework how the status is handled in OstreeAsyncProgress so that it’s now
a well-known key in the hash table. This means that it can be retrieved
and set atomically with other keys using
ostree_async_progress_[get|set]().

The behaviour of ostree_async_progress_[get|set]_status() is preserved,
with the caveat that `status` can now also be accessed using the other
API on OstreeAsyncProgress, and has to be accessed with the right
GVariant type.

Internally, a NULL status is represented by an empty status string
(since ostree_async_progress_[get|set]_variant() deliberately don’t
allow NULL variants to be set against keys, since that would break the
ostree_async_progress_get() API).

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #819
Approved by: cgwalters
2017-04-29 11:50:15 +00:00
Philip Withnall cdf876101b src: Port to new OstreeAsyncProgress atomic API
This will eliminate most of the potential races in progress reporting.
ostree_repo_pull_default_console_progress_changed() still calls three
getters, so there may still be races there, however.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #819
Approved by: cgwalters
2017-04-29 11:50:15 +00:00
Philip Withnall c27b66de80 libostree: Add multiple getter/setter support to OstreeAsyncProgress
OstreeAsyncProgress is thread-safe: it can have keys changed by one
thread while another is getting the same keys (modulo some locking
contention). However, the thread safety is done at the function call
level: if some code calls an OstreeAsyncProgress getter several times,
the key fetches are not atomic with respect to each other.

In the case of contention on the lock, this can result in consumers of
OstreeAsyncProgress data seeing an inconsistent state between the
properties they query, which could result in progress reporting
inaccuracies.

In the uncontested case, this results in the OstreeAsyncProgress lock
being locked and unlocked many times more than necessary.

Try to improve this by adding new API, which supports getting and
setting multiple keys atomically:
 • ostree_async_progress_get()
 • ostree_async_progress_set()

The new API uses GVariants and varargs: keys are passed as a
GVariantType string followed by arguments as for g_variant_new() or
g_variant_get(), followed by the next key, etc.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #819
Approved by: cgwalters
2017-04-29 11:50:15 +00:00
Philip Withnall f74e52a3a0 libostree: Rework OstreeAsyncProgress to use GVariants internally
OstreeAsyncProgress currently does some contortions to try and avoid
allocating space for guints and guint64s (on 64-bit platforms), but this
means it uses two GHashTables. A GHashTable allocates 8 buckets even
when empty. Given that the largest usage of OstreeAsyncProgress in
libostree puts 13 uints and 5 uint64s in it, this optimisation does not
save significant (if any) memory.

Instead, change OstreeAsyncProgress to store values internally as
GVariants, and expose this with some new API:
 • ostree_async_progress_get_variant()
 • ostree_async_progress_set_variant()
Each GVariant is allocated on the heap. As they are immutable, they are
thread-safe once returned by a getter.

The existing API continues to work as before, except in the case where a
key is set/got as both a uint and a uint64 — there will now be a
collision (and a GVariant type checking failure) whereas previously
there was no collision. Nothing in OSTree uses OstreeAsyncProgress this
way though.

The new API can be used to share more complex data via the progress API.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #819
Approved by: cgwalters
2017-04-29 11:50:15 +00:00
Colin Walters 838cbab585 lib/checkout: Use TEMP_FAILURE_RETRY()
I'm still not sure it's worth using, but it's easier on the eyes for sure.

Closes: #816
Approved by: jlebon
2017-04-27 14:46:05 +00:00
Philip Withnall c418600594 ostree: Use G_OPTION_ARG_FILENAME where appropriate
Instead of using G_OPTION_ARG_STRING, use G_OPTION_ARG_FILENAME, which
handles filename encoding conversion differently from the locale
conversion which G_OPTION_ARG_STRING. This will fix argument handling on
systems where the filename encoding is not the same as the locale
encoding (which is fairly unlikely since most systems use UTF-8).

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Closes: #810
Approved by: cgwalters
2017-04-27 13:43:49 +00:00
Colin Walters 90b24a8d43 sepolicy: Cache the value of is_selinux_enabled() to work around bug
This fixes a regression from:
https://github.com/ostreedev/ostree/pull/797
which is really due to an underlying bug in libselinux which
we're working around:
http://marc.info/?l=selinux&m=149323809332417&w=2

We drop the per-policy instance variable, since the SELinux state
is *really* per-kernel.

Closes: https://github.com/ostreedev/ostree/issues/814

Closes: #815
Approved by: jlebon
2017-04-27 13:30:19 +00:00
Colin Walters ceb8851806 lib/sepolicy: Convert to new code style
I have a fix I want to make here and it's really hard to write
the old style code now.

Closes: #815
Approved by: jlebon
2017-04-27 13:30:19 +00:00
Colin Walters 20b0836ec8 repo: Fix incorrect use of errno() error throwing
I happened to glance at the top of my most recent patch and
noticed that I used an `throw_errno()` function in a non-errno place.
I scanned the patch for other instances of this but didn't find one.

Closes: #811
Approved by: jlebon
2017-04-26 13:27:16 +00:00
Colin Walters 3d1b47803f repo: More porting to new style
I was planning to change some of the object loading code in the
future, so here's some porting.

Note that I rewrote `_ostree_repo_has_loose_object()` since it
used an error return across multiple functions.

Honestly I'm not sure about this `TEMP_FAILURE_RETRY()` business...
in reality we're going to end up with a ton of code linked in
process that doesn't do it.  Unix sucks =(  But I'm keeping
what was there out of consistency.

Closes: #809
Approved by: jlebon
2017-04-25 20:01:13 +00:00
Colin Walters 8d58ab1002 repo: Port object listing func to use libglnx more + new style
This did a `closedir` in the `goto out` section before, but it
turns out more nicely if we follow the usual pattern of doing
the `open(O_DIRECTORY)` in the callee function and handle `ENOENT`
there.

Closes: #809
Approved by: jlebon
2017-04-25 20:01:13 +00:00
Colin Walters e8efd1c8dc checkout: Add SELinux labeling for checkout, use in deploy
This is a variant of the efforts in https://github.com/ostreedev/ostree/pull/741
Working on `rpm-ostree livefs`, I realized though I needed to just
check out *new* files directly into the live `/etc` (and possibly
delete obsolete files).

The way the current `/etc` merge works is fundamentally different from
that.  So my plan currently is to probably do something like:

 - Compute diff
 - Check out each *new* file individually (as a copy)
 - Optionally delete obsolete files

Also, a few other things become more important - in the current deploy code, we
copy all of the files, then relabel them. But we shouldn't expose to *live*
systems the race conditions of doing that, plus we should only relabel files we
checked out.

By converting the deploy's /etc code to use this, we fix the same TODO item
there around atomically having the label set up as we create files. And further,
if we kill the `/var` relabeling which I think is unnecessary since Anaconda
does it, we could delete large chunks of code there.

In the implementation, there are two types of things: regular files, and
symlinks. For regular files, in the `O_TMPFILE` case, we have the ability to
do *everything* atomically (including SELinux labeling) before linking it into
place. So let's just use that. For symlinks, we use `setfscreatecon()`.

Closes: #797
Approved by: jlebon
2017-04-25 16:52:33 +00:00
Colin Walters 511b31cfb5 checkout: Merge union/add logic for copies during checkout
We really have an astonishing variety of similar functions which write files and
symlinks. I was working on a different PR and the duplication between the
union-mode and add-mode/none-mode checkout functions bothered me.

I realized that the "handle EEXIST" tri-state maps directly to the
`GLnxLinkTmpfileReplaceMode`, so deduping things makes even more sense.

Closes: #801
Approved by: jlebon
2017-04-25 13:52:35 +00:00
Colin Walters b7afe91e21 repo/checkout: Cache lookups of dirmeta objects
I was reading a strace the other day and noticed we were loading the same
`.dirmeta` object many times. Unlike the other object types, `.dirmeta` objects
don't accumulate much over time; there are only so many directory metadata types.
(Without SELinux involved it'd probably be 5-6 I'd guess offhand).

For `fedora-atomic/25/x86_64/docker-host` there are currently 34 `.dirmeta` in
the tree.

But how many times during a checkout did we load those 34 dirmeta objects?
With a quick strace:

```
$ strace -s 2048 -f -o strace.log ostree --repo=repo-build checkout -U fedora-atomic/25/x86_64/docker-host host-test-checkout
$ grep dirmeta strace.log | wc -l
7165
```

After, as you'd expect, we just loaded `34` from disk.  We do
6 system calls (`openat+fstat+fstat+read+read+close`) per dirmeta,
so we dropped a total of 42780 system calls - which is about 20% of the total
system calls made.

`perf record` tells me that we're spending ~40 of our time in the kernel during
a checkout, so reducing syscall traffic helps. Though most of that appears to be
in the VFS and XFS layers for `linkat` (which isn't surprising).

So how much did perf improve? Well, on my workstation, I get a lot of
fluctuation in timing, sometimes by 30%, so this was well within the noise. But
it's well worth speeding up checkout, and I think this optimization will shine
more as we improve performance elsewhere.

Closes: #795
Approved by: jlebon
2017-04-25 13:40:53 +00:00