Index: sys/kern/kern_descrip.c =================================================================== --- sys/kern/kern_descrip.c +++ sys/kern/kern_descrip.c @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -101,6 +102,8 @@ static __read_mostly uma_zone_t file_zone; static __read_mostly uma_zone_t filedesc0_zone; +static __read_mostly uma_zone_t pwd_zone; +static __read_mostly smr_t pwd_smr; static int closefp(struct filedesc *fdp, int fd, struct file *fp, struct thread *td, int holdleaders); @@ -3291,11 +3294,14 @@ fdp = td->td_proc->p_fd; - FILEDESC_SLOCK(fdp); - pwd = fdp->fd_pwd; - MPASS(pwd != NULL); - refcount_acquire(&pwd->pwd_refcount); - FILEDESC_SUNLOCK(fdp); + smr_enter(pwd_smr); + for (;;) { + pwd = atomic_load_ptr(&fdp->fd_pwd); + MPASS(pwd != NULL); + if (refcount_acquire_if_not_zero(&pwd->pwd_refcount)) + break; + } + smr_exit(pwd_smr); return (pwd); } @@ -3304,7 +3310,8 @@ { struct pwd *pwd; - pwd = malloc(sizeof(*pwd), M_PWD, M_WAITOK | M_ZERO); + pwd = uma_zalloc_smr(pwd_zone, M_WAITOK); + bzero(pwd, sizeof(*pwd)); refcount_init(&pwd->pwd_refcount, 1); return (pwd); } @@ -3322,7 +3329,7 @@ vrele(pwd->pwd_rdir); if (pwd->pwd_jdir != NULL) vrele(pwd->pwd_jdir); - free(pwd, M_PWD); + uma_zfree_smr(pwd_zone, pwd); } /* @@ -4277,6 +4284,9 @@ NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); filedesc0_zone = uma_zcreate("filedesc0", sizeof(struct filedesc0), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + pwd_zone = uma_zcreate("PWD", sizeof(struct pwd), NULL, NULL, + NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_SMR); + pwd_smr = uma_zone_get_smr(pwd_zone); mtx_init(&sigio_lock, "sigio lock", NULL, MTX_DEF); } SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, filelistinit, NULL); Index: sys/sys/filedesc.h =================================================================== --- sys/sys/filedesc.h +++ sys/sys/filedesc.h @@ -266,6 +266,7 @@ { FILEDESC_XLOCK_ASSERT(fdp); + atomic_thread_fence_rel(); fdp->fd_pwd = newpwd; }