Set cwd to '/' for the process executing insmod.

Ricardo has pointed out that under Solaris the cwd is set to '/'
during module load, while under Linux it is set to the callers cwd.
To handle this cleanly I've reworked the module *_init()/_exit()
macros so they call a *_setup()/_cleanup() function when any SPL
dependent module is loaded or unloaded.  This gives us a chance to
perform any needed modification of the process, in this case changing
the cwd.  It also handily provides a way to avoid creating wrapper
init()/exit() functions because the Solaris and Linux prototypes
differ slightly.  All dependent modules should now call the spl
helper macros spl_module_{init,exit}() instead of the native linux
versions.

Unfortunately, it appears that under Linux there has been no consistent
API in the kernel to set the cwd in a module.  Because of this I have
had to add more autoconf magic than I'd like.  However, what I have
done is correct and has been tested on RHEL5, SLES11, FC11, and CHAOS
kernels.

In addition, I have change the rootdir type from a 'void *' to the
correct 'vnode_t *' type.  And I've set rootdir to a non-NULL value.
This commit is contained in:
Brian Behlendorf
2009-10-01 16:06:15 -07:00
parent 0e77fc118e
commit 51a727e90f
10 changed files with 404 additions and 8 deletions
+35
View File
@@ -0,0 +1,35 @@
#ifndef _SPL_MODULE_COMPAT_H
#define _SPL_MODULE_COMPAT_H
#include <linux/module.h>
#define spl_module_init(init_fn) \
static int \
spl_##init_fn(void) \
{ \
int rc; \
\
spl_setup(); \
rc = init_fn(); \
\
return rc; \
} \
\
module_init(spl_##init_fn)
#define spl_module_exit(exit_fn) \
static void \
spl_##exit_fn(void) \
{ \
int rc; \
\
rc = exit_fn(); \
spl_cleanup(); \
if (rc) \
printk(KERN_ERR "SPL: Failure %d unloading " \
"dependent module\n", rc); \
} \
\
module_exit(spl_##exit_fn)
#endif /* _SPL_MODULE_COMPAT_H */
+2
View File
@@ -144,6 +144,8 @@ extern int p0;
/* Missing misc functions */
extern int highbit(unsigned long i);
extern uint32_t zone_get_hostid(void *zone);
extern void spl_setup(void);
extern void spl_cleanup(void);
#define makedevice(maj,min) makedev(maj,min)
+1
View File
@@ -18,6 +18,7 @@ extern "C" {
#include <linux/workqueue_compat.h>
#include <linux/kallsyms_compat.h>
#include <linux/mutex_compat.h>
#include <linux/module_compat.h>
#ifndef HAVE_UINTPTR_T
typedef unsigned long uintptr_t;
+2 -1
View File
@@ -215,6 +215,7 @@ extern int vn_getattr(vnode_t *vp, vattr_t *vap, int flags, void *x3, void *x4);
extern int vn_fsync(vnode_t *vp, int flags, void *x3, void *x4);
extern file_t *vn_getf(int fd);
extern void vn_releasef(int fd);
extern int vn_set_pwd(const char *filename);
int vn_init(void);
void vn_fini(void);
@@ -241,7 +242,7 @@ vn_putpage(vnode_t *vp, offset_t off, ssize_t size,
#define getf vn_getf
#define releasef vn_releasef
extern void *rootdir;
extern vnode_t *rootdir;
#ifdef __cplusplus
}