Revisiting Old APIs

Some of the kernel APIs we covered in their 2.5 form have changed a little before being nailed down for 2.6. Here's the updated information on the 2.6 versions.

It has been over a year since this column started, and due to the rapid rate of Linux kernel development, much of what was written back then is now wrong. This month, we cover the changes in the different kernel APIs that have been discussed previously.

tty Changes

The tty layer had been one of the most stable kernel APIs around, and it showed. The lack of proper reference counting, the locking shoved in where it looked needed and the strange way tty devices were allocated are all due to its age. Thankfully, Al Viro recently cleaned up a lot of the old cruft in the tty layer in the 2.5 kernel series. Because of this, a number of things have changed for anyone wanting to write a new tty driver.

In the August and October 2002 issues of LJ [available at /article/5896 and /article/6226], we discussed the tty layer and how to fill up the struct tty_driver structure with all the necessary function callbacks. Since then, a new structure, struct tty_operations, has been created to hold all of the function callbacks. The struct tty_driver still contains the older function pointers, so a new function has been created to copy these pointers over, tty_set_operations. Hopefully, this duplication will be eliminated soon.

A number of variables have been removed from the struct tty_driver. The table, termios, termios_locked and refcount fields are gone. The tty layer now handles all of the proper locking and reference counting, without forcing the individual tty drivers to allocate the space for these locks.

The magic and num variables no longer need to be set explicitly by the tty driver. These variables now are set in a new function, alloc_tty_driver, that must be called by all tty drivers to allocate the space for the tty driver. The number of different tty devices this driver is going to support is passed as a parameter to the function. For example, the tiny tty driver introduced in the original tty articles would create the struct tty_driver as:


/* allocate the tty driver */
tiny_tty_driver = alloc_tty_driver(TINY_TTY_MINORS);

In the past, picking the proper name for the tty driver was difficult, as the devfs kernel option overloaded the use of the name field. Christoph Hellwig finally fixed this mess by introducing a new variable in the struct tty_driver structure called devfs_name. Now, the name field should be set to a simple, small name that shows up in the tty proc files. The devfs_name should be set to the name that devfs uses to generate the device node for this driver.

In the 2.5 kernel series, the MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros were declared too racy, and almost all usage of them in the kernel was removed. In order to do this, module reference counting was pushed a layer higher than the original calls. This allows the kernel to increment a module's reference count before the kernel jumps into the module. Likewise, when the kernel is finished with the module, it knows to decrement the count automatically.

This module change was done in the tty layer, so no tty driver should contain the MOD_* macros. Instead, an owner variable was added to the struct tty_driver to show what module owns the tty driver. The following line shows how to set this variable properly:


tiny_tty_driver->owner = THIS_MODULE;

This tells the tty core what module is related to this tty driver.

As for these tty changes, here is how to initialize and register a tty driver with the kernel properly:


#define TINY_TTY_MAJOR240 /* experimental range */
#define TINY_TTY_MINORS	255
                        /* use the whole major up */

static struct tty_operations serial_ops = {
    .open =       tiny_open,
    .close =      tiny_close,
    .write =      tiny_write,
    .write_room = tiny_write_room,
};

static struct tty_driver *tiny_tty_driver;

static int __init tiny_init(void)
{
    /* allocate the tty driver */
    tiny_tty_driver =
        alloc_tty_driver(TINY_TTY_MINORS);

    /* initialize the tty driver */
    tiny_tty_driver->owner = THIS_MODULE;
    tiny_tty_driver->driver_name = "tiny_tty";
    tiny_tty_driver->name = "ttty";
    tiny_tty_driver->devfs_name = "tts/ttty%d";
    tiny_tty_driver->major = TINY_TTY_MAJOR,
    tiny_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
    tiny_tty_driver->subtype = SERIAL_TYPE_NORMAL,
    tiny_tty_driver->flags =
        TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
    tiny_tty_driver->init_termios = tty_std_termios;
    tiny_tty_driver->init_termios.c_cflag =
        B9600 | CS8 | CREAD | HUPCL | CLOCAL;
    tty_set_operations(tiny_tty_driver, &serial_ops);
    if (tty_register_driver(tiny_tty_driver)) {
       printk(KERN_ERR
              "failed to register tiny tty driver");
       return -1;
    }

    printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION);
    return 0;
}

static void __exit tiny_exit (void)
{
    tty_unregister_driver(tiny_tty_driver);
}

module_init(tiny_init);
module_exit(tiny_exit);

tty callout devices also are now removed entirely from the kernel. Any tty driver living in the 2.5 kernel tree that used callout support has had it removed.

______________________

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState