Merge branch 'sp/emfile'
* sp/emfile: Work around EMFILE when there are too many pack files Use git_open_noatime when accessing pack data
This commit is contained in:
41
sha1_file.c
41
sha1_file.c
@ -35,6 +35,8 @@ static size_t sz_fmt(size_t s) { return s; }
|
|||||||
|
|
||||||
const unsigned char null_sha1[20];
|
const unsigned char null_sha1[20];
|
||||||
|
|
||||||
|
static int git_open_noatime(const char *name, struct packed_git *p);
|
||||||
|
|
||||||
int safe_create_leading_directories(char *path)
|
int safe_create_leading_directories(char *path)
|
||||||
{
|
{
|
||||||
char *pos = path + offset_1st_component(path);
|
char *pos = path + offset_1st_component(path);
|
||||||
@ -298,7 +300,7 @@ static void read_info_alternates(const char * relative_base, int depth)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
sprintf(path, "%s/%s", relative_base, alt_file_name);
|
sprintf(path, "%s/%s", relative_base, alt_file_name);
|
||||||
fd = open(path, O_RDONLY);
|
fd = git_open_noatime(path, NULL);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return;
|
return;
|
||||||
if (fstat(fd, &st) || (st.st_size == 0)) {
|
if (fstat(fd, &st) || (st.st_size == 0)) {
|
||||||
@ -411,7 +413,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
|
|||||||
struct pack_idx_header *hdr;
|
struct pack_idx_header *hdr;
|
||||||
size_t idx_size;
|
size_t idx_size;
|
||||||
uint32_t version, nr, i, *index;
|
uint32_t version, nr, i, *index;
|
||||||
int fd = open(path, O_RDONLY);
|
int fd = git_open_noatime(path, p);
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -655,9 +657,7 @@ static int open_packed_git_1(struct packed_git *p)
|
|||||||
if (!p->index_data && open_pack_index(p))
|
if (!p->index_data && open_pack_index(p))
|
||||||
return error("packfile %s index unavailable", p->pack_name);
|
return error("packfile %s index unavailable", p->pack_name);
|
||||||
|
|
||||||
p->pack_fd = open(p->pack_name, O_RDONLY);
|
p->pack_fd = git_open_noatime(p->pack_name, p);
|
||||||
while (p->pack_fd < 0 && errno == EMFILE && unuse_one_window(p, -1))
|
|
||||||
p->pack_fd = open(p->pack_name, O_RDONLY);
|
|
||||||
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
|
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -874,7 +874,7 @@ static void prepare_packed_git_one(char *objdir, int local)
|
|||||||
sprintf(path, "%s/pack", objdir);
|
sprintf(path, "%s/pack", objdir);
|
||||||
len = strlen(path);
|
len = strlen(path);
|
||||||
dir = opendir(path);
|
dir = opendir(path);
|
||||||
while (!dir && errno == EMFILE && unuse_one_window(packed_git, -1))
|
while (!dir && errno == EMFILE && unuse_one_window(NULL, -1))
|
||||||
dir = opendir(path);
|
dir = opendir(path);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
@ -1022,18 +1022,31 @@ int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long siz
|
|||||||
return hashcmp(sha1, real_sha1) ? -1 : 0;
|
return hashcmp(sha1, real_sha1) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int git_open_noatime(const char *name)
|
static int git_open_noatime(const char *name, struct packed_git *p)
|
||||||
{
|
{
|
||||||
static int sha1_file_open_flag = O_NOATIME;
|
static int sha1_file_open_flag = O_NOATIME;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
int fd = open(name, O_RDONLY | sha1_file_open_flag);
|
int fd = open(name, O_RDONLY | sha1_file_open_flag);
|
||||||
|
if (fd >= 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
/* Might the failure be insufficient file descriptors? */
|
||||||
|
if (errno == EMFILE) {
|
||||||
|
if (unuse_one_window(p, -1))
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Might the failure be due to O_NOATIME? */
|
/* Might the failure be due to O_NOATIME? */
|
||||||
if (fd < 0 && errno != ENOENT && sha1_file_open_flag) {
|
if (errno != ENOENT && sha1_file_open_flag) {
|
||||||
fd = open(name, O_RDONLY);
|
|
||||||
if (fd >= 0)
|
|
||||||
sha1_file_open_flag = 0;
|
sha1_file_open_flag = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_sha1_file(const unsigned char *sha1)
|
static int open_sha1_file(const unsigned char *sha1)
|
||||||
@ -1042,7 +1055,7 @@ static int open_sha1_file(const unsigned char *sha1)
|
|||||||
char *name = sha1_file_name(sha1);
|
char *name = sha1_file_name(sha1);
|
||||||
struct alternate_object_database *alt;
|
struct alternate_object_database *alt;
|
||||||
|
|
||||||
fd = git_open_noatime(name);
|
fd = git_open_noatime(name, NULL);
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
@ -1051,7 +1064,7 @@ static int open_sha1_file(const unsigned char *sha1)
|
|||||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
for (alt = alt_odb_list; alt; alt = alt->next) {
|
||||||
name = alt->name;
|
name = alt->name;
|
||||||
fill_sha1_path(name, sha1);
|
fill_sha1_path(name, sha1);
|
||||||
fd = git_open_noatime(alt->base);
|
fd = git_open_noatime(alt->base, NULL);
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@ -2312,7 +2325,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
|
|||||||
|
|
||||||
filename = sha1_file_name(sha1);
|
filename = sha1_file_name(sha1);
|
||||||
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
|
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
|
||||||
while (fd < 0 && errno == EMFILE && unuse_one_window(packed_git, -1))
|
while (fd < 0 && errno == EMFILE && unuse_one_window(NULL, -1))
|
||||||
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
|
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno == EACCES)
|
if (errno == EACCES)
|
||||||
|
Reference in New Issue
Block a user