+ u_int32_t reqblks, freeblks, rsrvblks;
+ uint32_t bt_rsrv;
+ struct hfsmount *hfsmp;
+
+ /*
+ * For UNIX conformance, we try and reserve the MIN of either 5% of
+ * total file blocks or 10MB worth of blocks, for growing existing
+ * files. On non-HFS filesystems, creating a new directory entry may
+ * not cause additional disk space to be allocated, but on HFS, creating
+ * a new entry could cause the b-tree to grow. As a result, we take
+ * some precautions here to prevent that on configurations that try to
+ * satisfy conformance.
+ */
+ hfsmp = VTOVCB(btree->fileRefNum);
+ rsrvblks = ((u_int64_t)hfsmp->allocLimit * 5) / 100;
+ if (hfsmp->blockSize > HFS_BT_MAXRESERVE) {
+ bt_rsrv = 1;
+ }
+ else {
+ bt_rsrv = (HFS_BT_MAXRESERVE / hfsmp->blockSize);
+ }
+ rsrvblks = MIN(rsrvblks, bt_rsrv);
+
+ freeblks = hfs_freeblks(hfsmp, 0);
+ if (freeblks <= rsrvblks) {
+ /* When running low, disallow adding new items. */
+ if ((inserts > 0) && (deletes == 0)) {
+ return (ENOSPC);
+ }
+ freeblks = 0;
+ } else {
+ freeblks -= rsrvblks;
+ }
+ reqblks = clumpsize / hfsmp->blockSize;
+
+ if (reqblks > freeblks) {
+ reqblks = ((rsrvNodes - availNodes) * btree->nodeSize) / hfsmp->blockSize;
+ /* When running low, disallow adding new items. */
+ if ((reqblks > freeblks) && (inserts > 0) && (deletes == 0)) {
+ return (ENOSPC);
+ }
+ file->ff_clumpsize = freeblks * hfsmp->blockSize;
+ }