static void store_pageinfo(int fd) { int i; sigset_t mask, old_mask; sigfillset(&mask); sigprocmask(SIG_BLOCK, &mask, &old_mask); /* Hint we'll be using this file only once; * the Linux kernel will currently ignore this */ fadv_noreuse(fd, 0, 0); /* check if there's space to store the info */ pthread_mutex_lock(&lock); for(i = 0; i < max_fds && fds[i].fd != -1; i++) ; if(i == max_fds) { pthread_mutex_unlock(&lock); goto restoresigset; /* no space! */ } fds[i].fd = fd; pthread_mutex_unlock(&lock); if(!fd_get_pageinfo(fd, &fds[i])) goto cleanup; DEBUG("store_pageinfo(fd=%d): pages in cache: %zd/%zd (%.1f%%) [filesize=%.1fK, " "pagesize=%dK]\n", fd, fds[i].nr_pages_cached, fds[i].nr_pages, fds[i].nr_pages == 0 ? 0 : (100.0 * fds[i].nr_pages_cached / fds[i].nr_pages), 1.0 * fds[i].size / 1024, (int) PAGESIZE / 1024); goto restoresigset; cleanup: fds[i].fd = -1; restoresigset: sigprocmask(SIG_SETMASK, &old_mask, NULL); return; }
static void store_pageinfo(int fd) { int i; int pages; struct stat st; void *file = NULL; unsigned char *pageinfo = NULL; sigset_t mask, old_mask; sigfillset(&mask); sigprocmask(SIG_BLOCK, &mask, &old_mask); if(fstat(fd, &st) == -1 || !S_ISREG(st.st_mode)) goto restoresigset; /* Hint we'll be using this file only once; * the Linux kernel will currently ignore this */ fadv_noreuse(fd, 0, 0); /* check if there's space to store the info */ pthread_mutex_lock(&lock); for(i = 0; i < max_fds && fds[i].fd != -1; i++) ; if(i == max_fds) { pthread_mutex_unlock(&lock); goto restoresigset; /* no space! */ } fds[i].fd = fd; pthread_mutex_unlock(&lock); /* If size is 0, mmap() will fail. We'll keep the fd stored, anyway, to * make sure the newly written pages will be freed (so no cleanup!). */ if(st.st_size == 0) { fds[i].size = 0; fds[i].nr_pages = 0; fds[i].info = NULL; DEBUG("store_pageinfo(fd=%d): file size is ZERO, slot=%d\n", fd, i); goto restoresigset; } DEBUG("store_pageinfo(fd=%d): st.st_size=%ld\n", fd, st.st_size); fds[i].size = st.st_size; pages = fds[i].nr_pages = (st.st_size + PAGESIZE - 1) / PAGESIZE; pageinfo = calloc(sizeof(*pageinfo), pages); if(!pageinfo) { DEBUG("calloc failed: size=%d on fd=%d slot=%d\n", pages, fd, i); goto cleanup; } file = mmap(NULL, st.st_size, PROT_NONE, MAP_SHARED, fd, 0); if(file == MAP_FAILED) { DEBUG("store_pageinfo(fd=%d): mmap failed, errno:%d, %s\n", fd, errno, strerror(errno)); goto cleanup; } if(mincore(file, st.st_size, pageinfo) == -1) goto cleanup; fds[i].info = pageinfo; munmap(file, st.st_size); if(debugfp != NULL) { int j, n = 0; for(j = 0; j < pages; j++) if(pageinfo[j] & 1) n++; DEBUG("store_pageinfo(fd=%d): pages in cache: %d/%d (%.1f%%) [filesize=%.1fK, " "pagesize=%dK]\n", fd, n, pages, 100.0 * n / pages, 1.0 * st.st_size / 1024, (int) PAGESIZE / 1024); } goto restoresigset; cleanup: fds[i].fd = -1; if(pageinfo) free(pageinfo); if(file) munmap(file, st.st_size); restoresigset: sigprocmask(SIG_SETMASK, &old_mask, NULL); return; }