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



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