{"thread":{"id":"49208","subject":"clone, hardlinks, and file modes (and CAP_FOWNER)","startedAt":"2018-08-24T12:20:27Z","lastAt":"2018-08-24T19:59:38Z","messageCount":3,"participants":["Andreas Krey","Ævar Arnfjörð Bjarmason"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"356445","messageId":"20180824121407.GA19597@inner.h.apk.li","threadId":"49208","inReplyTo":null,"subject":"clone, hardlinks, and file modes (and CAP_FOWNER)","fromName":"Andreas Krey","fromEmail":"a.krey@gmx.de","sentAt":"2018-08-24T12:14:07Z","receivedAt":"2018-08-24T12:20:27Z","isPatch":false,"sender":{"key":"a.krey@gmx.de","avatar":"https://avatars.githubusercontent.com/u/37810?v=4"},"body":"Hi everybody,\n\nI'm currently looking into more aggressively sharing space between multiple repositories,\nand into getting them to share again after one did a repack (which costs us 15G space).\n\nOne thing I stumbled on is the /proc/sys/fs/protected_hardlinks stuff which disallows\nhardlinking pack files belonging to someone else. This consequently inhibits sharing\nwhen first cloning from a common shared cache repo.\n\nInstalling git with CAP_FOWNER is probably too dangerous;\nat least the capability should only be enabled during the directory copying.\n\n*\n\nAnd the next thing is that copied object/pack files are created with mode rw-rw-r--,\nunlike those that come out of the regular transports.\n\nApparent patch:\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex fd2c3ef090..6ffb4db4da 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -448,7 +448,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,\n                                die_errno(_(\"failed to create link '%s'\"), dest->buf);\n                        option_no_hardlinks = 1;\n                }\n-               if (copy_file_with_time(dest->buf, src->buf, 0666))\n+               if (copy_file_with_time(dest->buf, src->buf, 0444))\n                        die_errno(_(\"failed to copy file to '%s'\"), dest->buf);\n        }\n        closedir(dir);\n\nAlas, copy_file takes the mode just as a crude hint to executability, so also:\n\ndiff --git a/copy.c b/copy.c\nindex 4de6a110f0..883060009c 100644\n--- a/copy.c\n+++ b/copy.c\n@@ -32,7 +32,7 @@ int copy_file(const char *dst, const char *src, int mode)\n {\n        int fdi, fdo, status;\n \n-       mode = (mode & 0111) ? 0777 : 0666;\n+       mode = (mode & 0111) ? 0777 : (mode & 0222) ? 0666 : 0444;\n        if ((fdi = open(src, O_RDONLY)) < 0)\n                return fdi;\n        if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {\n\n(copy_file is also used with 0644 instead of the usual 0666 in refs/files-backend.c)\n\nWill submit as patch if acceptable; I'm not sure what the mode casing will\ndo with other users.\n\n- Andreas\n\n-- \n\"Totally trivial. Famous last words.\"\nFrom: Linus Torvalds <torvalds@*.org>\nDate: Fri, 22 Jan 2010 07:29:21 -0800\n"},{"id":"356461","messageId":"87tvnjes6y.fsf@evledraar.gmail.com","threadId":"49208","inReplyTo":"20180824121407.GA19597@inner.h.apk.li","subject":"Re: clone, hardlinks, and file modes (and CAP_FOWNER)","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-08-24T14:48:37Z","receivedAt":"2018-08-24T14:48:43Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Aug 24 2018, Andreas Krey wrote:\n\n> I'm currently looking into more aggressively sharing space between multiple repositories,\n> and into getting them to share again after one did a repack (which costs us 15G space).\n>\n> One thing I stumbled on is the /proc/sys/fs/protected_hardlinks stuff which disallows\n> hardlinking pack files belonging to someone else. This consequently inhibits sharing\n> when first cloning from a common shared cache repo.\n>\n> Installing git with CAP_FOWNER is probably too dangerous;\n> at least the capability should only be enabled during the directory copying.\n>\n> *\n>\n> And the next thing is that copied object/pack files are created with mode rw-rw-r--,\n> unlike those that come out of the regular transports.\n>\n> Apparent patch:\n>\n> diff --git a/builtin/clone.c b/builtin/clone.c\n> index fd2c3ef090..6ffb4db4da 100644\n> --- a/builtin/clone.c\n> +++ b/builtin/clone.c\n> @@ -448,7 +448,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,\n>                                 die_errno(_(\"failed to create link '%s'\"), dest->buf);\n>                         option_no_hardlinks = 1;\n>                 }\n> -               if (copy_file_with_time(dest->buf, src->buf, 0666))\n> +               if (copy_file_with_time(dest->buf, src->buf, 0444))\n>                         die_errno(_(\"failed to copy file to '%s'\"), dest->buf);\n>         }\n>         closedir(dir);\n>\n> Alas, copy_file takes the mode just as a crude hint to executability, so also:\n>\n> diff --git a/copy.c b/copy.c\n> index 4de6a110f0..883060009c 100644\n> --- a/copy.c\n> +++ b/copy.c\n> @@ -32,7 +32,7 @@ int copy_file(const char *dst, const char *src, int mode)\n>  {\n>         int fdi, fdo, status;\n>\n> -       mode = (mode & 0111) ? 0777 : 0666;\n> +       mode = (mode & 0111) ? 0777 : (mode & 0222) ? 0666 : 0444;\n>         if ((fdi = open(src, O_RDONLY)) < 0)\n>                 return fdi;\n>         if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {\n>\n> (copy_file is also used with 0644 instead of the usual 0666 in refs/files-backend.c)\n>\n> Will submit as patch if acceptable; I'm not sure what the mode casing will\n> do with other users.\n\nThis is mostly unrelated to your suggestion, but you might be interested\nin this thread I started a while ago of doing this with an approach\nunrelated to hardlinks, although you'll need a FS that does block\nde-duplication (and it won't work at all currently, needs some\npatching):\nhttps://public-inbox.org/git/87bmhiykvw.fsf@evledraar.gmail.com/\n\nI don't understand how this hardlink approach would work (doesn't mean\nit won't, just that I don't get it).\n\nAre you meaning to clone without --reference and instead via file:// and\nrely on FS-local hardlinks, but then how will that work once one of the\nrepos does a full repack? Are you going to inhibit that in some way,\ne.g. with gc.bigPackThreshold (but then why doesn't that work already?).\n\nIf you have such a tightly coupled approach isn't --reference closed to\nwhat you want in that case?\n"},{"id":"356487","messageId":"20180824195905.GA19781@inner.h.apk.li","threadId":"49208","inReplyTo":"87tvnjes6y.fsf@evledraar.gmail.com","subject":"Re: clone, hardlinks, and file modes (and CAP_FOWNER)","fromName":"Andreas Krey","fromEmail":"a.krey@gmx.de","sentAt":"2018-08-24T19:59:05Z","receivedAt":"2018-08-24T19:59:38Z","isPatch":false,"sender":{"key":"a.krey@gmx.de","avatar":"https://avatars.githubusercontent.com/u/37810?v=4"},"body":"On Fri, 24 Aug 2018 16:48:37 +0000, Ævar Arnfjörð Bjarmason wrote:\n...\n> I don't understand how this hardlink approach would work (doesn't mean\n> it won't, just that I don't get it).\n\nI just detect whether there is insufficient sharing (df is quite handy\nhere; 'df this/.git that/.git' tells the unshared part of that/.git only).\n\nWhen I detect 'unsharedness', I just hardlink the biggest .pack and the\ncorresponding .idx into the target repo, create a .keep file for that,\nrun 'git gc', and remove the .keep file. Effect: repack uses the .kept\nfile and only creates a small additional pack file for the remaining\nobjects, thus the biggest part of the objects are now shared between\nthe cache and the target repo.\n\nThis is going to be run once a week over all the repos on a machine\n(that were created by our tooling and thus have known locations),\nto avoid eventual repacks of repos to gradually and completely\nlose the sharedness of the objects/packs.\n\n> If you have such a tightly coupled approach isn't --reference closed to\n> what you want in that case?\n\nClose, but not. --reference et al. all need the promise that the\nreferenced repo isn't going away, and I don't want to rely on this\n(if someone thinks he can drop the cache this should not lead to\nbreakage in the work repos).\n\n- Andreas\n\n-- \n\"Totally trivial. Famous last words.\"\nFrom: Linus Torvalds <torvalds@*.org>\nDate: Fri, 22 Jan 2010 07:29:21 -0800\n"}]}