# HG changeset patch # User Matthew Ahrens # Date 1348493842 25200 # Node ID eea81edc4f143dae73cdbc4e65972d06de371b59 # Parent 58bc6f85b7997e6fe5c0e0c1a52d4a1779664e54 3208 moving zpool cross-endian results in incorrect user/group accounting Reviewed by: Adam Leventhal Reviewed by: Christopher Siden Approved by: Richard Lowe diff -r 58bc6f85b799 -r eea81edc4f14 usr/src/uts/common/fs/zfs/sys/sa_impl.h --- a/usr/src/uts/common/fs/zfs/sys/sa_impl.h Sun Jul 22 16:03:46 2012 -0400 +++ b/usr/src/uts/common/fs/zfs/sys/sa_impl.h Mon Sep 24 06:37:22 2012 -0700 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_SA_IMPL_H @@ -181,7 +182,7 @@ */ #define SA_HDR_LAYOUT_NUM(hdr) BF32_GET(hdr->sa_layout_info, 0, 10) -#define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0) +#define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 6, 3, 0) #define SA_HDR_LAYOUT_INFO_ENCODE(x, num, size) \ { \ BF32_SET_SB(x, 10, 6, 3, 0, size); \ diff -r 58bc6f85b799 -r eea81edc4f14 usr/src/uts/common/fs/zfs/zfs_vfsops.c --- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c Sun Jul 22 16:03:46 2012 -0400 +++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c Mon Sep 24 06:37:22 2012 -0700 @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -63,7 +64,6 @@ #include #include #include -#include #include "zfs_comutil.h" int zfsfstype; @@ -577,7 +577,6 @@ zfs_space_delta_cb(dmu_object_type_t bonustype, void *data, uint64_t *userp, uint64_t *groupp) { - znode_phys_t *znp = data; int error = 0; /* @@ -596,20 +595,18 @@ return (EEXIST); if (bonustype == DMU_OT_ZNODE) { + znode_phys_t *znp = data; *userp = znp->zp_uid; *groupp = znp->zp_gid; } else { int hdrsize; + sa_hdr_phys_t *sap = data; + sa_hdr_phys_t sa = *sap; + boolean_t swap = B_FALSE; ASSERT(bonustype == DMU_OT_SA); - hdrsize = sa_hdrsize(data); - if (hdrsize != 0) { - *userp = *((uint64_t *)((uintptr_t)data + hdrsize + - SA_UID_OFFSET)); - *groupp = *((uint64_t *)((uintptr_t)data + hdrsize + - SA_GID_OFFSET)); - } else { + if (sa.sa_magic == 0) { /* * This should only happen for newly created * files that haven't had the znode data filled @@ -617,6 +614,25 @@ */ *userp = 0; *groupp = 0; + return (0); + } + if (sa.sa_magic == BSWAP_32(SA_MAGIC)) { + sa.sa_magic = SA_MAGIC; + sa.sa_layout_info = BSWAP_16(sa.sa_layout_info); + swap = B_TRUE; + } else { + VERIFY3U(sa.sa_magic, ==, SA_MAGIC); + } + + hdrsize = sa_hdrsize(&sa); + VERIFY3U(hdrsize, >=, sizeof (sa_hdr_phys_t)); + *userp = *((uint64_t *)((uintptr_t)data + hdrsize + + SA_UID_OFFSET)); + *groupp = *((uint64_t *)((uintptr_t)data + hdrsize + + SA_GID_OFFSET)); + if (swap) { + *userp = BSWAP_64(*userp); + *groupp = BSWAP_64(*groupp); } } return (error);