* Release a filedesc structure, we use this. */
| 2520 | * Release a filedesc structure, we use this. |
| 2521 | */ |
| 2522 | static void |
| 2523 | fdescfree_fds_adapt_use(struct thread *td, struct filedesc *fdp, bool needclose) |
| 2524 | { |
| 2525 | struct filedesc0 *fdp0; |
| 2526 | struct freetable *ft, *tft; |
| 2527 | struct filedescent *fde; |
| 2528 | struct file *fp; |
| 2529 | int i, lastfile; |
| 2530 | |
| 2531 | KASSERT(refcount_load(&fdp->fd_refcnt) == 0, |
| 2532 | ("%s: fd table %p carries references", __func__, fdp)); |
| 2533 | |
| 2534 | /* |
| 2535 | * Serialize with threads iterating over the table, if any. |
| 2536 | */ |
| 2537 | if (refcount_load(&fdp->fd_holdcnt) > 1) { |
| 2538 | FILEDESC_XLOCK(fdp); |
| 2539 | FILEDESC_XUNLOCK(fdp); |
| 2540 | } |
| 2541 | |
| 2542 | lastfile = fdlastfile_single(fdp); |
| 2543 | for (i = 0; i <= lastfile; i++) { |
| 2544 | fde = &fdp->fd_ofiles[i]; |
| 2545 | fp = fde->fde_file; |
| 2546 | if (fp != NULL) { |
| 2547 | fdefree_last(fde); |
| 2548 | if (needclose) |
| 2549 | (void) closefp_impl(fdp, i, fp, td, true); |
| 2550 | else |
| 2551 | fdrop(fp, td); |
| 2552 | } |
| 2553 | } |
| 2554 | |
| 2555 | if (NDSLOTS(fdp->fd_nfiles) > NDSLOTS(NDFILE)) |
| 2556 | free(fdp->fd_map, M_FILEDESC); |
| 2557 | if (fdp->fd_nfiles > NDFILE) |
| 2558 | free(fdp->fd_files, M_FILEDESC); |
| 2559 | |
| 2560 | fdp0 = (struct filedesc0 *)fdp; |
| 2561 | SLIST_FOREACH_SAFE(ft, &fdp0->fd_free, ft_next, tft) |
| 2562 | free(ft->ft_table, M_FILEDESC); |
| 2563 | |
| 2564 | fddrop(fdp); |
| 2565 | } |
| 2566 | |
| 2567 | void |
| 2568 | fdescfree_adapt_use(struct thread *td) |
no test coverage detected