+void mmap_cache_close_fd_range(MMapCache *m, int fd, uint64_t p) {
+ unsigned fd_index, c, w;
+ int r;
+
+ assert(m);
+ assert(fd > 0);
+
+ /* This drops all windows that include space right of the
+ * specified offset. This is useful to ensure that after the
+ * file size is extended we drop our mappings of the end and
+ * create it anew, since otherwise it is undefined whether
+ * mapping will continue to work as intended. */
+
+ r = mmap_cache_peek_fd_index(m, fd, &fd_index);
+ if (r <= 0)
+ return;
+
+ for (c = 0; c < m->contexts_max; c++) {
+ w = m->by_context[c];
+
+ if (w != (unsigned) -1 && m->windows[w].fd == fd)
+ mmap_cache_context_unset(m, c);
+ }
+
+ w = m->by_fd[fd_index].windows;
+ while (w != (unsigned) -1) {
+ Window *v;
+
+ v = m->windows + w;
+ assert(v->fd == fd);
+ assert(v->by_fd_next == (unsigned) -1 ||
+ m->windows[v->by_fd_next].fd == fd);
+
+ if (v->offset + v->size > p) {
+
+ mmap_cache_window_unmap(m, w);
+ mmap_cache_fd_remove(m, fd_index, w);
+ v->fd = -1;
+
+ w = m->by_fd[fd_index].windows;
+ } else
+ w = v->by_fd_next;
+ }
+}
+