/*
                 * A directory small enough to fit in the inode must be stored
                 * in local format.  The directory sf <-> extents conversion
-                * code updates the directory size accordingly.
+                * code updates the directory size accordingly.  Directories
+                * being truncated have zero size and are not subject to this
+                * check.
                 */
                if (S_ISDIR(mode)) {
-                       if (be64_to_cpu(dip->di_size) <= fork_size &&
+                       if (dip->di_size &&
+                           be64_to_cpu(dip->di_size) <= fork_size &&
                            fork_format != XFS_DINODE_FMT_LOCAL)
                                return __this_address;
                }
        if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
                return __this_address;
 
-       /* No zero-length symlinks/dirs. */
-       if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
-               return __this_address;
+       /*
+        * No zero-length symlinks/dirs unless they're unlinked and hence being
+        * inactivated.
+        */
+       if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0) {
+               if (dip->di_version > 1) {
+                       if (dip->di_nlink)
+                               return __this_address;
+               } else {
+                       if (dip->di_onlink)
+                               return __this_address;
+               }
+       }
 
        fa = xfs_dinode_verify_nrext64(mp, dip);
        if (fa)