Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing kernel memory to ext2 block

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.

like image 652
Anthony Avatar asked Oct 26 '11 09:10

Anthony


2 Answers

Dumb homework assignment.

The code does not work. Try mmap() and die.

like image 28
Joshua Avatar answered Nov 20 '22 10:11

Joshua


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.

like image 89
Anthony Avatar answered Nov 20 '22 10:11

Anthony