+ avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
+ avgndir = fs->fs_cstotal.cs_ndir / fs->fs_ncg;
+
+ /*
+ * Force allocation in another cg if creating a first level dir.
+ */
+ if (ITOV(pip)->v_flag & VROOT) {
+#ifdef __APPLE__
+ prefcg = random() % fs->fs_ncg;
+#else
+ prefcg = arc4random() % fs->fs_ncg;
+#endif
+ mincg = prefcg;
+ minndir = fs->fs_ipg;
+ for (cg = prefcg; cg < fs->fs_ncg; cg++)
+ if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
+ fs->fs_cs(fs, cg).cs_nifree >= avgifree &&
+ fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+ mincg = cg;
+ minndir = fs->fs_cs(fs, cg).cs_ndir;
+ }
+ for (cg = 0; cg < prefcg; cg++)
+ if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
+ fs->fs_cs(fs, cg).cs_nifree >= avgifree &&
+ fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+ mincg = cg;
+ minndir = fs->fs_cs(fs, cg).cs_ndir;
+ }
+ return ((ino_t)(fs->fs_ipg * mincg));
+ }
+
+ /*
+ * Count various limits which used for
+ * optimal allocation of a directory inode.
+ */
+ maxndir = min(avgndir + fs->fs_ipg / 16, fs->fs_ipg);
+ minifree = avgifree - fs->fs_ipg / 4;
+ if (minifree < 0)
+ minifree = 0;
+ minbfree = avgbfree - fs->fs_fpg / fs->fs_frag / 4;
+ if (minbfree < 0)
+ minbfree = 0;
+ cgsize = fs->fs_fsize * fs->fs_fpg;
+ dirsize = fs->fs_avgfilesize * fs->fs_avgfpdir;
+ curdirsize = avgndir ? (cgsize - avgbfree * fs->fs_bsize) / avgndir : 0;
+ if (dirsize < curdirsize)
+ dirsize = curdirsize;
+ maxcontigdirs = min(cgsize / dirsize, 255);
+ if (fs->fs_avgfpdir > 0)
+ maxcontigdirs = min(maxcontigdirs,
+ fs->fs_ipg / fs->fs_avgfpdir);
+ if (maxcontigdirs == 0)
+ maxcontigdirs = 1;
+
+ /*
+ * Limit number of dirs in one cg and reserve space for
+ * regular files, but only if we have no deficit in
+ * inodes or space.
+ */
+ prefcg = ino_to_cg(fs, pip->i_number);
+ for (cg = prefcg; cg < fs->fs_ncg; cg++)
+ if (fs->fs_cs(fs, cg).cs_ndir < maxndir &&
+ fs->fs_cs(fs, cg).cs_nifree >= minifree &&
+ fs->fs_cs(fs, cg).cs_nbfree >= minbfree) {
+ if (fs->fs_contigdirs[cg] < maxcontigdirs)
+ return ((ino_t)(fs->fs_ipg * cg));
+ }
+ for (cg = 0; cg < prefcg; cg++)
+ if (fs->fs_cs(fs, cg).cs_ndir < maxndir &&
+ fs->fs_cs(fs, cg).cs_nifree >= minifree &&
+ fs->fs_cs(fs, cg).cs_nbfree >= minbfree) {
+ if (fs->fs_contigdirs[cg] < maxcontigdirs)
+ return ((ino_t)(fs->fs_ipg * cg));