Introduce SYSCALL_INIT_HELPER and SYSCALL32_INIT_HELPER macros and

neccessary support functions to allow registering dynamically loaded
syscalls from the MOD_LOAD handlers. Helpers handle registration
failures semi-automatically.

Reviewed by:	jhb
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2010-03-19 10:56:30 +00:00
parent 99b331a982
commit 0687ba3e90
4 changed files with 95 additions and 0 deletions

View File

@ -3084,6 +3084,36 @@ syscall32_module_handler(struct module *mod, int what, void *arg)
}
}
int
syscall32_helper_register(struct syscall_helper_data *sd)
{
struct syscall_helper_data *sd1;
int error;
for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) {
error = syscall32_register(&sd1->syscall_no, &sd1->new_sysent,
&sd1->old_sysent);
if (error != 0) {
syscall32_helper_unregister(sd);
return (error);
}
sd1->registered = 1;
}
return (0);
}
int
syscall32_helper_unregister(struct syscall_helper_data *sd)
{
struct syscall_helper_data *sd1;
for (sd1 = sd; sd1->registered != 0; sd1++) {
syscall32_deregister(&sd1->syscall_no, &sd1->old_sysent);
sd1->registered = 0;
}
return (0);
}
register_t *
freebsd32_copyout_strings(struct image_params *imgp)
{

View File

@ -78,10 +78,21 @@ SYSCALL32_MODULE(syscallname, \
& syscallname##_syscall32, & syscallname##_sysent32,\
NULL, NULL);
#define SYSCALL32_INIT_HELPER(syscallname) { \
.new_sysent = { \
.sy_narg = (sizeof(struct syscallname ## _args ) \
/ sizeof(register_t)), \
.sy_call = (sy_call_t *)& syscallname, \
}, \
.syscall_no = FREEBSD32_SYS_##syscallname \
}
int syscall32_register(int *offset, struct sysent *new_sysent,
struct sysent *old_sysent);
int syscall32_deregister(int *offset, struct sysent *old_sysent);
int syscall32_module_handler(struct module *mod, int what, void *arg);
int syscall32_helper_register(struct syscall_helper_data *sd);
int syscall32_helper_unregister(struct syscall_helper_data *sd);
register_t *freebsd32_copyout_strings(struct image_params *imgp);
struct iovec32;

View File

@ -135,3 +135,33 @@ syscall_module_handler(struct module *mod, int what, void *arg)
else
return (0);
}
int
syscall_helper_register(struct syscall_helper_data *sd)
{
struct syscall_helper_data *sd1;
int error;
for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) {
error = syscall_register(&sd1->syscall_no, &sd1->new_sysent,
&sd1->old_sysent);
if (error != 0) {
syscall_helper_unregister(sd);
return (error);
}
sd1->registered = 1;
}
return (0);
}
int
syscall_helper_unregister(struct syscall_helper_data *sd)
{
struct syscall_helper_data *sd1;
for (sd1 = sd; sd1->registered != 0; sd1++) {
syscall_deregister(&sd1->syscall_no, &sd1->old_sysent);
sd1->registered = 0;
}
return (0);
}

View File

@ -166,10 +166,34 @@ SYSCALL_MODULE(syscallname, \
(sysent[SYS_##syscallname].sy_call != (sy_call_t *)lkmnosys && \
sysent[SYS_##syscallname].sy_call != (sy_call_t *)lkmressys)
/*
* Syscall registration helpers with resource allocation handling.
*/
struct syscall_helper_data {
struct sysent new_sysent;
struct sysent old_sysent;
int syscall_no;
int registered;
};
#define SYSCALL_INIT_HELPER(syscallname) { \
.new_sysent = { \
.sy_narg = (sizeof(struct syscallname ## _args ) \
/ sizeof(register_t)), \
.sy_call = (sy_call_t *)& syscallname, \
.sy_auevent = SYS_AUE_##syscallname \
}, \
.syscall_no = SYS_##syscallname \
}
#define SYSCALL_INIT_LAST { \
.syscall_no = NO_SYSCALL \
}
int syscall_register(int *offset, struct sysent *new_sysent,
struct sysent *old_sysent);
int syscall_deregister(int *offset, struct sysent *old_sysent);
int syscall_module_handler(struct module *mod, int what, void *arg);
int syscall_helper_register(struct syscall_helper_data *sd);
int syscall_helper_unregister(struct syscall_helper_data *sd);
/* Special purpose system call functions. */
struct nosys_args;