I wrote a function, read_fox_rcu() for getting an element from RCU-protected list in a linux device driver. read_fox_rcu() reads the first element, converts it to string , stores it to tmp and stores the first pointer to ppfox.
I wonder that I used locks (rcu_read_lock(), synchronize_rcu(), etc), in an appropriate way.
static int read_fox_rcu(struct fox ** ppfox, char *tmp, size_t size){
struct fox *f;
rcu_read_lock();
f = list_first_or_null_rcu(&fox_list_rcu, struct fox, list);
if (f==NULL) {
rcu_read_unlock();
return -1;
}
snprintf(tmp, size, "%lu/%lu/%d\t",
f->tail_length, f->weight, f->is_fantastic);
*ppfox = f;
rcu_read_unlock();
return 0;
}
#define MAX_BUF_SIZE 1024
static ssize_t show_pop_fox_r(struct device *dev, struct device_attribute *attr, char *buf)
{
int ret;
struct fox * f;
char tmp[MAX_BUF_SIZE];
if (read_fox_rcu(&f, tmp, MAX_BUF_SIZE)) {
ret = scnprintf(buf, PAGE_SIZE, "failure on read_fox_rcu()\n");
return ret;
}
list_del_rcu(&f->list);
synchronize_rcu();
kfree(f);
ret = scnprintf(buf, PAGE_SIZE, "%s\n", tmp);
return ret;
}
static DEVICE_ATTR(pop_fox_r, S_IRUGO, show_pop_fox_r, NULL);
dev_attr_pop_fox_r.attr is declared by DEVICE_ATTR. And pop_fox_r is created, by calling sysfs_create_group() in the probe function.
fox_list_rcu and struct fox is defined like below.
struct fox {
size_t tail_length;
size_t weight;
bool is_fantastic;
struct list_head list;
};
static LIST_HEAD(fox_list_rcu);