Writing kernel memory to ext2 block
Asked Answered
S

2

6

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.

Somatoplasm answered 26/10, 2011 at 9:12 Comment(4)
Hint: take a look at symlinks. IIRC they are stored in the inode too, given small enough size.Remy
Yeah, I can see where they just memcpy the link name to EXT2_I(inode)->i_data. My problem is what if you then want to copy that data to a block. The generic way that the ext2 module does it expects user data.Somatoplasm
I'm not doing your homework or reading, just giving you a hint. Take a look at what the symlink code does when the payload grows too big to fit into the inode. Obviously a disk block has to be allocated and the inode block pointers need to be initialised to point to it. Don't mention the bitmaps (don't know if ext2 had them)Remy
Thanks, wildplasser, I wouldn't expect you to! I noticed that symlinks behaved in the way I want my files to, I just though it was all 'symlink-specific'.Somatoplasm
S
1

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.

Somatoplasm answered 4/11, 2011 at 0:34 Comment(0)
S
1

Dumb homework assignment.

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

Sidonie answered 26/10, 2011 at 9:12 Comment(0)
S
1

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.

Somatoplasm answered 4/11, 2011 at 0:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.