+
+/*
+ * MAXBPG bounds the number of blocks of data per cylinder group,
+ * and is limited by the fact that cylinder groups are at most one block.
+ * Its size is derived from the size of blocks and the (struct cg) size,
+ * by the number of remaining bits.
+ */
+#define MAXBPG(fs) \
+ (NBBY * ((fs)->fs_bsize - (sizeof (struct cg))) / (fs)->fs_frag)
+
+/*
+ * Turn file system block numbers into disk block addresses.
+ * This maps file system blocks to device size blocks.
+ */
+#define fsbtodb(fs, b) ((b) * ((fs)->fs_fsize / DEV_BSIZE))
+#define dbtofsb(fs, b) ((b) / ((fs)->fs_fsize / DEV_BSIZE))
+
+/*
+ * Cylinder group macros to locate things in cylinder groups.
+ *
+ * cylinder group to disk block address of spare boot block
+ * and super block
+ * Note that these are in absolute addresses, and can NOT
+ * in general be expressable in terms of file system addresses.
+ */
+#define cgbblock(c,fs) (fsbtodb(fs, cgbase(c,fs)) + (fs)->fs_bblkno)
+#define cgsblock(c,fs) (fsbtodb(fs, cgbase(c,fs)) + (fs)->fs_sblkno)
+
+/*
+ * cylinder group to disk block at very beginning
+ */
+#define cgbase(c,fs) ((daddr_t)((fs)->fs_fpg * (c)))
+
+/*
+ * convert cylinder group to index of its cg block
+ */
+#define cgtod(c,fs) (cgbase(c,fs) + (fs)->fs_cblkno)
+
+/*
+ * give address of first inode block in cylinder group
+ */
+#define cgimin(c,fs) (cgbase(c,fs) + (fs)->fs_iblkno)
+
+/*
+ * give address of first data block in cylinder group
+ */
+#define cgdmin(c,fs) (cgbase(c,fs) + (fs)->fs_dblkno)
+
+/*
+ * turn inode number into cylinder group number
+ */
+#define itog(x,fs) ((x) / (fs)->fs_ipg)
+
+/*
+ * turn inode number into file system block address
+ */
+#define itod(x,fs) \
+ ((daddr_t)(cgimin(itog(x,fs),fs) + \
+ (x) % (fs)->fs_ipg / INOPB(fs) * (fs)->fs_frag))
+
+/*
+ * turn inode number into file system block offset
+ */
+#define itoo(x,fs) ((x) % INOPB(fs))
+
+/*
+ * give cylinder group number for a file system block
+ */
+#define dtog(d,fs) ((d) / (fs)->fs_fpg)
+
+/*
+ * give cylinder group block number for a file system block
+ */
+#define dtogd(d,fs) ((d) % (fs)->fs_fpg)
+
+/*
+ * compute the cylinder and rotational position of a cyl block addr
+ */
+#define cbtocylno(fs, bno) \
+ ((bno) * NSPF(fs) / (fs)->fs_spc)
+#define cbtorpos(fs, bno) \
+ ((bno) * NSPF(fs) % (fs)->fs_nsect * NRPOS / (fs)->fs_nsect)
+
+/*
+ * determining the size of a file block in the file system
+ */
+#define blksize(fs, ip, lbn) \
+ (((lbn) >= NDADDR || (ip)->i_size >= ((lbn) + 1) * (fs)->fs_bsize) \
+ ? (fs)->fs_bsize \
+ : (roundup((ip)->i_size % (fs)->fs_bsize, (fs)->fs_fsize)))
+#define dblksize(fs, dip, lbn) \
+ (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) * (fs)->fs_bsize) \
+ ? (fs)->fs_bsize \
+ : (roundup((dip)->di_size % (fs)->fs_bsize, (fs)->fs_fsize)))
+
+/*
+ * number of disk sectors per block; assumes DEV_BSIZE byte sector size
+ */
+#define NSPB(fs) ((fs)->fs_bsize / DEV_BSIZE)
+#define NSPF(fs) ((fs)->fs_fsize / DEV_BSIZE)
+
+/*
+ * INOPB is the number of inodes in a secondary storage block
+ */
+#define INOPB(fs) ((fs)->fs_bsize / sizeof (struct dinode))
+#define INOPF(fs) ((fs)->fs_fsize / sizeof (struct dinode))
+
+/*
+ * NINDIR is the number of indirects in a file system block
+ */
+#define NINDIR(fs) ((fs)->fs_bsize / sizeof (daddr_t))