Reading file in the Linux Kernel

1.7k Views Asked by At

so before I get the barrage of "you shouldn't be doing that", I know I shouldn't. But it is for a dirty, quick proof of concept for some research work. If the concept works I will look at proper exporting of information to my module. My knowledge of this area is very small as I have only ever used sysfs to expose values I generate within my modules, any pointers in the right direction would be greatly appreciated. I have done a lot of googling and have come up short unfortunately.

What I need to achieve: I need to read out device and sysfs values for power sensors and GPU for my specific android board (Odroid XU3) running 3.10.9 kernel.

Where is my module running: I am writing a cpufreq power governor that is trying to create a FSM from system information (hence need for file reading).

In my governor I am attempting to open the files into file pointers that I will then keep and read every governor tick.

struct file* f_mali_freq;
struct file* f_mali_load;
struct file* f_big_ina231;
struct file* f_little_ina231;
struct file* f_mem_ina231;
struct file* f_gpu_ina231;

I have then tried to implement methods similar to those explain here and here.

Currently I have tried the following for my sensors' files:

defines and structs

#define INA231_IOCGREG      _IOR('i', 1, struct ina231_iocreg *)
#define INA231_IOCSSTATUS   _IOW('i', 2, struct ina231_iocreg *)
#define INA231_IOCGSTATUS   _IOR('i', 3, struct ina231_iocreg *)

 struct ina231_iocreg {
     unsigned char name[20];
     unsigned int enable;
     unsigned int cur_uV;
     unsigned int cur_uA;
     unsigned int cur_uW;
 } __attribute__ ((packed));

called from within my governor's init

f_big_ina231 = open_ina231("/dev/sensor_arm");

static struct file *open_ina231(const char *path)
{
    mm_segment_t old_fs = get_fs();
    struct ina231_iocreg reg;
    struct file *f;
    int ret;

    f = file_open(path);
    if (!f)
        return NULL; // <FAILS HERE

    set_fs(KERNEL_DS);
    if (!f->f_op || !f->f_op->unlocked_ioctl)
        goto out_error;

    /* enable if necessary */
    ret = f->f_op->unlocked_ioctl(f, INA231_IOCGSTATUS, (long unsigned int) &reg);
    if (ret)
        goto out_error;

    if (!reg.enable) {
        reg.enable = true;
        ret = f->f_op->unlocked_ioctl(f, INA231_IOCSSTATUS, (long unsigned int) &reg);
        if (ret)
            goto out_error;
    }
    set_fs(old_fs);
    return f;
out_error:
    KERNEL_DEBUG_MSG(" [OPTIGOV] open_ina231 out_error\n");
    set_fs(old_fs);
    filp_close(f, NULL);
    return NULL;
}

static struct file* file_open(const char *path){
     struct file *f = NULL;

     f = filp_open(path, O_RDWR, 0);
     if(IS_ERR(f)){
         KERNEL_DEBUG_MSG(" [OPTIGOV] file_open failed filp_open\n");
         return NULL;
     }
     return f;
 }

Opening the file always fails so the only conclusion I can come to is that the file does not exist. As such I moved the code into my governor's reoccurring task with an "opened" flag which would stop the files from being repeatedly opened. This achieved the same results where the files could not be opened.

I tried a more simplified approach (below) which also failed.

f_mali_load = file_open("/sys/bus/platform/drivers/mali/11800000.mali/utilization");


static struct file* file_open(const char *path){
struct file *f = NULL;
mm_segment_t oldfs;
int err = 0;

oldfs = get_fs();
set_fs(get_ds());

f = filp_open(path, O_RDONLY, 0);
set_fs(oldfs);

if(IS_ERR(f)){
    KERNEL_DEBUG_MSG(" [OPTIGOV] file_open failed filp_open\n");
    return NULL; // <FAILS HERE
}

KERNEL_DEBUG_MSG(" [OPTIGOV] file_open succedded filp_open\n");

return f;

}

I am hoping someone can help or point me in the right direction as I cannot for the life of me figure out what I am missing.

I have been unable to find anyway of testing if a file exists within the kernel (other than trying to open it, which is what I am doing).

Cheers

0

There are 0 best solutions below