]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/miscfs/devfs/devfs_tree.c
xnu-7195.60.75.tar.gz
[apple/xnu.git] / bsd / miscfs / devfs / devfs_tree.c
index fe32a3c680b4cea0030b335634f51dec69367cb1..21a0ac5c07093d1eace4732d7e03410a38376c5e 100644 (file)
@@ -99,6 +99,7 @@
 #include <sys/vnode_internal.h>
 #include <stdarg.h>
 #include <libkern/OSAtomic.h>
+#include <os/refcnt.h>
 #define BSD_KERNEL_PRIVATE      1       /* devfs_make_link() prototype */
 #include "devfs.h"
 #include "devfsdefs.h"
@@ -150,6 +151,8 @@ lck_attr_t      * devfs_lck_attr;
 lck_mtx_t         devfs_mutex;
 lck_mtx_t         devfs_attr_mutex;
 
+os_refgrp_decl(static, devfs_refgrp, "devfs", NULL);
+
 devdirent_t *           dev_root = NULL;        /* root of backing tree */
 struct devfs_stats      devfs_stats;            /* hold stats */
 
@@ -197,9 +200,7 @@ devfs_sinit(void)
                return ENOTSUP;
        }
 #ifdef HIDDEN_MOUNTPOINT
-       MALLOC(devfs_hidden_mount, struct mount *, sizeof(struct mount),
-           M_MOUNT, M_WAITOK);
-       bzero(devfs_hidden_mount, sizeof(struct mount));
+       devfs_hidden_mount = zalloc_flags(mount_zone, Z_WAITOK | Z_ZERO);
        mount_lock_init(devfs_hidden_mount);
        TAILQ_INIT(&devfs_hidden_mount->mnt_vnodelist);
        TAILQ_INIT(&devfs_hidden_mount->mnt_workerqueue);
@@ -221,7 +222,7 @@ devfs_sinit(void)
                = (struct devfsmount *)devfs_hidden_mount->mnt_data;
 #endif /* HIDDEN_MOUNTPOINT */
 #if CONFIG_MACF
-       mac_devfs_label_associate_directory("/", strlen("/"),
+       mac_devfs_label_associate_directory("/", (int) strlen("/"),
            dev_root->de_dnp, "/");
 #endif
        devfs_ready = 1;
@@ -357,7 +358,7 @@ dev_finddir(const char * path,
 #if CONFIG_MACF
                        mac_devfs_label_associate_directory(
                                dirnode->dn_typeinfo.Dir.myname->de_name,
-                               strlen(dirnode->dn_typeinfo.Dir.myname->de_name),
+                               (int) strlen(dirnode->dn_typeinfo.Dir.myname->de_name),
                                dnp, fullpath);
 #endif
                        devfs_propogate(dirnode->dn_typeinfo.Dir.myname, dirent_p, delp);
@@ -515,6 +516,7 @@ dev_add_node(int entrytype, devnode_type_t * typeinfo, devnode_t * proto,
     devnode_t * *dn_pp, struct devfsmount *dvm)
 {
        devnode_t *     dnp = NULL;
+       int     error = 0;
 
 #if defined SPLIT_DEVS
        /*
@@ -587,7 +589,9 @@ dev_add_node(int entrytype, devnode_type_t * typeinfo, devnode_t * proto,
 #endif
        }
        dnp->dn_dvm = dvm;
-       dnp->dn_refcount = 0;
+
+       /* Note: this inits the reference count to 1, this is considered unreferenced */
+       os_ref_init_raw(&dnp->dn_refcount, &devfs_refgrp);
        dnp->dn_ino = devfs_unique_fileno;
        devfs_unique_fileno++;
 
@@ -627,8 +631,8 @@ dev_add_node(int entrytype, devnode_type_t * typeinfo, devnode_t * proto,
                    typeinfo->Slnk.namelen + 1,
                    M_DEVFSNODE, M_WAITOK);
                if (!dnp->dn_typeinfo.Slnk.name) {
-                       FREE(dnp, M_DEVFSNODE);
-                       return ENOMEM;
+                       error = ENOMEM;
+                       break;
                }
                strlcpy(dnp->dn_typeinfo.Slnk.name, typeinfo->Slnk.name,
                    typeinfo->Slnk.namelen + 1);
@@ -656,12 +660,17 @@ dev_add_node(int entrytype, devnode_type_t * typeinfo, devnode_t * proto,
 
        #endif /* FDESC */
        default:
-               return EINVAL;
+               error = EINVAL;
        }
 
-       *dn_pp = dnp;
-       DEVFS_INCR_NODES();
-       return 0;
+       if (error) {
+               FREE(dnp, M_DEVFSNODE);
+       } else {
+               *dn_pp = dnp;
+               DEVFS_INCR_NODES();
+       }
+
+       return error;
 }
 
 
@@ -698,7 +707,10 @@ devfs_dn_free(devnode_t * dnp)
                }
 
                /* Can only free if there are no references; otherwise, wait for last vnode to be reclaimed */
-               if (dnp->dn_refcount == 0) {
+               os_ref_count_t rc = os_ref_get_count_raw(&dnp->dn_refcount);
+               if (rc == 1) {
+                       /* release final reference from dev_add_node */
+                       (void) os_ref_release_locked_raw(&dnp->dn_refcount, &devfs_refgrp);
                        devnode_free(dnp);
                } else {
                        dnp->dn_lflags |= DN_DELETE;
@@ -1362,20 +1374,22 @@ out:
 void
 devfs_ref_node(devnode_t *dnp)
 {
-       dnp->dn_refcount++;
+       os_ref_retain_locked_raw(&dnp->dn_refcount, &devfs_refgrp);
 }
 
 /*
  * Release a reference on a devnode.  If the devnode is marked for
- * free and the refcount is dropped to zero, do the free.
+ * free and the refcount is dropped to one, do the free.
  */
 void
 devfs_rele_node(devnode_t *dnp)
 {
-       dnp->dn_refcount--;
-       if (dnp->dn_refcount < 0) {
-               panic("devfs_rele_node: devnode with a negative refcount!\n");
-       } else if ((dnp->dn_refcount == 0) && (dnp->dn_lflags & DN_DELETE)) {
+       os_ref_count_t rc = os_ref_release_locked_raw(&dnp->dn_refcount, &devfs_refgrp);
+       if (rc < 1) {
+               panic("devfs_rele_node: devnode without a refcount!\n");
+       } else if ((rc == 1) && (dnp->dn_lflags & DN_DELETE)) {
+               /* release final reference from dev_add_node */
+               (void) os_ref_release_locked_raw(&dnp->dn_refcount, &devfs_refgrp);
                devnode_free(dnp);
        }
 }
@@ -1565,7 +1579,7 @@ devfs_make_node_internal(dev_t dev, devfstype_t type, uid_t uid,
 #if CONFIG_MACF
        char buff[sizeof(buf)];
 #endif
-       int             i;
+       size_t          i;
        uint32_t        log_count;
        struct devfs_event_log event_log;
        struct devfs_vnode_event stackbuf[NUM_STACK_ENTRIES];
@@ -1666,7 +1680,7 @@ devfs_make_link(void *original, char *fmt, ...)
 
        va_list ap;
        char *p, buf[256]; /* XXX */
-       int i;
+       size_t i;
 
        DEVFS_LOCK();