diff --git a/tsk/fs/tsk_xfs.h b/tsk/fs/tsk_xfs.h
index f9a0f0232b9f36b11b62b64caf4d7e599697abf4..3a9e89dcfa68cda7a063ae06d9d5e24182e71710 100644
--- a/tsk/fs/tsk_xfs.h
+++ b/tsk/fs/tsk_xfs.h
@@ -511,13 +511,12 @@ static inline uint xfs_dinode_size(int version)
     if (version == 3)
     {
         //return sizeof(struct xfs_dinode);
-        //return 176;
-        return 0; // apparently it's something more than null
+        return 176; // hardcode for now
     }
 
-    //return sizeof(xfs_dinode_core_t);
-
-    return offsetof(struct xfs_dinode, di_next_unlinked) + sizeof(__uint32_t); // hacky
+    return 100; // hardcode for now
+     //sizeof(xfs_dinode_core_t) + sizeof(uint32_t);
+     // offsetof(struct xfs_dinode, di_next_unlinked) + sizeof(__uint32_t); // hacky
      //96;
 }
 
diff --git a/tsk/fs/xfs.cpp b/tsk/fs/xfs.cpp
index 757541bb491edcb1671d8a34fda414a921b9c50e..c610e7184fe128e56f063e45eb1fd83e042b69a4 100644
--- a/tsk/fs/xfs.cpp
+++ b/tsk/fs/xfs.cpp
@@ -68,7 +68,7 @@ TSK_FS_META_FLAG_ENUM xfs_inode_getallocflag(XFSFS_INFO * xfsfs, TSK_INUM_T dino
     dino_aginum = dino_inum & rel_inum_neg;
 
     // take inode agi b+tree
-    cur_block_num = ag_num * xfsfs->fs->sb_agblocks + xfsfs->agi[ag_num].agi_root;
+    cur_block_num = (TSK_DADDR_T) ag_num * (TSK_DADDR_T) xfsfs->fs->sb_agblocks + (TSK_DADDR_T) xfsfs->agi[ag_num].agi_root;
     len = sizeof(xfs_inobt_block_t);
     cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) xfsfs->fs->sb_blocksize * cur_block_num, (char *) cur_inobt_block, sizeof(xfs_inobt_block_t));
     if (cnt != len) {
@@ -107,7 +107,7 @@ TSK_FS_META_FLAG_ENUM xfs_inode_getallocflag(XFSFS_INFO * xfsfs, TSK_INUM_T dino
 
         // read all the node pointers
         len = cur_inobt_block->bb_numrecs * sizeof(xfs_inobt_ptr_t);
-        cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) xfsfs->fs->sb_blocksize * cur_block_num + sizeof(xfs_inobt_block_t) + cur_inobt_block->bb_numrecs * sizeof(xfs_inobt_key_t), (char *) iptrs, len);
+        cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) xfsfs->fs->sb_blocksize * cur_block_num + (TSK_OFF_T) sizeof(xfs_inobt_block_t) + (TSK_OFF_T) (cur_inobt_block->bb_numrecs * sizeof(xfs_inobt_key_t)), (char *) iptrs, len);
         if (cnt != len) {
             if (cnt >= 0) {
                 tsk_error_reset();
@@ -129,7 +129,7 @@ TSK_FS_META_FLAG_ENUM xfs_inode_getallocflag(XFSFS_INFO * xfsfs, TSK_INUM_T dino
                 // found in a range, go one level down in b+tree, read the next
                 found_key = true;
 
-                cur_block_num = ag_num * xfsfs->fs->sb_agblocks + (TSK_DADDR_T) tsk_getu32(TSK_BIG_ENDIAN, iptrs[cur_key]);
+                cur_block_num = (TSK_DADDR_T) ag_num * (TSK_DADDR_T) xfsfs->fs->sb_agblocks + (TSK_DADDR_T) tsk_getu32(TSK_BIG_ENDIAN, iptrs[cur_key]);
 
                 if (tsk_verbose) { tsk_fprintf(stderr, "go one level down in b+tree, cur_block_num = %u \n", cur_block_num); }
 
@@ -178,7 +178,7 @@ TSK_FS_META_FLAG_ENUM xfs_inode_getallocflag(XFSFS_INFO * xfsfs, TSK_INUM_T dino
 
         if(dino_aginum >= irecs[cur_key].ir_startino && dino_aginum - irecs[cur_key].ir_startino < 64)
         {
-            if (tsk_verbose) { tsk_fprintf(stderr, "found at cur_inobt_block->bb_level = %u, cur_key = %u, irecs[cur_key].ar_startblock = %u, irecs[cur_key].ir_free = %" PRIx64 " \n",
+            if (tsk_verbose) { tsk_fprintf(stderr, "found at cur_inobt_block->bb_level = %u, cur_key = %u, irecs[cur_key].ir_startino = %u, irecs[cur_key].ir_free = %" PRIx64 " \n",
                 cur_inobt_block->bb_level, cur_key, irecs[cur_key].ir_startino, irecs[cur_key].ir_free); }
 
             free(cur_inobt_block);
@@ -223,6 +223,12 @@ xfs_dinode_load(XFSFS_INFO * xfsfs, TSK_INUM_T dino_inum,
 {
     char *myname = "xfs_dinode_load";
     TSK_FS_INFO *fs = &(xfsfs->fs_info);
+    xfs_agnumber_t ag_num = 0;
+    uint64_t rel_inum_neg = 0;
+    xfs_agino_t dino_aginum = 0;
+    uint64_t offset_neg = 0;
+    TSK_DADDR_T ag_block = 0;
+    xfs_off_t offset = 0;
     TSK_OFF_T addr = 0;
     ssize_t cnt;
 
@@ -244,7 +250,20 @@ xfs_dinode_load(XFSFS_INFO * xfsfs, TSK_INUM_T dino_inum,
         return 1;
     }
 
-    addr = dino_inum * xfsfs->inode_size;
+    ag_num = dino_inum >> xfsfs->fs->sb_agblklog >> xfsfs->fs->sb_inopblog;
+    rel_inum_neg = 1 << (xfsfs->fs->sb_agblklog + xfsfs->fs->sb_inopblog);
+    rel_inum_neg -= 1;
+    dino_aginum = dino_inum & rel_inum_neg;
+    ag_block = dino_aginum >> xfsfs->fs->sb_inopblog;
+    offset_neg = 1 << xfsfs->fs->sb_inopblog;
+    offset_neg -= 1;
+    offset = dino_aginum & offset_neg;
+
+    addr = (TSK_OFF_T) ag_num * (TSK_OFF_T) xfsfs->fs->sb_agblocks * (TSK_OFF_T) xfsfs->fs->sb_blocksize +
+     (TSK_OFF_T) ag_block * (TSK_OFF_T) xfsfs->fs->sb_blocksize + (TSK_OFF_T) offset * (TSK_OFF_T) xfsfs->fs->sb_inodesize;
+
+    if (tsk_verbose) { tsk_fprintf(stderr, "ag_num = %" PRId64 " ag_block = %" PRId64 " offset  = %" PRId64 ", addr = %" PRId64 " \n", ag_num, ag_block, offset, addr); }
+
     cnt = tsk_fs_read(fs, addr, (char *) dino_buf, xfsfs->inode_size);
     if (cnt != xfsfs->fs->sb_inodesize) {
         if (cnt >= 0) {
@@ -517,6 +536,7 @@ xfs_dinode_copy(XFSFS_INFO * xfsfs, TSK_FS_META * fs_meta,
 
         di_core_ptr = (xfs_dinode_core_t*) &dino_buf->di_core;
         extent_data_offset = (xfs_bmbt_rec_t*) XFS_DFORK_PTR(di_core_ptr, XFS_DATA_FORK);
+
         memcpy(fs_meta->content_ptr, extent_data_offset, content_len);
     }
     else {
@@ -748,7 +768,7 @@ TSK_FS_BLOCK_FLAG_ENUM
 xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
 {
     XFSFS_INFO *xfsfs = (XFSFS_INFO *) a_fs;
-    TSK_DADDR_T ag_start = 0;
+    TSK_OFF_T ag_start_off = 0;
     TSK_OFF_T offset = 0;
     unsigned int len = 0;
     xfs_agf *agf = NULL;
@@ -764,6 +784,17 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
     // actually, determining the status of a block in a general case, without the reverse-mapping B+tree is difficult, or at least nonoptimal
     // but let's try
 
+    xfs_agnumber_t ag_num = a_addr >> xfsfs->fs->sb_agblklog;
+    uint64_t rel_blk_neg = 1 << (xfsfs->fs->sb_agblklog);
+    rel_blk_neg -= 1;
+    uint64_t rel_blk = a_addr & rel_blk_neg;
+
+    // Sanity check
+    if (rel_blk >= xfsfs->fs->sb_agblocks)
+    {
+        // TODO: error msg
+        return (TSK_FS_BLOCK_FLAG_ENUM) NULL;
+    }
 
     // 0 - superblock, agf, agi, agfl
     // 1 - inobt
@@ -774,11 +805,10 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
     //        the free list array. This size may increase as features are added." (c) http://ftp.ntu.edu.tw/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
     //
 
-    if (a_addr % xfsfs->fs->sb_agblocks <= 7)
+    if (rel_blk <= 7)
         return (TSK_FS_BLOCK_FLAG_ENUM) (TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_ALLOC);
 
-
-    ag_start = rounddown(a_addr, xfsfs->fs->sb_agblocks);
+    ag_start_off = (TSK_OFF_T) ag_num * (TSK_OFF_T) xfsfs->fs->sb_agblocks * (TSK_OFF_T) xfsfs->fs->sb_blocksize;
 
     // Check agfl
 
@@ -786,8 +816,8 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
     if ((agf = (xfs_agf *) tsk_malloc(len)) == NULL)
         return (TSK_FS_BLOCK_FLAG_ENUM) NULL;
 
-    if (tsk_verbose) { tsk_fprintf(stderr, "reading xfs AG Free Space Block, ag_start = %" PRId64 ", sect_size = %u, len = %u \n", ag_start, xfsfs->fs->sb_sectsize, len); }
-    cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) (ag_start * xfsfs->fs->sb_blocksize + xfsfs->fs->sb_sectsize), (char *) agf, len);
+    if (tsk_verbose) { tsk_fprintf(stderr, "reading xfs AG Free Space Block, ag_start_off = %" PRId64 ", sect_size = %u, len = %u \n", ag_start_off, xfsfs->fs->sb_sectsize, len); }
+    cnt = tsk_fs_read(&xfsfs->fs_info, ag_start_off + (TSK_OFF_T) xfsfs->fs->sb_sectsize, (char *) agf, len);
     if (cnt != len) {
         if (cnt >= 0) {
             tsk_error_reset();
@@ -825,7 +855,7 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
     if ((agfl = (xfs_agblock_t *) tsk_malloc(len)) == NULL)
         return (TSK_FS_BLOCK_FLAG_ENUM) NULL;
 
-    offset = ag_start * xfsfs->fs->sb_blocksize + xfsfs->fs->sb_sectsize * 3;
+    offset = ag_start_off + (TSK_OFF_T) xfsfs->fs->sb_sectsize * 3;
     len = xfsfs->fs->sb_sectsize;
     if (XFS_SB_VERSION_NUM(xfsfs->fs) == 5)
     {
@@ -858,7 +888,7 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
     // the free list array. This size may increase as features are added." (c) http://ftp.ntu.edu.tw/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
     // Q: will they be reserved right after the 7th block?
 
-    offset = ag_start * xfsfs->fs->sb_blocksize + xfsfs->fs->sb_blocksize * 4;
+    offset = ag_start_off + (TSK_OFF_T) xfsfs->fs->sb_blocksize * 4;
     len = xfsfs->fs->sb_blocksize * 4;
     cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) offset, ((char *) agfl) + agfl_cur_len, len);
     if (cnt != len) {
@@ -874,19 +904,22 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
 
     for (cur_key = agf->agf_flfirst; cur_key <= agf->agf_fllast; cur_key++)
     {
-        if (a_addr % xfsfs->fs->sb_agblocks == tsk_getu32(TSK_BIG_ENDIAN, &agfl[cur_key]))
+        if (rel_blk == tsk_getu32(TSK_BIG_ENDIAN, &agfl[cur_key]))
         {
             // free
             return (TSK_FS_BLOCK_FLAG_ENUM) (TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_UNALLOC);
         }
     }
 
+    uint64_t aginode_num = rel_blk * (uint64_t) xfsfs->fs->sb_inopblock;
+    uint64_t inode_num = (uint64_t) ag_num << xfsfs->fs->sb_agblklog + aginode_num;
+
     // Pet trick here: if the block possibly stores inodes, try to read the corresponding inode flags
-    if (tsk_verbose) { tsk_fprintf(stderr, "trying to treat block %u as inode %u \n", a_addr, a_addr * xfsfs->fs->sb_blocksize / xfsfs->fs->sb_inodesize); }
+    if (tsk_verbose) { tsk_fprintf(stderr, "trying to treat rel_block %" PRId64 " in ag %" PRId64 " as rel inode %" PRId64 " (abs inode %" PRId64 ") \n", rel_blk, ag_num, aginode_num, inode_num); }
 
     inode_flag =
       //(TSK_FS_META_FLAG_ENUM) 0;
-        xfs_inode_getallocflag(xfsfs, a_addr * xfsfs->fs->sb_blocksize / xfsfs->fs->sb_inodesize, NULL);
+        xfs_inode_getallocflag(xfsfs, inode_num, NULL);
     if (inode_flag)
     {
         // free
@@ -938,7 +971,7 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
     {
         // read all the keys
         len = cur_btree_sblock->bb_numrecs * sizeof(xfs_alloc_key_t);
-        cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) xfsfs->fs->sb_blocksize * cur_sblock_num + sizeof(xfs_btree_sblock_t), (char *) recs, len);
+        cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) xfsfs->fs->sb_blocksize * (TSK_OFF_T) cur_sblock_num + (TSK_OFF_T) sizeof(xfs_btree_sblock_t), (char *) recs, len);
         if (cnt != len) {
             if (cnt >= 0) {
                 tsk_error_reset();
@@ -952,7 +985,8 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
 
         // read all the node pointers
         len = cur_btree_sblock->bb_numrecs * sizeof(xfs_alloc_ptr_t);
-        cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) xfsfs->fs->sb_blocksize * cur_sblock_num + sizeof(xfs_btree_sblock_t) + cur_btree_sblock->bb_numrecs * sizeof(xfs_alloc_key_t), (char *) ptrs, len);
+        cnt = tsk_fs_read(&xfsfs->fs_info, (TSK_OFF_T) xfsfs->fs->sb_blocksize * (TSK_OFF_T) cur_sblock_num + (TSK_OFF_T) sizeof(xfs_btree_sblock_t) + (TSK_OFF_T) (cur_btree_sblock->bb_numrecs * sizeof(xfs_alloc_key_t)),
+            (char *) ptrs, len);
         if (cnt != len) {
             if (cnt >= 0) {
                 tsk_error_reset();
@@ -971,7 +1005,7 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
             recs[cur_key].ar_startblock = tsk_getu32(TSK_BIG_ENDIAN, &recs[cur_key].ar_startblock);
             recs[cur_key].ar_blockcount = tsk_getu32(TSK_BIG_ENDIAN, &recs[cur_key].ar_blockcount);
 
-            if(a_addr >= recs[cur_key].ar_startblock && a_addr - recs[cur_key].ar_startblock < recs[cur_key].ar_blockcount)
+            if(rel_blk >= recs[cur_key].ar_startblock && rel_blk - recs[cur_key].ar_startblock < recs[cur_key].ar_blockcount)
             {
                 // go one level down in b+tree
                 found = true;
@@ -1022,7 +1056,7 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
         if (tsk_verbose) { tsk_fprintf(stderr, "checking cur_key = %u, recs[cur_key].ar_startblock = %u, recs[cur_key].ar_blockcount = %u \n",
             cur_key, recs[cur_key].ar_startblock, recs[cur_key].ar_blockcount); }
 
-        if(a_addr >= recs[cur_key].ar_startblock && a_addr - recs[cur_key].ar_startblock < recs[cur_key].ar_blockcount)
+        if(rel_blk >= recs[cur_key].ar_startblock && rel_blk - recs[cur_key].ar_startblock < recs[cur_key].ar_blockcount)
         {
             if (tsk_verbose) { tsk_fprintf(stderr, "found at cur_btree_sblock->bb_level = %u, cur_key = %u, recs[cur_key].ar_startblock = %u, recs[cur_key].ar_blockcount = %u \n",
                 cur_btree_sblock->bb_level, cur_key, recs[cur_key].ar_startblock, recs[cur_key].ar_blockcount); }
@@ -1102,6 +1136,7 @@ xfs_block_walk(TSK_FS_INFO * a_fs, TSK_DADDR_T a_start_blk,
      * Iterate
      */
 
+    // TODO: iterate AGs and iterate block numbers until sb_agblocks
     for (addr = a_start_blk; addr <= a_end_blk; addr++) {
         int retval;
         int myflags;
@@ -1154,6 +1189,7 @@ xfs_load_attrs(TSK_FS_FILE * fs_file)
 {
     TSK_FS_META *fs_meta = fs_file->meta;
     TSK_FS_INFO *fs_info = fs_file->fs_info;
+    XFSFS_INFO *xfs = (XFSFS_INFO *) fs_info;
     TSK_FS_ATTR *fs_attr;
     TSK_OFF_T length = 0;
     xfs_bmbt_irec_t irec;
@@ -1194,15 +1230,23 @@ xfs_load_attrs(TSK_FS_FILE * fs_file)
             xfs_bmbt_disk_get_all(&addr_ptr[extent_num], &irec);
 
             if (tsk_verbose) {
-                xfs_bmbt_disk_get_all(&addr_ptr[extent_num], &irec);
-                tsk_fprintf(stderr, "extent_num = %d, adding br_startblock = %d / br_blockcount = %d \n", extent_num, irec.br_startblock, irec.br_blockcount);
+                tsk_fprintf(stderr, "extent_num = %d, adding br_startblock = %" PRIu64 " / br_blockcount = %d \n", extent_num, irec.br_startblock, irec.br_blockcount);
             }
 
             TSK_FS_ATTR_RUN *data_run = tsk_fs_attr_run_alloc();
             if (data_run == NULL) {
                 return 1;
             }
-            data_run->addr = irec.br_startblock;
+
+            xfs_agnumber_t ag_num = irec.br_startblock >> xfs->fs->sb_agblklog;
+            uint64_t rel_blk_neg = 1 << (xfs->fs->sb_agblklog);
+            rel_blk_neg -= 1;
+            uint64_t rel_blk = (uint64_t) irec.br_startblock & rel_blk_neg;
+            TSK_OFF_T offset = ((TSK_OFF_T) ag_num * (TSK_OFF_T) xfs->fs->sb_agblocks + rel_blk) * (TSK_OFF_T) fs_info->block_size;
+
+            // converting logical xfs block number into a "physical" number
+            // this block number is later processed by tsk_fs_read_block, which does (TSK_OFF_T) (a_addr) * a_fs->block_size
+            data_run->addr = offset / fs_info->block_size;
             data_run->len = irec.br_blockcount;
 
             if (tsk_fs_attr_add_run(fs_info, fs_attr, data_run)) {
@@ -1793,7 +1837,12 @@ xfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
 
         size = irec.br_blockcount * a_fs->block_size;
 
-        TSK_OFF_T offset = irec.br_startblock * a_fs->block_size;
+        xfs_agnumber_t ag_num = (TSK_OFF_T) irec.br_startblock >> xfs->fs->sb_agblklog;
+        uint64_t rel_blk_neg = 1 << (xfs->fs->sb_agblklog);
+        rel_blk_neg -= 1;
+        uint64_t rel_blk = (TSK_OFF_T) irec.br_startblock & rel_blk_neg;
+        TSK_OFF_T offset = ((TSK_OFF_T) ag_num * (TSK_OFF_T) xfs->fs->sb_agblocks + rel_blk) * (TSK_OFF_T) a_fs->block_size;
+
         TSK_OFF_T offset_in_block = 0;
 
         // read xfs_dir2_data_hdr (on a v5 filesystem this is xfs_dir3_data_hdr_t)
@@ -2002,6 +2051,14 @@ TSK_FS_INFO *
     unsigned int len = 0;
     ssize_t cnt;
 
+    // temporary sanity check
+    if (xfs_dinode_size(2) != 100) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_FS_ARG);
+        tsk_error_set_errstr("Invalid FS Type in xfsfs_open");
+        return NULL;
+    }
+
     // clean up any error messages that are lying around
     tsk_error_reset();
 
@@ -2112,7 +2169,7 @@ TSK_FS_INFO *
 
     for (xfs_agnumber_t current_ag = 0; current_ag < xfsfs->fs->sb_agcount; current_ag++)
     {
-        TSK_OFF_T agi_offset = current_ag * xfsfs->fs->sb_agblocks * xfsfs->fs->sb_blocksize + xfsfs->fs->sb_sectsize * 2;
+        TSK_OFF_T agi_offset = (TSK_OFF_T) current_ag * (TSK_OFF_T) xfsfs->fs->sb_agblocks * (TSK_OFF_T) xfsfs->fs->sb_blocksize + (TSK_OFF_T) (xfsfs->fs->sb_sectsize * 2);
         len = sizeof(xfs_agi);
 
         if (tsk_verbose) { tsk_fprintf(stderr, "reading xfs AGI[%d/%d] from agi_offset = %" PRId64 " \n", current_ag, xfsfs->fs->sb_agcount, agi_offset); }
@@ -2161,7 +2218,15 @@ TSK_FS_INFO *
     fs->dev_bsize = img_info->sector_size;
     fs->block_count = xfsfs->fs->sb_dblocks;
     fs->first_block = 0;
-    fs->last_block_act = fs->last_block = fs->block_count - 1;
+
+    if (xfsfs->fs->sb_agcount < 1)
+    {
+        tsk_fprintf(stderr, "xfsfs->fs->sb_agcount is <1");
+    }
+
+    fs->last_block = (TSK_DADDR_T) (xfsfs->fs->sb_agcount - 1) << xfsfs->fs->sb_agblklog;
+    fs->last_block += (TSK_DADDR_T) agi[xfsfs->fs->sb_agcount - 1].agi_length;
+    fs->last_block_act = fs->last_block;
     fs->block_size = xfsfs->fs->sb_blocksize;
 
     /*
@@ -2169,7 +2234,9 @@ TSK_FS_INFO *
      */
     fs->root_inum = fs->first_inum = xfsfs->fs->sb_rootino; // usually 128
     fs->inum_count = xfsfs->fs->sb_icount;
-    fs->last_inum = img_info->size / xfsfs->inode_size - 1; // pragmatic upper bound is defined by the image size
+    fs->last_inum = (uint64_t) (xfsfs->fs->sb_agcount - 1) << (xfsfs->fs->sb_agblklog + xfsfs->fs->sb_inopblog);
+    fs->last_inum += (uint64_t) agi[xfsfs->fs->sb_agcount - 1].agi_length * (uint64_t) xfsfs->fs->sb_inopblock;
+    fs->last_inum -= 1;
     // right now, 0xffff prefix signifies the start of unused space in directory entry, so theoretical last inode num is 0xffff000000000000
 
     fs->get_default_attr_type = tsk_fs_unix_get_default_attr_type;