linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* uid-Another Problem in writing to /proc/loadavg file
@ 2004-01-13 14:55 ` sena
       [not found]   ` <20040113120727.GB7506@lnx-holt>
  0 siblings, 1 reply; 2+ messages in thread
From: sena @ 2004-01-13 14:55 UTC (permalink / raw)
  To: Robin Holt; +Cc: linux-kernel

Hi Robin,

Though I was able to run my code and get good results  as a kernel 
module (This was everytime only one set of results per loading of  the 
module).

Anyway I felt that it was hanging on a bit while values being 
calculated. (It looks like the host computer sends some messages to the 
users)

Thinking everything was well,  I then integrated it to the kernel code 
with those extra loops of mine,  this time there was nothing written to 
/proc/loadavg file.

First I thought that this was because the long list(5) of USER's UIDs I 
am saving in that file. (only 5)

Anyway it looks like that is not the real problem as I do calculate 
every 5 seconds and that seems to be enough time.


 Robin for further Real testing I thought of first running it as  a 
kernel module. Then this code has to be called every 5 seconds and will 
have to be scheduled as a task.?


I made the following attempt.

I have 2 questions for you.

What is this error about?    THE ERROR WAS sched.o: unresolved symbol 
proc_unregister

Thanks
Sena Seneviratene
Computer Engineering Lab
Sydney University


sched.c
/* The necessary header files */

/* Standard in kernel modules */
#include <linux/kernel.h>   /* We're doing kernel work */
#include <linux/module.h>   /* Specifically, a module */

/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif        

/* Necessary because we use the proc fs */
#include <linux/proc_fs.h>

/* We scheduale tasks here */
#include <linux/tqueue.h>

/* We also need the ability to put ourselves to sleep 
 * and wake up later */
#include <linux/sched.h>

/* In 2.2.3 /usr/include/linux/version.h includes a 
 * macro for this, but 2.0.35 doesn't - so I add it 
 * here if necessary. */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
#endif



/* The number of times the timer interrupt has been 
 * called so far */
static int TimerIntrpt = 0;


/* This is used by cleanup, to prevent the module from 
 * being unloaded while intrpt_routine is still in 
 * the task queue */
static struct wait_queue *WaitQ = NULL;

static void intrpt_routine(void *);


/* The task queue structure for this task, from tqueue.h */
static struct tq_struct Task = {
  NULL,   /* Next item in list - queue_task will do 
           * this for us */
  0,      /* A flag meaning we haven't been inserted 
           * into a task queue yet */
  intrpt_routine, /* The function to run */
  NULL    /* The void* parameter for that function */
};

/*IN THIS FUNCTION LOAD AVERAGE CALCULATIONS BE INCLUDED*/
static void intrpt_routine(void *irrelevant)
{
  /* Increment the counter */
  TimerIntrpt++;

  /* If cleanup wants us to die */
  if (WaitQ != NULL) 
    wake_up(&WaitQ);   /* Now cleanup_module can return */
  else
    /* Put ourselves back in the task queue */
    queue_task(&Task, &tq_timer);  
}




/* Put data into the proc fs file. */
int procfile_read(char *buffer, 
                  char **buffer_location, off_t offset, 
                  int buffer_length, int zero)
{
  int len;  /* The number of bytes actually used */

  
  static char my_buffer[80];  

  static int count = 1;

  
  if (offset > 0)
    return 0;

  /* Fill the buffer and get its length */
  len = sprintf(my_buffer, 
                "Timer was called %d times so far\n", 
                TimerIntrpt);
  count++;

  /* Tell the function which called us where the 
   * buffer is */
  *buffer_location = my_buffer;

  /* Return the length */
  return len;
}


struct proc_dir_entry Our_Proc_File = 
  {
    0, /* Inode number - ignore, it will be filled by 
        * proc_register_dynamic */
    5, /* Length of the file name */
    "sched", /* The file name */
    S_IFREG | S_IRUGO, 
    /* File mode - this is a regular file which can
     * be read by its owner, its group, and everybody
     * else */
    1,  /* Number of links (directories where 
         * the file is referenced) */
    0, 0,  /* The uid and gid for the file - we give 
            * it to root */
    80, /* The size of the file reported by ls. */
    NULL, /* functions which can be done on the 
           * inode (linking, removing, etc.) - we don't 
           * support any. */
    procfile_read, 
    /* The read function for this file, the function called
     * when somebody tries to read something from it. */
    NULL 
    /* We could have here a function to fill the 
     * file's inode, to enable us to play with 
     * permissions, ownership, etc. */
  }; 


/* Initialize the module - register the proc file */
int init_module()
{
  /* Put the task in the tq_timer task queue, so it 
   * will be executed at next timer interrupt */
  queue_task(&Task, &tq_timer);

  /* Success if proc_register_dynamic is a success, 
   * failure otherwise */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
  return proc_register(&proc_root, &Our_Proc_File);
#else
  return proc_register_dynamic(&proc_root, &Our_Proc_File);
#endif
}


/* Cleanup */
void cleanup_module()
{
  /* Unregister our /proc file */
  proc_unregister(&proc_root, Our_Proc_File.low_ino);
  
  /* Sleep until intrpt_routine is called one last 
   * time. This is necessary, because otherwise we'll 
   * deallocate the memory holding intrpt_routine and
   * Task while tq_timer still references them. 
   * Notice that here we don't allow signals to 
   * interrupt us. 
   *
   * Since WaitQ is now not NULL, this automatically 
   * tells the interrupt routine it's time to die. */
 sleep_on(&WaitQ);
}




^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: uid-Another Problem in writing to /proc/loadavg file
       [not found]     ` <20040114114900.GB14674@lnx-holt>
@ 2004-01-15  3:06       ` auntvini
  0 siblings, 0 replies; 2+ messages in thread
From: auntvini @ 2004-01-15  3:06 UTC (permalink / raw)
  To: Robin Holt; +Cc: linux-kernel

Hi Robin,

That is done and the name of the new file is /proc/loadavgus. I hope that 
does not sound like usa.

Never mind the data is being collected without any problem.

Thanks
Sena Seneviratne
Computer Engineering Lab
Sydney University

At 05:49 AM 1/14/2004 -0600, you wrote:
>On Wed, Jan 14, 2004 at 08:14:43PM +1100, sena wrote:
> > Hi Robin,
> >
> > Thanks for the reply and for your time.
> >
> > My previous observation about hanging on is not correct. There is no
> > hanging on whatsoever.
> >
> > I had put some printks in my kernel code and according to them the load
> > averages per user are being calculated correctly.
> >
> > I found the values in /var/log/messages
> >
> > This means my calculation code every 5 seconds do their part.
> >
> >
> > I find the problem with the writing to /proc/loadavg file.
>
>Did you specify your read handler in the create_proc_read_entry() call?
>If you didn't use create_proc_read_entry, you need to point the resulting
>file structures read handler to your read routine.
>
>You should probably not use /proc/loadavg.  It is an already existing
>file.  Try using your own directory with seperate read handler(s).
>Maybe something like /proc/loadavg_per_user/<uid> which gives the
>load averages per user.
>
>Good Luck,
>Robin
> >
> > My loadavg file is empty. ?
> > (I experienced this situation only with this compilation.)
> >
> >
> > Thanks
> >
> > Sena Seneviratne
> > Computer Engineering Lab
> > Sydney University
> >
> >
> > Robin Holt wrote:
> >
> > >Sena,
> > >
> > >Let's keep this off the lkml.  This is _NOT_ the type of chatter that
> > >should be going on at that list.  That forum is for kernel developers
> > >to discuss features that relate to the kernel proper.  This will never
> > >go in without some serious discussion about _WHAT_ is being accomplished
> > >and _WHY_.  The what is weak at best since this is limited to a certain
> > >number of users.  The why is completely vague to me.
> > >
> > >On Wed, Jan 14, 2004 at 01:55:07AM +1100, sena wrote:
> > >
> > >
> > >>Hi Robin,
> > >>
> > >>Though I was able to run my code and get good results  as a kernel
> > >>module (This was everytime only one set of results per loading of  the
> > >>module).
> > >>
> > >>
> > >
> > >You should write your routine to calculate load averages as a timer
> > >service routine.
> > >
> > >Look at struct timer_list.  That might give you some ideas of how to use
> > >it:
> > >
> > >I guess I would write something like:
> > >
> > >static struct timer_list loadavg_per_user_timer;
> > >
> > >...
> > >
> > >     /* during module init, register the timer */
> > >     loadavg_per_user_timer.function = loadavg_per_user_calc;
> > >     loadavg_per_user_calc(0);
> > >
> > >...
> > >
> > >static void
> > >loadavg_per_user_calc(unsigned long _dummy)
> > >{
> > >     loadavg_per_user_timer.expires = (5 * HZ) + jiffies;
> > >     /* Body of calculating loadavg_per_user goes here */
> > >}
> > >
> > >This type of timer would run every 5 seconds and calculate your load
> > >averages.
> > >
> > >One thing we haven't talked about doing is using an extremely simple
> > >lookup instead of searching a list for the uid.  Since the uids you
> > >are concerned with are always in the range of 500-504, Why don't you
> > >just do something like:
> > >
> > >     int loadavg_bucket;
> > >
> > >     loadavg_bucket = p->uid - 499;
> > >     if ((loadavg_bucket < 0) || (loadavg_bucket > 5)) {
> > >             loadavg_bucket = 0;
> > >     }
> > >
> > >With this, any process that has a uid in the range of 500-504 gets
> > >mapped to entries 1-5 in your array and entry 0 is used for everyone
> > >else.  Certainly simpler than the looping lookup you are doing.
> > >
> > >
> > >
> > >>Anyway I felt that it was hanging on a bit while values being
> > >>calculated. (It looks like the host computer sends some messages to the
> > >>users)
> > >>
> > >>
> > >
> > >Describe what you think you felt.  There are all types of hangs.  Did it
> > >feel like the kernel wasn't starting new processes or did it feel like
> > >interrupts were not being serviced?  I sort of need to know which way
> > >it responded to help further.
> > >
> > >
> > >
> > >>Thinking everything was well,  I then integrated it to the kernel code
> > >>with those extra loops of mine,  this time there was nothing written to
> > >>/proc/loadavg file.
> > >>
> > >>
> > >
> > >You should probably consider creating your own /proc file since the 
> loadavg
> > >is really meant for the proc_ps stuff to consume.  You might consider
> > >creating a /proc/loadavg_per_user/<pid> type directory.
> > >
> > >
> > >
> > >>First I thought that this was because the long list(5) of USER's UIDs I
> > >>am saving in that file. (only 5)
> > >>
> > >>
> > >
> > >I doubt that anyone would consider 5 too long.
> > >
> > >
> > >
> > >>Anyway it looks like that is not the real problem as I do calculate
> > >>every 5 seconds and that seems to be enough time.
> > >>
> > >>
> > >>Robin for further Real testing I thought of first running it as  a
> > >>kernel module. Then this code has to be called every 5 seconds and will
> > >>have to be scheduled as a task.?
> > >>
> > >>
> > >
> > >You should be able to use a timer for this.
> > >
> > >
> > >
> > >>I made the following attempt.
> > >>
> > >>I have 2 questions for you.
> > >>
> > >>What is this error about?    THE ERROR WAS sched.o: unresolved symbol
> > >>proc_unregister
> > >>
> > >>
> > >
> > >proc_register and proc_unregister have been going away for some time.
> > >You should be using create_proc_entry and remove_proc_entry.  These
> > >are pointed out in the Documentation/DocBook/procfs_example.c file.
> > >
> > >
> > >
> > >>Thanks
> > >>Sena Seneviratene
> > >>Computer Engineering Lab
> > >>Sydney University
> > >>
> > >>
> > >>sched.c
> > >>/* The necessary header files */
> > >>
> > >>/* Standard in kernel modules */
> > >>#include <linux/kernel.h>   /* We're doing kernel work */
> > >>#include <linux/module.h>   /* Specifically, a module */
> > >>
> > >>/* Deal with CONFIG_MODVERSIONS */
> > >>#if CONFIG_MODVERSIONS==1
> > >>#define MODVERSIONS
> > >>#include <linux/modversions.h>
> > >>#endif
> > >>
> > >>/* Necessary because we use the proc fs */
> > >>#include <linux/proc_fs.h>
> > >>
> > >>/* We scheduale tasks here */
> > >>#include <linux/tqueue.h>
> > >>
> > >>/* We also need the ability to put ourselves to sleep
> > >>* and wake up later */
> > >>#include <linux/sched.h>
> > >>
> > >>/* In 2.2.3 /usr/include/linux/version.h includes a
> > >>* macro for this, but 2.0.35 doesn't - so I add it
> > >>* here if necessary. */
> > >>#ifndef KERNEL_VERSION
> > >>#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
> > >>#endif
> > >>
> > >>
> > >>
> > >>/* The number of times the timer interrupt has been
> > >>* called so far */
> > >>static int TimerIntrpt = 0;
> > >>
> > >>
> > >>/* This is used by cleanup, to prevent the module from
> > >>* being unloaded while intrpt_routine is still in
> > >>* the task queue */
> > >>static struct wait_queue *WaitQ = NULL;
> > >>
> > >>static void intrpt_routine(void *);
> > >>
> > >>
> > >>/* The task queue structure for this task, from tqueue.h */
> > >>static struct tq_struct Task = {
> > >>NULL,   /* Next item in list - queue_task will do
> > >>         * this for us */
> > >>0,      /* A flag meaning we haven't been inserted
> > >>         * into a task queue yet */
> > >>intrpt_routine, /* The function to run */
> > >>NULL    /* The void* parameter for that function */
> > >>};
> > >>
> > >>/*IN THIS FUNCTION LOAD AVERAGE CALCULATIONS BE INCLUDED*/
> > >>static void intrpt_routine(void *irrelevant)
> > >>{
> > >>/* Increment the counter */
> > >>TimerIntrpt++;
> > >>
> > >>/* If cleanup wants us to die */
> > >>if (WaitQ != NULL)
> > >>  wake_up(&WaitQ);   /* Now cleanup_module can return */
> > >>else
> > >>  /* Put ourselves back in the task queue */
> > >>  queue_task(&Task, &tq_timer);
> > >>}
> > >>
> > >>
> > >>
> > >>
> > >>/* Put data into the proc fs file. */
> > >>int procfile_read(char *buffer,
> > >>                char **buffer_location, off_t offset,
> > >>                int buffer_length, int zero)
> > >>{
> > >>int len;  /* The number of bytes actually used */
> > >>
> > >>
> > >>static char my_buffer[80];
> > >>
> > >>static int count = 1;
> > >>
> > >>
> > >>if (offset > 0)
> > >>  return 0;
> > >>
> > >>/* Fill the buffer and get its length */
> > >>len = sprintf(my_buffer,
> > >>              "Timer was called %d times so far\n",
> > >>              TimerIntrpt);
> > >>count++;
> > >>
> > >>/* Tell the function which called us where the
> > >> * buffer is */
> > >>*buffer_location = my_buffer;
> > >>
> > >>/* Return the length */
> > >>return len;
> > >>}
> > >>
> > >>
> > >>struct proc_dir_entry Our_Proc_File =
> > >>{
> > >>  0, /* Inode number - ignore, it will be filled by
> > >>      * proc_register_dynamic */
> > >>  5, /* Length of the file name */
> > >>  "sched", /* The file name */
> > >>  S_IFREG | S_IRUGO,
> > >>  /* File mode - this is a regular file which can
> > >>   * be read by its owner, its group, and everybody
> > >>   * else */
> > >>  1,  /* Number of links (directories where
> > >>       * the file is referenced) */
> > >>  0, 0,  /* The uid and gid for the file - we give
> > >>          * it to root */
> > >>  80, /* The size of the file reported by ls. */
> > >>  NULL, /* functions which can be done on the
> > >>         * inode (linking, removing, etc.) - we don't
> > >>         * support any. */
> > >>  procfile_read,
> > >>  /* The read function for this file, the function called
> > >>   * when somebody tries to read something from it. */
> > >>  NULL
> > >>  /* We could have here a function to fill the
> > >>   * file's inode, to enable us to play with
> > >>   * permissions, ownership, etc. */
> > >>};
> > >>
> > >>
> > >>/* Initialize the module - register the proc file */
> > >>int init_module()
> > >>{
> > >>/* Put the task in the tq_timer task queue, so it
> > >> * will be executed at next timer interrupt */
> > >>queue_task(&Task, &tq_timer);
> > >>
> > >>/* Success if proc_register_dynamic is a success,
> > >> * failure otherwise */
> > >>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
> > >>return proc_register(&proc_root, &Our_Proc_File);
> > >>#else
> > >>return proc_register_dynamic(&proc_root, &Our_Proc_File);
> > >>#endif
> > >>}
> > >>
> > >>
> > >>/* Cleanup */
> > >>void cleanup_module()
> > >>{
> > >>/* Unregister our /proc file */
> > >>proc_unregister(&proc_root, Our_Proc_File.low_ino);
> > >>
> > >>/* Sleep until intrpt_routine is called one last
> > >> * time. This is necessary, because otherwise we'll
> > >> * deallocate the memory holding intrpt_routine and
> > >> * Task while tq_timer still references them.
> > >> * Notice that here we don't allow signals to
> > >> * interrupt us.
> > >> *
> > >> * Since WaitQ is now not NULL, this automatically
> > >> * tells the interrupt routine it's time to die. */
> > >>sleep_on(&WaitQ);
> > >>}
> > >>
> > >>
> > >>
> > >>
> > >
> > >
> > >
> >
> >


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-01-15  3:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <40050883.30000@sedal.usyd.edu.au>
2004-01-13 14:55 ` uid-Another Problem in writing to /proc/loadavg file sena
     [not found]   ` <20040113120727.GB7506@lnx-holt>
     [not found]     ` <20040114114900.GB14674@lnx-holt>
2004-01-15  3:06       ` auntvini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).