[REVIEW] Fix unaligned accesses in IA64 in xfsprogs

Barry Naujok bnaujok at sgi.com
Mon Dec 1 00:34:39 CST 2008


xfs_repair is the main culprit when getting disk extents which aren't
properly aligned in memory. This patch does not call
xfs_bmbt_disk_get_all directly anymore but does an unaligned get on
the disk extent record and calls xfs_bmbt_get_all which is host-based
like the rest of the kernel routines do.

===========================================================================
xfsprogs/db/bmap.c
===========================================================================

--- a/xfsprogs/db/bmap.c	2008-12-01 17:10:37.000000000 +1100
+++ b/xfsprogs/db/bmap.c	2008-12-01 17:03:17.956547706 +1100
@@ -277,21 +277,17 @@ convert_extent(
  	xfs_dfilblks_t		*cp,
  	int			*fp)
  {
-	xfs_bmbt_irec_t irec, *s = &irec;
-	xfs_bmbt_rec_t rpcopy, *p = &rpcopy;
+	xfs_bmbt_irec_t		irec;
+	xfs_bmbt_rec_host_t	rec;

-	memmove(&rpcopy, rp, sizeof(rpcopy));
-	libxfs_bmbt_disk_get_all(p, s);
-
-	if (s->br_state == XFS_EXT_UNWRITTEN) {
-		*fp = 1;
-	} else {
-		*fp = 0;
-	}
-
-	*op = s->br_startoff;
-	*sp = s->br_startblock;
-	*cp = s->br_blockcount;
+	rec.l0 = get_unaligned_be64(&rp->l0);
+	rec.l1 = get_unaligned_be64(&rp->l1);
+	libxfs_bmbt_get_all(&rec, &irec);
+
+	*fp = irec.br_state == XFS_EXT_UNWRITTEN;
+	*op = irec.br_startoff;
+	*sp = irec.br_startblock;
+	*cp = irec.br_blockcount;
  }

  void

===========================================================================
xfsprogs/include/libxfs.h
===========================================================================

--- a/xfsprogs/include/libxfs.h	2008-12-01 17:10:37.000000000 +1100
+++ b/xfsprogs/include/libxfs.h	2008-12-01 16:45:05.941577400 +1100
@@ -502,7 +502,7 @@ xfs_bmbt_rec_host_t *xfs_bmap_search_ext
  #define libxfs_bunmapi			xfs_bunmapi

  /* xfs_bmap_btree.h */
-#define libxfs_bmbt_disk_get_all	xfs_bmbt_disk_get_all
+#define libxfs_bmbt_get_all		xfs_bmbt_get_all

  /* xfs_da_btree.h */
  #define libxfs_da_brelse		xfs_da_brelse

===========================================================================
xfsprogs/include/xfs_arch.h
===========================================================================

--- a/xfsprogs/include/xfs_arch.h	2008-12-01 17:10:37.000000000 +1100
+++ b/xfsprogs/include/xfs_arch.h	2008-12-01 17:06:38.819726283 +1100
@@ -71,6 +71,13 @@ static inline void be64_add_cpu(__be64 *
  	*a = cpu_to_be64(be64_to_cpu(*a) + b);
  }

+static inline __u64 get_unaligned_be64(void *ptr)
+{
+	__be64	__tmp;
+	memmove(&__tmp, ptr, 8);
+	return be64_to_cpu(__tmp);
+}
+
  #endif	/* __KERNEL__ */

  /* do we need conversion? */

===========================================================================
xfsprogs/libxfs/xfs.h
===========================================================================

--- a/xfsprogs/libxfs/xfs.h	2008-12-01 17:10:37.000000000 +1100
+++ b/xfsprogs/libxfs/xfs.h	2008-12-01 17:05:22.041221304 +1100
@@ -127,14 +127,6 @@ static inline int __do_div(unsigned long
  #define max_t(type,x,y) \
  	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })

-/* only 64 bit accesses used in xfs kernel code */
-static inline __u64 get_unaligned_be64(void *ptr)
-{
-	__be64	__tmp;
-	memmove(&__tmp, ptr, 8);
-	return be64_to_cpu(__tmp);
-}
-
  static inline void put_unaligned(__be64 val, void *ptr)
  {
  	memmove(ptr, &val, 8);

===========================================================================
xfsprogs/repair/dino_chunks.c
===========================================================================

--- a/xfsprogs/repair/dino_chunks.c	2008-12-01 17:10:37.000000000 +1100
+++ b/xfsprogs/repair/dino_chunks.c	2008-12-01 16:11:11.549834281 +1100
@@ -609,7 +609,8 @@ process_inode_chunk(
  	if (blks_per_cluster == 0)
  		blks_per_cluster = 1;
  	cluster_count = XFS_INODES_PER_CHUNK / inodes_per_cluster;
-	ASSERT(cluster_count > 0);
+	if (cluster_count == 0)
+		cluster_count = 1;

  	/*
  	 * get all blocks required to read in this chunk (may wind up

===========================================================================
xfsprogs/repair/dinode.c
===========================================================================

--- a/xfsprogs/repair/dinode.c	2008-12-01 17:10:37.000000000 +1100
+++ b/xfsprogs/repair/dinode.c	2008-12-01 17:03:40.217799833 +1100
@@ -460,10 +460,13 @@ get_bmbt_reclist(
  	xfs_dfiloff_t		fblock)
  {
  	int			i;
+	xfs_bmbt_rec_host_t	rec;
  	xfs_bmbt_irec_t 	irec;

-	for (i = 0; i < numrecs; i++) {
-		libxfs_bmbt_disk_get_all(rp + i, &irec);
+	for (i = 0; i < numrecs; i++, rp++) {
+		rec.l0 = get_unaligned_be64(&rp->l0);
+		rec.l1 = get_unaligned_be64(&rp->l1);
+		xfs_bmbt_get_all(&rec, &irec);
  		if (irec.br_startoff >= fblock &&
  				irec.br_startoff + irec.br_blockcount < fblock)
  			return (irec.br_startblock + fblock - irec.br_startoff);
@@ -612,6 +615,7 @@ process_bmbt_reclist_int(
  	int			whichfork)
  {
  	xfs_bmbt_irec_t		irec;
+	xfs_bmbt_rec_host_t	rec;
  	xfs_dfilblks_t		cp = 0;		/* prev count */
  	xfs_dfsbno_t		sp = 0;		/* prev start */
  	xfs_dfiloff_t		op = 0;		/* prev offset */
@@ -636,8 +640,10 @@ process_bmbt_reclist_int(
  	else
  		ftype = _("regular");

-	for (i = 0; i < numrecs; i++) {
-		libxfs_bmbt_disk_get_all(rp + i, &irec);
+	for (i = 0; i < numrecs; i++, rp++) {
+		rec.l0 = get_unaligned_be64(&rp->l0);
+		rec.l1 = get_unaligned_be64(&rp->l1);
+		libxfs_bmbt_get_all(&rec, &irec);
  		if (i == 0)
  			*last_key = *first_key = irec.br_startoff;
  		else
@@ -913,14 +919,17 @@ getfunc_extlist(xfs_mount_t		*mp,
  		int			whichfork)
  {
  	xfs_bmbt_irec_t		irec;
+	xfs_bmbt_rec_host_t	rec;
  	xfs_dfsbno_t		final_fsbno = NULLDFSBNO;
-	xfs_bmbt_rec_t		*rootblock = (xfs_bmbt_rec_t *)
+	xfs_bmbt_rec_t		*rp = (xfs_bmbt_rec_t *)
  						XFS_DFORK_PTR(dip, whichfork);
  	xfs_extnum_t		nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
  	int			i;

-	for (i = 0; i < nextents; i++)  {
-		libxfs_bmbt_disk_get_all(rootblock + i, &irec);
+	for (i = 0; i < nextents; i++, rp++)  {
+		rec.l0 = get_unaligned_be64(&rp->l0);
+		rec.l1 = get_unaligned_be64(&rp->l1);
+		libxfs_bmbt_get_all(&rec, &irec);
  		if (irec.br_startoff <= bno &&
  				bno < irec.br_startoff + irec.br_blockcount) {
  			final_fsbno = bno - irec.br_startoff + irec.br_startblock;
@@ -948,6 +957,7 @@ getfunc_btree(xfs_mount_t		*mp,
  	int			found;
  	int			numrecs;
  	xfs_bmbt_rec_t		*rec;
+	xfs_bmbt_rec_host_t	hrec;
  	xfs_bmbt_irec_t		irec;
  	xfs_bmbt_ptr_t		*pp;
  	xfs_bmbt_key_t		*key;
@@ -1072,8 +1082,10 @@ getfunc_btree(xfs_mount_t		*mp,
  			ino, numrecs, mp->m_bmap_dmnr[0]);

  	rec = XFS_BMBT_REC_ADDR(mp, block, 1);
-	for (i = 0; i < numrecs; i++)  {
-		libxfs_bmbt_disk_get_all(rec + i, &irec);
+	for (i = 0; i < numrecs; i++, rec++) {
+		hrec.l0 = get_unaligned_be64(&rec->l0);
+		hrec.l1 = get_unaligned_be64(&rec->l1);
+		libxfs_bmbt_get_all(&hrec, &irec);
  		if (irec.br_startoff <= bno &&
  				bno < irec.br_startoff + irec.br_blockcount) {
  			final_fsbno = bno - irec.br_startoff +
@@ -1387,6 +1399,7 @@ process_symlink_extlist(xfs_mount_t *mp,
  {
  	xfs_dfiloff_t		expected_offset;
  	xfs_bmbt_rec_t		*rp;
+	xfs_bmbt_rec_host_t	rec;
  	xfs_bmbt_irec_t		irec;
  	int			numrecs;
  	int			i;
@@ -1424,8 +1437,10 @@ process_symlink_extlist(xfs_mount_t *mp,
  	max_blocks = max_symlink_blocks;
  	expected_offset = 0;

-	for (i = 0; i < numrecs; i++)  {
-		libxfs_bmbt_disk_get_all(rp + i, &irec);
+	for (i = 0; i < numrecs; i++, rp++)  {
+		rec.l0 = get_unaligned_be64(&rp->l0);
+		rec.l1 = get_unaligned_be64(&rp->l1);
+		libxfs_bmbt_get_all(&rec, &irec);

  		if (irec.br_startoff != expected_offset)  {
  			do_warn(

===========================================================================
xfsprogs/repair/prefetch.c
===========================================================================

--- a/xfsprogs/repair/prefetch.c	2008-12-01 17:10:37.000000000 +1100
+++ b/xfsprogs/repair/prefetch.c	2008-12-01 17:03:46.972965840 +1100
@@ -170,12 +170,15 @@ pf_read_bmbt_reclist(
  	int			numrecs)
  {
  	int			i;
+	xfs_bmbt_rec_host_t	rec;
  	xfs_bmbt_irec_t		irec;
  	xfs_dfilblks_t		cp = 0;		/* prev count */
  	xfs_dfiloff_t		op = 0;		/* prev offset */

-	for (i = 0; i < numrecs; i++) {
-		libxfs_bmbt_disk_get_all(rp + i, &irec);
+	for (i = 0; i < numrecs; i++, rp++) {
+		rec.l0 = get_unaligned_be64(&rp->l0);
+		rec.l1 = get_unaligned_be64(&rp->l1);
+		libxfs_bmbt_get_all(&rec, &irec);

  		if (((i > 0) && (op + cp > irec.br_startoff)) ||
  				(irec.br_blockcount == 0) ||




More information about the xfs mailing list