diff options
author | Matthew Ahrens <[email protected]> | 2013-01-14 09:31:53 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2013-01-14 09:32:22 -0800 |
commit | a94addd9749e8272664a2476460e75829626a465 (patch) | |
tree | 98dfe99d487dc9343bc7ed528397e65eec36550e /module/zfs/zfs_vfsops.c | |
parent | e6f7d015028a21d81d9f119928221c69d03c95be (diff) |
Illumos #3208 cross-endian incorrect user/group accounting
3208 moving zpool cross-endian results in incorrect user/group
accounting
Reviewed by: Adam Leventhal <[email protected]>
Reviewed by: Christopher Siden <[email protected]>
Approved by: Richard Lowe <[email protected]>
References:
illumos/illumos-gate@e828a46d29ad418487f50d56b5c19e2a1f9033a7
illumos changeset: 13835:eea81edc4f14
https://www.illumos.org/issues/3208
Ported-by: Brian Behlendorf <[email protected]>
Closes #627
Closes #1136
Diffstat (limited to 'module/zfs/zfs_vfsops.c')
-rw-r--r-- | module/zfs/zfs_vfsops.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c index 175dca821..fc5c2ba39 100644 --- a/module/zfs/zfs_vfsops.c +++ b/module/zfs/zfs_vfsops.c @@ -49,6 +49,7 @@ #include <sys/spa.h> #include <sys/zap.h> #include <sys/sa.h> +#include <sys/sa_impl.h> #include <sys/varargs.h> #include <sys/policy.h> #include <sys/atomic.h> @@ -63,7 +64,6 @@ #include <sys/dnlc.h> #include <sys/dmu_objset.h> #include <sys/spa_boot.h> -#include <sys/sa.h> #include <sys/zpl.h> #include "zfs_comutil.h" @@ -300,7 +300,6 @@ static int 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; /* @@ -319,20 +318,18 @@ zfs_space_delta_cb(dmu_object_type_t bonustype, void *data, 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 @@ -340,6 +337,25 @@ zfs_space_delta_cb(dmu_object_type_t bonustype, void *data, */ *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); |