Sitemap

Beyond 4KB Pages: Implementing Dynamic Multi-Folio Support in OpenAFS

5 min readJul 8, 2025
Press enter or click to view image in full size

Welcome back to my GSoC 2025 series with OpenAFS! This is my third blog post where I share what I’ve been working on during my Google Summer of Code project. In my previous posts, I talked about getting started with OpenAFS. Now, I want to dive into something really exciting that I’ve been implementing — adding support for large folios in OpenAFS.

If you’re not familiar with what folios are, don’t worry — I’ll explain everything step by step. But here’s the basic idea: traditionally, Linux handles memory in small 4KB chunks called pages. This works fine for most things, but when you’re dealing with large files or lots of data (which happens a lot in distributed file systems like OpenAFS), these small chunks can become a bottleneck. Folios are a newer way to handle bigger chunks of memory at once, which can make things much faster.

Over the past few weeks, I’ve been working on making OpenAFS smart enough to use these larger memory chunks when it makes sense, while still falling back to the old 4KB pages when needed. It’s been a challenging but really rewarding experience, and I’m excited to share what I’ve learned with you.

What Are Pages and Folios Anyway?

Let me start by explaining the basics, because this stuff can get confusing pretty quickly. When your computer reads a file, it doesn’t just grab the whole thing at once. Instead, it breaks everything down into smaller, manageable pieces.

For years, Linux has used something called “pages” — these are fixed 4KB chunks of memory. Think of them like pages in a book, where each page can hold a certain amount of text. When you want to read a file, the kernel loads it page by page into memory. This system has worked well for decades, but it has some limitations.

The problem comes when you’re working with really large files. Imagine trying to read a massive textbook by loading just one page at a time — you’d spend a lot of time just turning pages instead of actually reading. That’s kind of what happens with 4KB pages when dealing with big files.

Folios are the solution to this problem. A folio can contain multiple pages grouped together, so instead of handling one 4KB chunk at a time, you might handle 16KB, 64KB, or even larger chunks. It’s like being able to read several pages of that textbook at once. The kernel can move more data with fewer operations, which means better performance and less overhead.

For file systems like OpenAFS that often deal with large files and lots of data movement between servers and clients, this can make a huge difference in how fast things run.

The Challenge in OpenAFS

Now that you understand the basics of pages and folios, let me explain why implementing this in OpenAFS was particularly tricky.

OpenAFS is a distributed file system that’s been around since very long. It was built during a time when 4KB pages were the standard, and honestly, they worked fine for the hardware and use cases back then. The entire memory management system in OpenAFS was designed around this assumption.

The main file where all the memory magic happens is called osi_vnodeops.c. This file contains hundreds of lines of code that handle how OpenAFS reads files, manages its cache, and moves data around. Every function in there was written with the idea that memory comes in neat little 4KB packages.

Here’s what makes it complicated: OpenAFS doesn’t just read files directly from disk like a simple file system. It has this sophisticated caching system where it stores frequently accessed files locally to speed things up. When you request a file, OpenAFS has to figure out whether to get it from the local cache, fetch it from a remote server, or maybe do a bit of both.

All of this logic was built around managing individual pages. The code would ask for one page, process it, then ask for the next page, and so on. It worked, but it wasn’t very efficient for large files.

The challenge I faced was: how do you add support for larger folios without breaking all the existing functionality? OpenAFS is used in production environments where stability is crucial. I couldn’t just rip out the old page-based code and replace it with something completely new.

Instead, I needed to make the system “dynamic” — smart enough to use folios when they would help, but still able to fall back to the old page-based approach when needed. This meant understanding not just how the new folio system works, but also how all the existing OpenAFS memory management was designed and why it was built that way.

My Implementation Approach

After understanding how the existing code worked, I knew I needed to make OpenAFS smart enough to choose between pages and folios automatically.

I built what I call “dynamic multi-folio support” — a system that detects what’s best for each situation instead of always using one approach.

First, I created a detection function called afs_detect_dynamic_folio_support() that checks if the kernel supports folios and whether it makes sense to use them. This runs when OpenAFS starts up.

Then I wrote afs_calculate_optimal_folio_order() which looks at each read operation and decides what size memory chunk would work best. It considers things like file size, how much data is being requested, and whether the request aligns with OpenAFS's 64KB chunks.

The cool part is that when someone requests a full 64KB chunk that’s perfectly aligned, the system uses a large folio. For smaller requests, it falls back to regular pages. This gives us the benefits of folios when they help, without wasting memory when they don’t.

I also added a simple on/off switch called enable_dynamic_multifolio so administrators can easily disable the feature if needed.

Results and Benefits

After implementing the dynamic folio support, I’m optimistic about the potential improvements this could bring to OpenAFS. Based on my understanding of how folios work, I expect to see significant performance gains, especially with large file operations.

The theory is that instead of making hundreds of separate 4KB requests, OpenAFS should now handle the same amount of data with fewer, larger operations. This should improve memory utilization and reduce overhead. I’m particularly excited about how this might work with OpenAFS’s cache bypass feature for very large files.

For smaller files, the system should correctly fall back to regular pages, so there shouldn’t be any performance penalty.

However, extensive testing is still needed to prove this actually works as intended. While the code compiles and the logic seems sound, real-world performance testing is a completely different challenge.

That’s what I’ll be focusing on next. I plan to use bpftrace extensively to monitor what’s actually happening — watching memory allocations in real-time, seeing when folios are used versus pages, and measuring the actual performance impact.

I also need to test various scenarios: small files, large files, heavy concurrent access, different cache configurations, and edge cases where things might break. Only after thorough testing will I know if this implementation delivers the performance benefits I’m hoping for.

The goal is to ensure all existing OpenAFS functionality continues to work exactly as before, while users get performance benefits automatically when appropriate.

--

--