How can I test if a physical address is already mapped or not.
Hi all, In a kernel module is there a way to test if an address range has been already mapped by the kernel or not. Ex: (on a PC with the latest kernel) - an access to physical 0xC0000000 will return the value at this address - an access to physical 0x00100000 will have the kernel kill the module/application using the module. Dmesg: BUG: unable to handle kernel paging request at 00100000. How can I test this condition before dereferencing the address. Thanks, Stephan.
On Tue, Oct 18, 2011 at 1:34 AM, StephanT <stman937-linewbie@yahoo.com> wrote:
Hi all, In a kernel module is there a way to test if an address range has been already mapped by the kernel or not. Ex: (on a PC with the latest kernel) - an access to physical 0xC0000000 will return the value at this address - an access to physical 0x00100000 will have the kernel kill the module/application using the module. Dmesg: BUG: unable to handle kernel paging request at 00100000.
How can I test this condition before dereferencing the address. Thanks, Stephan.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
When you say an access to physical address, how are you managing to access the physical address directly?
-----Original Message----- From: kernelnewbies-bounces@kernelnewbies.org [mailto:kernelnewbies- bounces@kernelnewbies.org] On Behalf Of StephanT Sent: Tuesday, October 18, 2011 10:23 AM To: kernelnewbies Subject: Re: How can I test if a physical address is already mapped or not.
When you say an access to physical address, how are you managing to access the physical address directly?
Like this:
unsigned long * const pReg = (unsigned long*) 0XC0000000 ;
printk( KERN_INFO"** read (%p) %08lX.\n", pReg, *pReg) ;
On any virtual memory processor I am aware of, the above will cause pReg to contain a virtual address, not a physical address. Jeff Haran
unsigned long * const pReg = (unsigned long*) 0XC0000000 ;
printk( KERN_INFO"** read (%p) %08lX.\n", pReg, *pReg) ;
On any virtual memory processor I am aware of, the above will cause pReg to contain a virtual address, not a physical address. Jeff, I do not follow you... Could you, please be more explicit. Thanks.
-----Original Message----- From: StephanT [mailto:stman937-linewbie@yahoo.com] Sent: Tuesday, October 18, 2011 1:58 PM To: Jeff Haran; kernelnewbies Subject: Re: How can I test if a physical address is already mapped or not.
unsigned long * const pReg = (unsigned long*) 0XC0000000 ;
printk( KERN_INFO"** read (%p) %08lX.\n", pReg, *pReg) ;
On any virtual memory processor I am aware of, the above will cause pReg to contain a virtual address, not a physical address.
Jeff,
I do not follow you... Could you, please be more explicit.
Thanks.
I am assuming the processor you are running this on has an MMU (Memory Management Unit). This statement: unsigned long * const pReg = (unsigned long*) 0XC0000000 ; will cause the variable pReg to contain the constant 0xC0000000. When *pReg is evaluated in your printk(), the MMU will load the unsigned long located at virtual address 0xC0000000 into some processor register. How the mapping of the virtual address to physical address occurs is processor specific, but in Linux ultimately the physical address to get the data from will be derived from a page table that provides a mapping between the physical and virtual addresses of 4KB (usually 4KB) pages . Do a search on "Understanding the Linux Virtual Memory Manager" by Mel Gorman. It's a little dated, but the PDF can be obtained for free. I suspect reading this will help you to understand what is going on better than I can explain in this post. I know it helped me out a lot many years ago when I was puzzling through a problem related to this. Jeff Haran
> unsigned long * const pReg = (unsigned long*) 0XC0000000 ;
> > printk( KERN_INFO"** read (%p) %08lX.\n", pReg, *pReg) ;
I am assuming the processor you are running this on has an MMU (Memory Management Unit). This statement:
unsigned long * const pReg = (unsigned long*) 0XC0000000 ;
will cause the variable pReg to contain the constant 0xC0000000.
When *pReg is evaluated in your printk(), the MMU will load the unsigned long located at virtual address 0xC0000000 into some processor register. How the mapping of the virtual address to physical address occurs is processor specific, but in Linux ultimately the physical address to get the data from will be derived from a page table that provides a mapping between the physical and virtual addresses of 4KB (usually 4KB) pages .
Jeff, Thanks for your kind explanation. I understand now your comment. Yes you are right when you are in user space. However in a kernel module this would be physical address. I test on an embedded Linux board but I translated the problem to a PC which everyone can test. The 0xC0000000 falls under PCI address range. I guess on a PC Linux just doesn't map this address range or it maps it one2one (phys==virt) I can dereference this address and I get something plausible. The physical 0x00100000 is the Linux load address - see /proc/iomap. It was previously discussed on this group: (http://lists.kernelnewbies.org/pipermail/kernelnewbies/2011-October/003483.h...) When I try to dereference it (physical level) I get the error listed in my first post and Linux kills my module (or if it is installed as a driver kills the application which uses the driver). I guess it is normal because this address range is already mapped by Linux - in virtual address Linux starts at 0xC0000000. By using ioremap I can ask for a second map of this physical address and I can dereference it without getting killed. To get back to my initial question I'd like to be able to check this status before dereferencing the physical address and avoid to be killed if the address is already mapped :) Are there any kernel calls allowing me to do so ? Thanks, Stephan.
-----Original Message----- From: StephanT [mailto:stman937-linewbie@yahoo.com] Sent: Tuesday, October 18, 2011 5:29 PM To: Jeff Haran; kernelnewbies Subject: Re: How can I test if a physical address is already mapped or not.
> unsigned long * const pReg = (unsigned long*) 0XC0000000 ;
> > printk( KERN_INFO"** read (%p) %08lX.\n", pReg, *pReg) ;
I am assuming the processor you are running this on has an MMU (Memory Management Unit). This statement:
unsigned long * const pReg = (unsigned long*) 0XC0000000 ;
will cause the variable pReg to contain the constant 0xC0000000.
When *pReg is evaluated in your printk(), the MMU will load the unsigned long located at virtual address 0xC0000000 into some processor register. How the mapping of the virtual address to physical address occurs is processor specific, but in Linux ultimately the physical address to get the data from will be derived from a page table that provides a mapping between the physical and virtual addresses of 4KB (usually 4KB) pages .
Jeff,
Thanks for your kind explanation. I understand now your comment.
Yes you are right when you are in user space. However in a kernel module this would be physical address.
Nope. Unless you are using some really strange processor that I am not familiar with, a memory read is a memory read. *pReg is going to read what's at virtual address 0xc0000000 regardless of whether you are executing in user or kernel context. I know it's going to work this way on a PC with an Intel x86 processor.
I test on an embedded Linux board but I translated the problem to a PC which everyone can test.
The 0xC0000000 falls under PCI address range. I guess on a PC Linux just doesn't map this address range or it maps it one2one (phys==virt) I can dereference this address and I get something plausible.
On most 32 bit Intel processors running "standard" Linux 0xC0000000 is the first address of kernel VM. This is a function of kernel configuration, but it's this way by default. It's still a virtual address. So yes, on your PC virtual address 0xC0000000 is mapped to physical RAM.
The physical 0x00100000 is the Linux load address - see /proc/iomap. It was previously discussed on this group: (http://lists.kernelnewbies.org/pipermail/kernelnewbies/2011- October/003483.html) When I try to dereference it (physical level) I get the error listed in my first post and Linux kills my module (or if it is installed as a driver kills the application which uses the driver). I guess it is normal because this address range is already mapped by Linux - in virtual address Linux starts at 0xC0000000. By using ioremap I can ask for a second map of this physical address and I can dereference it without getting killed.
To get back to my initial question I'd like to be able to check this status before dereferencing the physical address and avoid to be killed if the address is already mapped :) Are there any kernel calls allowing me to do so ?
Not to my knowledge. Doesn't mean they don't exist, I just don't know of any such thing. Jeff Haran
Yes you are right when you are in user space. However in a kernel module this would be physical address.
Nope. Unless you are using some really strange processor that I am not familiar with, a memory read is a memory read. *pReg is going to read what's at virtual address 0xc0000000 regardless of whether you are executing in user or kernel context. I know it's going to work this way on a PC with an Intel x86 processor.
OK, but how do you explain I can read 0xC0000000 and I get kicked out if I try 0x00100000.
The 0xC0000000 falls under PCI address range. I guess on a PC Linux just doesn't map this address range or it maps it one2one (phys==virt) I can dereference this address and I get something plausible.
On most 32 bit Intel processors running "standard" Linux 0xC0000000 is the first address of kernel VM. This is a function of kernel configuration, but it's this way by default. It's still a virtual address. So yes, on your PC virtual address 0xC0000000 is mapped to physical RAM.
Would this mean by reading the 0xC0000000 I am reading the Linux code not PCI registers? Thanks, Stephan.
-----Original Message----- From: StephanT [mailto:stman937-linewbie@yahoo.com] Sent: Tuesday, October 18, 2011 6:01 PM To: Jeff Haran; kernelnewbies Subject: Re: How can I test if a physical address is already mapped or not.
Yes you are right when you are in user space. However in a kernel module this would be physical address.
Nope. Unless you are using some really strange processor that I am not familiar with, a memory read is a memory read. *pReg is going to read what's at virtual address 0xc0000000 regardless of whether you are executing in user or kernel context. I know it's going to work this way on a PC with an Intel x86 processor.
OK, but how do you explain I can read 0xC0000000 and I get kicked out if I try 0x00100000.
I can only assume that there is nothing mapped to virtual address 0x00100000. On a 32 bit PC, the bottom 3 GB of virtual memory is by default mapped to user space, so if anything you are accessing memory in the current process' virtual memory.
The 0xC0000000 falls under PCI address range. I guess on a PC Linux just doesn't map this address range or it maps it one2one (phys==virt) I can dereference this address and I get something plausible.
On most 32 bit Intel processors running "standard" Linux 0xC0000000 is the first address of kernel VM. This is a function of kernel configuration, but it's this way by default. It's still a virtual address. So yes, on your PC virtual address 0xC0000000 is mapped to physical RAM.
Would this mean by reading the 0xC0000000 I am reading the Linux code not PCI registers?
First part of the page table, I think. I don't really remember what the kernel maps down there but I don't think its code. Read the Gorman book. It's a lot to get through, but you'll likely learn a lot. There might even be something newer out there. Jeff Haran
On Wed, Oct 19, 2011 at 6:46 AM, Jeff Haran <jharan@bytemobile.com> wrote:
-----Original Message----- From: StephanT [mailto:stman937-linewbie@yahoo.com] Sent: Tuesday, October 18, 2011 6:01 PM To: Jeff Haran; kernelnewbies Subject: Re: How can I test if a physical address is already mapped or not.
Yes you are right when you are in user space. However in a kernel module this would be physical address.
Nope. Unless you are using some really strange processor that I am not familiar with, a memory read is a memory read. *pReg is going to read what's at virtual address 0xc0000000 regardless of whether you are executing in user or kernel context. I know it's going to work this way on a PC with an Intel x86 processor.
OK, but how do you explain I can read 0xC0000000 and I get kicked out if I try 0x00100000.
I can only assume that there is nothing mapped to virtual address 0x00100000. On a 32 bit PC, the bottom 3 GB of virtual memory is by default mapped to user space, so if anything you are accessing memory in the current process' virtual memory.
The 0xC0000000 falls under PCI address range. I guess on a PC Linux just doesn't map this address range or it maps it one2one (phys==virt) I can dereference this address and I get something plausible.
On most 32 bit Intel processors running "standard" Linux 0xC0000000 is the first address of kernel VM. This is a function of kernel configuration, but it's this way by default. It's still a virtual address. So yes, on your PC virtual address 0xC0000000 is mapped to physical RAM.
Would this mean by reading the 0xC0000000 I am reading the Linux code not PCI registers?
First part of the page table, I think. I don't really remember what the kernel maps down there but I don't think its code. Read the Gorman book. It's a lot to get through, but you'll likely learn a lot. There might even be something newer out there.
Jeff Haran
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Stephan,
From your post it looks like you are trying to simulate environment on Embedded Linux board to your PC? Did you check if embedded Linux has CONFIG_MMU kernel config option set? If that is the case then you might be bypassing page-table translation on your board and CPU assumes virtual address = physical address in that case. However same may not be true on PC which uses page-tables.
"Understanding Linux Kernel" book is also a good reference for understanding memory management in Linux. One Advice: when shifting from one hardware to another, be ready for surprises and open to unlearn things :) Thanks, Rajat
I can't seem to get my character device to remove itself from the /proc/devices list. I'm calling all of the following functions like so: alloc_chrdev_region(&dev, 0, 5, "my_char"); cdev_init(&my_cdev, &my_ops); cdev_add(&my_cdev, MKDEV(my_major, my_minor), 1); cdev_del(&my_cdev); unregister_chrdev_region(my_major, 5); It seems like I'm missing something, but I can't find it. I'm referencing the Linux Device Drivers v3, chapter 3. In the example code, the scull_cleanup_module function calls cdev_dell and unregister_chrdev_region, just like I do. To be clear, after I unload my module (after calling cdev_del and unregister_chrdev_region), my "my_char" string still shows up in /proc/devices. -Kai Meyer
On Wed, Oct 19, 2011 at 7:04 PM, Kai Meyer <kai@gnukai.com> wrote:
I can't seem to get my character device to remove itself from the /proc/devices list. I'm calling all of the following functions like so:
alloc_chrdev_region(&dev, 0, 5, "my_char"); cdev_init(&my_cdev, &my_ops); cdev_add(&my_cdev, MKDEV(my_major, my_minor), 1); cdev_del(&my_cdev); unregister_chrdev_region(my_major, 5);
It seems like I'm missing something, but I can't find it. I'm referencing the Linux Device Drivers v3, chapter 3. In the example code, the scull_cleanup_module function calls cdev_dell and unregister_chrdev_region, just like I do.
To be clear, after I unload my module (after calling cdev_del and unregister_chrdev_region), my "my_char" string still shows up in /proc/devices.
Did you check return codes for all functions? Also, can you post a link to the code? thanks, Daniel.
Unfortunately I can't share the source code, it belongs to the company I work for. All of cdev_init, cdev_del, and unregister_chrdev_region are void functions, so they have no return value. I check the return value of alloc_chrdev_region and cdev_add and check for errors with BUG_ON (for now). -Kai Meyer On 10/19/2011 02:18 PM, Daniel Baluta wrote:
On Wed, Oct 19, 2011 at 7:04 PM, Kai Meyer<kai@gnukai.com> wrote:
I can't seem to get my character device to remove itself from the /proc/devices list. I'm calling all of the following functions like so:
alloc_chrdev_region(&dev, 0, 5, "my_char"); cdev_init(&my_cdev,&my_ops); cdev_add(&my_cdev, MKDEV(my_major, my_minor), 1); cdev_del(&my_cdev); unregister_chrdev_region(my_major, 5);
It seems like I'm missing something, but I can't find it. I'm referencing the Linux Device Drivers v3, chapter 3. In the example code, the scull_cleanup_module function calls cdev_dell and unregister_chrdev_region, just like I do.
To be clear, after I unload my module (after calling cdev_del and unregister_chrdev_region), my "my_char" string still shows up in /proc/devices. Did you check return codes for all functions? Also, can you post a link to the code?
thanks, Daniel.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
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.
On Thu, Oct 20, 2011 at 3:04 AM, Kai Meyer <kai@gnukai.com> wrote:
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));
This should be : - memcpy(&sb, buffer, 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.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Regards, Rohan Puri
Thanks for catching that :) I knew it would be something simple. On 10/19/2011 10:00 PM, rohan puri wrote:
On Thu, Oct 20, 2011 at 3:04 AM, Kai Meyer <kai@gnukai.com <mailto:kai@gnukai.com>> wrote:
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));
This should be : - memcpy(&sb, buffer, 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.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org <mailto:Kernelnewbies@kernelnewbies.org> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
Regards, Rohan Puri
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On Thu, Oct 20, 2011 at 2:25 AM, Kai Meyer <kai@gnukai.com> wrote:
Unfortunately I can't share the source code, it belongs to the company I work for.
All of cdev_init, cdev_del, and unregister_chrdev_region are void functions, so they have no return value.
I check the return value of alloc_chrdev_region and cdev_add and check for errors with BUG_ON (for now).
-Kai Meyer
On 10/19/2011 02:18 PM, Daniel Baluta wrote:
On Wed, Oct 19, 2011 at 7:04 PM, Kai Meyer<kai@gnukai.com> wrote:
I can't seem to get my character device to remove itself from the /proc/devices list. I'm calling all of the following functions like so:
alloc_chrdev_region(&dev, 0, 5, "my_char"); cdev_init(&my_cdev,&my_ops); cdev_add(&my_cdev, MKDEV(my_major, my_minor), 1); cdev_del(&my_cdev); unregister_chrdev_region(my_major, 5);
It seems like I'm missing something, but I can't find it. I'm referencing the Linux Device Drivers v3, chapter 3. In the example code, the scull_cleanup_module function calls cdev_dell and unregister_chrdev_region, just like I do.
To be clear, after I unload my module (after calling cdev_del and unregister_chrdev_region), my "my_char" string still shows up in /proc/devices. Did you check return codes for all functions? Also, can you post a link to the code?
thanks, Daniel.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
During cleanup i think you need to call function unregister_chrdev_region(). Regards, Rohan Puri
I do call unregister_chrdev_region. There are 5 functions in my original email that I call during the life of my module. Still no luck. -Kai Meyer On 10/19/2011 09:47 PM, rohan puri wrote:
On Thu, Oct 20, 2011 at 2:25 AM, Kai Meyer <kai@gnukai.com <mailto:kai@gnukai.com>> wrote:
Unfortunately I can't share the source code, it belongs to the company I work for.
All of cdev_init, cdev_del, and unregister_chrdev_region are void functions, so they have no return value.
I check the return value of alloc_chrdev_region and cdev_add and check for errors with BUG_ON (for now).
-Kai Meyer
On 10/19/2011 02:18 PM, Daniel Baluta wrote: > On Wed, Oct 19, 2011 at 7:04 PM, Kai Meyer<kai@gnukai.com <mailto:kai@gnukai.com>> wrote: >> I can't seem to get my character device to remove itself from the >> /proc/devices list. I'm calling all of the following functions like so: >> >> alloc_chrdev_region(&dev, 0, 5, "my_char"); >> cdev_init(&my_cdev,&my_ops); >> cdev_add(&my_cdev, MKDEV(my_major, my_minor), 1); >> cdev_del(&my_cdev); >> unregister_chrdev_region(my_major, 5); >> >> It seems like I'm missing something, but I can't find it. I'm >> referencing the Linux Device Drivers v3, chapter 3. In the example code, >> the scull_cleanup_module function calls cdev_dell and >> unregister_chrdev_region, just like I do. >> >> To be clear, after I unload my module (after calling cdev_del and >> unregister_chrdev_region), my "my_char" string still shows up in >> /proc/devices. > Did you check return codes for all functions? > Also, can you post a link to the code? > > thanks, > Daniel. > > _______________________________________________ > Kernelnewbies mailing list > Kernelnewbies@kernelnewbies.org <mailto:Kernelnewbies@kernelnewbies.org> > http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org <mailto:Kernelnewbies@kernelnewbies.org> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
During cleanup i think you need to call function unregister_chrdev_region().
Regards, Rohan Puri
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
participants (6)
-
Daniel Baluta -
Jeff Haran -
Kai Meyer -
Rajat Sharma -
rohan puri -
StephanT