Support unmapping windows on 'temporary' packfiles.
[gitweb.git] / sha1_file.c
index 63123cc47be29430565f594340374271248f01bc..01a2f8779e955a0ffa37440e5e680905155e84fe 100644 (file)
@@ -451,23 +451,34 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
        return 0;
 }
 
-static int unuse_one_window(void)
-{
-       struct packed_git *p, *lru_p = NULL;
-       struct pack_window *w, *w_l, *lru_w = NULL, *lru_l = NULL;
-
-       for (p = packed_git; p; p = p->next) {
-               for (w_l = NULL, w = p->windows; w; w = w->next) {
-                       if (!w->inuse_cnt) {
-                               if (!lru_w || w->last_used < lru_w->last_used) {
-                                       lru_p = p;
-                                       lru_w = w;
-                                       lru_l = w_l;
-                               }
+static void scan_windows(struct packed_git *p,
+       struct packed_git **lru_p,
+       struct pack_window **lru_w,
+       struct pack_window **lru_l)
+{
+       struct pack_window *w, *w_l;
+
+       for (w_l = NULL, w = p->windows; w; w = w->next) {
+               if (!w->inuse_cnt) {
+                       if (!*lru_w || w->last_used < (*lru_w)->last_used) {
+                               *lru_p = p;
+                               *lru_w = w;
+                               *lru_l = w_l;
                        }
-                       w_l = w;
                }
+               w_l = w;
        }
+}
+
+static int unuse_one_window(struct packed_git *current)
+{
+       struct packed_git *p, *lru_p = NULL;
+       struct pack_window *lru_w = NULL, *lru_l = NULL;
+
+       if (current)
+               scan_windows(current, &lru_p, &lru_w, &lru_l);
+       for (p = packed_git; p; p = p->next)
+               scan_windows(p, &lru_p, &lru_w, &lru_l);
        if (lru_p) {
                munmap(lru_w->base, lru_w->len);
                pack_mapped -= lru_w->len;
@@ -475,7 +486,7 @@ static int unuse_one_window(void)
                        lru_l->next = lru_w->next;
                else {
                        lru_p->windows = lru_w->next;
-                       if (!lru_p->windows) {
+                       if (!lru_p->windows && lru_p != current) {
                                close(lru_p->pack_fd);
                                lru_p->pack_fd = -1;
                        }
@@ -584,7 +595,8 @@ unsigned char* use_pack(struct packed_git *p,
                        if (win->len > packed_git_window_size)
                                win->len = packed_git_window_size;
                        pack_mapped += win->len;
-                       while (packed_git_limit < pack_mapped && unuse_one_window())
+                       while (packed_git_limit < pack_mapped
+                               && unuse_one_window(p))
                                ; /* nothing */
                        win->base = mmap(NULL, win->len,
                                PROT_READ, MAP_PRIVATE,