+ return (cg * fs->fs_fpg + bno);
+}
+
+/*
+ * Allocate a block in a cylinder group.
+ *
+ * This algorithm implements the following policy:
+ * 1) allocate the requested block.
+ * 2) allocate a rotationally optimal block in the same cylinder.
+ * 3) allocate the next available block on the block rotor for the
+ * specified cylinder group.
+ * Note that this routine only allocates fs_bsize blocks; these
+ * blocks may be fragmented by the routine that allocates them.
+ */
+daddr_t
+alloccgblk(fs, cgp, bpref)
+ register struct fs *fs;
+ register struct cg *cgp;
+ daddr_t bpref;
+{
+ daddr_t bno;
+ int cylno, pos, delta;
+ short *cylbp;
+ register int i;
+
+ if (bpref == 0) {
+ bpref = cgp->cg_rotor;
+ goto norot;
+ }
+ bpref &= ~(fs->fs_frag - 1);
+ bpref = dtogd(fs, bpref);
+ /*
+ * if the requested block is available, use it
+ */
+ if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
+ bno = bpref;
+ goto gotit;
+ }
+ /*
+ * check for a block available on the same cylinder
+ */
+ cylno = cbtocylno(fs, bpref);
+ if (cgp->cg_btot[cylno] == 0)
+ goto norot;
+ if (fs->fs_cpc == 0) {
+ /*
+ * block layout info is not available, so just have
+ * to take any block in this cylinder.
+ */
+ bpref = howmany(fs->fs_spc * cylno, NSPF(fs));
+ goto norot;
+ }
+ /*
+ * check the summary information to see if a block is
+ * available in the requested cylinder starting at the
+ * requested rotational position and proceeding around.
+ */
+ cylbp = cgp->cg_b[cylno];
+ pos = cbtorpos(fs, bpref);
+ for (i = pos; i < NRPOS; i++)
+ if (cylbp[i] > 0)
+ break;
+ if (i == NRPOS)
+ for (i = 0; i < pos; i++)
+ if (cylbp[i] > 0)
+ break;
+ if (cylbp[i] > 0) {
+ /*
+ * found a rotational position, now find the actual
+ * block. A panic if none is actually there.
+ */
+ pos = cylno % fs->fs_cpc;
+ bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
+ if (fs->fs_postbl[pos][i] == -1) {
+ printf("pos = %d, i = %d, fs = %s\n",
+ pos, i, fs->fs_fsmnt);
+ panic("alloccgblk: cyl groups corrupted");
+ }
+ for (i = fs->fs_postbl[pos][i];; ) {
+ if (isblock(fs, cgp->cg_free, bno + i)) {
+ bno = (bno + i) * fs->fs_frag;
+ goto gotit;
+ }
+ delta = fs->fs_rotbl[i];
+ if (delta <= 0 || delta > MAXBPC - i)
+ break;
+ i += delta;
+ }
+ printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt);
+ panic("alloccgblk: can't find blk in cyl");
+ }
+norot:
+ /*
+ * no blocks in the requested cylinder, so take next
+ * available one in this cylinder group.
+ */
+ bno = mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
+ if (bno < 0)
+ return (NULL);
+ cgp->cg_rotor = bno;
+gotit:
+ clrblock(fs, cgp->cg_free, (long)(bno/fs->fs_frag));
+ cgp->cg_cs.cs_nbfree--;
+ fs->fs_cstotal.cs_nbfree--;
+ fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
+ cylno = cbtocylno(fs, bno);
+ cgp->cg_b[cylno][cbtorpos(fs, bno)]--;
+ cgp->cg_btot[cylno]--;
+ fs->fs_fmod++;
+ return (cgp->cg_cgx * fs->fs_fpg + bno);