1*d318c565SJaakko Heinonen /*- 2*d318c565SJaakko Heinonen * Copyright (c) 2010 Jaakko Heinonen <jh@FreeBSD.org> 3*d318c565SJaakko Heinonen * All rights reserved. 4*d318c565SJaakko Heinonen * 5*d318c565SJaakko Heinonen * Redistribution and use in source and binary forms, with or without 6*d318c565SJaakko Heinonen * modification, are permitted provided that the following conditions 7*d318c565SJaakko Heinonen * are met: 8*d318c565SJaakko Heinonen * 1. Redistributions of source code must retain the above copyright 9*d318c565SJaakko Heinonen * notice, this list of conditions and the following disclaimer. 10*d318c565SJaakko Heinonen * 2. Redistributions in binary form must reproduce the above copyright 11*d318c565SJaakko Heinonen * notice, this list of conditions and the following disclaimer in the 12*d318c565SJaakko Heinonen * documentation and/or other materials provided with the distribution. 13*d318c565SJaakko Heinonen * 14*d318c565SJaakko Heinonen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*d318c565SJaakko Heinonen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*d318c565SJaakko Heinonen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*d318c565SJaakko Heinonen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*d318c565SJaakko Heinonen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*d318c565SJaakko Heinonen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*d318c565SJaakko Heinonen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*d318c565SJaakko Heinonen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*d318c565SJaakko Heinonen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*d318c565SJaakko Heinonen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*d318c565SJaakko Heinonen * SUCH DAMAGE. 25*d318c565SJaakko Heinonen * 26*d318c565SJaakko Heinonen * $FreeBSD$ 27*d318c565SJaakko Heinonen */ 28*d318c565SJaakko Heinonen 29*d318c565SJaakko Heinonen #include <sys/param.h> 30*d318c565SJaakko Heinonen #include <sys/conf.h> 31*d318c565SJaakko Heinonen #include <sys/types.h> 32*d318c565SJaakko Heinonen #include <sys/kernel.h> 33*d318c565SJaakko Heinonen #include <sys/libkern.h> 34*d318c565SJaakko Heinonen #include <sys/lock.h> 35*d318c565SJaakko Heinonen #include <sys/malloc.h> 36*d318c565SJaakko Heinonen #include <sys/mutex.h> 37*d318c565SJaakko Heinonen #include <sys/queue.h> 38*d318c565SJaakko Heinonen #include <sys/systm.h> 39*d318c565SJaakko Heinonen #include <sys/sx.h> 40*d318c565SJaakko Heinonen 41*d318c565SJaakko Heinonen #include <fs/devfs/devfs.h> 42*d318c565SJaakko Heinonen #include <fs/devfs/devfs_int.h> 43*d318c565SJaakko Heinonen 44*d318c565SJaakko Heinonen struct dirlistent { 45*d318c565SJaakko Heinonen char *dir; 46*d318c565SJaakko Heinonen int refcnt; 47*d318c565SJaakko Heinonen LIST_ENTRY(dirlistent) link; 48*d318c565SJaakko Heinonen }; 49*d318c565SJaakko Heinonen 50*d318c565SJaakko Heinonen static LIST_HEAD(, dirlistent) devfs_dirlist = 51*d318c565SJaakko Heinonen LIST_HEAD_INITIALIZER(devfs_dirlist); 52*d318c565SJaakko Heinonen 53*d318c565SJaakko Heinonen static MALLOC_DEFINE(M_DEVFS4, "DEVFS4", "DEVFS directory list"); 54*d318c565SJaakko Heinonen 55*d318c565SJaakko Heinonen static struct mtx dirlist_mtx; 56*d318c565SJaakko Heinonen MTX_SYSINIT(dirlist_mtx, &dirlist_mtx, "devfs dirlist lock", MTX_DEF); 57*d318c565SJaakko Heinonen 58*d318c565SJaakko Heinonen /* Returns 1 if the path is in the directory list. */ 59*d318c565SJaakko Heinonen int 60*d318c565SJaakko Heinonen devfs_dir_find(const char *path) 61*d318c565SJaakko Heinonen { 62*d318c565SJaakko Heinonen struct dirlistent *dle; 63*d318c565SJaakko Heinonen 64*d318c565SJaakko Heinonen mtx_lock(&dirlist_mtx); 65*d318c565SJaakko Heinonen LIST_FOREACH(dle, &devfs_dirlist, link) { 66*d318c565SJaakko Heinonen if (devfs_pathpath(dle->dir, path) != 0) { 67*d318c565SJaakko Heinonen mtx_unlock(&dirlist_mtx); 68*d318c565SJaakko Heinonen return (1); 69*d318c565SJaakko Heinonen } 70*d318c565SJaakko Heinonen } 71*d318c565SJaakko Heinonen mtx_unlock(&dirlist_mtx); 72*d318c565SJaakko Heinonen 73*d318c565SJaakko Heinonen return (0); 74*d318c565SJaakko Heinonen } 75*d318c565SJaakko Heinonen 76*d318c565SJaakko Heinonen static struct dirlistent * 77*d318c565SJaakko Heinonen devfs_dir_findent_locked(const char *dir) 78*d318c565SJaakko Heinonen { 79*d318c565SJaakko Heinonen struct dirlistent *dle; 80*d318c565SJaakko Heinonen 81*d318c565SJaakko Heinonen mtx_assert(&dirlist_mtx, MA_OWNED); 82*d318c565SJaakko Heinonen 83*d318c565SJaakko Heinonen LIST_FOREACH(dle, &devfs_dirlist, link) { 84*d318c565SJaakko Heinonen if (strcmp(dir, dle->dir) == 0) 85*d318c565SJaakko Heinonen return (dle); 86*d318c565SJaakko Heinonen } 87*d318c565SJaakko Heinonen 88*d318c565SJaakko Heinonen return (NULL); 89*d318c565SJaakko Heinonen } 90*d318c565SJaakko Heinonen 91*d318c565SJaakko Heinonen static void 92*d318c565SJaakko Heinonen devfs_dir_ref(const char *dir) 93*d318c565SJaakko Heinonen { 94*d318c565SJaakko Heinonen struct dirlistent *dle, *dle_new; 95*d318c565SJaakko Heinonen 96*d318c565SJaakko Heinonen if (*dir == '\0') 97*d318c565SJaakko Heinonen return; 98*d318c565SJaakko Heinonen 99*d318c565SJaakko Heinonen dle_new = malloc(sizeof(*dle), M_DEVFS4, M_WAITOK); 100*d318c565SJaakko Heinonen dle_new->dir = strdup(dir, M_DEVFS4); 101*d318c565SJaakko Heinonen dle_new->refcnt = 1; 102*d318c565SJaakko Heinonen 103*d318c565SJaakko Heinonen mtx_lock(&dirlist_mtx); 104*d318c565SJaakko Heinonen dle = devfs_dir_findent_locked(dir); 105*d318c565SJaakko Heinonen if (dle != NULL) { 106*d318c565SJaakko Heinonen dle->refcnt++; 107*d318c565SJaakko Heinonen mtx_unlock(&dirlist_mtx); 108*d318c565SJaakko Heinonen free(dle_new->dir, M_DEVFS4); 109*d318c565SJaakko Heinonen free(dle_new, M_DEVFS4); 110*d318c565SJaakko Heinonen return; 111*d318c565SJaakko Heinonen } 112*d318c565SJaakko Heinonen LIST_INSERT_HEAD(&devfs_dirlist, dle_new, link); 113*d318c565SJaakko Heinonen mtx_unlock(&dirlist_mtx); 114*d318c565SJaakko Heinonen } 115*d318c565SJaakko Heinonen 116*d318c565SJaakko Heinonen void 117*d318c565SJaakko Heinonen devfs_dir_ref_de(struct devfs_mount *dm, struct devfs_dirent *de) 118*d318c565SJaakko Heinonen { 119*d318c565SJaakko Heinonen char dirname[SPECNAMELEN + 1], *namep; 120*d318c565SJaakko Heinonen 121*d318c565SJaakko Heinonen namep = devfs_fqpn(dirname, dm, de, NULL); 122*d318c565SJaakko Heinonen KASSERT(namep != NULL, ("devfs_ref_dir_de: NULL namep")); 123*d318c565SJaakko Heinonen 124*d318c565SJaakko Heinonen devfs_dir_ref(namep); 125*d318c565SJaakko Heinonen } 126*d318c565SJaakko Heinonen 127*d318c565SJaakko Heinonen static void 128*d318c565SJaakko Heinonen devfs_dir_unref(const char *dir) 129*d318c565SJaakko Heinonen { 130*d318c565SJaakko Heinonen struct dirlistent *dle; 131*d318c565SJaakko Heinonen 132*d318c565SJaakko Heinonen if (*dir == '\0') 133*d318c565SJaakko Heinonen return; 134*d318c565SJaakko Heinonen 135*d318c565SJaakko Heinonen mtx_lock(&dirlist_mtx); 136*d318c565SJaakko Heinonen dle = devfs_dir_findent_locked(dir); 137*d318c565SJaakko Heinonen KASSERT(dle != NULL, ("devfs_dir_unref: dir %s not referenced", dir)); 138*d318c565SJaakko Heinonen dle->refcnt--; 139*d318c565SJaakko Heinonen KASSERT(dle->refcnt >= 0, ("devfs_dir_unref: negative refcnt")); 140*d318c565SJaakko Heinonen if (dle->refcnt == 0) { 141*d318c565SJaakko Heinonen LIST_REMOVE(dle, link); 142*d318c565SJaakko Heinonen mtx_unlock(&dirlist_mtx); 143*d318c565SJaakko Heinonen free(dle->dir, M_DEVFS4); 144*d318c565SJaakko Heinonen free(dle, M_DEVFS4); 145*d318c565SJaakko Heinonen } else 146*d318c565SJaakko Heinonen mtx_unlock(&dirlist_mtx); 147*d318c565SJaakko Heinonen } 148*d318c565SJaakko Heinonen 149*d318c565SJaakko Heinonen void 150*d318c565SJaakko Heinonen devfs_dir_unref_de(struct devfs_mount *dm, struct devfs_dirent *de) 151*d318c565SJaakko Heinonen { 152*d318c565SJaakko Heinonen char dirname[SPECNAMELEN + 1], *namep; 153*d318c565SJaakko Heinonen 154*d318c565SJaakko Heinonen namep = devfs_fqpn(dirname, dm, de, NULL); 155*d318c565SJaakko Heinonen KASSERT(namep != NULL, ("devfs_unref_dir_de: NULL namep")); 156*d318c565SJaakko Heinonen 157*d318c565SJaakko Heinonen devfs_dir_unref(namep); 158*d318c565SJaakko Heinonen } 159*d318c565SJaakko Heinonen 160*d318c565SJaakko Heinonen /* Returns 1 if the path p1 contains the path p2. */ 161*d318c565SJaakko Heinonen int 162*d318c565SJaakko Heinonen devfs_pathpath(const char *p1, const char *p2) 163*d318c565SJaakko Heinonen { 164*d318c565SJaakko Heinonen 165*d318c565SJaakko Heinonen for (;;p1++, p2++) { 166*d318c565SJaakko Heinonen if (*p1 != *p2) { 167*d318c565SJaakko Heinonen if (*p1 == '/' && *p2 == '\0') 168*d318c565SJaakko Heinonen return (1); 169*d318c565SJaakko Heinonen else 170*d318c565SJaakko Heinonen return (0); 171*d318c565SJaakko Heinonen } else if (*p1 == '\0') 172*d318c565SJaakko Heinonen return (1); 173*d318c565SJaakko Heinonen } 174*d318c565SJaakko Heinonen /* NOTREACHED */ 175*d318c565SJaakko Heinonen } 176