All of lore.kernel.org
 help / color / mirror / Atom feed
* Problem with line discipline in new kernels
@ 2015-08-13 13:00 Margarita Glushkin
  2015-08-21 21:21 ` Valdis.Kletnieks at vt.edu
  0 siblings, 1 reply; 4+ messages in thread
From: Margarita Glushkin @ 2015-08-13 13:00 UTC (permalink / raw)
  To: kernelnewbies

I have a linux kernel driver for serial device, which uses line discipline 
and char device. Driver works with all old kernels, starting from 3.8 this 
driver still works, but when I unload it and load again to the memory 
(modprobe -r bpsctl_mod, after modprobe bpsctl_mod), it crashes the kernel. 
It can't unregister line discipline, because this line discipline is busy. 
I use system device, i.e., ttyS0. Here is problematic code:

static struct file* bps_file_open(const char* path, int flags, int rights)
{
    struct file* filp = NULL;    
    mm_segment_t oldfs;    
    oldfs = get_fs();    
    set_fs(get_ds());    
    filp = filp_open(path, flags, rights);    
    set_fs(oldfs);    
    if (IS_ERR(filp))
        return NULL;    

    return filp;
}

int register_ldisc(void)
{
    int           status;
    // Fill in our line protocol discipline, and register it
    extbp_drv.ebtty_ldisc.magic = TTY_LDISC_MAGIC;
    extbp_drv.ebtty_ldisc.name  = BP_LDISC_NAME;
    extbp_drv.ebtty_ldisc.flags = 0;
    extbp_drv.ebtty_ldisc.open  = ebtty_open;
    extbp_drv.ebtty_ldisc.close = ebtty_close;
    extbp_drv.ebtty_ldisc.read  = NULL;
    extbp_drv.ebtty_ldisc.write = NULL;
    extbp_drv.ebtty_ldisc.ioctl =
    (int (*)(struct tty_struct *, struct file *,
        unsigned int, unsigned long)) ebtty_ioctl;
    extbp_drv.ebtty_ldisc.poll  = NULL;
    extbp_drv.ebtty_ldisc.receive_buf  = ebtty_receive_buf;
    extbp_drv.ebtty_ldisc.write_wakeup = NULL; //ebtty_write_wakeup;
    if ((status = tty_register_ldisc(extbp_drv.line_disc,
                                     &extbp_drv.ebtty_ldisc)) == 0) {
        extbp_drv.drv_state |= ST_LDISC_REGISTRATED;
    }
    return status;
}

int ebtty_init (void)
{
    int status = -1;
    if (register_ldisc())
    {
        err_print(KERN_ERR, DBG_ERROR,
                  ("Can't register line discipline (%d).\n", line_disc));
        goto ebtty_init_exit;
    }    
    status = 0;
ebtty_init_exit:
    if (status)
    {
        dbg_print(KERN_DEBUG, DBG_ERROR, ("Module initialization failed.
\n"));
        cleanup();
    }
    return status;
}

static void cleanup(void)
{
    int status;
    if ((status = tty_unregister_ldisc(extbp_drv.line_disc)) != 0)
    {
        err_print(KERN_ERR, DBG_ERROR,
            ("Can't unregister line discipline (err = %d)\n", status));
    }
}

int init_ebtty_module(void)
{
    memset(&port_name_path, 0, sizeof(port_name_path));
    printk(BSEM_DRV_NAME BP_VER);
    sprintf((char *)&port_name_path, "//dev//%s", port_name);
    fd=bps_file_open((char *)&port_name_path, 0, O_RDWR);
    memset((void*)&extbp_drv, 0, sizeof(struct ext_bypass_drv));
    extbp_drv.drv_name      = BP_MOD_NAME;
    extbp_drv.dev_name      = port_name;
    extbp_drv.line_disc     = line_disc;
    extbp_drv.wait_data     = LAST_CHAR;
    extbp_drv.drv_state     = 0;
    init_waitqueue_head(&extbp_drv.read_wait);

    if (!ebtty_init())
    {
        extbp_drv.ebtty_major = register_chrdev(0, extbp_drv.drv_name,   
            &ebtty_fops);
        if (extbp_drv.ebtty_major < 0)
        {
            err_print(KERN_ERR, DBG_ERROR,
                      ("can't get major %d\n", extbp_drv.ebtty_major));
            return extbp_drv.ebtty_major;
        }        
        if (fd != NULL)
        {
            if (!(bps_vfs_ioctl(fd, TIOCSETD, (unsigned long)&line_disc)))
            {
                bps_start_flag = 1;
            }            
            return 0;
        }
     }
     else
     {
        if (fd)
            filp_close(fd, NULL);
        cleanup();
        return -1;
     }
}

void exit_ebtty_module(void)
{
    if (fd)
    {
        filp_close(fd, NULL);
        fd = 0;
    }   
    cleanup();
}

Please advice, maybe I should use something else, instead of line 
discipline and char device, or maybe I should register and unregister them 
other way?

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

* Problem with line discipline in new kernels
  2015-08-13 13:00 Problem with line discipline in new kernels Margarita Glushkin
@ 2015-08-21 21:21 ` Valdis.Kletnieks at vt.edu
  2015-08-23  7:14   ` Ruth Glushkin
  0 siblings, 1 reply; 4+ messages in thread
From: Valdis.Kletnieks at vt.edu @ 2015-08-21 21:21 UTC (permalink / raw)
  To: kernelnewbies

On Thu, 13 Aug 2015 13:00:58 -0000, Margarita Glushkin said:
> I have a linux kernel driver for serial device, which uses line discipline
> and char device. Driver works with all old kernels, starting from 3.8 this
> driver still works, but when I unload it and load again to the memory
> (modprobe -r bpsctl_mod, after modprobe bpsctl_mod), it crashes the kernel.
> It can't unregister line discipline, because this line discipline is busy.

Sounds like a reference counting problem.  When your line discipline is busy,
somebody should have a reference on the module so it can't be unloaded.  I don't
see any such reference taking/freeing in your posted code.

Your crash is almost certainly because you're unloading it out from
under active use, which will probably result in somebody overlaying storage.
Frankly, you're probably lucky the system lives long enough for you to
reload it.....

Oh, and filp_open() is usually the wrong way to solve whatever problem you
were trying to solve by using it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 848 bytes
Desc: not available
Url : http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20150821/3aab7b73/attachment-0001.bin 

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

* Problem with line discipline in new kernels
  2015-08-21 21:21 ` Valdis.Kletnieks at vt.edu
@ 2015-08-23  7:14   ` Ruth Glushkin
  2015-08-23 14:10     ` Valdis.Kletnieks at vt.edu
  0 siblings, 1 reply; 4+ messages in thread
From: Ruth Glushkin @ 2015-08-23  7:14 UTC (permalink / raw)
  To: kernelnewbies

On Thu, 22 Aug 2015 00:21:00 -0000, Valdis Kletnieks said:

> Sounds like a reference counting problem.

As far as I know, reference counter for line discipline sets to 0 in
tty_register_ldisc(),

increases to 1 in get_ldops() and decreases to 1 in put_ldops().

In tty_unregister_ldisc() it checks this value and if the reference
counter > 0, it returns error -EBUSY

And please advice how could I transfer data between kernel and user
space not using filp_open() and filp_close().

2015-08-22 0:21 GMT+03:00  <Valdis.Kletnieks@vt.edu>:
> On Thu, 13 Aug 2015 13:00:58 -0000, Margarita Glushkin said:
>> I have a linux kernel driver for serial device, which uses line discipline
>> and char device. Driver works with all old kernels, starting from 3.8 this
>> driver still works, but when I unload it and load again to the memory
>> (modprobe -r bpsctl_mod, after modprobe bpsctl_mod), it crashes the kernel.
>> It can't unregister line discipline, because this line discipline is busy.
>
> Sounds like a reference counting problem.  When your line discipline is busy,
> somebody should have a reference on the module so it can't be unloaded.  I don't
> see any such reference taking/freeing in your posted code.
>
> Your crash is almost certainly because you're unloading it out from
> under active use, which will probably result in somebody overlaying storage.
> Frankly, you're probably lucky the system lives long enough for you to
> reload it.....
>
> Oh, and filp_open() is usually the wrong way to solve whatever problem you
> were trying to solve by using it.

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

* Problem with line discipline in new kernels
  2015-08-23  7:14   ` Ruth Glushkin
@ 2015-08-23 14:10     ` Valdis.Kletnieks at vt.edu
  0 siblings, 0 replies; 4+ messages in thread
From: Valdis.Kletnieks at vt.edu @ 2015-08-23 14:10 UTC (permalink / raw)
  To: kernelnewbies

On Sun, 23 Aug 2015 10:14:20 +0300, Ruth Glushkin said:
> On Thu, 22 Aug 2015 00:21:00 -0000, Valdis Kletnieks said:
>
> > Sounds like a reference counting problem.
>
> As far as I know, reference counter for line discipline sets to 0 in
> tty_register_ldisc(),

Not for the discipline, for the *MODULE*.

> And please advice how could I transfer data between kernel and user
> space not using filp_open() and filp_close().

Depends on the data.  sysfs, netlink, debugfs, or having userspace open the
file and using that, or any number of other ways to do it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 848 bytes
Desc: not available
Url : http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20150823/b79f29e1/attachment.bin 

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

end of thread, other threads:[~2015-08-23 14:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-13 13:00 Problem with line discipline in new kernels Margarita Glushkin
2015-08-21 21:21 ` Valdis.Kletnieks at vt.edu
2015-08-23  7:14   ` Ruth Glushkin
2015-08-23 14:10     ` Valdis.Kletnieks at vt.edu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.