* Grow the file table to accommodate (at least) nfd descriptors. */
| 1794 | * Grow the file table to accommodate (at least) nfd descriptors. |
| 1795 | */ |
| 1796 | static void |
| 1797 | fdgrowtable(struct filedesc *fdp, int nfd) |
| 1798 | { |
| 1799 | struct filedesc0 *fdp0; |
| 1800 | struct freetable *ft; |
| 1801 | struct fdescenttbl *ntable; |
| 1802 | struct fdescenttbl *otable; |
| 1803 | int nnfiles, onfiles; |
| 1804 | NDSLOTTYPE *nmap, *omap; |
| 1805 | |
| 1806 | KASSERT(fdp->fd_nfiles > 0, ("zero-length file table")); |
| 1807 | |
| 1808 | /* save old values */ |
| 1809 | onfiles = fdp->fd_nfiles; |
| 1810 | otable = fdp->fd_files; |
| 1811 | omap = fdp->fd_map; |
| 1812 | |
| 1813 | /* compute the size of the new table */ |
| 1814 | nnfiles = NDSLOTS(nfd) * NDENTRIES; /* round up */ |
| 1815 | if (nnfiles <= onfiles) |
| 1816 | /* the table is already large enough */ |
| 1817 | return; |
| 1818 | |
| 1819 | /* |
| 1820 | * Allocate a new table. We need enough space for the number of |
| 1821 | * entries, file entries themselves and the struct freetable we will use |
| 1822 | * when we decommission the table and place it on the freelist. |
| 1823 | * We place the struct freetable in the middle so we don't have |
| 1824 | * to worry about padding. |
| 1825 | */ |
| 1826 | ntable = malloc(offsetof(struct fdescenttbl, fdt_ofiles) + |
| 1827 | nnfiles * sizeof(ntable->fdt_ofiles[0]) + |
| 1828 | sizeof(struct freetable), |
| 1829 | M_FILEDESC, M_ZERO | M_WAITOK); |
| 1830 | /* copy the old data */ |
| 1831 | ntable->fdt_nfiles = nnfiles; |
| 1832 | memcpy(ntable->fdt_ofiles, otable->fdt_ofiles, |
| 1833 | onfiles * sizeof(ntable->fdt_ofiles[0])); |
| 1834 | |
| 1835 | /* |
| 1836 | * Allocate a new map only if the old is not large enough. It will |
| 1837 | * grow at a slower rate than the table as it can map more |
| 1838 | * entries than the table can hold. |
| 1839 | */ |
| 1840 | if (NDSLOTS(nnfiles) > NDSLOTS(onfiles)) { |
| 1841 | nmap = malloc(NDSLOTS(nnfiles) * NDSLOTSIZE, M_FILEDESC, |
| 1842 | M_ZERO | M_WAITOK); |
| 1843 | /* copy over the old data and update the pointer */ |
| 1844 | memcpy(nmap, omap, NDSLOTS(onfiles) * sizeof(*omap)); |
| 1845 | fdp->fd_map = nmap; |
| 1846 | } |
| 1847 | |
| 1848 | /* |
| 1849 | * Make sure that ntable is correctly initialized before we replace |
| 1850 | * fd_files poiner. Otherwise fget_unlocked() may see inconsistent |
| 1851 | * data. |
| 1852 | */ |
| 1853 | atomic_store_rel_ptr((volatile void *)&fdp->fd_files, (uintptr_t)ntable); |
no test coverage detected