+/**
+ * Obtain the number of indirect blocks that contains
+ * pointers to next level blocks.
+ *
+ * Let N be the number of ids that a data block can hold,
+ * then the total number of data blocks assigned (reserved)
+ * to the inode:
+ *
+ * i_blocks = 12 + (N + 1) + (N^2 + N + 1) + (N^3 + N^2 + N + 1)
+ */
+static int
+__get_nr_indblks(struct ext2_sbinfo* sb, size_t fsblks)
+{
+ ssize_t blks;
+ int nr_ents;
+ int nr_inds, n, acc_nr;
+
+ blks = (ssize_t)fsblks;
+ nr_ents = sb->block_size / sizeof(int);
+ acc_nr = 1;
+
+ if (blks <= 12)
+ return 0;
+
+ blks -= 12;
+
+ if (blks > 0) // order-1 indirection
+ {
+ n = MIN(ICEIL(blks, nr_ents), acc_nr);
+ blks -= n * nr_ents;
+
+ nr_inds += 1;
+ acc_nr *= nr_ents;
+ }
+
+ if (blks > 0) // order-2 indirection
+ {
+ n = MIN(ICEIL(blks, nr_ents), acc_nr);
+ blks -= n * nr_ents;
+
+ nr_inds += n + 1;
+ acc_nr *= nr_ents;
+ }
+
+ if (blks > 0) // order-3 indirection
+ {
+ n = MAX(ICEIL(blks, nr_ents), acc_nr);
+ blks -= n * nr_ents;
+
+ nr_inds += n + ICEIL(n, nr_ents) + 1;
+ }
+
+ assert_fs(blks <= 0);
+
+ return nr_inds;
+}
+