NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/47879: vnd cannot handle disk image larger than 2TiB
The following reply was made to PR kern/47879; it has been noted by GNATS.
From: Takahiro HAYASHI <t-hash%abox3.so-net.ne.jp@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: gnats-admin%NetBSD.org@localhost, kern-bug-people%NetBSD.org@localhost,
netbsd-bugs%NetBSD.org@localhost
Subject: Re: kern/47879: vnd cannot handle disk image larger than 2TiB
Date: Sun, 15 Sep 2013 20:48:47 +0900
About this problem on netbsd-5.
netbsd-5 has same problem and the patch for netbsd-6 can be applied
to netbsd-5 to fix kernel.
But vnconfig(8) shows incorrent value (realsize % 2^32) even on
patched kernel if configured vnd size > 2GiB because typeof vnd_size
in struct vnd_ioctl is signed int.
To fix this, rename old structure, add 64bit version of vnd_size
to new struct vnd_ioctl and modify sys/dev/vnd.c and usr.sbin/vnconfig
to use new structure like netbsd-6 or later do.
However it includes COMPAT_50 part.
Folowing patch works, but i'm not sure this is acceptable.
Index: src/sys/dev/vnd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/vnd.c,v
retrieving revision 1.187.4.6
diff -u -p -r1.187.4.6 vnd.c
--- src/sys/dev/vnd.c 22 Aug 2012 20:29:20 -0000 1.187.4.6
+++ src/sys/dev/vnd.c 15 Sep 2013 10:59:04 -0000
@@ -128,6 +128,9 @@
*
* NOTE 3: Doesn't interact with leases, should it?
*/
+#ifndef COMPAT_50
+#define COMPAT_50 /* XXX */
+#endif
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.187.4.6 2012/08/22 20:29:20 bouyer Exp
$");
@@ -1000,7 +1002,10 @@ vndioctl(dev_t dev, u_long cmd, void *da
vnd = device_lookup_private(&vnd_cd, unit);
if (vnd == NULL &&
#ifdef COMPAT_30
- cmd != VNDIOOCGET &&
+ cmd != VNDIOCGET30 &&
+#endif
+#ifdef COMPAT_50
+ cmd != VNDIOCGET50 &&
#endif
cmd != VNDIOCGET)
return ENXIO;
@@ -1010,6 +1015,10 @@ vndioctl(dev_t dev, u_long cmd, void *da
switch (cmd) {
case VNDIOCSET:
case VNDIOCCLR:
+#ifdef COMPAT_50
+ case VNDIOCSET50:
+ case VNDIOCCLR50:
+#endif
case DIOCSDINFO:
case DIOCWDINFO:
#ifdef __HAVE_OLD_DISKLABEL
@@ -1025,6 +1034,9 @@ vndioctl(dev_t dev, u_long cmd, void *da
/* Must be initialized for these... */
switch (cmd) {
case VNDIOCCLR:
+#ifdef VNDIOCCLR50
+ case VNDIOCCLR50:
+#endif
case DIOCGDINFO:
case DIOCSDINFO:
case DIOCWDINFO:
@@ -1044,6 +1056,9 @@ vndioctl(dev_t dev, u_long cmd, void *da
}
switch (cmd) {
+#ifdef VNDIOCSET50
+ case VNDIOCSET50:
+#endif
case VNDIOCSET:
if (vnd->sc_flags & VNF_INITED)
return (EBUSY);
@@ -1248,7 +1264,11 @@ vndioctl(dev_t dev, u_long cmd, void *da
goto close_and_exit;
vndthrottle(vnd, vnd->sc_vp);
- vio->vnd_size = dbtob(vnd->sc_size);
+ vio->vnd_osize = dbtob(vnd->sc_size);
+#ifdef VNDIOCSET50
+ if (cmd != VNDIOCSET50)
+#endif
+ vio->vnd_size = dbtob(vnd->sc_size);
vnd->sc_flags |= VNF_INITED;
/* create the kernel thread, wait for it to be up */
@@ -1312,6 +1332,9 @@ unlock_and_exit:
vndunlock(vnd);
return (error);
+#ifdef VNDIOCCLR50
+ case VNDIOCCLR50:
+#endif
case VNDIOCCLR:
if ((error = vndlock(vnd)) != 0)
return (error);
@@ -1351,10 +1374,10 @@ unlock_and_exit:
break;
#ifdef COMPAT_30
- case VNDIOOCGET: {
- struct vnd_ouser *vnu;
+ case VNDIOCGET30: {
+ struct vnd_user30 *vnu;
struct vattr va;
- vnu = (struct vnd_ouser *)data;
+ vnu = (struct vnd_user30 *)data;
KASSERT(l);
switch (error = vnd_cget(l, unit, &vnu->vnu_unit, &va)) {
case 0:
@@ -1372,6 +1395,16 @@ unlock_and_exit:
break;
}
#endif
+
+#if 0
+#ifdef COMPAT_50
+ /*
+ * on netbsd-5 vnd_user50 is actually vnd_user because
+ * dev_t is still uint32_t, so VNDIOCGET50 is VNDIOCGET.
+ */
+ case VNDIOCGET50:
+#endif
+#endif
case VNDIOCGET: {
struct vnd_user *vnu;
struct vattr va;
@@ -1956,7 +1989,7 @@ vnd_set_properties(struct vnd_softc *vnd
geom = prop_dictionary_create();
prop_dictionary_set_uint64(geom, "sectors-per-unit",
- vnd->sc_geom.vng_nsectors * vnd->sc_geom.vng_ntracks *
+ (uint64_t)vnd->sc_geom.vng_nsectors * vnd->sc_geom.vng_ntracks *
vnd->sc_geom.vng_ncylinders);
prop_dictionary_set_uint32(geom, "sector-size",
Index: src/sys/dev/vndvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/vndvar.h,v
retrieving revision 1.23.10.1
diff -u -p -r1.23.10.1 vndvar.h
--- src/sys/dev/vndvar.h 31 Dec 2011 22:11:12 -0000 1.23.10.1
+++ src/sys/dev/vndvar.h 15 Sep 2013 10:59:04 -0000
@@ -105,6 +105,8 @@
*
* @(#)vnioctl.h 8.1 (Berkeley) 6/10/93
*/
+#ifndef _SYS_DEV_VNDVAR_H_
+#define _SYS_DEV_VNDVAR_H_
#include <sys/pool.h>
@@ -125,7 +127,8 @@ struct vnd_ioctl {
char *vnd_file; /* pathname of file to mount */
int vnd_flags; /* flags; see below */
struct vndgeom vnd_geom; /* geometry to emulate */
- int vnd_size; /* (returned) size of disk */
+ unsigned int vnd_osize; /* (returned) size of disk */
+ uint64_t vnd_size; /* (returned) size of disk */
};
/* vnd_flags */
@@ -143,7 +146,7 @@ struct vnode;
struct vnd_softc {
device_t sc_dev;
int sc_flags; /* flags */
- size_t sc_size; /* size of vnd */
+ uint64_t sc_size; /* size of vnd */
struct vnode *sc_vp; /* vnode */
kauth_cred_t sc_cred; /* credentials */
int sc_maxactive; /* max # of active requests */
@@ -189,14 +192,6 @@ struct vnd_comp_header
/*
* A simple structure for describing which vnd units are in use.
*/
-#ifdef COMPAT_30
-struct vnd_ouser {
- int vnu_unit; /* which vnd unit */
- dev_t vnu_dev; /* file is on this device... */
- uint32_t vnu_ino; /* ...at this inode */
-};
-#define VNDIOOCGET _IOWR('F', 2, struct vnd_ouser) /* get list */
-#endif
struct vnd_user {
int vnu_unit; /* which vnd unit */
@@ -213,3 +208,38 @@ struct vnd_user {
#define VNDIOCSET _IOWR('F', 0, struct vnd_ioctl) /* enable disk */
#define VNDIOCCLR _IOW('F', 1, struct vnd_ioctl) /* disable disk */
#define VNDIOCGET _IOWR('F', 3, struct vnd_user) /* get list */
+
+#ifdef _KERNEL
+/*
+ * Everything else is kernel-private, mostly exported for compat/netbsd32.
+ *
+ * NetBSD 3.0 had a 32-bit value for vnu_ino.
+ *
+ * NetBSD 5.0 had a 32-bit value for vnu_dev, and vnd_size.
+ */
+struct vnd_user30 {
+ int vnu_unit; /* which vnd unit */
+ uint32_t vnu_dev; /* file is on this device... */
+ uint32_t vnu_ino; /* ...at this inode */
+};
+#define VNDIOCGET30 _IOWR('F', 2, struct vnd_user30) /* get list */
+
+struct vnd_user50 {
+ int vnu_unit; /* which vnd unit */
+ uint32_t vnu_dev; /* file is on this device... */
+ ino_t vnu_ino; /* ...at this inode */
+};
+#define VNDIOCGET50 _IOWR('F', 3, struct vnd_user50) /* get list */
+
+struct vnd_ioctl50 {
+ char *vnd_file; /* pathname of file to mount */
+ int vnd_flags; /* flags; see below */
+ struct vndgeom vnd_geom; /* geometry to emulate */
+ unsigned int vnd_size; /* (returned) size of disk */
+};
+#define VNDIOCSET50 _IOWR('F', 0, struct vnd_ioctl50)
+#define VNDIOCCLR50 _IOW('F', 1, struct vnd_ioctl50)
+
+#endif /* _KERNEL */
+
+#endif /* _SYS_DEV_VNDVAR_H_ */
Index: src/usr.sbin/vnconfig/vnconfig.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/vnconfig/vnconfig.c,v
retrieving revision 1.35
diff -u -p -r1.35 vnconfig.c
--- src/usr.sbin/vnconfig/vnconfig.c 28 Apr 2008 20:24:17 -0000 1.35
+++ src/usr.sbin/vnconfig/vnconfig.c 15 Sep 2013 11:02:20 -0000
@@ -325,6 +325,10 @@ config(dev, file, geom, action)
if (force)
vndio.vnd_flags |= VNDIOF_FORCE;
rv = ioctl(fd, VNDIOCCLR, &vndio);
+#ifdef VNDIOOCCLR
+ if (rv && errno == ENOTTY)
+ rv = ioctl(fd, VNDIOOCCLR, &vndio);
+#endif
if (rv)
warn("%s: VNDIOCCLR", rdev);
else if (verbose)
@@ -343,10 +347,16 @@ config(dev, file, geom, action)
(void) close(ffd);
rv = ioctl(fd, VNDIOCSET, &vndio);
+#ifdef VNDIOOCSET
+ if (rv && errno == ENOTTY) {
+ rv = ioctl(fd, VNDIOOCSET, &vndio);
+ vndio.vnd_size = vndio.vnd_osize;
+ }
+#endif
if (rv)
warn("%s: VNDIOCSET", rdev);
else if (verbose) {
- printf("%s: %d bytes on %s", rdev,
+ printf("%s: %" PRIu64 " bytes on %s", rdev,
vndio.vnd_size, file);
if (vndio.vnd_flags & VNDIOF_HASGEOM)
printf(" using geometry %d/%d/%d/%d",
--
t-hash
Home |
Main Index |
Thread Index |
Old Index