@@ -417,6 +417,8 @@ static unsigned int pack_used_ctr;
417417static unsigned int pack_mmap_calls ;
418418static unsigned int peak_pack_open_windows ;
419419static unsigned int pack_open_windows ;
420+ static unsigned int pack_open_fds ;
421+ static unsigned int pack_max_fds ;
420422static size_t peak_pack_mapped ;
421423static size_t pack_mapped ;
422424struct packed_git * packed_git ;
@@ -594,8 +596,10 @@ static int unuse_one_window(struct packed_git *current, int keep_fd)
594596 lru_l -> next = lru_w -> next ;
595597 else {
596598 lru_p -> windows = lru_w -> next ;
597- if (!lru_p -> windows && lru_p -> pack_fd != keep_fd ) {
599+ if (!lru_p -> windows && lru_p -> pack_fd != -1
600+ && lru_p -> pack_fd != keep_fd ) {
598601 close (lru_p -> pack_fd );
602+ pack_open_fds -- ;
599603 lru_p -> pack_fd = -1 ;
600604 }
601605 }
@@ -680,8 +684,10 @@ void free_pack_by_name(const char *pack_name)
680684 if (strcmp (pack_name , p -> pack_name ) == 0 ) {
681685 clear_delta_base_cache ();
682686 close_pack_windows (p );
683- if (p -> pack_fd != -1 )
687+ if (p -> pack_fd != -1 ) {
684688 close (p -> pack_fd );
689+ pack_open_fds -- ;
690+ }
685691 close_pack_index (p );
686692 free (p -> bad_object_sha1 );
687693 * pp = p -> next ;
@@ -707,9 +713,29 @@ static int open_packed_git_1(struct packed_git *p)
707713 if (!p -> index_data && open_pack_index (p ))
708714 return error ("packfile %s index unavailable" , p -> pack_name );
709715
716+ if (!pack_max_fds ) {
717+ struct rlimit lim ;
718+ unsigned int max_fds ;
719+
720+ if (getrlimit (RLIMIT_NOFILE , & lim ))
721+ die_errno ("cannot get RLIMIT_NOFILE" );
722+
723+ max_fds = lim .rlim_cur ;
724+
725+ /* Save 3 for stdin/stdout/stderr, 22 for work */
726+ if (25 < max_fds )
727+ pack_max_fds = max_fds - 25 ;
728+ else
729+ pack_max_fds = 1 ;
730+ }
731+
732+ while (pack_max_fds <= pack_open_fds && unuse_one_window (NULL , -1 ))
733+ ; /* nothing */
734+
710735 p -> pack_fd = git_open_noatime (p -> pack_name , p );
711736 if (p -> pack_fd < 0 || fstat (p -> pack_fd , & st ))
712737 return -1 ;
738+ pack_open_fds ++ ;
713739
714740 /* If we created the struct before we had the pack we lack size. */
715741 if (!p -> pack_size ) {
@@ -761,6 +787,7 @@ static int open_packed_git(struct packed_git *p)
761787 return 0 ;
762788 if (p -> pack_fd != -1 ) {
763789 close (p -> pack_fd );
790+ pack_open_fds -- ;
764791 p -> pack_fd = -1 ;
765792 }
766793 return -1 ;
@@ -786,14 +813,13 @@ unsigned char *use_pack(struct packed_git *p,
786813{
787814 struct pack_window * win = * w_cursor ;
788815
789- if (p -> pack_fd == -1 && open_packed_git (p ))
790- die ("packfile %s cannot be accessed" , p -> pack_name );
791-
792816 /* Since packfiles end in a hash of their content and it's
793817 * pointless to ask for an offset into the middle of that
794818 * hash, and the in_window function above wouldn't match
795819 * don't allow an offset too close to the end of the file.
796820 */
821+ if (!p -> pack_size && p -> pack_fd == -1 && open_packed_git (p ))
822+ die ("packfile %s cannot be accessed" , p -> pack_name );
797823 if (offset > (p -> pack_size - 20 ))
798824 die ("offset beyond end of packfile (truncated pack?)" );
799825
@@ -807,6 +833,10 @@ unsigned char *use_pack(struct packed_git *p,
807833 if (!win ) {
808834 size_t window_align = packed_git_window_size / 2 ;
809835 off_t len ;
836+
837+ if (p -> pack_fd == -1 && open_packed_git (p ))
838+ die ("packfile %s cannot be accessed" , p -> pack_name );
839+
810840 win = xcalloc (1 , sizeof (* win ));
811841 win -> offset = (offset / window_align ) * window_align ;
812842 len = p -> pack_size - win -> offset ;
@@ -824,6 +854,12 @@ unsigned char *use_pack(struct packed_git *p,
824854 die ("packfile %s cannot be mapped: %s" ,
825855 p -> pack_name ,
826856 strerror (errno ));
857+ if (!win -> offset && win -> len == p -> pack_size
858+ && !p -> do_not_close ) {
859+ close (p -> pack_fd );
860+ pack_open_fds -- ;
861+ p -> pack_fd = -1 ;
862+ }
827863 pack_mmap_calls ++ ;
828864 pack_open_windows ++ ;
829865 if (pack_mapped > peak_pack_mapped )
@@ -918,6 +954,9 @@ struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
918954
919955void install_packed_git (struct packed_git * pack )
920956{
957+ if (pack -> pack_fd != -1 )
958+ pack_open_fds ++ ;
959+
921960 pack -> next = packed_git ;
922961 packed_git = pack ;
923962}
@@ -935,8 +974,6 @@ static void prepare_packed_git_one(char *objdir, int local)
935974 sprintf (path , "%s/pack" , objdir );
936975 len = strlen (path );
937976 dir = opendir (path );
938- while (!dir && errno == EMFILE && unuse_one_window (NULL , -1 ))
939- dir = opendir (path );
940977 if (!dir ) {
941978 if (errno != ENOENT )
942979 error ("unable to open object pack directory: %s: %s" ,
@@ -1092,14 +1129,6 @@ static int git_open_noatime(const char *name, struct packed_git *p)
10921129 if (fd >= 0 )
10931130 return fd ;
10941131
1095- /* Might the failure be insufficient file descriptors? */
1096- if (errno == EMFILE ) {
1097- if (unuse_one_window (p , -1 ))
1098- continue ;
1099- else
1100- return -1 ;
1101- }
1102-
11031132 /* Might the failure be due to O_NOATIME? */
11041133 if (errno != ENOENT && sha1_file_open_flag ) {
11051134 sha1_file_open_flag = 0 ;
@@ -1931,6 +1960,27 @@ off_t find_pack_entry_one(const unsigned char *sha1,
19311960 return 0 ;
19321961}
19331962
1963+ static int is_pack_valid (struct packed_git * p )
1964+ {
1965+ /* An already open pack is known to be valid. */
1966+ if (p -> pack_fd != -1 )
1967+ return 1 ;
1968+
1969+ /* If the pack has one window completely covering the
1970+ * file size, the pack is known to be valid even if
1971+ * the descriptor is not currently open.
1972+ */
1973+ if (p -> windows ) {
1974+ struct pack_window * w = p -> windows ;
1975+
1976+ if (!w -> offset && w -> len == p -> pack_size )
1977+ return 1 ;
1978+ }
1979+
1980+ /* Force the pack to open to prove its valid. */
1981+ return !open_packed_git (p );
1982+ }
1983+
19341984static int find_pack_entry (const unsigned char * sha1 , struct pack_entry * e )
19351985{
19361986 static struct packed_git * last_found = (void * )1 ;
@@ -1960,7 +2010,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
19602010 * it may have been deleted since the index
19612011 * was loaded!
19622012 */
1963- if (p -> pack_fd == -1 && open_packed_git (p )) {
2013+ if (! is_pack_valid (p )) {
19642014 error ("packfile %s cannot be accessed" , p -> pack_name );
19652015 goto next ;
19662016 }
@@ -2359,8 +2409,6 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
23592409
23602410 filename = sha1_file_name (sha1 );
23612411 fd = create_tmpfile (tmpfile , sizeof (tmpfile ), filename );
2362- while (fd < 0 && errno == EMFILE && unuse_one_window (NULL , -1 ))
2363- fd = create_tmpfile (tmpfile , sizeof (tmpfile ), filename );
23642412 if (fd < 0 ) {
23652413 if (errno == EACCES )
23662414 return error ("insufficient permission for adding an object to repository database %s\n" , get_object_directory ());
0 commit comments