summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authormarks <none@none>2006-04-17 08:08:54 -0700
committermarks <none@none>2006-04-17 08:08:54 -0700
commit72fc53bc90bd3b199d29d03ee68adb4a5a17d35b (patch)
treedafd5e6da6d67a2da1c39d2d25ab74be001f1d4f /usr/src
parent7cb42c7ebab29418f23e6bc16bd40cea6f303d10 (diff)
downloadillumos-gate-72fc53bc90bd3b199d29d03ee68adb4a5a17d35b.tar.gz
6408482 64-bit system can't read some 32-bit dev_ts created on zfs
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_znode.h1
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_replay.c9
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c2
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_znode.c62
4 files changed, 66 insertions, 8 deletions
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
index 4d069b5209..019eefb1a5 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
@@ -255,6 +255,7 @@ extern void zfs_delete_wait_empty(zfsvfs_t *zfsvfs);
extern void zfs_remove_op_tables();
extern int zfs_create_op_tables();
extern int zfs_sync(vfs_t *vfsp, short flag, cred_t *cr);
+extern dev_t zfs_cmpldev(uint64_t);
extern uint64_t zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, int txtype,
znode_t *dzp, znode_t *zp, char *name);
diff --git a/usr/src/uts/common/fs/zfs/zfs_replay.c b/usr/src/uts/common/fs/zfs/zfs_replay.c
index cd5a3848cb..85a681c3dc 100644
--- a/usr/src/uts/common/fs/zfs/zfs_replay.c
+++ b/usr/src/uts/common/fs/zfs/zfs_replay.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -65,7 +64,7 @@ zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode,
vap->va_mode = mode & MODEMASK;
vap->va_uid = (uid_t)uid;
vap->va_gid = (gid_t)gid;
- vap->va_rdev = (dev_t)rdev;
+ vap->va_rdev = zfs_cmpldev(rdev);
vap->va_nodeid = nodeid;
}
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index 67e886cac2..b4ec0fd662 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -1875,7 +1875,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
vap->va_nodeid = zp->z_id;
vap->va_nlink = MIN(pzp->zp_links, UINT32_MAX); /* nlink_t limit! */
vap->va_size = pzp->zp_size;
- vap->va_rdev = pzp->zp_rdev;
+ vap->va_rdev = vp->v_rdev;
vap->va_seq = zp->z_seq;
ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime);
diff --git a/usr/src/uts/common/fs/zfs/zfs_znode.c b/usr/src/uts/common/fs/zfs/zfs_znode.c
index 74e5c97cc5..15b23b5854 100644
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c
@@ -32,6 +32,7 @@
#include <sys/sysmacros.h>
#include <sys/resource.h>
#include <sys/mntent.h>
+#include <sys/mkdev.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/file.h>
@@ -327,6 +328,63 @@ zfs_init_fs(zfsvfs_t *zfsvfs, znode_t **zpp, cred_t *cr)
}
/*
+ * define a couple of values we need available
+ * for both 64 and 32 bit environments.
+ */
+#ifndef NBITSMINOR64
+#define NBITSMINOR64 32
+#endif
+#ifndef MAXMAJ64
+#define MAXMAJ64 0xffffffffUL
+#endif
+#ifndef MAXMIN64
+#define MAXMIN64 0xffffffffUL
+#endif
+
+/*
+ * Create special expldev for ZFS private use.
+ * Can't use standard expldev since it doesn't do
+ * what we want. The standard expldev() takes a
+ * dev32_t in LP64 and expands it to a long dev_t.
+ * We need an interface that takes a dev32_t in ILP32
+ * and expands it to a long dev_t.
+ */
+static uint64_t
+zfs_expldev(dev_t dev)
+{
+#ifndef _LP64
+ major_t major = (major_t)dev >> NBITSMINOR32 & MAXMAJ32;
+ return (((uint64_t)major << NBITSMINOR64) |
+ ((minor_t)dev & MAXMIN32));
+#else
+ return (dev);
+#endif
+}
+
+/*
+ * Special cmpldev for ZFS private use.
+ * Can't use standard cmpldev since it takes
+ * a long dev_t and compresses it to dev32_t in
+ * LP64. We need to do a compaction of a long dev_t
+ * to a dev32_t in ILP32.
+ */
+dev_t
+zfs_cmpldev(uint64_t dev)
+{
+#ifndef _LP64
+ minor_t minor = (minor_t)dev & MAXMIN64;
+ major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64;
+
+ if (major > MAXMAJ32 || minor > MAXMIN32)
+ return (NODEV32);
+
+ return (((dev32_t)major << NBITSMINOR32) | minor);
+#else
+ return (dev);
+#endif
+}
+
+/*
* Construct a new znode/vnode and intialize.
*
* This does not do a call to dmu_set_user() that is
@@ -377,7 +435,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, uint64_t obj_num, int blksz)
break;
case VBLK:
case VCHR:
- vp->v_rdev = (dev_t)zp->z_phys->zp_rdev;
+ vp->v_rdev = zfs_cmpldev(zp->z_phys->zp_rdev);
/*FALLTHROUGH*/
case VFIFO:
case VSOCK:
@@ -528,7 +586,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, uint64_t *oid, dmu_tx_t *tx, cred_t *cr,
flag |= IS_XATTR;
if (vap->va_type == VBLK || vap->va_type == VCHR) {
- pzp->zp_rdev = vap->va_rdev;
+ pzp->zp_rdev = zfs_expldev(vap->va_rdev);
}
if (vap->va_type == VDIR) {