An API is available for writing adaptation handlers. Calls to activate a different version of a function, or query the framework for presence of a specific version of a function are available. Part of the function signature of the adaptation handler is defined by the framework, and the remaining arguments could match the original arguments of the function on which the adaptation handler is applied.
Figure 4-4 shows the signature of pipe_write, the producer function of pipefs in Linux 2.4. Figure 4-5 shows an example adaptation handler written for pipe_write. The arguments supplied to the original pipe_write are still accessible on the stack and can be used to determine which version of pipe_write should run next. In this (simplified) example, when more than 64K of data are written through a pipe the second version of pipe_write is used.
Figure 4-4. Function signature of pipe_write.
static ssize_t pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
Figure 4-5. Example adaptation handler for pipe_write.
long pipe_write_total_count = 0; void pipe_write_adaptation_handler(dynreplace_version_table_entry_t *entry, redirection_state_t redir_state, rule_evaluation_call_state_t rec_state, struct file *filp, char *buf, size_t count, loff_t *ppos) { pipe_write_total_count += count; dynreplace_version_table_lock(); if (pipe_write_total_count > 64 * 1024) dynreplace_activate_function(&entry->unique, 2); else dynreplace_activate_function(&entry->unique, 1); dynreplace_version_table_unlock(); }