Index: share/man/man9/Makefile =================================================================== --- share/man/man9/Makefile +++ share/man/man9/Makefile @@ -414,6 +414,7 @@ MLINKS= unr.9 alloc_unr.9 \ unr.9 alloc_unrl.9 \ unr.9 alloc_unr_specific.9 \ + unr.9 clear_unrhdr.9 \ unr.9 delete_unrhdr.9 \ unr.9 free_unr.9 \ unr.9 new_unrhdr.9 Index: share/man/man9/unr.9 =================================================================== --- share/man/man9/unr.9 +++ share/man/man9/unr.9 @@ -24,11 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd July 5, 2010 +.Dd October 4, 2017 .Dt UNR 9 .Os .Sh NAME .Nm new_unrhdr , +.Nm clear_unrhdr , .Nm delete_unrhdr , .Nm alloc_unr , .Nm alloc_unr_specific , @@ -39,6 +40,8 @@ .Ft "struct unrhdr *" .Fn new_unrhdr "int low" "int high" "struct mtx *mutex" .Ft void +.Fn clear_unrhdr "struct unrhdr *uh" +.Ft void .Fn delete_unrhdr "struct unrhdr *uh" .Ft int .Fn alloc_unr "struct unrhdr *uh" @@ -70,8 +73,14 @@ .Dv NULL , it is used for locking when allocating and freeing units. Otherwise, internal mutex is used. +.It Fn clear_unrhdr uh +Clear all units from the specified unit number allocator entity. This function +resets the entity as if it were just initialized with +.Fn new_unrhdr . .It Fn delete_unrhdr uh -Destroy specified unit number allocator entity. +Delete specified unit number allocator entity. This function frees the memory +associated with the entity, it does not free any units. To free all units use +.Fn clear_unrhdr . .It Fn alloc_unr uh Return a new unit number. The lowest free number is always allocated. Index: sys/fs/tmpfs/tmpfs_subr.c =================================================================== --- sys/fs/tmpfs/tmpfs_subr.c +++ sys/fs/tmpfs/tmpfs_subr.c @@ -362,7 +362,8 @@ panic("tmpfs_free_node: type %p %d", node, (int)node->tn_type); } - free_unr(tmp->tm_ino_unr, node->tn_id); + if (!detach) + free_unr(tmp->tm_ino_unr, node->tn_id); uma_zfree(tmp->tm_node_pool, node); TMPFS_LOCK(tmp); tmpfs_free_tmp(tmp); Index: sys/fs/tmpfs/tmpfs_vfsops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vfsops.c +++ sys/fs/tmpfs/tmpfs_vfsops.c @@ -317,6 +317,8 @@ TMPFS_NODE_UNLOCK(node); } + clear_unrhdr(tmp->tm_ino_unr); + mp->mnt_data = NULL; tmpfs_free_tmp(tmp); vfs_write_resume(mp, VR_START_WRITE); Index: sys/kern/subr_unit.c =================================================================== --- sys/kern/subr_unit.c +++ sys/kern/subr_unit.c @@ -366,6 +366,27 @@ Free(uh); } +void +clear_unrhdr(struct unrhdr *uh) +{ + struct unr *up, *uq; + + up = TAILQ_FIRST(&uh->head); + while (up != NULL) { + uq = TAILQ_NEXT(up, list); + if (up->ptr != uh) { + Free(up->ptr); + } + Free(up); + up = uq; + } + TAILQ_INIT(&uh->head); + uh->busy = 0; + uh->alloc = 0; + KASSERT(TAILQ_EMPTY(&uh->ppfree), + ("unrhdr has postponed item for free")); +} + static __inline int is_bitmap(struct unrhdr *uh, struct unr *up) { Index: sys/sys/systm.h =================================================================== --- sys/sys/systm.h +++ sys/sys/systm.h @@ -450,6 +450,7 @@ struct unrhdr *new_unrhdr(int low, int high, struct mtx *mutex); void init_unrhdr(struct unrhdr *uh, int low, int high, struct mtx *mutex); void delete_unrhdr(struct unrhdr *uh); +void clear_unrhdr(struct unrhdr *uh); void clean_unrhdr(struct unrhdr *uh); void clean_unrhdrl(struct unrhdr *uh); int alloc_unr(struct unrhdr *uh);