diff --git a/ChangeLog b/ChangeLog index cb231cb012..8d023992ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-11-13 Brian Behlendorf + + * include/sys/sunddi.h, modules/spl/spl-module.c : Removed default + udev support from sunddi implementation because it uses GPL-only + symbols. This support is optionally available for SPL consumers + if they define HAVE_GPL_ONLY_SYMBOLS and license their module as + GPL using the MODULE_LICENSE("GPL") macro. + 2008-11-05 Brian Behlendorf * : Tag spl-0.3.4 diff --git a/autoconf/spl-build.m4 b/autoconf/spl-build.m4 index 0ac7ae8a6c..c5c0319772 100644 --- a/autoconf/spl-build.m4 +++ b/autoconf/spl-build.m4 @@ -30,7 +30,7 @@ AC_DEFUN([SPL_AC_KERNEL], [ AC_MSG_RESULT([Not found]) AC_MSG_ERROR([ *** Please specify the location of the kernel source - *** with the '--with-kernel=PATH' option]) + *** with the '--with-linux=PATH' option]) fi fi @@ -74,6 +74,12 @@ AC_DEFUN([SPL_AC_KERNEL], [ AC_SUBST(kmoduledir) ]) +AC_DEFUN([SPL_AC_LICENSE], [ + AC_MSG_CHECKING([license]) + AC_MSG_RESULT([GPL]) + KERNELCPPFLAGS="${KERNELCPPFLAGS} -DHAVE_GPL_ONLY_SYMBOLS" +]) + AC_DEFUN([SPL_AC_DEBUG], [ AC_MSG_CHECKING([whether debugging is enabled]) AC_ARG_ENABLE( [debug], diff --git a/configure.ac b/configure.ac index a50fe92e11..b3835d0e2f 100644 --- a/configure.ac +++ b/configure.ac @@ -38,6 +38,7 @@ LINUX= LINUX_OBJ= SPL_AC_KERNEL +SPL_AC_LICENSE SPL_AC_DEBUG SPL_AC_DEBUG_KMEM SPL_AC_DEBUG_MUTEX diff --git a/include/sys/sunddi.h b/include/sys/sunddi.h index bbfd412daf..dea09d171c 100644 --- a/include/sys/sunddi.h +++ b/include/sys/sunddi.h @@ -87,6 +87,7 @@ typedef struct dev_info { minor_t di_minor; dev_t di_dev; unsigned di_minors; + int di_flags; struct list_head di_list; } dev_info_t; @@ -180,6 +181,11 @@ typedef struct modldrv { #define DDI_PROP_DONTPASS 0x0001 #define DDI_PROP_CANSLEEP 0x0002 +#define GLOBAL_DEV 0x02 +#define NODEBOUND_DEV 0x04 +#define NODESPECIFIC_DEV 0x06 +#define ENUMERATED_DEV 0x08 + #define ddi_prop_lookup_string(x1,x2,x3,x4,x5) (*x5 = NULL) #define ddi_prop_free(x) (void)0 #define ddi_root_node() (void)0 @@ -189,7 +195,7 @@ typedef struct modldrv { extern int __ddi_create_minor_node(dev_info_t *dip, char *name, int spec_type, minor_t minor_num, char *node_type, - int flag, struct module *mod); + int flags, struct module *mod); extern void __ddi_remove_minor_node(dev_info_t *dip, char *name); extern int __mod_install(struct modlinkage *modlp); extern int __mod_remove(struct modlinkage *modlp); @@ -197,19 +203,64 @@ extern int __mod_remove(struct modlinkage *modlp); static __inline__ void ddi_report_dev(dev_info_t *d) { } static __inline__ void ddi_prop_remove_all(dev_info_t *dip) { } +static __inline__ void +ddi_remove_minor_node(dev_info_t *di, char *name) +{ +#ifdef HAVE_GPL_ONLY_SYMBOLS + /* Cleanup udev (GPL-only symbols required). This is performed as + * part of an inline function to ensure that these symbols are not + * linked against the SPL which is GPL'ed. But instead they are + * linked against the package building against the SPL to ensure + * its license allows linking with GPL-only symbols. */ + if (di->di_class) { + spl_device_destroy(di->di_class, di->di_device, di->di_dev); + spl_class_destroy(di->di_class); + di->di_class = NULL; + di->di_dev = 0; + } +#endif + + __ddi_remove_minor_node(di, name); +} + static __inline__ int ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, - minor_t minor_num, char *node_type, int flag) + minor_t minor_num, char *node_type, int flags) { - return __ddi_create_minor_node(di, name, spec_type, minor_num, - node_type, flag, THIS_MODULE); + int rc; + rc = __ddi_create_minor_node(di, name, spec_type, minor_num, + node_type, flags, THIS_MODULE); + if (rc) + return rc; + +#ifdef HAVE_GPL_ONLY_SYMBOLS + /* Setup udev (GPL-only symbols required). This is performed as + * part of an inline function to ensure that these symbols are not + * linked against the SPL which is GPL'ed. But instead they are + * linked against the package building against the SPL to ensure + * its license allows linking with GPL-only symbols. */ + di->di_class = spl_class_create(THIS_MODULE, name); + if (IS_ERR(di->di_class)) { + rc = PTR_ERR(di->di_class); + di->di_class = NULL; + ddi_remove_minor_node(di, name); + CERROR("Error creating %s class, %d\n", name, rc); + RETURN(DDI_FAILURE); + } + + /* Do not append a 0 to devices with minor nums of 0 */ + di->di_device = spl_device_create(di->di_class, NULL, di->di_dev, NULL, + (di->di_minor == 0) ? "%s" : "%s%d", + name, di->di_minor); +#endif + + return rc; } #undef mod_install #undef mod_remove -#define ddi_remove_minor_node __ddi_remove_minor_node #define mod_install __mod_install #define mod_remove __mod_remove diff --git a/modules/spl/spl-module.c b/modules/spl/spl-module.c index 0dd4cfdedb..700c761829 100644 --- a/modules/spl/spl-module.c +++ b/modules/spl/spl-module.c @@ -58,7 +58,7 @@ mod_generic_ioctl(struct inode *ino, struct file *filp, unsigned int cmd, unsigned long arg) { struct dev_info *di; - int rc, flag = 0, rvalp = 0; + int rc, flags = 0, rvalp = 0; cred_t *cr = NULL; di = get_dev_info(MKDEV(imajor(ino), iminor(ino))); @@ -67,14 +67,14 @@ mod_generic_ioctl(struct inode *ino, struct file *filp, rc = di->di_ops->devo_cb_ops->cb_ioctl(di->di_dev, (int)cmd,(intptr_t)arg, - flag, cr, &rvalp); + flags, cr, &rvalp); return rc; } int __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, minor_t minor_num, char *node_type, - int flag, struct module *mod) + int flags, struct module *mod) { struct cdev *cdev; struct dev_ops *dev_ops; @@ -86,7 +86,6 @@ __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, ASSERT(spec_type == S_IFCHR); ASSERT(minor_num < di->di_minors); ASSERT(!strcmp(node_type, DDI_PSEUDO)); - ASSERT(flag == 0); fops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); if (fops == NULL) @@ -141,8 +140,10 @@ __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, ASSERT(cb_ops->cb_aread == NULL); ASSERT(cb_ops->cb_awrite == NULL); + di->di_cdev = cdev; + di->di_flags = flags; di->di_minor = minor_num; - di->di_dev = MKDEV(di->di_major, di->di_minor); + di->di_dev = MKDEV(di->di_major, di->di_minor); rc = cdev_add(cdev, di->di_dev, 1); if (rc) { @@ -153,29 +154,6 @@ __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, RETURN(DDI_FAILURE); } - di->di_class = spl_class_create(THIS_MODULE, name); - if (IS_ERR(di->di_class)) { - rc = PTR_ERR(di->di_class); - CERROR("Error creating %s class, %d\n", name, rc); - kfree(fops); - cdev_del(di->di_cdev); - mutex_exit(&di->di_lock); - RETURN(DDI_FAILURE); - } - - /* Do not append a 0 to devices with minor nums of 0 */ - if (di->di_minor == 0) { - di->di_device = spl_device_create(di->di_class, NULL, - di->di_dev, NULL, - "%s", name); - } else { - di->di_device = spl_device_create(di->di_class, NULL, - di->di_dev, NULL, - "%s%d", name, di->di_minor); - } - - di->di_cdev = cdev; - spin_lock(&dev_info_lock); list_add(&di->di_list, &dev_info_list); spin_unlock(&dev_info_lock); @@ -184,19 +162,11 @@ __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, RETURN(DDI_SUCCESS); } -EXPORT_SYMBOL_GPL(__ddi_create_minor_node); +EXPORT_SYMBOL(__ddi_create_minor_node); static void __ddi_remove_minor_node_locked(dev_info_t *di, char *name) { - if (di->di_class) { - spl_device_destroy(di->di_class, di->di_device, di->di_dev); - spl_class_destroy(di->di_class); - - di->di_class = NULL; - di->di_dev = 0; - } - if (di->di_cdev) { cdev_del(di->di_cdev); di->di_cdev = NULL; @@ -216,19 +186,19 @@ __ddi_remove_minor_node(dev_info_t *di, char *name) mutex_exit(&di->di_lock); EXIT; } -EXPORT_SYMBOL_GPL(ddi_remove_minor_node); +EXPORT_SYMBOL(__ddi_remove_minor_node); #if 0 static int mod_generic_open(struct inode *, struct file *) { - open(dev_t *devp, int flag, int otyp, cred_t *credp); + open(dev_t *devp, int flags, int otyp, cred_t *credp); } static int mod_generic_close(struct inode *, struct file *) { - close(dev_t dev, int flag, int otyp, cred_t *credp); + close(dev_t dev, int flags, int otyp, cred_t *credp); } static ssize_t