Using struct causes kernel panic? - linux-kernel

I'm taking my first crack at writing some linux kernel code, and I'm hitting a weird kernel panic.
I have a linked list I am maintaining with the kernel's built-in macros (include/linux/list.h). If the list is empty, I allocate an instance of the following structure:
struct time_span
{
struct timeval start;
struct timeval end;
};
and point to it with a pointer called "tmp". I add tmp to the list I'm maintaining with list_add_tail().
Later, if the list is not empty (I'm trying to test with one list item to simplify debugging), I point to the first item in the list with tmp and try to print out the contents of tmp->end.tv_sec. Unfortunately, this causes a kernel panic.
tmp is not NULL (I check at run-time) and neither is "tmp->end" (I am able to print both). It's only when I try to access one of the fields in "end" that I get a kernel panic. I've never seen something like this before -- does anyone have any ideas?
Thanks for any assistance!
-------EDIT------
Code example (this lives in a function that will be called repeatedly):
// .........
struct timeval now_tv;
do_gettimeofday(&now_tv);
if(!list_empty(&(my_list.time_list)))
{
tmp = list_first_entry(&(my_list.time_list), struct time_span, time_list);
if(tmp != NULL)
{
tmp->end.tv_sec = now_tv.tv_sec; // THIS BREAKS
// Attempting to print "tmp->end.tv_sec" also breaks.
tmp->end.tv_usec = now_tv.tv_usec;
}
}
// .........
if(list_empty(&(my_list.time_list)))
{
new_time_span = (struct time_span *) kmalloc(sizeof(struct time_span), GFP_KERNEL);
INIT_LIST_HEAD(&(new_time_span->time_list));
list_add_tail(&(new_time_span->time_list), &(my_list.time_list));
do_gettimeofday(&(new_time_span->start));
}
// ........

You're missing some fundamentals about Linux linked lists.
The following should change:
struct time_span
{
struct timeval start;
struct timeval end;
};
To:
struct time_span
{
struct timeval start;
struct timeval end;
struct list_head time_list;
}
When using Linux linked lists you should put the struct list_head inside your struct that you want a list of.
In the code below, you're allocating a type struct time_span and referencing a variable named time_list inside the allocated variable new_time_span... but you haven't added that to your struct above.
// .........
struct timeval now_tv;
do_gettimeofday(&now_tv);
if(!list_empty(&(my_list.time_list)))
{
tmp = list_first_entry(&(my_list.time_list), struct time_span, time_list);
if(tmp != NULL)
{
tmp->end.tv_sec = now_tv.tv_sec; // THIS BREAKS
// Attempting to print "tmp->end.tv_sec" also breaks.
tmp->end.tv_usec = now_tv.tv_usec;
}
}
Based on the information you've provided, I don't know why the above breaks. Maybe it's just that tmp is a pointer pointing to garbage and that's why it crashes? If you have a kernel debugger setup it's easy to verify.
// .........
if(list_empty(&(my_list.time_list)))
{
new_time_span = (struct time_span *) kmalloc(sizeof(struct time_span), GFP_KERNEL);
INIT_LIST_HEAD(&(new_time_span->time_list));
list_add_tail(&(new_time_span->time_list), &(my_list.time_list));
do_gettimeofday(&(new_time_span->start));
}
// ........
Here are some good articles that should help:
http://kernelnewbies.org/FAQ/LinkedLists
http://sumanadak.blogspot.com/2006/09/linux-kernel-linked-list.html

Related

How do I update the value of void** in other function, and save it to another?

If I have a code for example like this:
#include <iostream>
using namespace std;
void swap(void** a) {
int tmp = 5;
void* b = &tmp;
a = &b;
}
int main()
{
int x=11;
void* y=&x;
void** z=&y;
swap(z);
void* a = *z;
cout << *(int*)a << endl;
return 0;
}
The code above prints 11, but I want to update the value of z (its address) to point to a place so I can print 5 (I mean update it). What should I do so that when I send z to the function and get back to main I can receive 5 instead of 11.
I'm just not that good with pointers.
EDIT: I must send to swap an argument with void**
You can't update the value of a void** (i.e. what it points to) by passing it to a function that takes a void**. That only allows to modify the pointed-to memory, not what address the pointer you pass to the function points to.
To update what it points to, the parameter should be a void**& or a void***.
Regardless of what solution you choose, the code you posted is extremely error prone and a hell to maintain. You should totally avoid it.
Also, note that &tmp becomes invalid as long as you exit the function, because the local variable tmp gets destroyed.

How to attach file operations to sysfs attribute in platform driver?

I wrote a platform driver for a peripheral we developed and would like to expose some configuration options to the sysfs. I have managed to create the appropriate files using attribute structs (see below) and sysfs_create_file in the probe function, but I can't figure out how to attach the show/store functions to the structs in a platform driver.
Most resources I found online used a device_attribute struct or something similar to create their files, is that also appropriate here? Is there another way to do this for a platform driver?
My attribute struct looks like this:
struct attribute subkey_attr = {
.name = "subkeys",
.mode = S_IWUGO | S_IRUGO,
};
And I register the file using this call:
riddler_kobject = &pdev->dev.kobj;
ret_val = sysfs_create_file(riddler_kobject, &subkey_attr);
It boils down to next:
reuse existing kobject from struct device (from your struct platform_device) for sysfs_create_group() (instead of creating your own kobject)
use DEVICE_ATTR() to declare struct device_attribute instead of regular __ATTR(), which creates struct kobj_attribute.
Here is how I created sysfs attributes for my platform driver.
Create structure you'll be using as private data in show() / store() operations for your sysfs attribute (file). For example:
struct mydrv {
struct device *dev;
long myparam;
};
Allocate this structure in your driver's probe():
static int mydrv_probe(struct platform_device *pdev)
{
struct mydrv *mydrv;
mydrv = devm_kzalloc(&pdev->dev, sizeof(*mydrv), GFP_KERNEL);
mydrv->dev = &pdev->dev;
platform_set_drvdata(pdev, mydrv);
...
}
Create show() / store() functions:
static ssize_t mydrv_myparam_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mydrv *mydrv = dev_get_drvdata(dev);
int len;
len = sprintf(buf, "%d\n", mydrv->myparam);
if (len <= 0)
dev_err(dev, "mydrv: Invalid sprintf len: %d\n", len);
return len;
}
static ssize_t mydrv_myparam_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct mydrv *mydrv = dev_get_drvdata(dev);
kstrtol(buf, 10, &mydrv->myparam);
return count;
}
Create device attribute for those functions (right after those functions):
static DEVICE_ATTR(myparam, S_IRUGO | S_IWUSR, mydrv_myparam_show,
mydrv_myparam_store);
Declare attributes table (listing in fact sysfs files for you driver):
static struct attribute *mydrv_attrs[] = {
&dev_attr_myparam.attr,
NULL
};
Declare attribute group (specifying in fact sysfs directory for your driver):
static struct attribute_group mydrv_group = {
.name = "mydrv",
.attrs = mydrv_attrs,
};
static struct attribute_group *mydrv_groups[] = {
&mydrv_group,
NULL
}
which can be actually replaced with one line:
ATTRIBUTE_GROUPS(mydrv);
Create sysfs directory and files in your driver's probe() function:
static int mydrv_probe(struct platform_device *pdev)
{
int ret;
...
ret = sysfs_create_group(&pdev->dev.kobj, &mydrv_group);
if (ret) {
dev_err(&pdev->dev, "sysfs creation failed\n");
return ret;
}
...
}
Remove your sysfs files in your driver's remove() function:
static int mydrv_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &mydrv_group);
...
}
Race condition note
As #FranzForstmayr correctly pointed out, there may be race condition when adding sysfs files with sysfs_create_group() in mydrv_probe(). That's because user-space can be already notified that those files exist before mydrv_probe() called (where those files are actually being created by sysfs_create_group() function). This issue covered in details in "How to Create a sysfs File Correctly" article by Greg Kroah-Hartman.
So in our case of platform_device, instead of calling sysfs_create_group() (and its counterpart sysfs_remove_group()), you can use default attribute group. To do so, you need to assign corresponding .groups field of your struct device to your attribute groups variable:
static int mydrv_probe(struct platform_device *pdev)
{
...
pdev->dev.groups = mydrv_groups;
...
}
DISCLAIMER: I didn't test this code, though it should work, because of this code.
See [1,2,3] links for more insights on mentioned race condition.
For more examples, run next command in kernel source directory:
$ git grep -l --all-match -e platform_device -e attribute -e '\.groups =' -- drivers/
Also you can search by "default attribute" in commit messages:
$ git log --no-merges --oneline --grep="default attribute" -- drivers/
Some commits I found this way: [4,5,6,7].
References
[1] My attributes are way too racy, what should I do?
[2] PATCH: sysfs: add devm_sysfs_create_group() and friends
[3] [GIT PATCH] Driver core patches for 3.11-rc2
[4] commit 1
[5] commit 2
[6] commit 3
[7] commit 4
Not enough reputation to post a comment, but I just want to comment on the default attribute group note from the accepted answer.
My understanding is that this should not be added in the probe function, as given in the example, but instead should be set in the device struct, (or device_driver, class, or bus depending on your driver) usually defined at the end of your file.
For example:
static struct device iio_evgen_dev = {
.bus = &iio_bus_type,
.groups = iio_evgen_groups,
.release = &iio_evgen_release,
};
from this example
Strangely, according to this it doesn't work correctly when using DEVICE_INT_ATTR to create the attribute, so not sure what that's all about.
Also, I'm not 100% sure, but I think that this is invoked when the driver is loaded, not when the device is probed.
This is an addition to Sam Protsenko's and Anthony's answers
If you create device attributes via the DEVICE_ATTR macros then you have to register the attribute groups (mydrv_groups) in the .dev_groups instead of the .groups field.
static struct device iio_evgen_dev = {
.bus = &iio_bus_type,
.dev_groups = iio_evgen_groups, // .dev_groups for DEVICE_ATTR
.groups = another_attr_group, // .groups for DRIVER_ATTR
.release = &iio_evgen_release,
};
Then the attributes are automatically registered correctly without setting up anything in the probe/remove functions, as described in Greg Kroah-Hartman's article.
Assume that the module has been loaded into the kernel and the driver is registered in
/sys/bus/platform/drivers/mydrv
every device instances will be a subdirectory of the driver's folder like
/sys/bus/platform/drivers/mydrv/mydrv1
/sys/bus/platform/drivers/mydrv/mydrv2
Registering attributes in the .groups field creates the attributes in the driver folder.
Registering attributes in the .dev_groups field creates the attributes in the device's instance folder.
mydrv
├── driver_attr1
├── driver_attr2
└── mydrv1
├── device_attr1
└── device_attr2
The show/store functions of the attributes in the .groups field do not have access to the driver data set via platform_set_drvdata(pdev, mydrv).
At least not by accessing it via dev_get_drvdata(dev).
Accessing the driver data via dev_get_drvdata(dev) returns NULL and dereferencing it will result in a kernel oops.
In turn, he show/store functions of the attributes in the .dev_groups field have access to the driver data via
struct mydrv *mydrv = dev_get_drvdata(dev);

How to construct C struct in Go side?

I need to call a C function which needs a pointer of struct as argument.
Here's the C code:
struct Position
{
uint64_t index;
uint64_t offset;
};
int read(const char* filename, const Position* pos, const char** data)
So in Go code, I think I have to malloc memory to construct a Position object and pass its pointer to C function. Maybe I also need to free memory. It seems like what C.CString() did. So how can I do that? Is there any code example? THX.
How call c from golang is clear by the generated stub. use go build -work src/main.go to generate the stub and get the working directory. find the function prototype in _obj/_cgo_gotypes.go file.
i.e. I can get the following generated go stub:
type _Ctype_Position _Ctype_struct__Position
type _Ctype_struct__Position struct {
//line :1
index _Ctype_int
//line :1
offset _Ctype_int
//line :1
}
func _Cfunc_read(p0 *_Ctype_char, p1 *_Ctype_struct__Position, p2 **_Ctype_char) (r1 _Ctype_int)
if i have the c header file like this:
typedef struct _Position
{
int index;
int offset;
}Position;
extern int read(const char* filename, const Position* pos, const char** data);
BTW you need reference the c function in go source to make a dependency for go build to generate the referenced function stub.

What is the use of 'i2c_get_clientdata" and "i2c_set_clientdata"

I have been studying I2C driver (client) code for a while.
I have seen this function "i2c_get_clientdata" and "i2c_set_clientdata" every where.
I have seen the this question here .
Use of pointer to structure instead of creating static local copy
Some times i think like it is like "container_of" macro to get a pointer to the structure.
But still i didn't understood properly why to use it and when to use it.
Below i am posting a sample code where I see its usage.
If any one could help me understand why it is used there and when we shall use it when we write our own drivers.
struct max6875_data {
struct i2c_client *fake_client;
struct mutex update_lock;
u32 valid;
u8 data[USER_EEPROM_SIZE];
unsigned long last_updated[USER_EEPROM_SLICES];
};
static ssize_t max6875_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj);
struct max6875_data *data = i2c_get_clientdata(client);
int slice, max_slice;
if (off > USER_EEPROM_SIZE)
return 0;
if (off + count > USER_EEPROM_SIZE)
count = USER_EEPROM_SIZE - off;
/* refresh slices which contain requested bytes */
max_slice = (off + count - 1) >> SLICE_BITS;
for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
max6875_update_slice(client, slice);
memcpy(buf, &data->data[off], count);
return count;
}
Those functions are used to get/set the void *driver_data pointer that is part of the struct device, itself part of struct i2c_client.
This is a void pointer that is for the driver to use. One would use this pointer mainly to pass driver related data around.
That is what is happening in your example. The max6875_read is a callback getting a structu kobject. That kobject is an i2c_client which is enough to communicate with the underlying device using the driver_data pointer here allows to get back the driver related data (instead of using global variables for example).

Invalid free Valgrind

for some reason calling my function 'delAll' more than once will cause a invalid free error from Valgrind. I don't understand why if I call this function the second time would cause the program to go into the while loop again even though it just "delAll" of the node
//p is a linked list with call
struct node{
char *str, int data, struct node *next;
}
//here's the function I am having trouble with:
void delAll()
{
struct node *temp,*temp2;
temp=p;
while(temp!=NULL)
{
temp2=temp;
temp= temp->next;
free(temp2->str);
free(temp2);
}
}
p is the pointer to your list, and right now it will still after the delAll call point to the (free'd) start of the list. I'd just do;
p=NULL;
...right after your while loop to set p to null (ie have the list properly cleared). That will prevent your delAll from trying to free all elements again.
Of course that would depend on p not just being a temporary variable, I'm assuming it's the real "start of the list" pointer.

Resources