Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 44d1c19

Browse files
torvaldsgitster
authored andcommitted
Make loose object file reading more careful
We used to do 'stat()+open()+mmap()+close()' to read the loose object file data, which does work fine, but has a couple of problems: - it unnecessarily walks the filename twice (at 'stat()' time and then again to open it) - NFS generally has open-close consistency guarantees, which means that the initial 'stat()' was technically done outside of the normal consistency rules. So change it to do 'open()+fstat()+mmap()+close()' instead, which avoids both these issues. Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5723fe7 commit 44d1c19

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

sha1_file.c

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ static size_t sz_fmt(size_t s) { return s; }
3535

3636
const unsigned char null_sha1[20];
3737

38-
static unsigned int sha1_file_open_flag = O_NOATIME;
39-
4038
const signed char hexval_table[256] = {
4139
-1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */
4240
-1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */
@@ -997,38 +995,58 @@ int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long siz
997995
return hashcmp(sha1, real_sha1) ? -1 : 0;
998996
}
999997

998+
static int git_open_noatime(const char *name)
999+
{
1000+
static int sha1_file_open_flag = O_NOATIME;
1001+
int fd = open(name, O_RDONLY | sha1_file_open_flag);
1002+
1003+
/* Might the failure be due to O_NOATIME? */
1004+
if (fd < 0 && errno != ENOENT && sha1_file_open_flag) {
1005+
fd = open(name, O_RDONLY);
1006+
if (fd >= 0)
1007+
sha1_file_open_flag = 0;
1008+
}
1009+
return fd;
1010+
}
1011+
1012+
static int open_sha1_file(const unsigned char *sha1)
1013+
{
1014+
int fd;
1015+
char *name = sha1_file_name(sha1);
1016+
struct alternate_object_database *alt;
1017+
1018+
fd = git_open_noatime(name);
1019+
if (fd >= 0)
1020+
return fd;
1021+
1022+
prepare_alt_odb();
1023+
errno = ENOENT;
1024+
for (alt = alt_odb_list; alt; alt = alt->next) {
1025+
name = alt->name;
1026+
fill_sha1_path(name, sha1);
1027+
fd = git_open_noatime(alt->base);
1028+
if (fd >= 0)
1029+
return fd;
1030+
}
1031+
return -1;
1032+
}
1033+
10001034
static void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
10011035
{
1002-
struct stat st;
10031036
void *map;
10041037
int fd;
1005-
char *filename = find_sha1_file(sha1, &st);
10061038

1007-
if (!filename) {
1008-
return NULL;
1009-
}
1039+
fd = open_sha1_file(sha1);
1040+
map = NULL;
1041+
if (fd >= 0) {
1042+
struct stat st;
10101043

1011-
fd = open(filename, O_RDONLY | sha1_file_open_flag);
1012-
if (fd < 0) {
1013-
/* See if it works without O_NOATIME */
1014-
switch (sha1_file_open_flag) {
1015-
default:
1016-
fd = open(filename, O_RDONLY);
1017-
if (fd >= 0)
1018-
break;
1019-
/* Fallthrough */
1020-
case 0:
1021-
return NULL;
1044+
if (!fstat(fd, &st)) {
1045+
*size = xsize_t(st.st_size);
1046+
map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
10221047
}
1023-
1024-
/* If it failed once, it will probably fail again.
1025-
* Stop using O_NOATIME
1026-
*/
1027-
sha1_file_open_flag = 0;
1048+
close(fd);
10281049
}
1029-
*size = xsize_t(st.st_size);
1030-
map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
1031-
close(fd);
10321050
return map;
10331051
}
10341052

0 commit comments

Comments
 (0)