-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multipage Deallocator #19
base: main
Are you sure you want to change the base?
Changes from 14 commits
c42d438
1ba7094
2988a1a
7e319f9
b330656
b60af97
4148bf8
d4d2ece
ef92b91
91eb603
23cbbc8
2cb4bff
29ae1d2
85a99f9
c10bb2d
b0bb029
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#include <fcntl.h> | ||
#include <unistd.h> | ||
#include <stdbool.h> | ||
#include <stdio.h> | ||
#include <assert.h> | ||
#include <sys/statvfs.h> | ||
#define PAGESZ 4096 | ||
// consume all the pages and test effectiveness of the deallocator to make space for a new file | ||
// extend the size of a file or create a file and return the new size of the file | ||
long int enlarge_file(char *path, long int size) { | ||
int fd = open(path, O_CREAT | O_RDWR); | ||
assert (fd > -1); | ||
lseek(fd, size, SEEK_SET); | ||
FILE *fp = fdopen(fd, "w"); | ||
assert(fp); | ||
fputc('\0', fp); | ||
fclose(fp); | ||
close(fd); | ||
fd = open(path, O_CREAT | O_RDWR); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why close and reopen the file? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are write. I over complicated the code with lseek and changed to a write call. |
||
assert (fd > -1); | ||
lseek(fd, 0L, SEEK_END); | ||
long int new_size = lseek(fd, 0, SEEK_CUR) - 1; | ||
close(fd); | ||
return new_size; | ||
} | ||
|
||
int main(void) { | ||
struct statvfs stat; | ||
assert(statvfs("/mnt/pmem", &stat) == 0); | ||
unsigned long pages_start = stat.f_bfree; | ||
bool used_all_pages = false; | ||
int multiple = 1; | ||
long int prev_size = 0; | ||
char *path = "/mnt/pmem/myfile"; | ||
char *path2 = "/mnt/pmem/myfile2"; | ||
while (!used_all_pages) { | ||
long int new_size = enlarge_file(path, multiple * PAGESZ); | ||
used_all_pages = prev_size == new_size; | ||
multiple = used_all_pages ? multiple : multiple + 1; | ||
prev_size = new_size; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand exactly what this loop is doing; why increase There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The loop was intended to extend the file to use the maximum amount of pages before we run out, but that was overcomplicated. I now borrow the code from large_write and allocate 200000 pages instead. |
||
} | ||
// a new file with one less page should be able to be allocated after removal | ||
assert(prev_size > 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A stronger check would be to assert that the file you created is the expected size. |
||
assert (remove(path) == 0); | ||
|
||
assert(statvfs("/mnt/pmem", &stat) == 0); | ||
unsigned long pages_end = stat.f_bfree; | ||
assert(pages_start == pages_end); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another useful sanity check would be to ensure that between creating and deleting the big file, the number of pages in use has changed. |
||
|
||
long int new_size = enlarge_file(path2, PAGESZ * (multiple - 1)); | ||
assert (remove(path2) == 0); | ||
assert(new_size == PAGESZ * (multiple - 1)); | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#include <fcntl.h> | ||
#include <unistd.h> | ||
#include <stdbool.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <assert.h> | ||
#include <sys/statvfs.h> | ||
#define PAGESZ 4096 | ||
|
||
// create many files and test whether removing will return all pages to free list | ||
int main(void) { | ||
struct statvfs stat; | ||
assert(statvfs("/mnt/pmem", &stat) == 0); | ||
unsigned long pages_start = stat.f_bfree; | ||
unsigned num_files = 5000; | ||
char filename[64]; | ||
memset(filename, 0, 64); | ||
for (int i = 0; i < num_files; i ++) { | ||
sprintf(filename, "/mnt/pmem/%d", i); | ||
int fd = open(filename, O_CREAT | O_RDWR); | ||
lseek(fd, PAGESZ * 2, SEEK_SET); | ||
FILE *fp = fdopen(fd, "w"); | ||
assert(fp); | ||
putc('\0', fp); | ||
fclose(fp); | ||
close(fd); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as the other test w.r.t. increasing file size. |
||
|
||
for (int i = 0; i < num_files; i ++) { | ||
sprintf(filename, "/mnt/pmem/%d", i); | ||
assert(remove(filename) == 0); | ||
} | ||
assert(statvfs("/mnt/pmem", &stat) == 0); | ||
unsigned long pages_end = stat.f_bfree; | ||
assert(pages_start == pages_end); | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this actually increase the file's size? According tolseek
documentation (https://man7.org/linux/man-pages/man2/lseek.2.html),Edit: I see, the increase comes from the
fputc
writing a character at offsetsize
. I would still suggest switching to one of the following approaches.A more standard way of increasing the file's size (and one that would be sure to exercise page allocation code paths) would be to use the
write
system call to write a specified amount of data to the file: https://man7.org/linux/man-pages/man2/write.2.html, or thetruncate
syscall to set its size to a specified value. It doesn't actually matter what is written, so you could allocate a buffer but not update/set any of its bytes and just write whatever is already in it to the file. You can also do this with aFILE*
obtained fromfopen
/fdopen
using a function likefprintf
, but thewrite
system call may be easier because I thinkfprintf
requires you to provide bytes to write as a string.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great suggestion. I added a write call and it was much cleaner.