Search code examples
clinux-device-driver

How to block on write nicely in linux character driver?


I'm trying to write a linux character driver which implements a "tagged MUX" functionality writing to a special hardware link.

write() requests to the driver feed data into a kfifo and a separate kernel thread pulls the data from the FIFO as appropriate. If the FIFO is full, user-space writers to the file descriptor should block until FIFO space is available.

How do you implement such blocking in a character device driver?

I tried this in the "write" handler of my character driver. The user-space process did indeed block when the FIFO was full but it could not be interrupted or killed. Had to reboot the machine.

ssize_t
fifoWrite(struct file *pFile, const char __user *pUserData, size_t nBytes, loff_t *pOffset)
{
    unsigned char         *pktData = 0;

    pktData = memdup_user(pUserData, nBytes); // copy n bytes from user to kernel
    if (IS_ERR(pktData))
        return PTR_ERR(pktData);

    TDataPacket pkt;
    memcpy(pkt.buf, pktData, nBytes);

    while (kfifo_put(&pktFifo, pkt) == 0)
    {
        printk(KERN_ERR MODULE_NAME": write - FIFO full\n");
        msleep(1000);
    }

    int fifoLen = kfifo_len(&clientInfo->pktFifo);

    printk(KERN_INFO MODULE_NAME": WRITE - %zu bytes. LEN %d\n", , nBytes, fifoLen);

    kfree(pktData);

    return nBytes;
}

Solution

  • After searching for a long time, these resources proved to be very helpful: