/* * Parse path components and apply requested matching rule at * directory level. */ static void process_rule(struct sdev_node *dir, struct sdev_node *gdir, char *path, char *tgt, int type) { char *name; struct pathname pn; int rv = 0; if ((strlen(path) > 5) && (strncmp(path, "/dev/", 5) == 0)) { path += 5; } if (pn_get(path, UIO_SYSSPACE, &pn) != 0) return; name = kmem_alloc(MAXPATHLEN, KM_SLEEP); (void) pn_getcomponent(&pn, name); pn_skipslash(&pn); SDEV_HOLD(dir); while (pn_pathleft(&pn)) { /* If this is pattern, just add the pattern */ if (strpbrk(name, "*?[]") != NULL && (type == PROFILE_TYPE_INCLUDE || type == PROFILE_TYPE_EXCLUDE)) { ASSERT(tgt == NULL); tgt = pn.pn_path; break; } if ((rv = prof_make_dir(name, &gdir, &dir)) != 0) { cmn_err(CE_CONT, "process_rule: %s error %d\n", path, rv); break; } (void) pn_getcomponent(&pn, name); pn_skipslash(&pn); } /* process the leaf component */ if (rv == 0) { prof_add_rule(name, tgt, dir, type); SDEV_SIMPLE_RELE(dir); } kmem_free(name, MAXPATHLEN); pn_free(&pn); }
/* * Clean pts sdev_nodes that are no longer valid. */ static void devpts_prunedir(struct sdev_node *ddv) { struct vnode *vp; struct sdev_node *dv, *next = NULL; int (*vtor)(struct sdev_node *) = NULL; ASSERT(ddv->sdev_flags & SDEV_VTOR); vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv); ASSERT(vtor); if (rw_tryupgrade(&ddv->sdev_contents) == NULL) { rw_exit(&ddv->sdev_contents); rw_enter(&ddv->sdev_contents, RW_WRITER); } for (dv = ddv->sdev_dot; dv; dv = next) { next = dv->sdev_next; /* skip stale nodes */ if (dv->sdev_flags & SDEV_STALE) continue; /* validate and prune only ready nodes */ if (dv->sdev_state != SDEV_READY) continue; switch (vtor(dv)) { case SDEV_VTOR_VALID: case SDEV_VTOR_SKIP: continue; case SDEV_VTOR_INVALID: sdcmn_err7(("prunedir: destroy invalid " "node: %s(%p)\n", dv->sdev_name, (void *)dv)); break; } vp = SDEVTOV(dv); if (vp->v_count > 0) continue; SDEV_HOLD(dv); /* remove the cache node */ (void) sdev_cache_update(ddv, &dv, dv->sdev_name, SDEV_CACHE_DELETE); } rw_downgrade(&ddv->sdev_contents); }
/* * First step in refreshing directory contents. * Remove each invalid entry and rebuild the link * reference for each stale entry. */ static void devvt_prunedir(struct sdev_node *ddv) { struct vnode *vp; struct sdev_node *dv, *next = NULL; int (*vtor)(struct sdev_node *) = NULL; ASSERT(ddv->sdev_flags & SDEV_VTOR); vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv); ASSERT(vtor); for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = next) { next = SDEV_NEXT_ENTRY(ddv, dv); switch (vtor(dv)) { case SDEV_VTOR_VALID: break; case SDEV_VTOR_SKIP: break; case SDEV_VTOR_INVALID: vp = SDEVTOV(dv); if (vp->v_count != 0) break; /* remove the cached node */ SDEV_HOLD(dv); (void) sdev_cache_update(ddv, &dv, dv->sdev_name, SDEV_CACHE_DELETE); SDEV_RELE(dv); break; case SDEV_VTOR_STALE: devvt_rebuild_stale_link(ddv, dv); break; } } }