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