{"thread":{"id":"50094","subject":"Does \"git push\" open a pack for read before closing it?","startedAt":"2018-12-21T12:46:43Z","lastAt":"2019-01-07T15:56:55Z","messageCount":3,"participants":["git-mailinglist@happybeing.com","brian m. carlson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"365729","messageId":"5878633d-cdbd-ce05-30de-3417386c720e@happybeing.com","threadId":"50094","inReplyTo":null,"subject":"Does \"git push\" open a pack for read before closing it?","fromName":"","fromEmail":"git-mailinglist@happybeing.com","sentAt":"2018-12-21T12:46:35Z","receivedAt":"2018-12-21T12:46:43Z","isPatch":false,"sender":{"key":"git-mailinglist@happybeing.com","avatar":null},"body":"[Major ignorance alert]\n\nI'm writing software to implement a FUSE mount for a decentralised file\nsystem and during testing with git I see some strange behaviour which\nI'd like to investigate. It might be a bug in my code, or even the FUSE\nlib I'm using, or it might be intended behaviour by git.\n\nSo one thing I'd like to do is check if this is expected in git.\n\nSYSTEM\nOS: Ubuntu 18.10\ngit version 2.19.1\nDecentralised storage mounted at ~/SAFE\n\nWhat I'm doing\nI'm testing my FUSE implementation for SAFE Network while exploring the\nuse of git with decentralised storage, so not necessarily in a sensible\narrangement (comments on that also welcome).\n\nI have a folder at ~/SAFE/_public/tests/data1/ and want to create a bare\nrepo there to use as a remote from my local drive for an existing git\nrepo at ~/src/safe/sjs.git\n\nAnyway, I do the following sequence of commands which are all fine up\nuntil the last one which eventually fails:\n\n  cd ~/SAFE/_public/tests/data1\n  git init --bare blah\n  cd ~/src/safe/sjs.git\n  git remote remove origin\n  git remote add origin ~/SAFE/_public/tests/data1/blah\n  git push origin master\n\nHere's the output from the last command above:\n\nEnumerating objects: 373, done.\nCounting objects: 100% (373/373), done.\nDelta compression using up to 8 threads\nCompressing objects: 100% (371/371), done.\nWriting objects: 100% (373/373), 187.96 KiB | 33.00 KiB/s, done.\nTotal 373 (delta 254), reused 0 (delta 0)\nremote: fatal: unable to open\n/home/mrh/SAFE/_public/tests/data1/blah/./objects/incoming-73lbb6/pack/tmp_pack_pL28kQ:\nRemote I/O error\nerror: remote unpack failed: index-pack abnormal exit\nTo /home/mrh/SAFE/_public/tests/data1/blah\n ! [remote rejected] master -> master (unpacker error)\nerror: failed to push some refs to '/home/mrh/SAFE/_public/tests/data1/blah'\n\nInspecting the logs from my FUSE implementation I see that there's a\nproblem related to this file on the mounted storage:\n\n /_public/tests/data1/blah/objects/incoming-73lbb6/pack/tmp_pack_pL28kQ\n\nPrior to the error the file is written to multiple times by git - all\ngood (about 200kB in all). Then, before the file is closed I see an\nattempt to open it for read, which fails. The failure is because I don't\nsupport read on a file that is open for write yet, and I'm not sure if\nthat is sensible or what git might be expecting to do given the file has\nnot even been flushed to disk at this point.\n\nSo I'd like to know if this is expected behaviour by git (or where to\nlook to find out), and if it is expected, then what might git expect to\ndo if the file were opened successfully?\n\nN.B. After the failure, the file is closed and then deleted!\n\nAlso note that it is possible the behaviour I'm seeing is not really git\nbut another issue, such as a bug in the sync/async aspect of my code.\n\nThanks\n\nMark\n-- \nSecure Access For Everyone:\n- SAFE Network\n- First Autonomous Decentralised Internet\nhttps://safenetwork.tech\n\n"},{"id":"365757","messageId":"20181222231215.GC26554@genre.crustytoothpaste.net","threadId":"50094","inReplyTo":"5878633d-cdbd-ce05-30de-3417386c720e@happybeing.com","subject":"Re: Does \"git push\" open a pack for read before closing it?","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-12-22T23:12:18Z","receivedAt":"2018-12-22T23:12:42Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Fri, Dec 21, 2018 at 12:46:35PM +0000, git-mailinglist@happybeing.com wrote:\n> Here's the output from the last command above:\n> \n> Enumerating objects: 373, done.\n> Counting objects: 100% (373/373), done.\n> Delta compression using up to 8 threads\n> Compressing objects: 100% (371/371), done.\n> Writing objects: 100% (373/373), 187.96 KiB | 33.00 KiB/s, done.\n> Total 373 (delta 254), reused 0 (delta 0)\n> remote: fatal: unable to open\n> /home/mrh/SAFE/_public/tests/data1/blah/./objects/incoming-73lbb6/pack/tmp_pack_pL28kQ:\n> Remote I/O error\n> error: remote unpack failed: index-pack abnormal exit\n> To /home/mrh/SAFE/_public/tests/data1/blah\n>  ! [remote rejected] master -> master (unpacker error)\n> error: failed to push some refs to '/home/mrh/SAFE/_public/tests/data1/blah'\n> \n> Inspecting the logs from my FUSE implementation I see that there's a\n> problem related to this file on the mounted storage:\n> \n>  /_public/tests/data1/blah/objects/incoming-73lbb6/pack/tmp_pack_pL28kQ\n> \n> Prior to the error the file is written to multiple times by git - all\n> good (about 200kB in all). Then, before the file is closed I see an\n> attempt to open it for read, which fails. The failure is because I don't\n> support read on a file that is open for write yet, and I'm not sure if\n> that is sensible or what git might be expecting to do given the file has\n> not even been flushed to disk at this point.\n\nWhat I expect is happening is that Git receives the objects and writes\nthem to a temporary file (which you see in \"objects/incoming\") and then\nthey're passed to either git unpack-objects or git index-pack, which\nthen attempts to read it.\n\n> So I'd like to know if this is expected behaviour by git (or where to\n> look to find out), and if it is expected, then what might git expect to\n> do if the file were opened successfully?\n\nThis behavior is expected. POSIX says that a read that can be proved to\nhave occurred after a write must contain the new data, so it's possible\nthat a separate process may choose to read the file and index it,\nknowing that the index process was started after all the writes.\n\nThis is definitely an important invariant to preserve if your FUSE\nfile system is going to be used on a Unix system. In other words,\nconsistency (in the CAP sense) is required.\n\n> N.B. After the failure, the file is closed and then deleted!\n\nRight, if this had succeeded, we would have renamed it into place (or\nunpacked it and deleted it), but since it failed, we clean up after\nourselves so as not to leave large temporary files around.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"366259","messageId":"151d357d-4234-bb86-9764-8057b28d7117@markhughes.com","threadId":"50094","inReplyTo":"20181222231215.GC26554@genre.crustytoothpaste.net","subject":"Re: Does \"git push\" open a pack for read before closing it?","fromName":"","fromEmail":"git-mailinglist@happybeing.com","sentAt":"2019-01-07T15:56:48Z","receivedAt":"2019-01-07T15:56:55Z","isPatch":false,"sender":{"key":"git-mailinglist@happybeing.com","avatar":null},"body":"On 22/12/2018 23:12, brian m. carlson wrote:\nThanks Brian, you helped me make some progress. I'm stuck again trying\nto understand git behaviour though and wondering if there are better\nways of me seeing into git (source, debug o/p etc) than posting here.\n\nAs a reminder, I'm doing the following to create a bare repository on my\nFUSE mounted decentralised storage:\n\n  cd ~/SAFE/_public/tests/data1\n  git init --bare blah\n  cd ~/src/safe/sjs.git\n  git remote remove origin\n  git remote add origin ~/SAFE/_public/tests/data1/blah\n  git push origin master\n\nThe bugs are in my implementation of FUSE on the SAFE storage.\n\nI get additional output from git using the following (but it doesn't\nhelp me):\n set -x; GIT_TRACE=2 GIT_CURL_VERBOSE=2 GIT_TRACE_PERFORMANCE=2 \\\n GIT_TRACE_PACK_ACCESS=2 GIT_TRACE_PACKET=2 GIT_TRACE_PACKFILE=2 \\\n GIT_TRACE_SETUP=2 GIT_TRACE_SHALLOW=2 git push origin master -v -v \\\n 2>&1 |tee ~/git-trace.log; set +x\n\nAnyway, to add a little to your observations...\n\n> What I expect is happening is that Git receives the objects and writes\n> them to a temporary file (which you see in \"objects/incoming\") and then\n> they're passed to either git unpack-objects or git index-pack, which\n> then attempts to read it.\nThe git console output seems to confirm it is 'git index-pack' that\nencounters the error, which is currently:\n\n  Enumerating objects: 373, done.\n  Counting objects: 100% (373/373), done.\n  Delta compression using up to 8 threads\n  Compressing objects: 100% (371/371), done.\n  Writing objects: 100% (373/373), 192.43 KiB | 54.00 KiB/s, done.\n  Total 373 (delta 255), reused 0 (delta 0)\n  remote: fatal: premature end of pack file, 36 bytes missing\n  remote: fatal: premature end of pack file, 65 bytes missing\n  error: remote unpack failed: index-pack abnormal exit\n  To /home/mrh/SAFE/_public/tests/data1/blah\n   ! [remote rejected] master -> master (unpacker error)\n  error: failed to push some refs to\n'/home/mrh/SAFE/_public/tests/data/blah'\n\nSo I conclude I'm either not writing the file properly, or not reading\nit back properly. I can continue looking into that of course, but\nlooking at the file requests I'm curious about what git is doing and how\nto learn more about it as it looks odd.\n\nI have quite a few questions, but will focus on just the point at which\nit bails out. In summary, what I see is:\n\n- The pack file is created and written with multiple calls, ending up\nabout 200k long.\n\n- While still open for write, it is opened *four* times, so git has five\nhandles active on it. One write and four read.\n\n- At this point I see the following FUSE read operation:\n\n  read('/_public/tests/data1/blah/objects/incoming-quFPHB\n        /pack/tmp_pack_E4ea92', 58, buf, 4096, 16384)\n\n  58 is the file handle, 4096 the length of buf, and 16384 the position\n\n- Presumably this is where git encounters a problem because it then\ncloses everything and cleans up the incoming directory.\n\nIt seems odd to me that it is starting to read the pack file at position\n16384 rather than at 0 (or at 12 after the header). I can surmise it\nmight open it four times to speed access, but would expect to see it\nread the beginning of the file (or at position 12) before trying to\ninterpret the content and bailing out.\n\nSo I'm wondering what git is doing there. Any comments on this, or a\npointer to the relevant git code so I can look myself would be great.\n\nThanks,\n\nMak\n"}]}