Re: Tools for checking incorrect usage of locking techniques in k-space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 
Hi All,
 
While building the new kernel their are many option for kernel debugging
 
please refer the below link.
 
http://my.safaribooksonline.com/book/operating-systems-and-server-administration/linux/9780137072446/kernel-hacking-config-options/ch11
 
Hope this will help you catch the lock problem.
 
-Anand Moon
From: Vladimir Murzin <murzin.v@xxxxxxxxx>
To: Kumar amit mehta <gmate.amit@xxxxxxxxx>
Cc: Srivatsa Bhat <bhat.srivatsa@xxxxxxxxx>; kernelnewbies@xxxxxxxxxxxxxxxxx
Sent: Monday, November 5, 2012 11:21 AM
Subject: Re: Tools for checking incorrect usage of locking techniques in k-space

On Tue, Oct 30, 2012 at 9:41 AM, Kumar amit mehta <gmate.amit@xxxxxxxxx> wrote:
> On Mon, Oct 29, 2012 at 12:03:08AM +0530, Srivatsa Bhat wrote:
>> You'll need CONFIG_LOCKDEP=y as well. An easy way to configure lock debugging
>> checks is to run 'make menuconfig' and enable the required options under the
>> "Kernel hacking" section.
>>
>> >
>> > If above configuration is all that I need, then should I be seeing warning/error
>> > messages in kernel logs(/var/log/kern.log) when there is inconsistency in
>> > locking ? To test my hypothesis, I modified my simple kernel module to
>> > deliberately induce locking error (After initializing read-write semaphore, I call
>> > down_write() and do not free this semaphore lock by commenting out up_write()
>> > invocation). But still I don't see any error or warning message trace in kernel
>> > logs, I think, I'm missing something.
>
> Hi Srivatsa,
>
> Thank you for your mail. As per your suggestion, this time I've enabled
> CONFIG_LOCKDEP aslo in my running kernel and did the same experiment, but still
> I dont't see any warning/error messages in the kernel log. To give you more idea
> about what I'm doing, Please see the code below.(This is a simple char driver
> based on LDD3 examples)
>
> <echo.c>
>
> #include <linux/module.h>
> #include <linux/init.h>
> #include <linux/types.h> //MAJOR, MINOR
> #include <linux/fs.h> //register_chrdev_region, file_operations
> #include <linux/moduleparam.h>
> #include <linux/kernel.h> //container_of
> #include <linux/slab.h> //kmalloc
> #include <linux/cdev.h> //struct cdev
> #include <linux/version.h>
> #include <linux/uaccess.h> //copy_from/to_user()
> #include <linux/errno.h> //error code
>
> ssize_t echo_read(struct file *, char __user *, size_t, loff_t *);
> ssize_t echo_write(struct file *, const char __user *, size_t, loff_t *);
> int echo_open(struct inode *, struct file *);
> int echo_release(struct inode *, struct file *);
>
> struct echo_cdev {
>        char *data;
>        unsigned long size; //amount of data stored
>        struct semaphore sem;
>        struct cdev cdev;
> };
> MODULE_LICENSE("GPL v2");
> MODULE_AUTHOR("amit");
>
> int nr_major;
> module_param(nr_major, int, S_IRUGO);
> MODULE_PARM_DESC(nr_major, "major number");
>
> int nr_minor;
> char *chrdev_name = "echo";
>
> static dev_t device;
> static int echo_dev_count = 1;
> struct echo_cdev *echo_dev = NULL;
>
> static struct file_operations echo_fs_ops = {
>        .open = echo_open,
>        .release = echo_release,
>        .read = echo_read,
>        .write = echo_write,
>        .owner = THIS_MODULE,
> };
>
> int echo_open(struct inode *inode, struct file *filp)
> {
>        struct echo_cdev *dev;
>        pr_debug("%s: f_flags: 0x%x\n",__FUNCTION__,filp->f_flags);
>        //container_of(pointer, container_type, container_field);
>        dev = container_of(inode->i_cdev, struct echo_cdev, cdev);
>        filp->private_data = dev;
>        if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
>                //trim the device size to 0
>                dev->size = 0;
>        }
>        return 0;
> }
>
> int echo_release(struct inode *inode, struct file *filp)
> {
>        return 0;
> }
>
> ssize_t echo_read(struct file *filp, char __user *ubuff, size_t count, loff_t *poffset)
> {
>        struct echo_cdev *dev = filp->private_data;
>        pr_debug("%s: f_flags: 0x%x\n",__FUNCTION__,filp->f_flags);
>
>        //user trying to access an offset which is beyond the end of file
>        if (down_interruptible(&dev->sem))
>                return -ERESTARTSYS;
>        if (*poffset >= dev->size) {
>                up(&dev->sem);
>                return 0;
>        }
>
>        //user trying to access more than eof, return bytes read till the eof
>        if (*poffset + count >= dev->size)
>                //count = dev->size - *poffset;
>                count = dev->size;
>        //kspace --> uspace
>        if (copy_to_user(ubuff, (dev->data + *poffset), count) < 0) {
>                up(&dev->sem);
>                return -EFAULT;
>        }
>        //update the offset
>        *poffset += count;
>        up(&dev->sem);
>        return count;
> }
>
> //count is the size of requested data transfer
> ssize_t echo_write(struct file *filp, const char __user *ubuff, size_t count, loff_t *poffset)
> {
>        int ret;
>        struct echo_cdev *dev = filp->private_data;
>        pr_debug("%s: f_flags: 0x%x\n",__FUNCTION__,filp->f_flags);
>        if (down_interruptible(&dev->sem))
>                return -ERESTARTSYS;
>        if (dev->data == NULL) {
>                dev->data = "" *)kmalloc(count, GFP_KERNEL);
>                if (!dev->data) {
>                        up(&dev->sem);
>                        return -ENOMEM;
>                } else {
>                        memset(dev->data, 0, sizeof(count));
>                }
>        }
>        dev->size = count;
>        //uspace --> kspace
>        if (copy_from_user(dev->data, ubuff, count) < 0) {
>                up(&dev->sem);
>                return -EFAULT;
>        }
>
>        *poffset += count;
>        ret = count;
>
>        if (dev->size < *poffset)
>                dev->size = *poffset;
>        //Force lock error
>        //up(&dev->sem);
>        return ret;
> }
>
> static int __init echo_init(void)
> {
>        int ret;
>        printk(KERN_EMERG "entering %s\n",__FUNCTION__);
>        //let the user provide the major number.
>        if (nr_major) {
>                device = MKDEV(nr_major, nr_minor);
>                if ((ret = register_chrdev_region(device, echo_dev_count, chrdev_name)) < 0) {
>                        pr_debug("%s: failed to register %s\n",__FUNCTION__,
>                                        chrdev_name);
>                        return ret;
>                }
>        } else {
>                ret = alloc_chrdev_region(&device, 0, echo_dev_count, chrdev_name);
>                if (ret < 0) {
>                        pr_debug("%s: failed to register %s\n",__FUNCTION__,
>                                        chrdev_name);
>                        return ret;
>                }
>        }
>        nr_major = MAJOR(device);
>        nr_minor = MINOR(device);
>        //print the major and minor numbers
>        pr_debug("%s: major/minor:: %d/%d\n",__FUNCTION__,
>                        nr_major, nr_minor);
>        echo_dev = (struct echo_cdev *)kmalloc(sizeof(struct echo_cdev), GFP_KERNEL);
>        if (!echo_dev) {
>                printk(KERN_EMERG "Not enough memory\n");
>                unregister_chrdev_region(device, echo_dev_count);
>                return -ENOMEM;
>        }
>        memset(echo_dev, 0, sizeof(struct echo_cdev));
>        echo_dev->cdev.owner = THIS_MODULE;
>        echo_dev->cdev.ops = &echo_fs_ops;
>        //initialize the semaphore, before it is presented to the world
>        sema_init(&echo_dev->sem,1);
>        cdev_init(&echo_dev->cdev, &echo_fs_ops);
>        device = MKDEV(nr_major, nr_minor);
>        //tell the kernel about this char device
>        //telling the VFS layer to associate echo driver's fs operation for file r/w etc.
>        ret = cdev_add(&echo_dev->cdev, device, 1);
>        if (ret) {
>                kfree(echo_dev);
>                unregister_chrdev_region(device, echo_dev_count);
>                return ret;
>        }
>        return 0;
> }
>
> static void __exit echo_exit(void)
> {
>        printk(KERN_EMERG "entering %s\n",__FUNCTION__);
>        if (echo_dev->data) {
>                printk("Inside %s: kfree()\n",__FUNCTION__);
>                kfree(echo_dev->data);
>        }
>        cdev_del(&echo_dev->cdev);
>        kfree(echo_dev);
>        unregister_chrdev_region(device, echo_dev_count);
> }
>
> module_init(echo_init);
> module_exit(echo_exit);
>
> <echo.c>
>
> <Makefile>
> obj-m := echo.o
> CFLAGS_echo.o := -DDEBUG -Wall -Werror -Wmissing-prototypes \
>        -Wstrict-prototypes -Wunused-variable -O2 \
>        -Wunused-function -g
>
> modules:
>        make -C /lib/modules/`uname -r`/build M=`pwd`
> clean:
>        make -C /lib/modules/`uname -r`/build M=`pwd` clean
> <Makefile>
>
> Logs:
> root@ubuntu:/boot# egrep -i "debug_kernel|lockdep"
> config-3.7.0-rc3-next-20121029
> CONFIG_LOCKDEP_SUPPORT=y
> CONFIG_DEBUG_KERNEL=y
> CONFIG_LOCKDEP=y
> # CONFIG_DEBUG_LOCKDEP is not set
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# uname -a
> Linux ubuntu 3.7.0-rc3-next-20121029 #1 SMP Mon Oct 29 21:42:20 PDT 2012 i686
> i686 i386 GNU/Linux
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# dmesg
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# insmod echo.ko
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# dmesg
> [ 1156.704072] entering echo_init
> [ 1156.704914] echo_init: major/minor:: 249/0
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# mknod /dev/echo c 249 0
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# ll /dev/echo
> crw-r--r-- 1 root root 249, 0 Oct 29 22:29 /dev/echo
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# echo "kernel newbiee" >/dev/echo
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# dmesg
> [ 1156.704072] entering echo_init
> [ 1156.704914] echo_init: major/minor:: 249/0
> [ 1237.377205] echo_open: f_flags: 0x8241
> [ 1237.377392] echo_write: f_flags: 0x8001
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# cat /dev/echo
> --> Here the driver read routine gets stuck as I've not reliquished the
> semaphore lock
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# cat /dev/echo
> ^C <-- killing the user process
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# rmmod echo
>
> root@ubuntu:/home/amit/ldd3/misc-modules/echo# dmesg
> [ 1156.704072] entering echo_init
> [ 1156.704914] echo_init: major/minor:: 249/0
> [ 1237.377205] echo_open: f_flags: 0x8241
> [ 1237.377392] echo_write: f_flags: 0x8001
> [ 1270.622337] echo_open: f_flags: 0x8000
> [ 1270.622477] echo_read: f_flags: 0x8000
> [ 1394.180962] entering echo_exit
> [ 1394.180996] Inside echo_exit: kfree()
>
> As you can see, no warning/error messages reported by kernel.
> -Amit
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies@xxxxxxxxxxxxxxxxx
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

Hi

I've not tried your module, but I suppose that you should get warning
as soon as you try to take write semaphore once again.

Best wishes
Vladimir Murzin

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies


 
_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux