For a university assignment, we have to modify the ext2 file system to store files in the inode's block pointers if it's smaller than 60 bytes, and move to regular block storage once the file grows larger than that.
I copied the ext2 code from the 2.6 linux kernel source (as instructed) and went from there.
When the file grows larger than 60 bytes, I need to copy any data that is currently in the inode's block pointer array into real blocks. So, I need to write kernel memory into ext2 blocks. A simple call to do_sync_write
won't work here because it takes user-space memory.
I've looked at the implementation of do_sync_write
and I'm not really sure how to replicate what it does, but with kernel memory instead.
This is my current implementation of this specific part (does not work):
ssize_t extmod_write(struct file *filp, const char *buf,
size_t len, loff_t *ppos)
{
...
printk(KERN_INFO "Switching to regular file");
temp = kmalloc(inode->i_size, GFP_KERNEL);
memcpy(temp, EXT2_I(inode)->i_data, inode->i_size);
/* Need to clear the block pointers before they are allocated by kernel */
memset(EXT2_I(inode)->i_data, 0, sizeof(EXT2_I(inode)->i_data));
if (do_sync_write(filp, temp, inode->i_size, &dummy) < 0) {
printk(KERN_INFO "DAMN! Writing current buffer failed");
return -EINVAL;
}
kfree(temp);
return do_sync_write(filp, buf, len, ppos);
Edit:
I looked at symlinks. Basically, ext2 has the concept of "fast symlinks"; i.e. the link name is less than 60 bytes long. If it's a fast symlink, the data gets stored in the block pointers. This is easy to do and I've already implemented this for regular files. If the link is a not a fast symlink, the data is handled the same way as regular files. I think I'm back to square one.
Dumb homework assignment.
The code does not work. Try mmap() and die.
I managed to figure it out. It required getting struct buffer_head
instances and reading/writing the data in them. By looping through the logical block numbers and using to ext2_get_block
to retrieve blocks (allocating them if necessary) and then using sb_getblk
to get the real buffer out and write to it. I've posted an implementation on my blog.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With