diff options
author | Brian Behlendorf <[email protected]> | 2009-02-04 15:15:41 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2009-02-04 15:15:41 -0800 |
commit | 36b313dacf2f60f526fe98b7e9d1a6bbcbb250d2 (patch) | |
tree | f6441a23afb2eebbe2490dae46abd5aad8beede7 /include/sys/sunddi.h | |
parent | 31a033ecd49c2f691d6a377db2882ed941f47481 (diff) |
Linux VM integration / device special files
Support added to provide reasonable values for the global Solaris
VM variables: minfree, desfree, lotsfree, needfree. These values
are set to the sum of their per-zone linux counterparts which
should be close enough for Solaris consumers.
When a non-GPL app links against the SPL we cannot use the udev
interfaces, which means non of the device special files are created.
Because of this I had added a poor mans udev which cause the SPL
to invoke an upcall and create the basic devices when a minor
is registered. When a minor is unregistered we use the vnode
interface to unlink the special file.
Diffstat (limited to 'include/sys/sunddi.h')
-rw-r--r-- | include/sys/sunddi.h | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/include/sys/sunddi.h b/include/sys/sunddi.h index d2e71ebd5..404b14b38 100644 --- a/include/sys/sunddi.h +++ b/include/sys/sunddi.h @@ -32,12 +32,15 @@ #include <sys/sunldi.h> #include <sys/mutex.h> #include <sys/u8_textprep.h> +#include <sys/vnode.h> #include <linux/kdev_t.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/list.h> #include <spl-device.h> +#define DDI_MAX_NAME_LEN 32 + typedef int ddi_devid_t; typedef enum { @@ -80,6 +83,7 @@ typedef struct pollhead { typedef struct dev_info { kmutex_t di_lock; + char di_name[DDI_MAX_NAME_LEN]; struct dev_ops *di_ops; struct cdev *di_cdev; spl_class *di_class; @@ -202,6 +206,7 @@ extern void __ddi_remove_minor_node(dev_info_t *dip, char *name); extern int ddi_quiesce_not_needed(dev_info_t *dip); extern int __mod_install(struct modlinkage *modlp); extern int __mod_remove(struct modlinkage *modlp); +extern int __mod_mknod(char *name, char *type, int major, int minor); extern int ddi_strtoul(const char *, char **, int, unsigned long *); extern int ddi_strtol(const char *, char **, int, long *); @@ -226,7 +231,16 @@ ddi_remove_minor_node(dev_info_t *di, char *name) di->di_class = NULL; di->di_dev = 0; } -#endif +#else + /* When we do not have access to the GPL-only device interfaces we + * are forced to do something crude. We unlink the special device + * file in /dev/ ourselves from within the kernel. On the upside we + * are already providing this functionality for Solaris, and it is + * easy to leverage the Solaris API to perform the unlink. */ + if (strlen(di->di_name) > 0) + vn_remove(di->di_name, UIO_SYSSPACE, RMFILE); + +#endif /* HAVE_GPL_ONLY_SYMBOLS */ __ddi_remove_minor_node(di, name); } @@ -254,14 +268,28 @@ ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, di->di_class = NULL; ddi_remove_minor_node(di, name); CERROR("Error creating %s class, %d\n", name, rc); - RETURN(DDI_FAILURE); + 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 +#else + /* When we do not have access to the GPL-only device interfaces we + * are forced to do something horible. We use a user mode helper to + * create the special device file in /dev/. By futher extending the + * Solaris vnode implementation we could potentially do a vn_create() + * from within the kernel but that's still a hack. */ + if (name) { + rc = __mod_mknod(di->di_name, "c", di->di_major, di->di_minor); + if (rc) { + CERROR("Error mknod %s, %d\n", di->di_name, rc); + ddi_remove_minor_node(di, name); + } + } + +#endif /* HAVE_GPL_ONLY_SYMBOLS */ return rc; } |