Understanding memcpy
Kai Meyer
kai at gnukai.com
Wed Oct 19 17:34:23 EDT 2011
I'm trying to poke around an ext4 file system. I can submit a bio for
the correct block, and read in what seems to be the correct information,
but when I try to memcpy my char *buffer to a reference to a struct I've
made, it just doesn't seem to work. The relevant code looks like this:
typedef struct ext2_superblock {
/* 00-03 */ uint32_t e2sb_inode_count;
/* 04-07 */ uint32_t e2sb_block_count;
/* 08-11 */ uint32_t e2sb_blocks_reserved;
/* 12-15 */ uint32_t e2sb_unallocated_blocks;
/* 16-19 */ uint32_t e2sb_unallocated_inodes;
/* 20-23 */ uint32_t e2sb_sb_block;
/* 24-27 */ uint32_t e2sb_log_block_size;
/* 28-31 */ uint32_t e2sb_log_fragment_size;
/* 32-35 */ uint32_t e2sb_num_blocks_per_group;
/* 36-39 */ uint32_t e2sb_num_frag_per_group;
/* 40-43 */ uint32_t e2sb_num_inodes_per_group;
/* 44-47 */ uint32_t e2sb_last_mount_time;
/* 48-51 */ uint32_t e2sb_last_written_time;
/* 52-53 */ uint16_t e2sb_num_mounted;
/* 54-55 */ uint16_t e2sb_num_allowed_mounts;
/* 56-57 */ uint16_t e2sb_signature;
/* 58-59 */ uint16_t e2sb_fs_state;
/* 60-61 */ uint16_t e2sb_error_action;
/* 62-63 */ uint16_t e2sb_ver_minor;
/* 64-67 */ uint32_t e2sb_last_check;
/* 68-71 */ uint32_t e2sb_time_between_checks;
/* 72-75 */ uint32_t e2sb_os_id;
/* 76-79 */ uint32_t e2sb_ver_major;
/* 80-81 */ uint16_t e2sb_uid;
/* 82-83 */ uint16_t e2sb_gid;
} e2sb;
char *buffer;
uint32_t *pointer;
e2sb sb;
buffer = __bio_kmap_atomic(bio, 0, KM_USER0);
pointer = (uint32_t *)buffer;
printk(KERN_DEBUG "sizeof pbd->sb %lu\n", sizeof(bpd->sb));
printk(KERN_DEBUG "Inode Count: %u\n", pointer[0]); /* Works! */
printk(KERN_DEBUG "Block Count: %u\n", pointer[1]); /* Works! */
printk(KERN_DEBUG "Block Reserved: %u\n", pointer[2]); /* Works! */
printk(KERN_DEBUG "Unallocated blocks: %u\n", pointer[3]); /* Works! */
printk(KERN_DEBUG "Unallocated inodes: %u\n", pointer[4]); /* Works! */
memcpy(buffer, &sb, sizeof(sb));
__bio_kunmap_atomic(bio, KM_USER0);
printk(KERN_DEBUG "e2sb_debug: Total number of inodes in file system
%u\n", sb->e2sb_inode_count);/* Doesn't work! */
printk(KERN_DEBUG "e2sb_debug: Total number of blocks in file
system%u\n", sb->e2sb_block_count); /* Doesn't work! */
My code is actually much more verbose. The values I get from indexing
into pointer are correct, and match what I get from dumpe2fs. The values
I get from the e2sb struct are not. They are usually 0. I would imagine
that memcpy is the fastest way to copy data from buffer instead of
casting the pointer to something else, and using array indexing to get
the values.
I struggled to find where ext4 actually does this, so I'm making this up
as I go along. Any thing that you see that I should be doing a different
way that isn't actually part of my question is welcome too.
More information about the Kernelnewbies
mailing list