tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

options MODULAR improvements phase 1.0



     I'm finally making headway on my options MODULAR improvements.
This is phase 1.0, which is the ability to read <module>.prop files
located alongside a <module.kmod> file.  At this point, it will read a
<module>.prop file into memory, internalize it and pass it to the
<module> being loaded.  As suggested by ad@, the maximum file size is
PAGE_SIZE - 1 in order to simplify memory management.  On most systems,
PAGE_SIZE is 4K which would make a rather large property list.  With
this first implementation, if there is a <module>.prop file, it will be
used in preference to anything passed on the "command line".  The next
phase will merge the <module>.prop file with the "command line".  I
have checked every module that comes with the system and the only
module that pays any attention to the "command line" is example.kmod.
So, I feel that this temporary change in functionality is acceptable.
This is relatively simple code and it is fully tested, but it is new
code, so I'll allow 72 hours for comments before committing it.

Index: kern_module.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_module.c,v
retrieving revision 1.45
diff -u -r1.45 kern_module.c
--- kern_module.c       26 May 2009 08:34:23 -0000      1.45
+++ kern_module.c       3 Jun 2009 01:41:04 -0000
@@ -54,6 +54,9 @@
 #include <sys/kthread.h>
 #include <sys/sysctl.h>
 #include <sys/namei.h>
+#include <sys/lock.h>
+#include <sys/vnode.h>
+#include <sys/stat.h>

 #include <uvm/uvm_extern.h>

@@ -90,6 +93,8 @@
 static int     module_do_builtin(const char *, module_t **);
 static int     module_fetch_info(module_t *);
 static void    module_thread(void *);
+static int     module_load_plist_file(const char *, const bool, void **,
+                   size_t *);

 /*
  * module_error:
@@ -559,16 +564,20 @@
        const int maxdepth = 6;
        modinfo_t *mi;
        module_t *mod, *mod2;
+       prop_dictionary_t filedict;
+       void *plist;
        char buf[MAXMODNAME], *path;
        const char *s, *p;
        int error;
-       size_t len;
+       size_t len, plistlen;
        bool nochroot;

        KASSERT(mutex_owned(&module_lock));

+       filedict = NULL;
+       path = NULL;
        error = 0;
-       path=NULL;
+       nochroot = false;

        /*
         * Avoid recursing too far.
@@ -775,10 +784,35 @@
                goto fail2;
        }

+       /*
+        * Load and process <module>.prop if it exists.
+        */
+       if (mod->mod_source == MODULE_SOURCE_FILESYS) {
+               error = module_load_plist_file(path, nochroot, &plist,
+                   &plistlen);
+               if (error != 0) {
+                       module_print("plist load returned error %d for `%s'",
+                           error, path);
+                       kmem_free(plist, PAGE_SIZE);
+               } else {
+                       filedict = prop_dictionary_internalize(plist);
+                       if (filedict == NULL) {
+                               error = EINVAL;
+                       }
+               }
+               if ((error != 0) && (error != ENOENT)) {
+                       goto fail;
+               }
+       }
+
        KASSERT(module_active == NULL);
        module_active = mod;
-       error = (*mi->mi_modcmd)(MODULE_CMD_INIT, props);
+       error = (*mi->mi_modcmd)(MODULE_CMD_INIT, (filedict != NULL) ?
+           filedict : props);
        module_active = NULL;
+       if (filedict != NULL) {
+               prop_object_release(filedict);
+       }
        if (error != 0) {
                module_error("modcmd function returned error %d for `%s'",
                    error, mi->mi_name);
@@ -1081,3 +1115,82 @@
        }
 }
 #endif /* DDB */
+
+/*
+ * module_load_plist_file:
+ *
+ *     Load a plist located in the file system into memory.
+ */
+static int
+module_load_plist_file(const char *modpath, const bool nochroot,
+                      void **basep, size_t *length)
+{
+       struct nameidata nd;
+       struct stat sb;
+       void *base;
+       char *proppath;
+       size_t resid;
+       int error, pathlen;
+
+       base = NULL;
+       *length = 0;
+
+       proppath = PNBUF_GET();
+       strcpy(proppath, modpath);
+       pathlen = strlen(proppath);
+       if ((pathlen >= 5) && (strcmp(&proppath[pathlen - 5], ".kmod") == 0)) {
+               strcpy(&proppath[pathlen - 5], ".prop");
+       } else if (pathlen < MAXPATHLEN - 5) {
+                       strcat(proppath, ".prop");
+       } else {
+               error = ENOENT;
+               goto out1;
+       }
+
+       NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0),
+           UIO_SYSSPACE, proppath);
+
+       error = namei(&nd);
+       if (error != 0) {
+               goto out1;
+       }
+
+       error = vn_stat(nd.ni_vp, &sb);
+       if (sb.st_size >= (PAGE_SIZE - 1)) {    /* leave space for term \0 */
+               error = EINVAL;
+       }
+       if (error != 0) {
+               goto out1;
+       }
+
+       error = vn_open(&nd, FREAD, 0);
+       if (error != 0) {
+               goto out1;
+       }
+
+       base = kmem_zalloc(PAGE_SIZE, KM_SLEEP);
+       if (base == NULL) {
+               error = ENOMEM;
+               goto out;
+       }
+
+       error = vn_rdwr(UIO_READ, nd.ni_vp, base, sb.st_size, 0,
+           UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp);
+       if (error == 0 && resid != 0) {
+               error = EINVAL;
+       }
+       if (error != 0) {
+               kmem_free(base, PAGE_SIZE);
+               base = NULL;
+       }
+       *length = sb.st_size;
+
+out:
+       VOP_UNLOCK(nd.ni_vp, 0);
+       vn_close(nd.ni_vp, FREAD, kauth_cred_get());
+
+out1:
+       PNBUF_PUT(proppath);
+       *basep = base;
+       return error;
+}


Home | Main Index | Thread Index | Old Index