git-commit-vandalism/builtin
Jeff King 4c08018204 pack-objects: protect against disappearing packs
It's possible that while pack-objects is running, a
simultaneously running prune process might delete a pack
that we are interested in. Because we load the pack indices
early on, we know that the pack contains our item, but by
the time we try to open and map it, it is gone.

Since c715f78, we already protect against this in the normal
object access code path, but pack-objects accesses the packs
at a lower level.  In the normal access path, we call
find_pack_entry, which will call find_pack_entry_one on each
pack index, which does the actual lookup. If it gets a hit,
we will actually open and verify the validity of the
matching packfile (using c715f78's is_pack_valid). If we
can't open it, we'll issue a warning and pretend that we
didn't find it, causing us to go on to the next pack (or on
to loose objects).

Furthermore, we will cache the descriptor to the opened
packfile. Which means that later, when we actually try to
access the object, we are likely to still have that packfile
opened, and won't care if it has been unlinked from the
filesystem.

Notice the "likely" above. If there is another pack access
in the interim, and we run out of descriptors, we could
close the pack. And then a later attempt to access the
closed pack could fail (we'll try to re-open it, of course,
but it may have been deleted). In practice, this doesn't
happen because we tend to look up items and then access them
immediately.

Pack-objects does not follow this code path. Instead, it
accesses the packs at a much lower level, using
find_pack_entry_one directly. This means we skip the
is_pack_valid check, and may end up with the name of a
packfile, but no open descriptor.

We can add the same is_pack_valid check here. Unfortunately,
the access patterns of pack-objects are not quite as nice
for keeping lookup and object access together. We look up
each object as we find out about it, and the only later when
writing the packfile do we necessarily access it. Which
means that the opened packfile may be closed in the interim.

In practice, however, adding this check still has value, for
three reasons.

  1. If you have a reasonable number of packs and/or a
     reasonable file descriptor limit, you can keep all of
     your packs open simultaneously. If this is the case,
     then the race is impossible to trigger.

  2. Even if you can't keep all packs open at once, you
     may end up keeping the deleted one open (i.e., you may
     get lucky).

  3. The race window is shortened. You may notice early that
     the pack is gone, and not try to access it. Triggering
     the problem without this check means deleting the pack
     any time after we read the list of index files, but
     before we access the looked-up objects.  Triggering it
     with this check means deleting the pack means deleting
     the pack after we do a lookup (and successfully access
     the packfile), but before we access the object. Which
     is a smaller window.

Acked-by: Nicolas Pitre <nico@fluxnic.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-14 11:42:37 -07:00
..
add.c
annotate.c
apply.c zlib: zlib can only process 4GB at a time 2011-06-10 11:52:15 -07:00
archive.c upload-archive: allow user to turn off filters 2011-06-22 11:12:35 -07:00
bisect--helper.c bisect: introduce support for --no-checkout option. 2011-08-04 15:34:32 -07:00
blame.c blame: add --line-porcelain output format 2011-05-09 15:27:50 -07:00
branch.c Merge branch 'ci/forbid-unwanted-current-branch-update' 2011-09-16 21:48:10 -07:00
bundle.c
cat-file.c plug a few coverity-spotted leaks 2011-06-20 14:27:36 -07:00
check-attr.c git-check-attr: Normalize paths 2011-08-04 15:57:18 -07:00
check-ref-format.c check-ref-format --print: Normalize refnames that start with slashes 2011-08-25 13:39:38 -07:00
checkout-index.c checkout-index: remove obsolete comment 2011-08-17 10:39:47 -07:00
checkout.c Merge branch 'ci/forbid-unwanted-current-branch-update' 2011-09-16 21:48:10 -07:00
clean.c Documentation: clarify "git clean -e <pattern>" 2011-08-28 23:47:55 -07:00
clone.c Merge branch 'nd/maint-clone-gitdir' 2011-08-28 21:20:28 -07:00
commit-tree.c
commit.c Merge branch 'jk/color-and-pager' 2011-08-28 21:19:16 -07:00
config.c config: refactor get_colorbool function 2011-08-19 15:51:37 -07:00
count-objects.c
describe.c describe: Refresh the index when run with --dirty 2011-08-11 13:03:35 -07:00
diff-files.c Convert struct diff_options to use struct pathspec 2011-02-03 12:28:15 -08:00
diff-index.c
diff-tree.c
diff.c want_color: automatically fallback to color.ui 2011-08-19 15:51:38 -07:00
fast-export.c Merge branch 'jk/fast-export-quote-path' into maint 2011-08-16 12:41:12 -07:00
fetch-pack.c Merge branch 'nd/decorate-grafts' 2011-08-28 21:22:58 -07:00
fetch.c fetch: skip on-demand checking when no submodules are configured 2011-09-09 13:59:20 -07:00
fmt-merge-msg.c
for-each-ref.c
fsck.c
gc.c builtin/gc.c: add missing newline in message 2011-06-19 14:46:39 -07:00
grep.c Merge branch 'jk/color-and-pager' 2011-08-28 21:19:16 -07:00
hash-object.c
help.c
index-pack.c Merge branch 'jc/zlib-wrap' into maint 2011-08-16 11:23:26 -07:00
init-db.c read_gitfile_gently(): rename misnamed function to read_gitfile() 2011-08-22 14:04:56 -07:00
log.c format-patch: ignore ui.color 2011-09-12 11:43:58 -07:00
ls-files.c Merge branch 'cb/maint-ls-files-error-report' 2011-08-23 15:34:31 -07:00
ls-remote.c
ls-tree.c Ensure git ls-tree exits with a non-zero exit code if read_tree_recursive fails. 2011-07-25 10:50:11 -07:00
mailinfo.c
mailsplit.c
merge-base.c
merge-file.c
merge-index.c Fix sparse warnings 2011-03-22 10:16:54 -07:00
merge-ours.c
merge-recursive.c
merge-tree.c sparse: Fix an "symbol 'merge_file' not decared" warning 2011-04-11 10:35:25 -07:00
merge.c Merge branch 'jk/color-and-pager' 2011-08-28 21:19:16 -07:00
mktag.c
mktree.c
mv.c i18n: git-mv "bad" messages 2011-03-09 23:52:56 -08:00
name-rev.c object.h: Add OBJECT_ARRAY_INIT macro and make use of it. 2010-08-29 22:42:49 -07:00
notes.c
pack-objects.c pack-objects: protect against disappearing packs 2011-10-14 11:42:37 -07:00
pack-redundant.c
pack-refs.c
patch-id.c
prune-packed.c Move 'builtin-*' into a 'builtin/' subdirectory 2010-02-22 14:29:41 -08:00
prune.c add description parameter to OPT__DRY_RUN 2010-11-15 09:57:37 -08:00
push.c push: Don't push a repository with unpushed submodules 2011-08-20 23:03:52 -07:00
read-tree.c
receive-pack.c Sync with 1.7.6.2 2011-09-06 11:42:12 -07:00
reflog.c reflog: actually default to subcommand 'show' 2011-08-01 10:52:34 -07:00
remote-ext.c Remove unused variables 2011-03-22 11:43:27 -07:00
remote-fd.c
remote.c Merge branch 'maint' 2011-08-25 16:00:07 -07:00
replace.c
rerere.c
reset.c Merge branch 'jk/reset-reflog-message-fix' 2011-08-08 12:33:33 -07:00
rev-list.c Merge branch 'jk/format-patch-am' 2011-05-31 12:19:11 -07:00
rev-parse.c
revert.c Merge branch 'jn/plug-empty-tree-leak' 2011-08-25 16:00:29 -07:00
rm.c
send-pack.c Revert "Merge branch 'cb/maint-quiet-push' into maint" 2011-09-06 11:10:41 -07:00
shortlog.c Merge branch 'jk/format-patch-am' 2011-05-31 12:19:11 -07:00
show-branch.c want_color: automatically fallback to color.ui 2011-08-19 15:51:38 -07:00
show-ref.c
stripspace.c Move 'builtin-*' into a 'builtin/' subdirectory 2010-02-22 14:29:41 -08:00
symbolic-ref.c
tag.c Merge branch 'jk/tag-contains-ab' (early part) into maint 2011-09-11 21:54:32 -07:00
tar-tree.c
unpack-file.c
unpack-objects.c zlib: zlib can only process 4GB at a time 2011-06-10 11:52:15 -07:00
update-index.c plug a few coverity-spotted leaks 2011-06-20 14:27:36 -07:00
update-ref.c update-ref: whitespace fix 2011-08-25 14:42:11 -07:00
update-server-info.c
upload-archive.c upload-archive: allow user to turn off filters 2011-06-22 11:12:35 -07:00
var.c
verify-pack.c verify-pack: use index-pack --verify 2011-06-05 22:45:38 -07:00
verify-tag.c Merge branch 'mg/maint-tag-rfc1991' 2010-12-08 11:24:13 -08:00
write-tree.c