xfs_attr3_leaf_hdr_size(leaf);
}
+static inline bool
+ichdr_freemaps_overlap(
+ const struct xfs_attr3_icleaf_hdr *ichdr,
+ unsigned int x,
+ unsigned int y)
+{
+ const unsigned int xend =
+ ichdr->freemap[x].base + ichdr->freemap[x].size;
+ const unsigned int yend =
+ ichdr->freemap[y].base + ichdr->freemap[y].size;
+
+ /* empty slots do not overlap */
+ if (!ichdr->freemap[x].size || !ichdr->freemap[y].size)
+ return false;
+
+ return ichdr->freemap[x].base < yend && xend > ichdr->freemap[y].base;
+}
+
+static inline xfs_failaddr_t
+xfs_attr_leaf_ichdr_freemaps_verify(
+ const struct xfs_attr3_icleaf_hdr *ichdr,
+ const struct xfs_attr_leafblock *leaf)
+{
+ unsigned int entries_end =
+ xfs_attr_leaf_entries_end(ichdr->count, leaf);
+ int i;
+
+ if (ichdr_freemaps_overlap(ichdr, 0, 1))
+ return __this_address;
+ if (ichdr_freemaps_overlap(ichdr, 0, 2))
+ return __this_address;
+ if (ichdr_freemaps_overlap(ichdr, 1, 2))
+ return __this_address;
+
+ for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
+ if (ichdr->freemap[i].size > 0 &&
+ ichdr->freemap[i].base < entries_end)
+ return __this_address;
+ }
+
+ return NULL;
+}
+
/*
* attr3 block 'firstused' conversion helpers.
*
hdr3->freemap[i].base = cpu_to_be16(from->freemap[i].base);
hdr3->freemap[i].size = cpu_to_be16(from->freemap[i].size);
}
+
+ ASSERT(xfs_attr_leaf_ichdr_freemaps_verify(from, to) == NULL);
return;
}
to->hdr.info.forw = cpu_to_be32(from->forw);
to->hdr.freemap[i].base = cpu_to_be16(from->freemap[i].base);
to->hdr.freemap[i].size = cpu_to_be16(from->freemap[i].size);
}
+
+ ASSERT(xfs_attr_leaf_ichdr_freemaps_verify(from, to) == NULL);
}
static xfs_failaddr_t
return __this_address;
}
+ fa = xfs_attr_leaf_ichdr_freemaps_verify(&ichdr, leaf);
+ if (fa)
+ return fa;
+
return NULL;
}
ichdr_dst->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_src);
ichdr_dst->freemap[0].size = ichdr_dst->firstused -
ichdr_dst->freemap[0].base;
+ ichdr_dst->freemap[1].base = 0;
+ ichdr_dst->freemap[2].base = 0;
+ ichdr_dst->freemap[1].size = 0;
+ ichdr_dst->freemap[2].size = 0;
/* write the header back to initialise the underlying buffer */
xfs_attr3_leaf_hdr_to_disk(args->geo, leaf_dst, ichdr_dst);