clinuxkernelsysfs

Use poll() with POLLIN for waiting changes in file


I have to cooperate with kernel driver and wait in C application when sysfs_notify(3) for specific attribute was called. I want to use poll() approach via file descriptor.

My implementation looks like:

...
    struct pollfd *fds = malloc(sizeof(struct pollfd) * 1);

    fds[0].fd = open("/path/to/file", O_RDONLY);
    fds[0].events = POLLIN;
    fds[0].revents = 0;
    if (fds[0].fd < 0) return -EXIT_FAILURE;

    //! Poll and Process Descriptors
    while (poll(fds, 1, -1) > 0) {
        if (fds[0].events & fds[0].revents) {
            fds[0].revents = 0;
            ret = read(fds[0].fd, buf, sizeof(buf));
        }
    }
...

As result I got infinite unstoppable poll() activation in fds.revents by POLLIN even if no action were made for destination file.

I have tried my simple text file instead of kernel sysfs attribute and also got infinite unsoppable poll() activation for POLLIN with no action on file.

Can someone help me with solution? Thanks in advance, Anton!


Solution

  • UPD: Well, I've solved my problem. I had my own kernel driver and issue with sysfs_notify was here. I2C kernel driver has it's own structure struct i2c_driver and sysfs group registration sysfs_create_group(2) runs from internal driver probe. So instead of using sysfs_create_group(2) during probe just initialize struct i2c_driver internal struct device_driver driver field dev_groups by you group and it's registered in sysfs automatically during internal probe and also I've paste kobject_uevent_env(&chip->client->dev.kobj, KOBJ_CHANGE, envp); before sysfs_notify() e.g. on my driver:

    ATTRIBUTE_GROUPS(sfh7771_attribute);
    ...
    static struct i2c_driver sfh7771_driver = {
    .driver  = {
        .name   = SFH7771_NAME,
        .of_match_table = sfh7771_of_match,
        .dev_groups = sfh7771_attribute_groups,
    },
    .probe    = sfh7771_probe,
    .remove   = sfh7771_remove,
    .id_table = sfh7771_id,
    };
    ...
    kobject_uevent_env(&chip->client->dev.kobj, KOBJ_CHANGE, envp);
    sysfs_notify(&chip->client->dev.kobj, NULL, "your_attribute");
    

    On my user space code I've used poll(3) but as events there are POLLPRI | POLLERR flags and don't forget to use lseek() for seek to the begin of file. The short sample below:

    struct pollfd *fds = malloc(sizeof(struct pollfd) * 1);
    
    fds[0].fd = open("/path/to/file", O_RDONLY);
    fds[0].events = POLLPRI | POLLERR;
    fds[0].revents = 0;
    if (fds[0].fd < 0) return -EXIT_FAILURE;
    
    //! Poll and Process Descriptors
    while (poll(fds, 1, -1) > 0) {
        if (fds[0].events & fds[0].revents) {
            fds[0].revents = 0;
            lseek(fds[0].fd, 0, SEEK_SET);
            ret = read(fds[0].fd, buf, sizeof(buf));
        }
    }