Mercurial > illumos > illumos-gate
changeset 6065:b05c5c670963
6453345 devfs_getattr violates devfs locking rules
6527396 devfsadm -C taking hours after reconfiguration reboot
6661843 i_ddi_di_cache_invalidate() should only use taskq_dispatch on valid->invalid
6662461 reserved_links_exist() should be optimized
author | cth |
---|---|
date | Fri, 22 Feb 2008 09:02:16 -0800 |
parents | 45d29804ab93 |
children | 5e189196050c |
files | usr/src/cmd/devfsadm/devfsadm.c usr/src/cmd/devfsadm/devfsadm.h usr/src/cmd/devfsadm/disk_link.c usr/src/cmd/truss/print.c usr/src/lib/libdevinfo/devinfo_finddev.c usr/src/lib/libdevinfo/libdevinfo.h usr/src/lib/libdevinfo/mapfile-vers usr/src/uts/common/fs/dev/sdev_subr.c usr/src/uts/common/fs/devfs/devfs_vnops.c usr/src/uts/common/os/devcfg.c usr/src/uts/common/os/modctl.c usr/src/uts/common/sys/fs/sdev_impl.h usr/src/uts/common/sys/modctl.h |
diffstat | 13 files changed, 177 insertions(+), 77 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/devfsadm/devfsadm.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/cmd/devfsadm/devfsadm.c Fri Feb 22 09:02:16 2008 -0800 @@ -3153,9 +3153,6 @@ { char *ptr, path[PATH_MAX + 1]; char *fcn = "rm_parent_dir_if_empty: "; - finddevhdl_t fhandle; - const char *f; - int rv; vprint(REMOVE_MID, "%schecking %s if empty\n", fcn, pathname); @@ -3173,17 +3170,8 @@ *ptr = '\0'; - if ((rv = finddev_readdir(path, &fhandle)) != 0) { - err_print(OPENDIR_FAILED, path, strerror(rv)); - return; - } - - /* - * An empty pathlist implies an empty directory - */ - f = finddev_next(fhandle); - finddev_close(fhandle); - if (f == NULL) { + if (finddev_emptydir(path)) { + /* directory is empty */ if (s_rmdir(path) == 0) { vprint(REMOVE_MID, "%sremoving empty dir %s\n", fcn, path); @@ -8970,6 +8958,15 @@ } /* + * Return 1 if we have reserved links. + */ +int +devfsadm_have_reserved() +{ + return (enumerate_reserved ? 1 : 0); +} + +/* * This functions errs on the side of caution. If there is any error * we assume that the devlink is *not* reserved */
--- a/usr/src/cmd/devfsadm/devfsadm.h Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/cmd/devfsadm/devfsadm.h Fri Feb 22 09:02:16 2008 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -250,6 +250,7 @@ char *s_strdup(const char *ptr); /* Private interface between reserve subsystm and disks link generator */ +int devfsadm_have_reserved(void); int devfsadm_is_reserved(devlink_re_t re_array[], char *devlink); int devfsadm_reserve_id_cache(devlink_re_t re_array[], enumerate_file_t *head);
--- a/usr/src/cmd/devfsadm/disk_link.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/cmd/devfsadm/disk_link.c Fri Feb 22 09:02:16 2008 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -150,16 +150,14 @@ int targ; int *intp; - if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, - "target", &intp) <= 0) { + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "target", &intp) <= 0) { return (DEVFSADM_CONTINUE); } targ = *intp; - if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, - "lun", &intp) <= 0) { - lun = 0; + if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "lun", &intp) <= 0) { + lun = 0; } else { - lun = *intp; + lun = *intp; } (void) sprintf(disk, "t%dd%d", targ, lun); @@ -181,10 +179,10 @@ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "client-guid", (char **)&wwn) > 0) { - if (strlcpy((char *)ascii_wwn, (char *)wwn, sizeof (ascii_wwn)) - >= sizeof (ascii_wwn)) { + if (strlcpy((char *)ascii_wwn, (char *)wwn, + sizeof (ascii_wwn)) >= sizeof (ascii_wwn)) { devfsadm_errprint("SUNW_disk_link: GUID too long:%d", - strlen((char *)wwn)); + strlen((char *)wwn)); return (DEVFSADM_CONTINUE); } lun = 0; @@ -468,7 +466,6 @@ char *s; char l[PATH_MAX]; int switch_link = 0; - struct stat sb; char *mn = di_minor_name(minor); if (dvlink_cache == NULL || mn == NULL) { @@ -476,10 +473,8 @@ return (DEVFSADM_FAILURE); } - if (stat(ENUMERATE_RESERVED, &sb) == -1) { - devfsadm_print(disk_mid, "%s: No reserved file: %s. Will " - "not bypass new link creation\n", - modname, ENUMERATE_RESERVED); + if (!devfsadm_have_reserved()) { + devfsadm_print(disk_mid, "%s: No reserved links\n", modname); return (DEVFSADM_FAILURE); } @@ -512,8 +507,8 @@ return (DEVFSADM_FAILURE); } (void) snprintf(s+1, sizeof (phys_path) - (s + 1 - phys_path), - "%s%s", *mn == *(MN_SMI) ? MN_EFI : MN_SMI, - strstr(s, ",raw") ? ",raw" : ""); + "%s%s", *mn == *(MN_SMI) ? MN_EFI : MN_SMI, + strstr(s, ",raw") ? ",raw" : ""); (void) di_devlink_cache_walk(dvlink_cache, DISK_LINK_RE, phys_path, DI_PRIMARY_LINK, &head, dvlink_cb); }
--- a/usr/src/cmd/truss/print.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/cmd/truss/print.c Fri Feb 22 09:02:16 2008 -0800 @@ -1113,6 +1113,7 @@ case MODREMDRVCLEANUP: s = "MODREMDRVCLEANUP"; break; case MODDEVEXISTS: s = "MODDEVEXISTS"; break; case MODDEVREADDIR: s = "MODDEVREADDIR"; break; + case MODDEVEMPTYDIR: s = "MODDEVEMPTYDIR"; break; case MODDEVNAME: s = "MODDEVNAME"; break; case MODGETDEVFSPATH_MI_LEN: s = "MODGETDEVFSPATH_MI_LEN"; break;
--- a/usr/src/lib/libdevinfo/devinfo_finddev.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/lib/libdevinfo/devinfo_finddev.c Fri Feb 22 09:02:16 2008 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -256,6 +256,65 @@ return (finddev_readdir_alt(path, handlep)); } +/* + * Return true if a directory is empty + * Use the standard library readdir to determine if a directory is + * empty. + */ +static int +finddev_emptydir_alt(const char *path) +{ + DIR *dir; + struct dirent *dp; + + if ((dir = opendir(path)) == NULL) + return (ENOENT); + + while ((dp = readdir(dir)) != NULL) { + if ((strcmp(dp->d_name, ".") == 0) || + (strcmp(dp->d_name, "..") == 0)) + continue; + (void) closedir(dir); + return (0); /* not empty */ + } + (void) closedir(dir); + return (1); /* empty */ +} + +/* + * Use of the dev filesystem's private readdir does (not trigger + * the implicit device reconfiguration) to determine if a directory + * is empty. + * + * Note: only useable with paths mounted on an instance of the + * dev filesystem. + * + * Does not return the . and .. entries. + * Empty directories are returned as an zero-length list. + * ENOENT is returned as a NULL list pointer. + */ +static int +finddev_emptydir_devfs(const char *path) +{ + int rv; + int empty; + + rv = modctl(MODDEVEMPTYDIR, path, strlen(path), &empty); + if (rv == 0) { + return (empty); + } + return (0); +} + +int +finddev_emptydir(const char *path) +{ + if (GLOBAL_DEV_PATH(path)) { + return (finddev_emptydir_devfs(path)); + } + return (finddev_emptydir_alt(path)); +} + void finddev_close(finddevhdl_t arg) {
--- a/usr/src/lib/libdevinfo/libdevinfo.h Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/lib/libdevinfo/libdevinfo.h Fri Feb 22 09:02:16 2008 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -473,6 +473,7 @@ extern int device_exists(const char *); extern int finddev_readdir(const char *, finddevhdl_t *); +extern int finddev_emptydir(const char *); extern void finddev_close(finddevhdl_t); extern const char *finddev_next(finddevhdl_t);
--- a/usr/src/lib/libdevinfo/mapfile-vers Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/lib/libdevinfo/mapfile-vers Fri Feb 22 09:02:16 2008 -0800 @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -207,9 +207,10 @@ di_prom_prop_lookup_slot_names; di_prop_find; device_exists; + finddev_close; + finddev_emptydir; + finddev_next; finddev_readdir; - finddev_close; - finddev_next; di_flags; di_retire_device; di_unretire_device;
--- a/usr/src/uts/common/fs/dev/sdev_subr.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/uts/common/fs/dev/sdev_subr.c Fri Feb 22 09:02:16 2008 -0800 @@ -521,7 +521,7 @@ if (map->dir_invalid) { if (map->dir_module && map->dir_newmodule && (strcmp(map->dir_module, - map->dir_newmodule) == 0)) { + map->dir_newmodule) == 0)) { load = 0; } sdev_replace_nsmap(map, map->dir_newmodule, @@ -1230,7 +1230,7 @@ (void) sdev_dirdelete(nddv, *ndvp); *ndvp = NULL; error = VOP_RMDIR(nddv->sdev_attrvp, nnm, - nddv->sdev_attrvp, cred, NULL, 0); + nddv->sdev_attrvp, cred, NULL, 0); if (error) goto err_out; } else { @@ -1254,7 +1254,7 @@ error = VOP_REMOVE(nddv->sdev_attrvp, nnm, cred, NULL, 0); if (error) - goto err_out; + goto err_out; } } } @@ -1811,7 +1811,7 @@ error = 0; } else if (!DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state)) { sdcmn_err6(("lookup %s/%s starting devfsadm, 0x%x\n", - ddv->sdev_name, nm, devfsadm_state)); + ddv->sdev_name, nm, devfsadm_state)); sdev_devfsadmd_thread(ddv, dv, kcred); mutex_enter(&dv->sdev_lookup_lock); @@ -3026,7 +3026,7 @@ int sdev_modctl_readdir(const char *dir, char ***dirlistp, - int *npathsp, int *npathsp_alloc) + int *npathsp, int *npathsp_alloc, int checking_empty) { char **pathlist = NULL; char **newlist = NULL; @@ -3081,18 +3081,17 @@ break; for (dp = dbuf; ((intptr_t)dp < (intptr_t)dbuf + dbuflen); - dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) { + dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) { nm = dp->d_name; if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0) continue; - if (npaths == npaths_alloc) { npaths_alloc += 64; newlist = (char **) kmem_zalloc((npaths_alloc + 1) * - sizeof (char *), KM_SLEEP); + sizeof (char *), KM_SLEEP); if (pathlist) { bcopy(pathlist, newlist, npaths * sizeof (char *)); @@ -3106,6 +3105,12 @@ bcopy(nm, s, n); pathlist[npaths++] = s; sdcmn_err11((" %s/%s\n", dir, s)); + + /* if checking empty, one entry is as good as many */ + if (checking_empty) { + eof = 1; + break; + } } }
--- a/usr/src/uts/common/fs/devfs/devfs_vnops.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/uts/common/fs/devfs/devfs_vnops.c Fri Feb 22 09:02:16 2008 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -180,6 +180,7 @@ return (ENOENT); } + rw_enter(&dv->dv_contents, RW_READER); if (dv->dv_attr) { /* * obtain from the memory version of attribute. @@ -195,6 +196,7 @@ dsysdebug(error, ("vop_getattr %s %d\n", dv->dv_name, error)); dv_vattr_merge(dv, vap); } + rw_exit(&dv->dv_contents); /* * Restrict the permissions of the node fronting the console @@ -241,7 +243,7 @@ again: if (dv->dv_attr) { error = secpolicy_vnode_setattr(cr, vp, vap, - dv->dv_attr, flags, devfs_unlocked_access, dv); + dv->dv_attr, flags, devfs_unlocked_access, dv); if (error) goto out; @@ -281,9 +283,9 @@ if (vap->va_mask & (AT_MODE|AT_UID|AT_GID|AT_ATIME|AT_MTIME)) { /* Set the attributes */ error = VOP_SETATTR(dv->dv_attrvp, - vap, flags, cr, NULL); + vap, flags, cr, NULL); dsysdebug(error, - ("vop_setattr %s %d\n", dv->dv_name, error)); + ("vop_setattr %s %d\n", dv->dv_name, error)); /* * Some file systems may return EROFS for a setattr @@ -459,8 +461,7 @@ ASSERT(vp->v_type != VDIR); *vattrp = dv_vattr_file; error = VOP_GETATTR(dv->dv_attrvp, vattrp, 0, cr, ct); - dsysdebug(error, ("vop_getattr %s %d\n", - dv->dv_name, error)); + dsysdebug(error, ("vop_getattr %s %d\n", dv->dv_name, error)); if (error) goto out; dv->dv_attr = vattrp; @@ -469,10 +470,10 @@ } error = secpolicy_vnode_setattr(cr, vp, vap, dv->dv_attr, - flags, devfs_unlocked_access, dv); + flags, devfs_unlocked_access, dv); if (error) { dsysdebug(error, ("devfs_setattr %s secpolicy error %d\n", - dv->dv_name, error)); + dv->dv_name, error)); goto out; } @@ -530,13 +531,13 @@ } else { if (mask & AT_MODE) dcmn_err5(("%s persisting mode 0%o\n", - dv->dv_name, vap->va_mode)); + dv->dv_name, vap->va_mode)); if (mask & AT_UID) dcmn_err5(("%s persisting uid %d\n", - dv->dv_name, vap->va_uid)); + dv->dv_name, vap->va_uid)); if (mask & AT_GID) dcmn_err5(("%s persisting gid %d\n", - dv->dv_name, vap->va_gid)); + dv->dv_name, vap->va_gid)); if (dv->dv_attrvp == NULL) { dvp = DVTOV(dv->dv_dotdot); @@ -734,16 +735,14 @@ return (EACCES); } + rw_enter(&dv->dv_contents, RW_READER); if (dv->dv_attr && ((dv->dv_flags & DV_ACL) == 0)) { - rw_enter(&dv->dv_contents, RW_READER); - if (dv->dv_attr) { - res = devfs_unlocked_access(dv, mode, cr); - rw_exit(&dv->dv_contents); - return (res); - } - rw_exit(&dv->dv_contents); + res = devfs_unlocked_access(dv, mode, cr); + } else { + res = VOP_ACCESS(dv->dv_attrvp, mode, flags, cr, ct); } - return (VOP_ACCESS(dv->dv_attrvp, mode, flags, cr, ct)); + rw_exit(&dv->dv_contents); + return (res); } /*
--- a/usr/src/uts/common/os/devcfg.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/uts/common/os/devcfg.c Fri Feb 22 09:02:16 2008 -0800 @@ -7314,7 +7314,7 @@ void i_ddi_di_cache_invalidate(int kmflag) { - uint_t flag; + int cache_valid; if (!modrootloaded || !i_ddi_io_initialized()) { if (di_cache_debug) @@ -7322,16 +7322,15 @@ return; } - /* - * Invalidate the in-core cache and - * increment devtree generation number - */ - atomic_and_32(&di_cache.cache_valid, 0); + /* Increment devtree generation number. */ atomic_inc_ulong(&devtree_gen); - flag = (kmflag == KM_SLEEP) ? TQ_SLEEP : TQ_NOSLEEP; - - (void) taskq_dispatch(system_taskq, free_cache_task, NULL, flag); + /* Invalidate the in-core cache and dispatch free on valid->invalid */ + cache_valid = atomic_swap_uint(&di_cache.cache_valid, 0); + if (cache_valid) { + (void) taskq_dispatch(system_taskq, free_cache_task, NULL, + (kmflag == KM_SLEEP) ? TQ_SLEEP : TQ_NOSLEEP); + } if (di_cache_debug) { cmn_err(CE_NOTE, "invalidation with km_flag: %s",
--- a/usr/src/uts/common/os/modctl.c Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/uts/common/os/modctl.c Fri Feb 22 09:02:16 2008 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2046,7 +2046,7 @@ goto err; if ((ret = sdev_modctl_readdir(dir, &dirlist, - &npaths, &npaths_alloc)) != 0) { + &npaths, &npaths_alloc, 0)) != 0) { ASSERT(dirlist == NULL); goto err; } @@ -2093,6 +2093,42 @@ return (ret); } +static int +modctl_devemptydir(const char *udir, int udirlen, int *uempty) +{ + char *dir; + int ret; + char **dirlist = NULL; + int npaths; + int npaths_alloc; + int empty; + + /* + * copyin the /dev path including terminating null + */ + udirlen++; + if (udirlen <= 1 || udirlen > MAXPATHLEN) + return (EINVAL); + dir = kmem_zalloc(udirlen + 1, KM_SLEEP); + if ((ret = copyinstr(udir, dir, udirlen, NULL)) != 0) + goto err; + + if ((ret = sdev_modctl_readdir(dir, &dirlist, + &npaths, &npaths_alloc, 1)) != 0) { + goto err; + } + + empty = npaths ? 0 : 1; + if (copyout(&empty, uempty, sizeof (empty))) + ret = EFAULT; + +err: + if (dirlist) + sdev_modctl_readdir_free(dirlist, npaths, npaths_alloc); + kmem_free(dir, udirlen + 1); + return (ret); +} + int modctl_moddevname(int subcmd, uintptr_t a1, uintptr_t a2) { @@ -2347,6 +2383,11 @@ (char *)a3, (int64_t *)a4); break; + case MODDEVEMPTYDIR: /* non-reconfiguring /dev emptydir */ + error = modctl_devemptydir((const char *)a1, (size_t)a2, + (int *)a3); + break; + case MODDEVNAME: error = modctl_moddevname((int)a1, a2, a3); break;
--- a/usr/src/uts/common/sys/fs/sdev_impl.h Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/uts/common/sys/fs/sdev_impl.h Fri Feb 22 09:02:16 2008 -0800 @@ -624,7 +624,7 @@ /* * devinfo helpers */ -extern int sdev_modctl_readdir(const char *, char ***, int *, int *); +extern int sdev_modctl_readdir(const char *, char ***, int *, int *, int); extern void sdev_modctl_readdir_free(char **, int, int); extern int sdev_modctl_devexists(const char *);
--- a/usr/src/uts/common/sys/modctl.h Fri Feb 22 08:41:57 2008 -0800 +++ b/usr/src/uts/common/sys/modctl.h Fri Feb 22 09:02:16 2008 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -269,6 +269,7 @@ #define MODRETIRE 40 #define MODUNRETIRE 41 #define MODISRETIRED 42 +#define MODDEVEMPTYDIR 43 /* * sub cmds for MODEVENTS