+
+ /*
+ * Determine how many levels of indirection.
+ */
+ sh = 1;
+ bn -= NDADDR;
+ for (j = NIADDR; j > 0; j--) {
+ sh *= NINDIR(fs);
+ if (bn < sh)
+ break;
+ bn -= sh;
+ }
+ if (j == 0)
+ return (EFBIG);
+
+ /*
+ * fetch the first indirect block
+ */
+ nb = ip->i_ib[NIADDR - j];
+ if (nb == 0) {
+ *bnp = (daddr_t)-1;
+ return (0);
+ }
+
+ /*
+ * fetch through the indirect blocks
+ */
+ for (; j <= NIADDR; j++) {
+ if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
+ (int)fs->fs_bsize, NOCRED, &bp)) {
+ brelse(bp);
+ return (error);
+ }
+ bap = bp->b_un.b_daddr;
+ sh /= NINDIR(fs);
+ i = (bn / sh) % NINDIR(fs);
+ nb = bap[i];
+ if (nb == 0) {
+ *bnp = (daddr_t)-1;
+ brelse(bp);
+ return (0);
+ }
+ if (j < NIADDR)
+ brelse(bp);
+ }
+
+ /*
+ * calculate read-ahead.
+ */
+ if (rablockp && rasizep) {
+ if (i < NINDIR(fs) - 1) {
+ *rablockp = fsbtodb(fs, bap[i + 1]);
+ *rasizep = fs->fs_bsize;
+ } else {
+ *rablockp = 0;
+ *rasizep = 0;
+ }
+ }
+ *bnp = fsbtodb(fs, nb);
+ brelse(bp);
+ return (0);
+}
+
+/*
+ * Balloc defines the structure of file system storage
+ * by returning the physical block number on a device given the
+ * inode and the logical block number in a file.
+ * When unallocated entries are found, new physical blocks
+ * are allocated.
+ */
+balloc(ip, bn, size, bnp, flags)
+ register struct inode *ip;
+ register daddr_t bn;
+ int size;
+ daddr_t *bnp;
+ int flags;
+{
+ register struct fs *fs;
+ register daddr_t nb;
+ struct buf *bp, *nbp;
+ int osize, nsize, i, j, sh, error;
+ daddr_t lbn, *bap, pref, blkpref();
+
+ if (bn < 0)
+ return (EFBIG);