* Release a filedesc structure. */
| 2596 | * Release a filedesc structure. |
| 2597 | */ |
| 2598 | static void |
| 2599 | fdescfree_fds(struct thread *td, struct filedesc *fdp, bool needclose) |
| 2600 | { |
| 2601 | struct filedesc0 *fdp0; |
| 2602 | struct freetable *ft, *tft; |
| 2603 | struct filedescent *fde; |
| 2604 | struct file *fp; |
| 2605 | int i, lastfile; |
| 2606 | |
| 2607 | KASSERT(refcount_load(&fdp->fd_refcnt) == 0, |
| 2608 | ("%s: fd table %p carries references", __func__, fdp)); |
| 2609 | |
| 2610 | /* |
| 2611 | * Serialize with threads iterating over the table, if any. |
| 2612 | */ |
| 2613 | if (refcount_load(&fdp->fd_holdcnt) > 1) { |
| 2614 | FILEDESC_XLOCK(fdp); |
| 2615 | FILEDESC_XUNLOCK(fdp); |
| 2616 | } |
| 2617 | |
| 2618 | lastfile = fdlastfile_single(fdp); |
| 2619 | for (i = 0; i <= lastfile; i++) { |
| 2620 | fde = &fdp->fd_ofiles[i]; |
| 2621 | fp = fde->fde_file; |
| 2622 | if (fp != NULL) { |
| 2623 | fdefree_last(fde); |
| 2624 | if (needclose) |
| 2625 | (void) closef(fp, td); |
| 2626 | else |
| 2627 | fdrop(fp, td); |
| 2628 | } |
| 2629 | } |
| 2630 | |
| 2631 | if (NDSLOTS(fdp->fd_nfiles) > NDSLOTS(NDFILE)) |
| 2632 | free(fdp->fd_map, M_FILEDESC); |
| 2633 | if (fdp->fd_nfiles > NDFILE) |
| 2634 | free(fdp->fd_files, M_FILEDESC); |
| 2635 | |
| 2636 | fdp0 = (struct filedesc0 *)fdp; |
| 2637 | SLIST_FOREACH_SAFE(ft, &fdp0->fd_free, ft_next, tft) |
| 2638 | free(ft->ft_table, M_FILEDESC); |
| 2639 | |
| 2640 | fddrop(fdp); |
| 2641 | } |
| 2642 | |
| 2643 | void |
| 2644 | fdescfree(struct thread *td) |
no test coverage detected