LWN.net Logo

Some 2.6.13 API changes

The flood of patches going into the mainline 2.6.13 brings with it the usual assortment of changes to the internal kernel API. Here's a subset of those changes.

The configurable HZ patch has been merged. If there is, somehow, code which has survived this far with assumptions about the value of HZ, it should probably be fixed sometime soon.

There is a new timer function:

    int try_to_del_timer_sync(struct timer_list *timer);

This function will make a best effort to delete the timer. Should the timer function actually be running at the time, however, this version will not wait for it to complete; it will return -1 immediately. It can thus be used in interrupt handlers and other contexts where waiting for a timer function to finish is not an option.

The block_device_operations structure has a new member:

    long (*unlocked_ioctl) (struct file *filp, unsigned cmd, 
                            unsigned long arg);

If an unlocked_ioctl() method exists, it will be called (in preference to ioctl()), and the big kernel lock will not be held. Drivers which perform their own locking (which should be all of them, really) can use the new method to avoid the overhead of the BKL.

The netif_rx() function, used by network drivers (when not in NAPI mode) to feed packets into the kernel, has traditionally returned one of several values indicating how congested the system was. The idea was that drivers could use this information to reduce load on the kernel as congestion increases. No drivers do this, however; instead, NAPI is used for high-traffic situations. So netif_rx() now will return one of two values: NETIF_RX_SUCCESS if all is well, or NETIF_RX_DROP if the packet was dropped.

It's also worth noting that the sk_buff structure has changed again, leading to the usual troubles with binary-only drivers.

Authors of PCI drivers who want to squeeze out every bit of DMA performance from their hardware can use a new function to determine the optimal DMA burst size:

    void pci_dma_burst_advice(struct pci_dev *pdev, 
                              enum pci_dma_burst_strategy *strat,
			      unsigned long *param);

On return, strat will tell which strategy works best on the current platform. PCI_DMA_BURST_INFINITY says that bursts should simply be made as large as possible; in this case, param contains no information. PCI_DMA_BURST_BOUNDARY tells the driver to not burst across memory boundaries which are a multiple of the value returned in param. And PCI_DMA_BURST_MULTIPLE sets a maximum size (returned in param) on each individual burst.

Thomas Graf has contributed a generic text searching mechanism for the kernel. It can handle searching through non-contiguous data, and is designed to work with pluggable searching algorithms. A couple of search modules have been provided: a straight Knuth/Morris/Pratt string matcher and a finite state machine version which provides a limited regular expression mechanism. The initial application for this library is for flexible packet classification in the networking traffic control code, but other uses are possible.

Performing a search requires first setting up a configuration:

    struct ts_config *textsearch_prepare(const char *algorithm, 
                                         const void *pattern,
                                         unsigned int patlen, 
					 int gfp_mask, int flags);

Here, algorithm is the searching algorithm to use; "kmp" will get Knuth/Morris/Pratt. pattern is the actual pattern to search for; patlen is its length. The usual memory allocation flags are provided in gfp_mask, and flags is for search-specific flags. Currently, the only flag is TS_AUTOLOAD, which allows the kernel to load a module implementing the desired search algorithm, if necessary. The return value is a pointer to a configuration structure to be used with the other functions, or an error value (as determined by IS_ERR()).

A ts_config structure, once initialized, can be reused as many times as desired. It contains no per-search state, so it can be used in parallel searches as well. When the structure is no longer needed, it should be returned with a call to textsearch_destroy().

If the data to be searched is a single, contiguous block, then searching is a matter of calling:

    unsigned int textsearch_find_continuous(struct ts_config *config,
                                            struct ts_state *state,
					    const void *data, 
					    unsigned int datalen);
    unsigned int textsearch_next(struct ts_config *config,
                                 struct ts_state *state);

For these calls, config is a configuration returned from textsearch_prepare(), and state is a local state variable. A call to textsearch_find_continuous() must come first; it will initialize state for a search through the given data array. Both functions will return the offset of the beginning of the match, or UINT_MAX if no (further) match is found.

If the data to be searched is not contiguous in memory, things get a little more complicated. The caller must provide a method which can obtain a pointer to a block of data:

    unsigned int (*get_next_block)(unsigned int consumed,
			 	   const u8 **dst,
				   struct ts_config *config,
				   struct ts_state *state);

This function will be called by the textsearch code when it needs more data to look through. It should locate the first byte beyond consumed and store its address in *dst. The config pointer will not normally be used; state->cb is a 40-byte "control buffer" which can be used to store data between calls to get_next_block(). The return value is the length of the block, or zero if there is no more data.

Another method:

    void (*finish)(struct ts_config *config, struct ts_state *state);

will be called after each search completes. Note that there can be several get_next_block() calls for each call to finish().

Both of these methods are stored in the ts_config structure; they should be set there after the call to textsearch_prepare(). The first search is performed with:

    unsigned int textsearch_find(struct ts_config *config,
                                 struct ts_state *state);

Subsequent searches can be performed with textsearch_next().


(Log in to post comments)

Copyright © 2005, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds