summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2016-03-15 22:11:23 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2016-03-15 22:20:16 +0000
commit644273dc7cbf14a9d85099c3f9e954c14578ab07 (patch)
treedba4a1d07bca918aca923727d33ca3d4ceffeba2 /usr/src/uts/common
parente4d4570cd8291930d8ee472a0be3a723b25896a2 (diff)
downloadillumos-joyent-644273dc7cbf14a9d85099c3f9e954c14578ab07.tar.gz
OS-5248 lxbrand stat(2) does not properly mangle st_dev
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_stat.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_stat.c b/usr/src/uts/common/brand/lx/syscall/lx_stat.c
index 0ed50efb53..3eca84529f 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_stat.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_stat.c
@@ -28,6 +28,7 @@
#include <sys/lx_types.h>
#include <sys/lx_impl.h>
#include <sys/brand.h>
+#include <sys/ddi.h>
/* From "uts/common/syscall/stat.c" */
extern int cstatat_getvp(int, char *, int, vnode_t **, cred_t **);
@@ -109,6 +110,22 @@ typedef enum lx_stat_fmt {
LXF_STAT64_64
} lx_stat_fmt_t;
+static dev_t
+lx_makedevice(major_t maj, minor_t minor)
+{
+ /*
+ * Linux mangles major/minor numbers into dev_t differently than SunOS.
+ */
+#ifdef _LP64
+ return ((minor & 0xff) | ((maj & 0xfff) << 8) |
+ ((uint64_t)(minor & ~0xff) << 12) |
+ ((uint64_t)(maj & ~0xfff) << 32));
+#else
+ return ((minor & 0xff) | ((maj & 0xfff) << 8) |
+ ((minor & ~0xff) << 12));
+#endif
+}
+
static void
lx_stat_xlate_dev(vattr_t *vattr)
{
@@ -116,14 +133,18 @@ lx_stat_xlate_dev(vattr_t *vattr)
dev_t dev = vattr->va_fsid;
lx_virt_disk_t *vd;
+ /* Substitute emulated major/minor on mounted datasets */
vd = list_head(lxzd->lxzd_vdisks);
while (vd != NULL) {
if (vd->lxvd_real_dev == dev) {
- vattr->va_fsid = vd->lxvd_emul_dev;
- return;
+ dev = vd->lxvd_emul_dev;
+ break;
}
vd = list_next(lxzd->lxzd_vdisks, vd);
}
+
+ /* Mangle st_dev into expected format */
+ vattr->va_fsid = lx_makedevice(getmajor(dev), getminor(dev));
}
static long