severity 642603 serious
merge 642603 645009
tags 642603 + patch pending
quit

Antti Kultanen wrote:
> On Tue, 11 Oct 2011, Jonathan Nieder wrote:

>> Do you use btrfs?
>
> Yes. Yes I do.
>
> What's going on?

See http://bugs.debian.org/642603 for details.  How about this patch?

-- >8 --
Subject: debian: use symlinks instead of hardlinks for builtin aliases

dpkg upgrades a package in three stages:

 1. Extract the new version of each file to <foo>.dpkg-new,
    and link the old version to <foo>.dpkg-tmp so the next step can be
    backed out if it is interrupted.
 2. fsync() and rename() the new files into place.
 3. Unlink the backed-up old versions.

The git package includes many hardlinks in /usr/lib/git-core. It
fails to upgrade in step 1 if this directory is located on a btrfs,
which have a limit of links to one inode in one directory:

| dpkg: error processing /var/cache/apt/archives/git_1%3a1.7.6.3-1_amd64.deb 
(--unpack):
|  unable to make backup link of `./usr/lib/git-core/git-send-pack' before 
installing new version: Too many links

At least within git itself, most uses of builtins use the non-dashed
form ("git <command>"), so effort spent optimizing the dashed forms
(e.g., by using hardlinks instead of symlinks) is mostly a waste.
Let's just use symlinks here.

Requested-by: Bastian Blank <[email protected]>
Fixes: http://bugs.debian.org/642603
Signed-off-by: Jonathan Nieder <[email protected]>
---
 debian/changelog                                   |    4 +
 ...d-a-knob-to-turn-off-hardlinks-within-same.diff |   84 ++++++++++++++++++++
 debian/rules                                       |    3 +-
 3 files changed, 90 insertions(+), 1 deletions(-)
 create mode 100644 
debian/diff/0018-Makefile-add-a-knob-to-turn-off-hardlinks-within-same.diff

diff --git a/debian/changelog b/debian/changelog
index 41c3ad7f..8e677616 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -15,6 +15,10 @@ git (1:1.7.7-1.1) unstable; urgency=low
         GNU/kFreeBSD
       * Makefile: fix permissions of mergetools/ when building from
         source extracted with permissive umask
+    * 0018-Makefile-add-a-knob-to-turn-off-hardlinks-...diff: new;
+      Makefile: add a knob to disable hardlinks within bindir and
+      gitexecdir.
+  * debian/rules: add NO_HARDLINKS=1 to OPTS (closes: #642603).
 
   [ Simon Chopin ]
   * debian/git.postinst: fix fresh install contrib/hooks cleaning
diff --git 
a/debian/diff/0018-Makefile-add-a-knob-to-turn-off-hardlinks-within-same.diff 
b/debian/diff/0018-Makefile-add-a-knob-to-turn-off-hardlinks-within-same.diff
new file mode 100644
index 00000000..222dcbf3
--- /dev/null
+++ 
b/debian/diff/0018-Makefile-add-a-knob-to-turn-off-hardlinks-within-same.diff
@@ -0,0 +1,84 @@
+From b58698d5c82baa52fb9aaba10c06152ad6b836d1 Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <[email protected]>
+Date: Wed, 12 Oct 2011 03:38:42 -0500
+Subject: Makefile: add a knob to turn off hardlinks within same directory
+
+The git builtins in $(gitexecdir) are implemented as hard links to a
+single git binary by default, so even the overhead of symlink
+resolution is not needed to run them.  However, the trick can be
+harmful, in two cases:
+
+ - on Windows, some tools to estimate directory size hugely
+   overestimate the size of git (each hardlink counts as taking up the
+   same amount of space as git.exe)
+
+ - various filesystems have limits on the number of hardlinks that
+   can be made to a particular file --- Linux's LINK_MAX is 127,
+   _POSIX_LINK_MAX is 8, and btrfs has a limit of 4096 /
+   ($len_filename + 8) or so links to a given inode in a single
+   directory.
+
+Normally that second case is not a problem (when ln fails, "make
+install" falls back to "ln -s"), but if git is tar'ed up on one
+filesystem and then extracted on a more limited one, it can result in
+"Too many links" errors.
+
+Nowadays people are encouraged to (and typically do) run builtins
+using the "git" command name directly rather than those dashed forms
+in scripts, making the use of hardlinks for the dashed forms a
+somewhat pointless optimization.  Introduce a new knob to allow people
+to turn it off with a simple "make install NO_HARDLINKS=YesPlease".
+
+Typically someone using this setting would want to set
+NO_CROSS_DIRECTORY_HARDLINKS, too, but that is not enforced, so you
+can make $(bindir)/git and $(gitexecdir)/git into hardlinks to the
+same inode and still make sure your tarball avoids the btrfs limits if
+you want.
+
+Requested-by: Bastian Blank <[email protected]>
+Signed-off-by: Jonathan Nieder <[email protected]>
+---
+ Makefile |    7 +++++++
+ 1 files changed, 7 insertions(+), 0 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 9afdcf2..ab64ff4 100644
+--- a/Makefile
++++ b/Makefile
+@@ -226,6 +226,10 @@ all::
+ # Define NO_CROSS_DIRECTORY_HARDLINKS if you plan to distribute the installed
+ # programs as a tar, where bin/ and libexec/ might be on different file 
systems.
+ #
++# Define NO_HARDLINKS if you plan to distribute the installed programs as a 
tar
++# that might be extracted on a filesystem like btrfs that does not cope well
++# with many links to one inode in one directory.
++#
+ # Define USE_NED_ALLOCATOR if you want to replace the platforms default
+ # memory allocators with the nedmalloc allocator written by Niall Douglas.
+ #
+@@ -2326,12 +2330,14 @@ endif
+       } && \
+       for p in $(filter $(install_bindir_programs),$(BUILT_INS)); do \
+               $(RM) "$$bindir/$$p" && \
++              test -z "$(NO_HARDLINKS)" && \
+               ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
+               ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
+               cp "$$bindir/git$X" "$$bindir/$$p" || exit; \
+       done && \
+       for p in $(BUILT_INS); do \
+               $(RM) "$$execdir/$$p" && \
++              test -z "$(NO_HARDLINKS)" && \
+               ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
+               ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
+               cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
+@@ -2339,6 +2345,7 @@ endif
+       remote_curl_aliases="$(REMOTE_CURL_ALIASES)" && \
+       for p in $$remote_curl_aliases; do \
+               $(RM) "$$execdir/$$p" && \
++              test -z "$(NO_HARDLINKS)" && \
+               ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || 
\
+               ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+               cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
+-- 
+1.7.7
+
diff --git a/debian/rules b/debian/rules
index 243b1335..a18ba26a 100755
--- a/debian/rules
+++ b/debian/rules
@@ -12,7 +12,8 @@ OPTS =NO_OPENSSL=1 prefix=/usr gitexecdir=/usr/lib/git-core \
   INSTALLDIRS=vendor \
   NO_PYTHON=1 \
   USE_SRV_RR=1 \
-  THREADED_DELTA_SEARCH=1 NO_CROSS_DIRECTORY_HARDLINKS=1 \
+  THREADED_DELTA_SEARCH=1 \
+  NO_CROSS_DIRECTORY_HARDLINKS=1 NO_HARDLINKS=1 \
   DEFAULT_PAGER=pager DEFAULT_EDITOR=editor
 DOC_OPTS =prefix=/usr htmldir=/usr/share/doc/git/html \
   ASCIIDOC8=1 ASCIIDOC_NO_ROFF=1
-- 
1.7.7




-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to