title: Why this proc driver crashes?
body: <p>I am trying to write a proc driver that will print the driver history up till 10 last updates. In this driver, I haven't added the kernel data structure that I want to print. But, I am relying on the 'i' value to print the value up till 10. Here is my code.</p>
  
  <pre><code>#include &lt;linux/init.h&gt;
  #include &lt;linux/module.h&gt; /** needed by all modules **/
  #include &lt;linux/kernel.h&gt;  /** This is for KERN_ALERT **/
  #include &lt;linux/proc_fs.h&gt;  /** This is for procfs **/
  #include &lt;linux/seq_file.h&gt;
  #include &lt;linux/cdev.h&gt;  /** character device **/
  #include &lt;linux/device.h&gt;  /** for sys device registration in /dev/ and /sys/class **/
  
  /** For class registration to work, you need GPL license **/
  MODULE_LICENSE("GPL");
  
  
  #define PROCFS_NAME  "basicProcfs1"
  
  static struct cdev basicCdev;
  static struct class *basicDriverClass;
  
  struct proc_dir_entry *procFileEntry = NULL;
  
  static int  basicMajorNumber = 0;
  
  #define NUMBER_OF_MINOR_DEVICE (0)
  
  #define NUM_MSG_HIST_ENTRIES (10)
  
  static int gui32CmdMsgHistoryStartIndex=0;
  
  /** This File operation table for proc file system **/
  
  static int av_cmd_hist_show( struct seq_file *filp, void *v )
  {
     int        i = *((int *)v);
  
      printk("the av_cmd_hist_show called\r\n");
  
      if ( i == 0)
      {
         seq_printf(filp, "Sequential print for debugging-- called for i-times i.e. 10 times \r\n");
  
      }
  
      seq_printf(filp, "Hello SJ proc! %d\r\n", i);
  
      return 0;
  
  }
  
  static void av_cmd_hist_stop( struct seq_file *filp, void *v )
  {
    printk("av_cmd_hist_stop called..\r\n");
  } /* av_cmd_hist_stop */
  
  
  static void *av_cmd_hist_next( struct seq_file *filp, void *v, loff_t *pos )
  {
     (*pos)++;
     printk("av_cmd_hist_next called..\r\n");
     return( ( *pos &lt; NUM_MSG_HIST_ENTRIES ) ? pos : NULL );
  
   } /* av_cmd_hist_next */
  
  
  static void *av_cmd_hist_start( struct seq_file *filp, loff_t *pos )
  {
      if( *pos == 0 )
      {
          printk("av_cmd_hist_start.. Initial..\r\n");
          gui32CmdMsgHistoryStartIndex = 5;
      }
  
      printk("av_cmd_hist_start.. the *pos=0..\r\n");
  
      return( ( *pos &lt; NUM_MSG_HIST_ENTRIES ) ? pos : NULL );
  
  } /* av_cmd_hist_start */
  
  
  static struct seq_operations av_seq_cmd_hist_fops =
  {
   .start = av_cmd_hist_start,
   .next  = av_cmd_hist_next,
   .stop  = av_cmd_hist_stop,
   .show  = av_cmd_hist_show
  };
  
  
  static int basicProcShow(struct seq_file *m, void *v) {
    seq_printf(m, "Hello SJ proc!\n");
    return 0;
  }
  
  static int basicProcOpen(struct inode *inode, struct file *file)
  {
     int i;
  
     i = seq_open( file, &amp;av_seq_cmd_hist_fops ); 
  
     return  i;
    //return single_open(file, basicProcShow, NULL);  
  
  }
  
  /** Put data into the proc fs file **/
  
  static const struct file_operations basic_proc_fops =
  {
  
    .owner = THIS_MODULE,
    .open = basicProcOpen,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,    
  
  };
  
  
  static struct file_operations fops = {
    .read = NULL,
    .write = NULL,
    .open = NULL,
    .release = NULL
  };
  
  
  static void setup_cdev(struct cdev *dev, int minor, struct file_operations *fops)
  {
           int err = -1;
           /** MKDEV call creates a device number i.e. combination of major and minor number **/
           int devno = MKDEV(basicMajorNumber, minor);
           /** Initiliaze character dev with fops **/
           cdev_init(dev, fops);
           /**owner and operations initialized **/
           dev-&gt;owner = THIS_MODULE;
           dev-&gt;ops = fops;
           /** add the character device to the system**/
           /** Here 1 means only 1 minor number, you can give 2 for 2 minor device, the last param is the count of minor number enrolled **/
           err = cdev_add (dev, devno, 1);
  
           if (err)
           {
                   printk (KERN_NOTICE "Couldn't add cdev");
           }
   }
  
  static int chrDriverInit(void)
  {
  
      int result;
      dev_t dev; 
  
      printk("Welcome!! Device Init now..");
  
      /** int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name);  **/
      /** dev -&gt; The dev_t variable type,which will get the major number that the kernel allocates.  **/
      /**The same name will appear in /proc/devices.  **/
  
      /** it is registering the character device **/   
      /** a major number will be dynamically allocated here **/
      /**  alloc_chrdev_region(&amp;dev_num, FIRST_MINOR, COUNT, DEVICE_NAME); **/
      result = alloc_chrdev_region(&amp;dev, 0, NUMBER_OF_MINOR_DEVICE, "pSeudoDrv1");
  
      if( result &lt; 0 )
      {
        printk("Error in allocating device");
        return -1;    
      }
  
      /** From these two if's we are avoiding the manual mknod command to create the /dev/&lt;driver&gt; **/
      /**  creating class, and then device created removes the dependency of calling mknod  **/
      /** A good method - the mknod way is depreciated **/
      /** mknod way is -  mknod /dev/&lt;driver_name&gt; c &lt;majorNumber&gt; &lt;minorNumber&gt;
  
  
      /** add the driver to /sys/class/chardrv **/
      if ((basicDriverClass = class_create(THIS_MODULE, "chardrv")) == NULL)    //$ls /sys/class
      {
          unregister_chrdev_region(dev, 1);
          return -1;
      }
  
       /** add the driver to /dev/pSeudoDrv -- here **/
      if (device_create(basicDriverClass, NULL, dev, NULL, "pSeudoDrv") == NULL) //$ls /dev/
      {
          class_destroy(basicDriverClass);
          unregister_chrdev_region(dev, 1);
          return -1;
      }
  
       /** let's see what major number was assigned by the Kernel **/
       basicMajorNumber = MAJOR(dev);
       printk("Kernel assigned major number is %d ..\r\n",basicMajorNumber );
  
      /** Now setup the cdev **/
      setup_cdev(&amp;basicCdev,NUMBER_OF_MINOR_DEVICE, &amp;fops);
  
      /** Setup Proc Entry here **/
      /** 0644 means - 
       * 0 - owning (user) : read and write - 110 
       * Group - only read - 100
       * Other - only read - 100 **/
  
  
      procFileEntry = proc_create(PROCFS_NAME, 0, NULL, &amp;basic_proc_fops);
  
      if ( procFileEntry == NULL)
      {
         remove_proc_entry(PROCFS_NAME, NULL);    
  
      }
  
  
      return 0;   
  
  }
  
  
  static void chrDriverExit(void)
  {
      /** A reverse - destroy mechansim -- the way it was created **/
      printk("Releasing Simple Devs -- %s\r\n",  __FUNCTION__);
      /** delete the character driver added **/
      cdev_del(&amp;basicCdev);
      /** destroy the device created **/
      device_destroy(basicDriverClass, MKDEV(basicMajorNumber, 0));
      /** destroy the class created **/
      class_destroy(basicDriverClass);
      /** unregister the chr dev **/
      unregister_chrdev(basicMajorNumber, NUMBER_OF_MINOR_DEVICE);
      remove_proc_entry(PROCFS_NAME, NULL);
  
  }
  
  
  module_init(chrDriverInit);
  module_exit(chrDriverExit);
  </code></pre>
  
  <p>The dmesg logs are the following.</p>
  
  <pre><code># dmesg
  [14102.921743] Releasing Simple Devs -- chrDriverExit
  [14163.285107] Welcome!! Device Init now..Kernel assigned major number is 244 ..
  [14174.979098] av_cmd_hist_start.. Initial..
  [14174.979103] av_cmd_hist_start.. the *pos=0..
  [14174.979104] the av_cmd_hist_show called
  [14174.979107] av_cmd_hist_next called..
  [14174.979108] the av_cmd_hist_show called
  [14174.979109] av_cmd_hist_next called..
  [14174.979110] the av_cmd_hist_show called
  [14174.979112] av_cmd_hist_next called..
  [14174.979113] the av_cmd_hist_show called
  [14174.979114] av_cmd_hist_next called..
  [14174.979115] the av_cmd_hist_show called
  [14174.979117] av_cmd_hist_next called..
  [14174.979118] the av_cmd_hist_show called
  [14174.979119] av_cmd_hist_next called..
  [14174.979120] the av_cmd_hist_show called
  [14174.979121] av_cmd_hist_next called..
  [14174.979122] the av_cmd_hist_show called
  [14174.979124] av_cmd_hist_next called..
  [14174.979125] the av_cmd_hist_show called
  [14174.979126] av_cmd_hist_next called..
  [14174.979127] the av_cmd_hist_show called
  [14174.979128] av_cmd_hist_next called..
  [14174.979130] av_cmd_hist_stop called..
  [14174.979231] av_cmd_hist_start.. the *pos=0..
  [14174.979233] av_cmd_hist_stop called..
  [14174.979250] ------------[ cut here ]------------
  [14174.979252] kernel BUG at mm/slub.c:3483!
  [14174.979254] invalid opcode: 0000 [#2] SMP 
  [14174.979258] Modules linked in: procfs_driver1(O) procfs_driver(O-) tcp_lp nfsv3 nfsv4 nfs fscache dns_resolver fuse vboxpci(O) vboxnetadp(O) vboxnetflt(O) 8021q garp stp llc binfmt_misc vboxdrv(O) tpm_bios snd_hda_codec_hdmi snd_hda_codec_realtek fglrx(PO) snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm iTCO_wdt iTCO_vendor_support r8169 snd_timer mii e1000e snd i2c_i801 lpc_ich i2c_core soundcore snd_page_alloc coretemp kvm_intel kvm serio_raw video dcdbas microcode uinput nfsd lockd nfs_acl auth_rpcgss sunrpc crc32c_intel [last unloaded: procfs_driver1]
  [14174.979297] Pid: 19055, comm: cat Tainted: P    B D  C O 3.6.11-4.fc16.i686 #1 Dell Inc. OptiPlex 9010/00F82W
  [14174.979300] EIP: 0060:[&lt;c0530891&gt;] EFLAGS: 00210246 CPU: 5
  </code></pre>
  
  <p>The proc output is the following -</p>
  
  <pre><code># cat /proc/basicProcfs1 
  Sequential print for debugging-- called for i-times i.e. 10 times 
  Hello SJ proc! 0
  Hello SJ proc! 1
  Hello SJ proc! 2
  Hello SJ proc! 3
  Hello SJ proc! 4
  Hello SJ proc! 5
  Hello SJ proc! 6
  Hello SJ proc! 7
  Hello SJ proc! 8
  Hello SJ proc! 9
  Segmentation fault
  </code></pre>