-
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 7 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 |
---|---|---|
|
@@ -261,23 +261,48 @@ impl PageAllocator for Option<PerCpuPageAllocator> { | |
fn dealloc_data_page_list(&self, pages: &DataPageListWrapper<Clean, Free>) -> Result<()> { | ||
if let Some(allocator) = self { | ||
let mut page_list = pages.get_page_list_cursor(); | ||
let mut page = page_list.current(); | ||
|
||
// RBTree to store the free list for every cpu | ||
let mut cpu_free_list_map : RBTree<usize, Vec<PageNum>> = RBTree::new(); | ||
|
||
let mut page = page_list.current(); // head of page list | ||
|
||
// get a list of pages #s for each cpu | ||
while page.is_some() { | ||
// janky syntax to deal with the fact that page_list.current() returns an Option | ||
if let Some(page) = page { | ||
// TODO: refactor to avoid acquiring lock on every iteration | ||
allocator.dealloc_page(page.get_page_no())?; | ||
// pr_info!("Page: {}", page.get_page_no()); | ||
|
||
let cpu : usize = allocator.pageno2cpuid(page.get_page_no())?; | ||
|
||
if cpu_free_list_map.get(&cpu).is_none() { | ||
cpu_free_list_map.try_insert(cpu, Vec::new())?; | ||
} | ||
|
||
// add cpu page to vector (vector is mutable) | ||
let cpu_page_vec_option : Option<&mut Vec<PageNum>> = cpu_free_list_map.get_mut(&cpu); | ||
|
||
if cpu_page_vec_option.is_some() { | ||
let cpu_page_vec : &mut Vec<PageNum> = cpu_page_vec_option.unwrap(); // safe unwrap | ||
cpu_page_vec.try_push(page.get_page_no())?; | ||
} else { | ||
pr_info!("CPU not added to RBTree\n"); | ||
return Err(EINVAL); | ||
} | ||
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 Rust idiom -- you can structure this code as follows:
It's a bit more concise. If you rename
Within the |
||
|
||
page_list.move_next(); | ||
} else { | ||
unreachable!() | ||
} | ||
page = page_list.current(); | ||
page = page_list.current(); | ||
} | ||
|
||
// pr_info!("Num Pages in List: {}", num_pages); | ||
|
||
allocator.dealloc_multiple_page(cpu_free_list_map)?; | ||
Ok(()) | ||
|
||
} else { | ||
pr_info!("ERROR: page allocator is uninitialized\n"); | ||
Err(EINVAL) | ||
} | ||
} | ||
} | ||
|
||
fn dealloc_dir_page<'a>(&self, page: &DirPageWrapper<'a, Clean, Dealloc>) -> Result<()> { | ||
|
@@ -343,6 +368,52 @@ impl PerCpuPageAllocator { | |
Ok(()) | ||
} | ||
} | ||
|
||
|
||
fn dealloc_multiple_page(&self, cpu_free_list_map : RBTree<usize, Vec<PageNum>>) -> Result<()> { | ||
// add pages to corresponding free list in ascending cpu # order | ||
for (cpu, page_nos) in cpu_free_list_map.iter() { | ||
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. Just to be sure -- have you confirmed/checked that this always iterates over the CPU keys in ascending order? 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've confirmed through |
||
|
||
let free_list = Arc::clone(&self.free_lists[*cpu]); | ||
let mut free_list = free_list.lock(); | ||
|
||
for page_no in page_nos.iter() { | ||
|
||
free_list.free_pages += 1; | ||
let res = free_list.list.try_insert(*page_no, ()); | ||
|
||
// unwrap the error so we can get at the option | ||
let res = match res { | ||
Ok(res) => res, | ||
Err(e) => { | ||
pr_info!( | ||
"ERROR: failed to insert {:?} into page allocator at CPU {:?}, error {:?}\n", | ||
page_no, | ||
cpu, | ||
e | ||
); | ||
return Err(e); | ||
} | ||
}; | ||
|
||
if res.is_some() { | ||
pr_info!( | ||
"ERROR: page {:?} was already in the allocator at CPU {:?}\n", | ||
page_no, | ||
cpu | ||
); | ||
return Err(EINVAL); | ||
} | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn pageno2cpuid(&self, page_no : PageNum) -> Result<usize> { | ||
let cpu: usize = ((page_no - self.start) / self.pages_per_cpu).try_into()?; | ||
Ok(cpu) | ||
} | ||
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. Is there not already a function for this? 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 haven't found one that does this in balloc.rs. I noticed in |
||
|
||
} | ||
|
||
// placeholder page descriptor that can represent either a dir or data page descriptor | ||
|
@@ -2365,4 +2436,4 @@ impl<Op> DataPageListWrapper<InFlight, Op> { | |
pages: self.pages, | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/bin/bash | ||
sudo umount /dev/pmem0 | ||
sudo rmmod hayleyfs | ||
make LLVM=-14 fs/hayleyfs/hayleyfs.ko | ||
sudo insmod fs/hayleyfs/hayleyfs.ko | ||
sudo mount -o init -t hayleyfs /dev/pmem0 /mnt/pmem | ||
touch test.txt | ||
echo "Hello World" > test.txt | ||
sudo mv test.txt /mnt/pmem | ||
rm test.txt | ||
cd /mnt/pmem | ||
pwd | ||
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. Have you written any tests beyond this? I think it would be good to add (in a 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 added two tests - one testing a large file and one testing a series of small files. |
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.
It would be cleaner (and potentially more efficient) to take out the
if
statement that checks ifcpu
is incpu_free_list_map
; instead, you can obtaincpu_page_vec_option
as you currently do, and then rather than returning an error ifcpu_page_vec_option
isNone
below, create a new vector with the page number and insert it into the map.Also -- the convention here would be to just name the vector
cpu_page_vec
; it doesn't have to reflect the fact that it's anOption
.