Emulation of ZBC v2.0.

Emulation of ZBC v2.0.

--- lib/zbc_fake.c
+++ lib/zbc_fake.c
@@ -10,7 +10,10 @@
  * with libzbc. If not, see  <http://opensource.org/licenses/BSD-2-Clause>.
  *
  * Author: Christoph Hellwig (hch@infradead.org)
- */
+ *         Damien Le Moal (damien.lemoal@hgst.com)
+ */
+
+/***** Including files *****/

 #include <sys/types.h>
 #include <sys/mman.h>
@@ -28,147 +31,303 @@

 #include "zbc.h"

-struct zbc_fake_device {
-        struct zbc_device dev;
-	pthread_mutex_t mutex;
-        unsigned int zbd_nr_zones;
-        struct zbc_zone *zbd_zones;
-        int zbd_meta_fd;
-
-};
-
-static inline struct zbc_fake_device *to_file_dev(struct zbc_device *dev)
-{
-        return container_of(dev, struct zbc_fake_device, dev);
-}
-
+/***** Macro and types definitions *****/
+
+/**
+ * Logical and physical sector size for emulation on top of a regular file.
+ * For emulation on top of a raw disk, the disk logical and physical
+ * sector sizes are used.
+ */
+#define ZBC_FAKE_FILE_SECTOR_SIZE       512
+
+/**
+ * Maximum number of open zones (implicit + explicit).
+ */
+#define ZBC_FAKE_MAX_OPEN_NR_ZONES      32
+
+/**
+ * Metadata header.
+ */
+typedef struct zbc_fake_meta {
+
+    /**
+     * Capacity in B.
+     */
+    uint64_t            zbd_capacity;
+
+    /**
+     * Total number of zones.
+     */
+    uint32_t            zbd_nr_zones;
+
+    /**
+     * Number of conventional zones.
+     */
+    uint32_t            zbd_nr_conv_zones;
+
+    /**
+     * Number of sequential zones.
+     */
+    uint32_t            zbd_nr_seq_zones;
+
+    /**
+     * Number of explicitly open zones.
+     */
+    uint32_t            zbd_nr_exp_open_zones;
+
+    /**
+     * Number of implicitely open zones.
+     */
+    uint32_t            zbd_nr_imp_open_zones;
+
+    /**
+     * Padding.
+     */
+    uint8_t             __pad[4];
+
+} zbc_fake_meta_t;
+
+/**
+ * Fake device descriptor data.
+ */
+typedef struct zbc_fake_device {
+
+    struct zbc_device   dev;
+
+    pthread_mutex_t     mutex;
+
+    int                 zbd_meta_fd;
+    size_t              zbd_meta_size;
+    zbc_fake_meta_t     *zbd_meta;
+
+    uint32_t            zbd_nr_zones;
+    struct zbc_zone     *zbd_zones;
+
+} zbc_fake_device_t;
+
+/***** Definition of private functions *****/
+
+/**
+ * Convert device address to fake device address.
+ */
+static inline zbc_fake_device_t *
+zbc_fake_to_file_dev(struct zbc_device *dev)
+{
+    return container_of(dev, struct zbc_fake_device, dev);
+}
+
+/**
+ * Find a zone using its start LBA.
+ */
 static struct zbc_zone *
-zbf_fake_find_zone(struct zbc_fake_device *fdev, uint64_t zone_start_lba)
-{
-        unsigned int i;
-
-        for (i = 0; i < fdev->zbd_nr_zones; i++)
-                if (fdev->zbd_zones[i].zbz_start == zone_start_lba)
-                        return &fdev->zbd_zones[i];
-        return NULL;
-}
-
+zbf_fake_find_zone(zbc_fake_device_t *fdev,
+                   uint64_t zone_start_lba)
+{
+    unsigned int i;
+
+    if ( fdev->zbd_zones ) {
+        for(i = 0; i < fdev->zbd_nr_zones; i++) {
+            if ( fdev->zbd_zones[i].zbz_start == zone_start_lba ) {
+                return &fdev->zbd_zones[i];
+            }
+        }
+    }
+
+    return NULL;
+
+}
+
+/**
+ * Close metadata file of a fake device.
+ */
+static void
+zbc_fake_close_metadata(zbc_fake_device_t *fdev)
+{
+
+    if ( fdev->zbd_meta_fd > 0 ) {
+
+        if ( fdev->zbd_meta ) {
+            msync(fdev->zbd_meta, fdev->zbd_meta_size, MS_SYNC);
+            munmap(fdev->zbd_meta, fdev->zbd_meta_size);
+            fdev->zbd_meta = NULL;
+            fdev->zbd_nr_zones = 0;
+            fdev->zbd_zones = NULL;
+        }
+
+        close(fdev->zbd_meta_fd);
+        fdev->zbd_meta_fd = -1;
+
+    }
+
+    return;
+
+}
+
+/**
+ * Open metadata file of a fake device.
+ */
 static int
-zbc_fake_open_metadata(struct zbc_fake_device *fdev)
-{
-        char meta_path[512];
-        struct stat st;
-        int error;
-        int i;
-
-        sprintf(meta_path, "/tmp/zbc-%s.meta",
-                basename(fdev->dev.zbd_filename));
-
-        zbc_debug("Device %s: using meta file %s\n",
+zbc_fake_open_metadata(zbc_fake_device_t *fdev)
+{
+    char meta_path[512];
+    struct stat st;
+    unsigned int i;
+    int ret;
+
+    sprintf(meta_path, "/tmp/zbc-%s.meta",
+            basename(fdev->dev.zbd_filename));
+
+    zbc_debug("Device %s: using meta file %s\n",
+              fdev->dev.zbd_filename,
+              meta_path);
+
+    fdev->zbd_meta_fd = open(meta_path, O_RDWR);
+    if ( fdev->zbd_meta_fd < 0 ) {
+        /* Metadata does not exist yet, we'll have to wait for a set_zones call */
+        if ( errno == ENOENT ) {
+            return 0;
+        }
+        ret = -errno;
+        zbc_error("%s: open metadata file %s failed %d (%s)\n",
+                  fdev->dev.zbd_filename,
+                  meta_path,
+                  errno,
+                  strerror(errno));
+        goto out;
+    }
+
+    if ( fstat(fdev->zbd_meta_fd, &st) < 0 ) {
+        zbc_error("%s: fstat metadata file %s failed %d (%s)\n",
+                  fdev->dev.zbd_filename,
+                  meta_path,
+                  errno,
+                  strerror(errno));
+        ret = -errno;
+        goto out;
+    }
+
+    /* mmap metadata file */
+    fdev->zbd_meta_size = st.st_size;
+    fdev->zbd_meta = mmap(NULL,
+                          fdev->zbd_meta_size,
+                          PROT_READ | PROT_WRITE,
+                          MAP_SHARED,
+                          fdev->zbd_meta_fd,
+                          0);
+    if ( fdev->zbd_meta == MAP_FAILED ) {
+        fdev->zbd_meta = NULL;
+        zbc_error("%s: mmap metadata file %s failed\n",
                   fdev->dev.zbd_filename,
                   meta_path);
-
-        fdev->zbd_meta_fd = open(meta_path, O_RDWR);
-        if (fdev->zbd_meta_fd < 0) {
-                /*
-                 * Metadata didn't exist yet, we'll have to wait for a set_zones
-                 * call.
-                 */
-                if (errno == ENOENT)
-                        return 0;
-                perror("open metadata");
-                error = -errno;
-                goto out_close;
-        }
-
-        if (fstat(fdev->zbd_meta_fd, &st) < 0) {
-                perror("fstat");
-                error = -errno;
-                goto out_close;
-        }
-
-        fdev->zbd_zones = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE,
-                                MAP_SHARED, fdev->zbd_meta_fd, 0);
-        if (fdev->zbd_zones == MAP_FAILED) {
-                perror("mmap\n");
-                error = -ENOMEM;
-                goto out_close;
-        }
-
-        for (i = 0; fdev->zbd_zones[i].zbz_length != 0; i++)
-                ;
-
-        fdev->zbd_nr_zones = i;
-        return 0;
-out_close:
-        close(fdev->zbd_meta_fd);
-        return error;
-}
-
-/**
- * Default to regular sector size for emulation on top of a regular file.
- */
-#define ZBC_FAKE_SECTOR_SIZE    512
-
+        ret = -ENOMEM;
+        goto out;
+    }
+    fdev->zbd_nr_zones = fdev->zbd_meta->zbd_nr_zones;
+    fdev->zbd_zones = (struct zbc_zone *) (fdev->zbd_meta + 1);
+
+    /* Check */
+    if ( (fdev->zbd_meta->zbd_capacity != (fdev->dev.zbd_info.zbd_logical_block_size * fdev->dev.zbd_info.zbd_logical_blocks))
+         || (! fdev->zbd_meta->zbd_nr_zones) ) {
+        zbc_error("%s: invalid metadata file %s\n",
+                  fdev->dev.zbd_filename,
+                  meta_path);
+        ret = -EINVAL;
+        goto out;
+    }
+
+#if 0
+    /* Make sure all open zones are closed */
+    for(i = 0; i < fdev->zbd_nr_zones; i++) {
+        if ( zbc_zone_is_open(&fdev->zbd_zones[i]) ) {
+            fdev->zbd_zones[i].zbz_condition = ZBC_ZC_CLOSED;
+        }
+    }
+    fdev->zbd_meta->zbd_nr_exp_open_zones = 0;
+    fdev->zbd_meta->zbd_nr_imp_open_zones = 0;
+#endif
+
+    ret = 0;
+
+out:
+
+    if ( ret != 0 ) {
+        zbc_fake_close_metadata(fdev);
+    }
+
+    return ret;
+}
+
+/**
+ * Set a device info.
+ */
 static int
-zbc_fake_get_info(struct zbc_device *dev, struct stat *st)
-{
-
-    dev->zbd_info.zbd_logical_block_size = ZBC_FAKE_SECTOR_SIZE;
-    dev->zbd_info.zbd_logical_blocks = st->st_size / ZBC_FAKE_SECTOR_SIZE;
-    dev->zbd_info.zbd_physical_block_size = dev->zbd_info.zbd_logical_block_size;
-    dev->zbd_info.zbd_physical_blocks = dev->zbd_info.zbd_logical_blocks;
-
-    strncpy(dev->zbd_info.zbd_vendor_id, "FAKE HGST HM libzbc", ZBC_DEVICE_INFO_LENGTH - 1);
-
-    return( 0 );
-
-}
-
-/**
- * Get a block device information (capacity & sector sizes).
- */
-static int
-zbc_blkdev_get_info(zbc_device_t *dev)
+zbc_fake_set_info(struct zbc_device *dev)
 {
     unsigned long long size64;
+    struct stat st;
     int size32;
     int ret;

-    /* Get logical block size */
-    ret = ioctl(dev->zbd_fd, BLKSSZGET, &size32);
-    if ( ret != 0 ) {
+    /* Get device stats */
+    if ( fstat(dev->zbd_fd, &st) < 0 ) {
         ret = -errno;
-        zbc_error("%s: ioctl BLKSSZGET failed %d (%s)\n",
+        zbc_error("%s: stat failed %d (%s)\n",
                   dev->zbd_filename,
                   errno,
                   strerror(errno));
-        goto out;
-    }
-
-    dev->zbd_info.zbd_logical_block_size = size32;
-
-    /* Get physical block size */
-    ret = ioctl(dev->zbd_fd, BLKPBSZGET, &size32);
-    if ( ret != 0 ) {
-        ret = -errno;
-        zbc_error("%s: ioctl BLKPBSZGET failed %d (%s)\n",
-                  dev->zbd_filename,
-                  errno,
-                  strerror(errno));
-        goto out;
-    }
-    dev->zbd_info.zbd_physical_block_size = size32;
-
-    /* Get capacity (B) */
-    ret = ioctl(dev->zbd_fd, BLKGETSIZE64, &size64);
-    if ( ret != 0 ) {
-        ret = -errno;
-        zbc_error("%s: ioctl BLKGETSIZE64 failed %d (%s)\n",
-                  dev->zbd_filename,
-                  errno,
-                  strerror(errno));
-        goto out;
+        return ret;
+    }
+
+    if ( S_ISBLK(st.st_mode) ) {
+
+        /* Get logical block size */
+        ret = ioctl(dev->zbd_fd, BLKSSZGET, &size32);
+        if ( ret != 0 ) {
+            ret = -errno;
+            zbc_error("%s: ioctl BLKSSZGET failed %d (%s)\n",
+                      dev->zbd_filename,
+                      errno,
+                      strerror(errno));
+            return ret;
+        }
+
+        dev->zbd_info.zbd_logical_block_size = size32;
+
+        /* Get physical block size */
+        ret = ioctl(dev->zbd_fd, BLKPBSZGET, &size32);
+        if ( ret != 0 ) {
+            ret = -errno;
+            zbc_error("%s: ioctl BLKPBSZGET failed %d (%s)\n",
+                      dev->zbd_filename,
+                      errno,
+                      strerror(errno));
+            return ret;
+        }
+        dev->zbd_info.zbd_physical_block_size = size32;
+
+        /* Get capacity (B) */
+        ret = ioctl(dev->zbd_fd, BLKGETSIZE64, &size64);
+        if ( ret != 0 ) {
+            ret = -errno;
+            zbc_error("%s: ioctl BLKGETSIZE64 failed %d (%s)\n",
+                      dev->zbd_filename,
+                      errno,
+                      strerror(errno));
+            return ret;
+        }
+
+    } else if ( S_ISREG(st.st_mode) ) {
+
+        /* Default value for files */
+        dev->zbd_info.zbd_logical_block_size = ZBC_FAKE_FILE_SECTOR_SIZE;
+        dev->zbd_info.zbd_logical_blocks = st.st_size / ZBC_FAKE_FILE_SECTOR_SIZE;
+        dev->zbd_info.zbd_physical_block_size = dev->zbd_info.zbd_logical_block_size;
+        dev->zbd_info.zbd_physical_blocks = dev->zbd_info.zbd_logical_blocks;
+
+    } else {
+
+        return -ENXIO;
+
     }

     /* Check */
@@ -176,586 +335,940 @@
         zbc_error("%s: invalid logical sector size %d\n",
                   dev->zbd_filename,
                   size32);
-        ret = -EINVAL;
-        goto out;
-    }
-
+        return -EINVAL;
+    }
+
     dev->zbd_info.zbd_logical_blocks = size64 / dev->zbd_info.zbd_logical_block_size;
     if ( ! dev->zbd_info.zbd_logical_blocks ) {
         zbc_error("%s: invalid capacity (logical blocks)\n",
                   dev->zbd_filename);
-        ret = -EINVAL;
-        goto out;
+        return -EINVAL;
     }

     if ( dev->zbd_info.zbd_physical_block_size <= 0 ) {
         zbc_error("%s: invalid physical sector size %d\n",
                   dev->zbd_filename,
                   size32);
-        ret = -EINVAL;
-        goto out;
+        return -EINVAL;
     }

     dev->zbd_info.zbd_physical_blocks = size64 / dev->zbd_info.zbd_physical_block_size;
     if ( ! dev->zbd_info.zbd_physical_blocks ) {
         zbc_error("%s: invalid capacity (physical blocks)\n",
                   dev->zbd_filename);
-        ret = -EINVAL;
-    }
+        return -EINVAL;
+    }
+
+    /* Finish setting */
+    dev->zbd_info.zbd_type = ZBC_DT_FAKE;
+    dev->zbd_info.zbd_model = ZBC_DM_HOST_MANAGED;
+    strncpy(dev->zbd_info.zbd_vendor_id, "FAKE HGST HM libzbc", ZBC_DEVICE_INFO_LENGTH - 1);
+
+    dev->zbd_info.zbd_opt_nr_open_seq_pref = 0;
+    dev->zbd_info.zbd_opt_nr_open_non_seq_write_seq_pref = 0;
+    dev->zbd_info.zbd_max_nr_open_seq_req = ZBC_FAKE_MAX_OPEN_NR_ZONES;
+
+    return 0;
+
+}
+
+/**
+ * Open an emulation device or file.
+ */
+static int
+zbc_fake_open(const char *filename,
+              int flags,
+              struct zbc_device **pdev)
+{
+    zbc_fake_device_t *fdev;
+    int fd, ret;
+
+    /* Open emulation device/file */
+    fd = open(filename, flags);
+    if ( fd < 0 ) {
+        ret = -errno;
+        zbc_error("%s: open failed %d (%s)\n",
+                  filename,
+                  errno,
+                  strerror(errno));
+        return ret;
+    }
+
+    /* ALlocate a handle */
+    ret = -ENOMEM;
+    fdev = calloc(1, sizeof(*fdev));
+    if ( ! fdev ) {
+        goto out;
+    }
+
+    fdev->dev.zbd_fd = fd;
+    fdev->zbd_meta_fd = -1;
+    fdev->dev.zbd_filename = strdup(filename);
+    if ( ! fdev->dev.zbd_filename ) {
+        goto out_free_dev;
+    }
+
+    /* Set the fake device information */
+    ret = zbc_fake_set_info(&fdev->dev);
+    if ( ret != 0 ) {
+        goto out_free_filename;
+    }
+
+    /* Open metadata */
+    ret = zbc_fake_open_metadata(fdev);
+    if ( ret ) {
+        goto out_free_filename;
+    }
+
+    pthread_mutex_init(&fdev->mutex, NULL);
+
+    *pdev = &fdev->dev;
+
+    return 0;
+
+out_free_filename:
+
+    free(fdev->dev.zbd_filename);
+
+out_free_dev:
+
+    free(fdev);

 out:

-    return( ret );
-
-}
-
-static int
-zbc_fake_open(const char *filename, int flags, struct zbc_device **pdev)
-{
-        struct zbc_fake_device *fdev;
-        struct stat st;
-        int fd, ret;
-
-        fd = open(filename, flags);
-        if (fd < 0) {
-                zbc_error("Open device file %s failed %d (%s)\n",
-                        filename,
-                        errno,
-                        strerror(errno));
-                return -errno;
-        }
-
-        if (fstat(fd, &st) < 0) {
-                zbc_error("Stat device %s failed %d (%s)\n",
-                        filename,
-                        errno,
-                        strerror(errno));
-                ret = -errno;
-                goto out;
-        }
-
-
-        /* Set device operation */
-        ret = -ENXIO;
-        if (!S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode))
-                goto out;
-
-        ret = -ENOMEM;
-        fdev = calloc(1, sizeof(*fdev));
-        if (!fdev)
-                goto out;
-
-        fdev->dev.zbd_fd = fd;
-        fdev->zbd_meta_fd = -1;
-        fdev->dev.zbd_filename = strdup(filename);
-        if (!fdev->dev.zbd_filename)
-                goto out_free_dev;
-
-        fdev->dev.zbd_info.zbd_type = ZBC_DT_FAKE;
-        fdev->dev.zbd_info.zbd_model = ZBC_DM_HOST_MANAGED;
-        if (S_ISBLK(st.st_mode))
-                ret = zbc_blkdev_get_info(&fdev->dev);
-        else
-                ret = zbc_fake_get_info(&fdev->dev, &st);
-
-        if (ret)
-                goto out_free_filename;
-
-        ret = zbc_fake_open_metadata(fdev);
-        if (ret)
-                goto out_free_filename;
-
-	pthread_mutex_init(&fdev->mutex, NULL);
-
-        *pdev = &fdev->dev;
-        return 0;
-
-out_free_filename:
-        free(fdev->dev.zbd_filename);
-out_free_dev:
-        free(fdev);
-out:
-        close(fd);
-        return ret;
-}
-
+    close(fd);
+
+    return ret;
+
+}
+
+/**
+ * close a device.
+ */
 static int
 zbc_fake_close(zbc_device_t *dev)
 {
-        struct zbc_fake_device *fdev = to_file_dev(dev);
-        int ret = 0;
-
-        if (fdev->zbd_meta_fd != -1) {
-                if (close(fdev->zbd_meta_fd) < 0)
-                        ret = -errno;
-        }
-        if (close(dev->zbd_fd) < 0) {
-                if (!ret)
-                        ret = -errno;
-        }
-
-        if (!ret) {
-                free(dev->zbd_filename);
-                free(dev);
-        }
-        return ret;
-}
-
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    int ret = 0;
+
+    /* CLose metadata */
+    zbc_fake_close_metadata(fdev);
+
+    /* Close device */
+    if ( close(dev->zbd_fd) < 0 ) {
+        ret = -errno;
+    }
+
+    if ( ret == 0 ) {
+        free(dev->zbd_filename);
+        free(dev);
+    }
+
+    return ret;
+
+}
+
+/**
+ * Test if a zone must be reported.
+ */
 static bool
-want_zone(struct zbc_zone *zone, uint64_t start_lba,
-                enum zbc_reporting_options options)
-{
-        if (zone->zbz_length == 0)
-                return false;
-        if (zone->zbz_start < start_lba)
-                return false;
-
-        switch (options) {
-        case ZBC_RO_ALL:
-                return true;
-        case ZBC_RO_EMPTY:
-                return zone->zbz_condition == ZBC_ZC_EMPTY;
-        case ZBC_RO_IMP_OPEN:
-                return zone->zbz_condition == ZBC_ZC_IMP_OPEN;
-        case ZBC_RO_EXP_OPEN:
-                return zone->zbz_condition == ZBC_ZC_EXP_OPEN;
-        case ZBC_RO_CLOSED:
-                return zone->zbz_condition == ZBC_ZC_CLOSED;
-        case ZBC_RO_FULL:
-                return zone->zbz_condition == ZBC_ZC_FULL;
-        case ZBC_RO_RDONLY:
-                return zone->zbz_condition == ZBC_ZC_RDONLY;
-        case ZBC_RO_OFFLINE:
-                return zone->zbz_condition == ZBC_ZC_OFFLINE;
-        case ZBC_RO_RESET:
-                return zbc_zone_need_reset(zone);
-        case ZBC_RO_NON_SEQ:
-                return zbc_zone_non_seq(zone);
-        case ZBC_RO_NOT_WP:
-                return zone->zbz_condition == ZBC_ZC_NOT_WP;
-        default:
-                return false;
-        }
-}
-
+zbc_fake_must_report_zone(struct zbc_zone *zone,
+                          uint64_t start_lba,
+                          enum zbc_reporting_options options)
+{
+
+    if ( (zbc_zone_length(zone) == 0)
+         || (zbc_zone_start_lba(zone) < start_lba) ) {
+        return false;
+    }
+
+    switch( options ) {
+    case ZBC_RO_ALL:
+        return true;
+    case ZBC_RO_EMPTY:
+        return zbc_zone_empty(zone);
+    case ZBC_RO_IMP_OPEN:
+        return zbc_zone_imp_open(zone);
+    case ZBC_RO_EXP_OPEN:
+        return zbc_zone_exp_open(zone);
+    case ZBC_RO_CLOSED:
+        return zbc_zone_closed(zone);
+    case ZBC_RO_FULL:
+        return zbc_zone_full(zone);
+    case ZBC_RO_RDONLY:
+        return zbc_zone_rdonly(zone);
+    case ZBC_RO_OFFLINE:
+        return zbc_zone_offline(zone);
+    case ZBC_RO_RESET:
+        return zbc_zone_need_reset(zone);
+    case ZBC_RO_NON_SEQ:
+        return zbc_zone_non_seq(zone);
+    case ZBC_RO_NOT_WP:
+        return zbc_zone_not_wp(zone);
+    }
+
+    return false;
+
+}
+
+/**
+ * Get device zone information.
+ */
 static int
-zbc_fake_nr_zones(struct zbc_fake_device *fdev, uint64_t start_lba,
-                  enum zbc_reporting_options options, unsigned int *nr_zones)
-{
-        unsigned int in, out;
-
-        out = 0;
-        for (in = 0; in < fdev->zbd_nr_zones; in++) {
-                if (want_zone(&fdev->zbd_zones[in], start_lba, options))
-                        out++;
-        }
-
-        *nr_zones = out;
-
-        return 0;
-
-}
-
+zbc_fake_report_zones(struct zbc_device *dev,
+                      uint64_t start_lba,
+                      enum zbc_reporting_options options,
+                      struct zbc_zone *zones,
+                      unsigned int *nr_zones)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    unsigned int max_nr_zones = *nr_zones;
+    unsigned int in, out = 0;
+
+    if ( ! fdev->zbd_meta ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    if ( ! zones ) {
+
+        /* Only get the number of matching zones */
+        for(in = 0; in < fdev->zbd_nr_zones; in++) {
+            if ( zbc_fake_must_report_zone(&fdev->zbd_zones[in], start_lba, options) ) {
+                out++;
+            }
+        }
+
+    } else {
+
+        /* Get matching zones */
+        for(in = 0; in < fdev->zbd_nr_zones; in++) {
+            if ( zbc_fake_must_report_zone(&fdev->zbd_zones[in], start_lba, options) ) {
+                memcpy(&zones[out], &fdev->zbd_zones[in], sizeof(struct zbc_zone));
+                if ( ++out == max_nr_zones ) {
+                    break;
+                }
+            }
+        }
+
+    }
+
+    *nr_zones = out;
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return 0;
+
+}
+
+/**
+ * Open zone(s).
+ */
 static int
-zbc_fake_report_zones(struct zbc_device *dev, uint64_t start_lba,
-                      enum zbc_reporting_options options, struct zbc_zone *zones,
-                      unsigned int *nr_zones)
-{
-        struct zbc_fake_device *fdev = to_file_dev(dev);
-        unsigned int max_nr_zones = *nr_zones;
-        unsigned int in, out;
-        int ret;
-
-        if (!fdev->zbd_zones)
-                return -ENXIO;
-
-	pthread_mutex_lock(&fdev->mutex);
-        if (!zones) {
-                ret = zbc_fake_nr_zones(fdev, start_lba, options, nr_zones);
-		goto out_unlock;
-	}
-
-        out = 0;
-        for (in = 0; in < fdev->zbd_nr_zones; in++) {
-                if (want_zone(&fdev->zbd_zones[in], start_lba, options)) {
-                        memcpy(&zones[out], &fdev->zbd_zones[in],
-                                sizeof(struct zbc_zone));
-                        if (++out == max_nr_zones)
-                                break;
-                }
-        }
-
-        *nr_zones = out;
-	ret = 0;
-
-out_unlock:
-
-	pthread_mutex_unlock(&fdev->mutex);
-
-        return ret;
-
-}
-
+zbc_fake_open_zone(zbc_device_t *dev,
+                   uint64_t start_lba)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    unsigned int i, open_count, need_close;
+    int ret = 0;
+
+    if ( ! fdev->zbd_meta ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    if ( start_lba == (uint64_t)-1 ) {
+
+        unsigned int need_open = 0;
+
+        /* Count how many zones can be open */
+        for(i = 0; i < fdev->zbd_nr_zones; i++) {
+            if ( zbc_zone_closed(&fdev->zbd_zones[i]) ) {
+                need_open++;
+            }
+        }
+
+        /* Check that all closed zones can be open */
+        if ( (need_open + fdev->zbd_meta->zbd_nr_exp_open_zones) > fdev->dev.zbd_info.zbd_max_nr_open_seq_req ) {
+            ret = -EBUSY;
+            goto out;
+        }
+
+        /* Open all closed zones */
+        for(i = 0; i < fdev->zbd_nr_zones; i++) {
+            if ( zbc_zone_closed(&fdev->zbd_zones[i]) ) {
+                fdev->zbd_zones[i].zbz_condition = ZBC_ZC_EXP_OPEN;
+            }
+        }
+        fdev->zbd_meta->zbd_nr_exp_open_zones += need_open;
+
+    } else {
+
+        struct zbc_zone *zone;
+
+        /* Check limit */
+        if ( (fdev->zbd_meta->zbd_nr_exp_open_zones + 1) > fdev->dev.zbd_info.zbd_max_nr_open_seq_req ) {
+            ret = -EBUSY;
+            goto out;
+        }
+
+        /* Open the specified zone */
+        zone = zbf_fake_find_zone(fdev, start_lba);
+        if ( zbc_zone_closed(zone)
+             || zbc_zone_imp_open(zone)
+             || zbc_zone_empty(zone) ) {
+            zone->zbz_condition = ZBC_ZC_EXP_OPEN;
+            fdev->zbd_meta->zbd_nr_exp_open_zones++;
+        } else {
+            ret = -EIO;
+        }
+
+    }
+
+    /* Close implicitely open zones */
+    open_count = fdev->zbd_meta->zbd_nr_imp_open_zones + fdev->zbd_meta->zbd_nr_exp_open_zones;
+    if ( open_count > fdev->dev.zbd_info.zbd_max_nr_open_seq_req ) {
+
+        need_close = open_count - fdev->dev.zbd_info.zbd_max_nr_open_seq_req;
+        for(i = 0; (i < fdev->zbd_nr_zones) && need_close; i++) {
+            if ( zbc_zone_imp_open(&fdev->zbd_zones[i]) ) {
+                fdev->zbd_zones[i].zbz_condition = ZBC_ZC_CLOSED;
+                need_close--;
+            }
+        }
+
+        if ( need_close ) {
+            zbc_error("%s: invalid implicit open zone count\n",
+                      fdev->dev.zbd_filename);
+            ret = -EINVAL;
+            goto out;
+        }
+
+        fdev->zbd_meta->zbd_nr_imp_open_zones -= need_close;
+
+    }
+
+out:
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;
+
+}
+
+/**
+ * Test if a zone can be closed.
+ */
+static bool
+zbc_zone_close_allowed(struct zbc_zone *zone)
+{
+
+    if ( zone && zbc_zone_sequential(zone) ) {
+        return zbc_zone_imp_open(zone)
+               || zbc_zone_exp_open(zone);
+    }
+
+    return false;
+
+}
+
+/**
+ * Close zone(s).
+ */
+static int
+zbc_fake_close_zone(zbc_device_t *dev,
+                    uint64_t start_lba)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    int ret = 0;
+
+    if ( ! fdev->zbd_zones ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    if ( start_lba == (uint64_t)-1 ) {
+
+        unsigned int i;
+
+        /* Close all open zones */
+        for(i = 0; i < fdev->zbd_nr_zones; i++) {
+            if ( zbc_zone_close_allowed(&fdev->zbd_zones[i]) ) {
+                fdev->zbd_zones[i].zbz_condition = ZBC_ZC_CLOSED;
+            }
+        }
+
+    } else {
+
+        struct zbc_zone *zone;
+
+        /* Close the specified zone */
+        zone = zbf_fake_find_zone(fdev, start_lba);
+        if ( zbc_zone_close_allowed(zone) ) {
+            zone->zbz_condition = ZBC_ZC_CLOSED;
+        } else {
+            ret = -EIO;
+        }
+
+    }
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;
+
+}
+
+/**
+ * Test if a zone can be finished.
+ */
+static bool
+zbc_zone_finish_allowed(struct zbc_zone *zone)
+{
+
+    if ( zone && zbc_zone_sequential(zone) ) {
+        return zbc_zone_imp_open(zone)
+               || zbc_zone_exp_open(zone)
+               || zbc_zone_closed(zone);
+    }
+
+    return false;
+
+}
+
+/**
+ * Finish zone(s).
+ */
+static int
+zbc_fake_finish_zone(zbc_device_t *dev,
+                     uint64_t start_lba)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    int ret = 0;
+
+    if ( ! fdev->zbd_zones ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    if ( start_lba == (uint64_t)-1 ) {
+
+        unsigned int i;
+
+        /* Finish all open and closed zones */
+        for(i = 0; i < fdev->zbd_nr_zones; i++) {
+            if ( zbc_zone_finish_allowed(&fdev->zbd_zones[i]) ) {
+                fdev->zbd_zones[i].zbz_write_pointer = (uint64_t)-1;
+                fdev->zbd_zones[i].zbz_condition = ZBC_ZC_FULL;
+            }
+        }
+
+    } else {
+
+        struct zbc_zone *zone;
+
+        /* Finish the specified zone */
+        zone = zbf_fake_find_zone(fdev, start_lba);
+        if ( zbc_zone_finish_allowed(zone) ) {
+            zone->zbz_write_pointer = (uint64_t)-1;
+            zone->zbz_condition = ZBC_ZC_FULL;
+        } else {
+            ret = -EIO;
+        }
+
+    }
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;
+
+}
+
+/**
+ * Test if a zone write pointer can be reset.
+ */
 static bool
 zbc_zone_reset_allowed(struct zbc_zone *zone)
 {
-        switch (zone->zbz_type) {
-        case ZBC_ZT_SEQUENTIAL_REQ:
-        case ZBC_ZT_SEQUENTIAL_PREF:
-                return zone->zbz_condition == ZBC_ZC_CLOSED ||
-                        zone->zbz_condition == ZBC_ZC_FULL;
-        default:
-                return false;
-        }
-}
-
+
+    if ( zone && zbc_zone_sequential(zone) ) {
+        return zbc_zone_imp_open(zone)
+               || zbc_zone_exp_open(zone)
+               || zbc_zone_closed(zone)
+               || zbc_zone_full(zone);
+    }
+
+    return false;
+
+}
+
+/**
+ * Reset zone(s) write pointer.
+ */
 static int
-zbc_fake_reset_one_write_pointer(struct zbc_zone *zone)
-{
-        if (!zbc_zone_reset_allowed(zone))
-                return -EINVAL;
+zbc_fake_reset_wp(struct zbc_device *dev,
+                  uint64_t start_lba)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    int ret = 0;
+
+    if ( ! fdev->zbd_zones ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    if ( start_lba == (uint64_t)-1 ) {
+
+        unsigned int i;
+
+        /* Reset all open, closed and full zones */
+        for(i = 0; i < fdev->zbd_nr_zones; i++) {
+            if ( zbc_zone_reset_allowed(&fdev->zbd_zones[i]) ) {
+                zbc_zone_wp_lba_reset(&fdev->zbd_zones[i]);
+            }
+        }
+
+    } else {
+
+        struct zbc_zone *zone;
+
+        /* Reset the specified zone */
+        zone = zbf_fake_find_zone(fdev, start_lba);
+        if ( zbc_zone_reset_allowed(zone) ) {
+            zbc_zone_wp_lba_reset(zone);
+        } else {
+            ret = -EIO;
+        }
+
+    }
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;
+
+}
+
+/**
+ * Read from the emulated device/file.
+ */
+static int32_t
+zbc_fake_pread(struct zbc_device *dev,
+               struct zbc_zone *z,
+               void *buf,
+               uint32_t lba_count,
+               uint64_t start_lba)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    struct zbc_zone *zone;
+    ssize_t ret = -EIO;
+    off_t offset;
+    size_t count;
+
+    if ( ! fdev->zbd_meta ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    /* Find the target zone */
+    zone = zbf_fake_find_zone(fdev, zbc_zone_start_lba(z));
+    if ( ! zone ) {
+        goto out;
+    }
+
+    if ( start_lba > zbc_zone_length(zone) ) {
+        goto out;
+    }
+
+    start_lba += zbc_zone_start_lba(zone);
+
+    /* Note: unrestricted read will be added to the standard */
+    /* and supported by a drive if the URSWRZ bit is set in  */
+    /* VPD page. So this test will need to change.           */
+    if ( zone->zbz_type == ZBC_ZT_SEQUENTIAL_REQ ) {
+
+        /* Cannot read unwritten data */
+        if ( (start_lba + lba_count) > zbc_zone_wp_lba(zone) ) {
+            goto out;
+        }
+
+    } else {
+
+        /* Reads spanning other types of zones are OK. */
+        uint64_t lba = zbc_zone_next_lba(zone);
+
+        if ( (start_lba + lba_count) > lba ) {
+
+            uint64_t count = start_lba + lba_count - lba;
+            struct zbc_zone *next_zone = zone;
+
+            while( count && (next_zone = zbf_fake_find_zone(fdev, lba)) ) {
+                if ( zbc_zone_sequential_req(next_zone) ) {
+                    goto out;
+                }
+                if ( count > zbc_zone_length(next_zone) ) {
+                    count -= zbc_zone_length(next_zone);
+                }
+                lba += zbc_zone_length(next_zone);
+            }
+
+        }
+
+    }
+
+    /* XXX: check for overflows */
+    count = lba_count * dev->zbd_info.zbd_logical_block_size;
+    offset = start_lba * dev->zbd_info.zbd_logical_block_size;
+
+    ret = pread(dev->zbd_fd, buf, count, offset);
+    if ( ret < 0 ) {
+        ret = -errno;
+    } else {
+        ret /= dev->zbd_info.zbd_logical_block_size;
+    }
+
+out:
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;
+
+}
+
+/**
+ * Write to the emulated device/file.
+ */
+static int32_t
+zbc_fake_pwrite(struct zbc_device *dev,
+                struct zbc_zone *z,
+                const void *buf,
+                uint32_t lba_count,
+                uint64_t start_lba)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    struct zbc_zone *zone;
+    off_t offset;
+    size_t count;
+    ssize_t ret = -EIO;
+
+    if ( ! fdev->zbd_meta ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    /* Find the target zone */
+    zone = zbf_fake_find_zone(fdev, zbc_zone_start_lba(z));
+    if ( ! zone ) {
+        goto out;
+    }
+
+    /* Writes cannot span zones */
+    if ( start_lba > zbc_zone_length(zone) ) {
+        goto out;
+    }
+
+    start_lba += zone->zbz_start;
+
+    if ( (start_lba + lba_count) > zbc_zone_next_lba(zone) ) {
+        goto out;
+    }
+
+    if ( zbc_zone_sequential_req(zone) ) {
+
+        /* Can only write at the write pointer */
+        if ( start_lba != zbc_zone_wp_lba(zone) ) {
+            goto out;
+        }
+
+        /* Can only write an open zone */
+        if ( ! zbc_zone_is_open(zone) ) {
+
+            if ( fdev->zbd_meta->zbd_nr_exp_open_zones >= fdev->dev.zbd_info.zbd_max_nr_open_seq_req ) {
+                /* Too many explicit open on-going */
+                ret = -EBUSY;
+                goto out;
+            }
+
+            /* Implicitely open the zone */
+            if ( fdev->zbd_meta->zbd_nr_imp_open_zones >= fdev->dev.zbd_info.zbd_max_nr_open_seq_req ) {
+                unsigned int i;
+                for(i = 0; i < fdev->zbd_nr_zones; i++) {
+                    if ( zbc_zone_imp_open(&fdev->zbd_zones[i]) ) {
+                        fdev->zbd_zones[i].zbz_condition = ZBC_ZC_CLOSED;
+                        fdev->zbd_meta->zbd_nr_imp_open_zones--;
+                        break;
+                    }
+                }
+            }
+
+            zone->zbz_condition = ZBC_ZC_IMP_OPEN;
+            fdev->zbd_meta->zbd_nr_imp_open_zones++;
+
+        }
+
+    }
+
+    /* XXX: check for overflows */
+    count = (size_t)lba_count * dev->zbd_info.zbd_logical_block_size;
+    offset = start_lba * dev->zbd_info.zbd_logical_block_size;
+
+    ret = pwrite(dev->zbd_fd, buf, count, offset);
+    if ( ret < 0 ) {
+
+        ret = -errno;
+
+    } else {
+
+        ret /= dev->zbd_info.zbd_logical_block_size;
+
+        if ( zbc_zone_sequential_req(zone) ) {
+
+            /*
+             * XXX: What protects us from a return value that's not LBA aligned?
+             * (Except for hoping the OS implementation isn't insane..)
+             */
+            if ( (zbc_zone_wp_lba(zone) + lba_count) >= zbc_zone_next_lba(zone) ) {
+                if ( zbc_zone_imp_open(zone) ) {
+                    fdev->zbd_meta->zbd_nr_imp_open_zones--;
+                } else {
+                    fdev->zbd_meta->zbd_nr_exp_open_zones--;
+                }
+            }
+
+            /* Advance write pointer */
+            zbc_zone_wp_lba_inc(zone, lba_count);
+
+        }
+
+    }
+
+out:
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;
+
+}
+
+/**
+ * Flush the emulated device data and metadata.
+ */
+static int
+zbc_fake_flush(struct zbc_device *dev,
+               uint64_t lba_offset,
+               uint32_t lba_count,
+               int immediate)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    int ret;
+
+    if ( ! fdev->zbd_meta ) {
+        return -ENXIO;
+    }
+
+    ret = msync(fdev->zbd_meta, fdev->zbd_meta_size, MS_SYNC);
+    if ( ret == 0 ) {
+        ret = fsync(dev->zbd_fd);
+    }
+
+    return ret;
+
+}
+
+/**
+ * Initialize an emulated device metadata.
+ */
+static int
+zbc_fake_set_zones(struct zbc_device *dev,
+                   uint64_t conv_zone_size,
+                   uint64_t seq_zone_size)
+{
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    uint64_t lba = 0, device_size = dev->zbd_info.zbd_logical_blocks;
+    zbc_fake_meta_t fmeta;
+    char meta_path[512];
+    struct zbc_zone *zone;
+    unsigned int z = 0;
+    int ret;
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    /* Initialize meta */
+    memset(&fmeta, 0, sizeof(zbc_fake_meta_t));
+    fmeta.zbd_capacity = device_size * dev->zbd_info.zbd_logical_block_size;
+
+    /* Convert device size into # of physical blocks */
+    if ( (conv_zone_size + seq_zone_size) > device_size ) {
+        zbc_error("%s: invalid zone sizes (too large)\n",
+                  fdev->dev.zbd_filename);
+        ret = -EINVAL;
+        goto out_unlock;
+    }
+
+    fmeta.zbd_nr_conv_zones = conv_zone_size / seq_zone_size;
+    if ( conv_zone_size && (! fmeta.zbd_nr_conv_zones) ) {
+        fmeta.zbd_nr_conv_zones = 1;
+    }
+
+    fmeta.zbd_nr_seq_zones = (device_size - (fmeta.zbd_nr_conv_zones * seq_zone_size)) / seq_zone_size;
+    if ( ! fmeta.zbd_nr_seq_zones ) {
+        zbc_error("%s: invalid zone sizes (too large)\n",
+                  fdev->dev.zbd_filename);
+        ret = -EINVAL;
+        goto out_unlock;
+    }
+
+    fmeta.zbd_nr_zones = fmeta.zbd_nr_conv_zones + fmeta.zbd_nr_seq_zones;
+    fdev->zbd_nr_zones = fmeta.zbd_nr_zones;
+
+    fdev->zbd_meta_size = sizeof(zbc_fake_meta_t) + fdev->zbd_nr_zones * sizeof(struct zbc_zone);
+    if ( fdev->zbd_meta_fd < 0 ) {
+        sprintf(meta_path, "/tmp/zbc-%s.meta",
+                basename(fdev->dev.zbd_filename));
+        fdev->zbd_meta_fd = open(meta_path, O_RDWR | O_CREAT, 0600);
+        if ( fdev->zbd_meta_fd < 0 ) {
+            ret = -errno;
+            zbc_error("%s: open metadata file %s failed %d (%s)\n",
+                      fdev->dev.zbd_filename,
+                      meta_path,
+                      errno,
+                      strerror(errno));
+            goto out_unlock;
+        }
+    }
+
+    if ( ftruncate(fdev->zbd_meta_fd, fdev->zbd_meta_size) < 0) {
+        ret = -errno;
+        zbc_error("%s: truncate metadata file %s to %zu B failed %d (%s)\n",
+                  fdev->dev.zbd_filename,
+                  meta_path,
+                  fdev->zbd_meta_size,
+                  errno,
+                  strerror(errno));
+        goto out_close;
+    }
+
+    fdev->zbd_meta = mmap(NULL, fdev->zbd_meta_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdev->zbd_meta_fd, 0);
+    if ( fdev->zbd_meta == MAP_FAILED ) {
+        fdev->zbd_meta = NULL;
+        zbc_error("%s: mmap metadata file %s failed\n",
+                  fdev->dev.zbd_filename,
+                  meta_path);
+        ret = -ENOMEM;
+        goto out_close;
+    }
+    fdev->zbd_zones = (struct zbc_zone *) (fdev->zbd_meta + 1);
+
+    /* Initialize header */
+    memcpy(fdev->zbd_meta, &fmeta, sizeof(zbc_fake_meta_t));
+
+    /* Initialize conventional zones */
+    for(z = 0; z < fmeta.zbd_nr_conv_zones; z++) {
+
+        zone = &fdev->zbd_zones[z];
+
+        zone->zbz_type = ZBC_ZT_CONVENTIONAL;
+        zone->zbz_condition = ZBC_ZC_NOT_WP;
+        zone->zbz_start = lba;
+        zone->zbz_length = seq_zone_size;
+        zone->zbz_write_pointer = (uint64_t)-1;
+        memset(&zone->__pad, 0, sizeof(zone->__pad));
+
+        lba += seq_zone_size;
+
+    }
+
+    for (; z < fdev->zbd_nr_zones; z++) {
+
+        zone = &fdev->zbd_zones[z];
+
+        zone->zbz_type = ZBC_ZT_SEQUENTIAL_REQ;
+        zone->zbz_condition = ZBC_ZC_EMPTY;
+
+        zone->zbz_start = lba;
         zone->zbz_write_pointer = zone->zbz_start;
-        zone->zbz_condition = ZBC_ZC_EMPTY;
-        return 0;
-}
-
+        zone->zbz_length = seq_zone_size;
+
+        memset(&zone->__pad, 0, sizeof(zone->__pad));
+
+        lba += seq_zone_size;
+
+    }
+
+    ret = 0;
+
+out_unlock:
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;
+
+out_close:
+
+    close(fdev->zbd_meta_fd);
+
+    goto out_unlock;
+
+}
+
+/**
+ * Change the value of a zone write pointer.
+ */
 static int
-zbc_fake_reset_wp(struct zbc_device *dev, uint64_t zone_start_lba)
-{
-        struct zbc_fake_device *fdev = to_file_dev(dev);
-        struct zbc_zone *zone;
-	int ret;
-
-        if (!fdev->zbd_zones)
-                return -ENXIO;
-
-	pthread_mutex_lock(&fdev->mutex);
-        if (zone_start_lba == (uint64_t)-1) {
-                unsigned int i;
-
-                for (i = 0; i < fdev->zbd_nr_zones; i++)
-                        zbc_fake_reset_one_write_pointer(&fdev->zbd_zones[i]);
-        } else {
-                zone = zbf_fake_find_zone(fdev, zone_start_lba);
-                if (!zone) {
-                        ret = -EIO;
-			goto out_unlock;
-		}
-
-                /* XXX(hch): reject for conventional zones? */
-
-                zbc_fake_reset_one_write_pointer(zone);
-        }
-
-	ret = 0;
-
-out_unlock:
-
-	pthread_mutex_unlock(&fdev->mutex);
-
-        return ret;
-
-}
-
-static int32_t
-zbc_fake_pread(struct zbc_device *dev, struct zbc_zone *zone, void *buf,
-               uint32_t lba_count, uint64_t start_lba)
-{
-        struct zbc_fake_device *fdev = to_file_dev(dev);
-        off_t offset;
-        size_t count;
-	ssize_t ret;
-
-        if (!fdev->zbd_zones)
-                return -ENXIO;
-
-        ret = -EIO;
-	pthread_mutex_lock(&fdev->mutex);
-        if (start_lba > zone->zbz_length)
-		goto out_unlock;
-        start_lba += zone->zbz_start;
-
-        /* Note: unrestricted read will be added to the standard */
-        /* and supported by a drive if the URSWRZ bit is set in  */
-        /* VPD page. So this test will need to change.           */
-        if (zone->zbz_type == ZBC_ZT_SEQUENTIAL_REQ) {
-                /* Cannot read unwritten data */
-                if (start_lba + lba_count > zone->zbz_write_pointer)
-			goto out_unlock;
-        } else {
-                /* Reads spanning other types of zones are OK. */
-                if (start_lba + lba_count > zone->zbz_start + zone->zbz_length) {
-                        uint64_t lba = zbc_zone_end_lba(zone) + 1;
-                        uint64_t count = start_lba + lba_count - lba;
-                        struct zbc_zone *next_zone = zone;
-                        while( count && (next_zone = zbf_fake_find_zone(fdev, lba)) ) {
-                                if (next_zone->zbz_type == ZBC_ZT_SEQUENTIAL_REQ)
-					goto out_unlock;
-                                if ( count > next_zone->zbz_length )
-                                        count -= next_zone->zbz_length;
-                                lba += next_zone->zbz_length;
-                        }
-                }
-        }
-	pthread_mutex_unlock(&fdev->mutex);
-
-        /* XXX: check for overflows */
-        count = lba_count * dev->zbd_info.zbd_logical_block_size;
-        offset = start_lba * dev->zbd_info.zbd_logical_block_size;
-
-        ret = pread(dev->zbd_fd, buf, count, offset);
-        if (ret < 0)
-                return -errno;
-
-        return ret / dev->zbd_info.zbd_logical_block_size;
-
-out_unlock:
-	pthread_mutex_unlock(&fdev->mutex);
-        return ret;
-}
-
-static int32_t
-zbc_fake_pwrite(struct zbc_device *dev, struct zbc_zone *z, const void *buf,
-                uint32_t lba_count, uint64_t start_lba)
-{
-        struct zbc_fake_device *fdev = to_file_dev(dev);
-        struct zbc_zone *zone;
-        off_t offset;
-        size_t count;
-	ssize_t ret = -EIO;
-
-        if (!fdev->zbd_zones)
-                return -ENXIO;
-
-	pthread_mutex_lock(&fdev->mutex);
-
-        zone = zbf_fake_find_zone(fdev, z->zbz_start);
-        if (!zone)
-                goto out_unlock;
-
-        if (start_lba > zone->zbz_length)
-                goto out_unlock;
-        start_lba += zone->zbz_start;
-
-        if (zone->zbz_type == ZBC_ZT_SEQUENTIAL_REQ) {
-                /* Can only write at the write pointer */
-                if (start_lba != zone->zbz_write_pointer)
-                        goto out_unlock;
-        }
-
-        /* Writes cannot span zones */
-        if (zone->zbz_type != ZBC_ZT_CONVENTIONAL) {
-                if (zone->zbz_write_pointer + lba_count >
-                    zone->zbz_start + zone->zbz_length)
-                        goto out_unlock;
-        } else {
-                if (start_lba + lba_count >
-                    zone->zbz_start + zone->zbz_length)
-                        goto out_unlock;
-        }
-
-        /* XXX: check for overflows */
-        count = (size_t)lba_count * dev->zbd_info.zbd_logical_block_size;
-        offset = start_lba * dev->zbd_info.zbd_logical_block_size;
-
-        ret = pwrite(dev->zbd_fd, buf, count, offset);
-        if (ret < 0) {
-                ret = -errno;
-		goto out_unlock;
-	}
-
-        ret /= dev->zbd_info.zbd_logical_block_size;
-
-        if (zone->zbz_type != ZBC_ZT_CONVENTIONAL) {
-                /*
-                * XXX: What protects us from a return value that's not LBA aligned?
-                * (Except for hoping the OS implementation isn't insane..)
-                */
-                if (zone->zbz_write_pointer == zone->zbz_start + zone->zbz_length)
-                        zone->zbz_condition = ZBC_ZC_FULL;
-                else
-                        zone->zbz_condition = ZBC_ZC_CLOSED;
-
-		/* write pointer in z is advanced on return of this function in zbc.c */
-		memcpy(z, zone, sizeof(*z));
-
-		/* Advance write pointer */
-                zone->zbz_write_pointer += ret;
-
-        }
-
-out_unlock:
-
-	pthread_mutex_unlock(&fdev->mutex);
-
-        return ret;
-
-}
-
-static int
-zbc_fake_flush(struct zbc_device *dev, uint64_t lba_offset, uint32_t lba_count,
-                int immediate)
-{
-        return fsync(dev->zbd_fd);
-}
-
-static int
-zbc_fake_set_zones(struct zbc_device *dev, uint64_t conv_zone_size,
-                   uint64_t seq_zone_size)
-{
-        struct zbc_fake_device *fdev = to_file_dev(dev);
-	uint64_t device_size = dev->zbd_info.zbd_logical_blocks;
-        char meta_path[512];
-        struct stat st;
-        off_t len;
-        int error;
-        off_t start = 0;
-        unsigned int z = 0;
-
-        if (fstat(dev->zbd_fd, &st) < 0) {
-                perror("fstat");
-                return -errno;
-        }
-
-	pthread_mutex_unlock(&fdev->mutex);
-
-        /* Convert device size into # of physical blocks */
-        if ( (conv_zone_size + seq_zone_size) > device_size ) {
-                printf("size: %llu + %llu > %llu\n",
-                       (unsigned long long) conv_zone_size,
-                       (unsigned long long) seq_zone_size,
-                       (unsigned long long) device_size);
-                error = -EINVAL;
-		goto out_unlock;
-        }
-
-        fdev->zbd_nr_zones =
-                (device_size - conv_zone_size + seq_zone_size - 1) /
-                 seq_zone_size;
-        if (conv_zone_size)
-                fdev->zbd_nr_zones++;
-
-        len = (off_t)fdev->zbd_nr_zones * sizeof(struct zbc_zone);
-
-        if (fdev->zbd_meta_fd < 0) {
-                sprintf(meta_path, "/tmp/zbc-%s.meta",
-                        basename(fdev->dev.zbd_filename));
-                fdev->zbd_meta_fd = open(meta_path, O_RDWR | O_CREAT, 0600);
-                if (fdev->zbd_meta_fd < 0) {
-                        perror("open");
-                        error = -errno;
-			goto out_unlock;
-                }
-        }
-
-        if (ftruncate(fdev->zbd_meta_fd, len) < 0) {
-                perror("ftruncate");
-                error = -errno;
-                goto out_close;
-        }
-
-        fdev->zbd_zones = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
-                        fdev->zbd_meta_fd, 0);
-        if (fdev->zbd_zones == MAP_FAILED) {
-                perror("mmap");
-                error = -ENOMEM;
-                goto out_close;
-        }
-
-        if (conv_zone_size) {
-                struct zbc_zone *zone = &fdev->zbd_zones[z];
-
-                zone->zbz_type = ZBC_ZT_CONVENTIONAL;
-                zone->zbz_condition = ZBC_ZC_NOT_WP;
-                zone->zbz_start = start;
-                zone->zbz_write_pointer = 0;
-                zone->zbz_length = conv_zone_size;
-                zone->zbz_need_reset = false;
-                zone->zbz_non_seq = false;
-                memset(&zone->__pad, 0, sizeof(zone->__pad));
-
-                start += conv_zone_size;
-                z++;
-        }
-
-        for (; z < fdev->zbd_nr_zones; z++) {
-                struct zbc_zone *zone = &fdev->zbd_zones[z];
-
-                zone->zbz_type = ZBC_ZT_SEQUENTIAL_REQ;
-                zone->zbz_condition = ZBC_ZC_EMPTY;
-
-                zone->zbz_start = start;
-                zone->zbz_write_pointer = zone->zbz_start;
-
-                if (zone->zbz_start + seq_zone_size <= device_size)
-                        zone->zbz_length = seq_zone_size;
-                else
-                        zone->zbz_length = device_size - zone->zbz_start;
-
-                zone->zbz_need_reset = false;
-                zone->zbz_non_seq = false;
-
-                memset(&zone->__pad, 0, sizeof(zone->__pad));
-
-                start += zone->zbz_length;
-        }
-
-        error = 0;
-out_unlock:
-	pthread_mutex_unlock(&fdev->mutex);
-        return error;
-out_close:
-        close(fdev->zbd_meta_fd);
-	goto out_unlock;
-}
-
-static int
-zbc_fake_set_write_pointer(struct zbc_device *dev, uint64_t start_lba,
+zbc_fake_set_write_pointer(struct zbc_device *dev,
+                           uint64_t start_lba,
                            uint64_t write_pointer)
 {
-        struct zbc_fake_device *fdev = to_file_dev(dev);
-        struct zbc_zone *zone;
-	int ret;
-
-	pthread_mutex_lock(&fdev->mutex);
-        if (!fdev->zbd_zones) {
-                ret = -ENXIO;
-		goto out_unlock;
-	}
-
-        zone = zbf_fake_find_zone(fdev, start_lba);
-        if (!zone) {
-                ret = -EINVAL;
-		goto out_unlock;
-	}
+    zbc_fake_device_t *fdev = zbc_fake_to_file_dev(dev);
+    struct zbc_zone *zone;
+    int ret = -EINVAL;
+
+    if ( ! fdev->zbd_meta ) {
+        return -ENXIO;
+    }
+
+    pthread_mutex_lock(&fdev->mutex);
+
+    zone = zbf_fake_find_zone(fdev, start_lba);
+    if ( zone ) {

         /* Do nothing for conventional zones */
-        if (zone->zbz_type != ZBC_ZT_CONVENTIONAL) {
-                zone->zbz_write_pointer = write_pointer;
-                if (zone->zbz_write_pointer == zone->zbz_start + zone->zbz_length)
-                        zone->zbz_condition = ZBC_ZC_FULL;
-                else
-                        zone->zbz_condition = ZBC_ZC_CLOSED;
+        if ( zbc_zone_sequential_req(zone) ) {
+            zone->zbz_write_pointer = write_pointer;
+            if ( zbc_zone_wp_within_zone(zone) ) {
+                zone->zbz_condition = ZBC_ZC_CLOSED;
+            } else {
+                zone->zbz_condition = ZBC_ZC_FULL;
+                zone->zbz_write_pointer = (uint64_t)-1;
+            }
         }

         ret = 0;

-out_unlock:
-
-	pthread_mutex_unlock(&fdev->mutex);
-
-        return ret;
+    }
+
+    pthread_mutex_unlock(&fdev->mutex);
+
+    return ret;

 }

 struct zbc_ops zbc_fake_ops = {
-        .zbd_open                       = zbc_fake_open,
-        .zbd_close                      = zbc_fake_close,
-        .zbd_pread                      = zbc_fake_pread,
-        .zbd_pwrite                     = zbc_fake_pwrite,
-        .zbd_flush                      = zbc_fake_flush,
-        .zbd_report_zones               = zbc_fake_report_zones,
-        .zbd_reset_wp                   = zbc_fake_reset_wp,
-        .zbd_set_zones                  = zbc_fake_set_zones,
-        .zbd_set_wp                     = zbc_fake_set_write_pointer,
+    .zbd_open         = zbc_fake_open,
+    .zbd_close        = zbc_fake_close,
+    .zbd_pread        = zbc_fake_pread,
+    .zbd_pwrite       = zbc_fake_pwrite,
+    .zbd_flush        = zbc_fake_flush,
+    .zbd_report_zones = zbc_fake_report_zones,
+    .zbd_open_zone    = zbc_fake_open_zone,
+    .zbd_close_zone   = zbc_fake_close_zone,
+    .zbd_finish_zone  = zbc_fake_finish_zone,
+    .zbd_reset_wp     = zbc_fake_reset_wp,
+    .zbd_set_zones    = zbc_fake_set_zones,
+    .zbd_set_wp       = zbc_fake_set_write_pointer,
 };


Taking into account the start and end bands in CNG

--- libcelt/celt.c
+++ libcelt/celt.c
@@ -1988,6 +1988,11 @@
       VARDECL(celt_norm, X);
       VARDECL(celt_ener, bandE);
       celt_uint32 seed;
+      int effEnd;
+
+      effEnd = st->end;
+      if (effEnd > st->mode->effEBands)
+         effEnd = st->mode->effEBands;

       ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
       ALLOC(X, C*N, celt_norm);   /**< Interleaved normalised MDCTs */
@@ -1998,6 +2003,8 @@
       seed = st->rng;
       for (c=0;c<C;c++)
       {
+         for (i=0;i<(st->mode->eBands[st->start]<<LM);i++)
+            X[c*N+i] = 0;
          for (i=0;i<st->mode->effEBands;i++)
          {
             int j;
@@ -2012,11 +2019,24 @@
             }
             renormalise_vector(X+boffs, blen, Q15ONE);
          }
+         for (i=(st->mode->eBands[st->end]<<LM);i<N;i++)
+            X[c*N+i] = 0;
       }
       st->rng = seed;

       denormalise_bands(st->mode, X, freq, bandE, st->mode->effEBands, C, 1<<LM);

+      c=0; do
+         for (i=0;i<st->mode->eBands[st->start]<<LM;i++)
+            freq[c*N+i] = 0;
+      while (++c<C);
+      c=0; do {
+         int bound = st->mode->eBands[effEnd]<<LM;
+         if (st->downsample!=1)
+            bound = IMIN(bound, N/st->downsample);
+         for (i=bound;i<N;i++)
+            freq[c*N+i] = 0;
+      } while (++c<C);
       compute_inv_mdcts(st->mode, 0, freq, out_syn, overlap_mem, C, LM);
       plc = 0;
    } else if (st->loss_count == 0)


code clean up

code clean up

--- hieroglyph/hgallocator.c
+++ hieroglyph/hgallocator.c
@@ -65,18 +65,18 @@

 /*< private >*/

-HG_INLINE_FUNC gsize
+HG_INLINE_FUNC hg_usize_t
 hg_allocator_get_page_size(void)
 {
-	static gsize retval = ((1LL << (HG_ALLOC_TYPE_BIT_INDEX_END - HG_ALLOC_TYPE_BIT_INDEX + 1)) - 1);
+	static hg_usize_t retval = ((1LL << (HG_ALLOC_TYPE_BIT_INDEX_END - HG_ALLOC_TYPE_BIT_INDEX + 1)) - 1);

 	return retval;
 }

-HG_INLINE_FUNC gsize
+HG_INLINE_FUNC hg_usize_t
 hg_allocator_get_max_page(void)
 {
-	static gsize retval = ((1LL << (HG_ALLOC_TYPE_BIT_PAGE_END - HG_ALLOC_TYPE_BIT_PAGE + 1)) - 1);
+	static hg_usize_t retval = ((1LL << (HG_ALLOC_TYPE_BIT_PAGE_END - HG_ALLOC_TYPE_BIT_PAGE + 1)) - 1);

 	return retval;
 }
@@ -84,16 +84,16 @@
 HG_INLINE_FUNC hg_pointer_t
 hg_allocator_get_allocated_object(hg_allocator_block_t *block)
 {
-	return (hg_pointer_t)((gchar *)(block) + HG_ALIGNED_TO_POINTER (sizeof (hg_allocator_block_t)));
+	return (hg_pointer_t)((hg_char_t *)(block) + HG_ALIGNED_TO_POINTER (sizeof (hg_allocator_block_t)));
 }

 /** bitmap operation **/
 HG_INLINE_FUNC hg_allocator_bitmap_t *
-_hg_allocator_bitmap_new(gsize size)
+_hg_allocator_bitmap_new(hg_usize_t size)
 {
 	hg_allocator_bitmap_t *retval;
-	gsize aligned_size, bitmap_size;
-	gint32 page, max_page = hg_allocator_get_max_page();
+	hg_usize_t aligned_size, bitmap_size;
+	hg_int_t page, max_page = hg_allocator_get_max_page();

 	hg_return_val_if_fail (size > 0, NULL);
 	hg_return_val_if_fail (size <= hg_allocator_get_page_size() * BLOCK_SIZE, NULL);
@@ -102,7 +102,7 @@
 	bitmap_size = HG_ALIGNED_TO (aligned_size / BLOCK_SIZE, sizeof (guint32));
 	retval = g_new0(hg_allocator_bitmap_t, 1);
 	if (retval) {
-		retval->bitmaps = g_new0(guint32 *, max_page);
+		retval->bitmaps = g_new0(hg_uint_t *, max_page);
 		retval->size = g_new0(gsize, max_page);
 		retval->last_index = g_new0(hg_quark_t, max_page);
 		page = _hg_allocator_bitmap_get_free_page(retval);
@@ -113,17 +113,17 @@
 			_hg_allocator_bitmap_destroy(retval);
 			return NULL;
 		}
-		retval->bitmaps[page] = g_new0(guint32, bitmap_size / sizeof (guint32));
+		retval->bitmaps[page] = g_new0(hg_uint_t, bitmap_size / sizeof (guint32));
 		retval->size[page] = bitmap_size;
 	}

 	return retval;
 }

-HG_INLINE_FUNC gint32
+HG_INLINE_FUNC hg_int_t
 _hg_allocator_bitmap_get_free_page(hg_allocator_bitmap_t *bitmap)
 {
-	gint32 i, max_page = hg_allocator_get_max_page();
+	hg_int_t i, max_page = hg_allocator_get_max_page();

 	for (i = 0; i < max_page; i++) {
 		if (!bitmap->bitmaps[i])
@@ -134,10 +134,10 @@
 }

 HG_INLINE_FUNC void
-_hg_allocator_bitmap_destroy(gpointer data)
+_hg_allocator_bitmap_destroy(hg_pointer_t data)
 {
 	hg_allocator_bitmap_t *bitmap = data;
-	gsize i, max_page = hg_allocator_get_max_page();
+	hg_usize_t i, max_page = hg_allocator_get_max_page();

 	if (!data)
 		return;
@@ -150,11 +150,11 @@
 	g_free(bitmap);
 }

-HG_INLINE_FUNC gint32
+HG_INLINE_FUNC hg_int_t
 _hg_allocator_bitmap_add_page(hg_allocator_bitmap_t *bitmap,
-			      gsize                  size)
-{
-	gint32 page;
+			      hg_usize_t             size)
+{
+	hg_int_t page;

 	page = _hg_allocator_bitmap_get_free_page(bitmap);
 	if (page >= 0) {
@@ -165,12 +165,12 @@
 	return page;
 }

-HG_INLINE_FUNC gboolean
+HG_INLINE_FUNC hg_bool_t
 _hg_allocator_bitmap_add_page_to(hg_allocator_bitmap_t *bitmap,
-				 gint32                 page,
-				 gsize                  size)
-{
-	gsize aligned_size, bitmap_size;
+				 hg_int_t               page,
+				 hg_usize_t             size)
+{
+	hg_usize_t aligned_size, bitmap_size;

 	hg_return_val_if_fail (size > 0 && size <= hg_allocator_get_page_size() * BLOCK_SIZE, FALSE);
 	hg_return_val_if_fail (page >= 0 && page < hg_allocator_get_max_page(), FALSE);
@@ -179,9 +179,9 @@
 	G_LOCK (bitmap);

 	aligned_size = HG_ALIGNED_TO (size, BLOCK_SIZE);
-	bitmap_size = HG_ALIGNED_TO (aligned_size / BLOCK_SIZE, sizeof (guint32));
+	bitmap_size = HG_ALIGNED_TO (aligned_size / BLOCK_SIZE, sizeof (hg_uint_t));
 	if (page >= 0) {
-		bitmap->bitmaps[page] = g_new0(guint32, bitmap_size / sizeof (guint32));
+		bitmap->bitmaps[page] = g_new0(hg_uint_t, bitmap_size / sizeof (hg_uint_t));
 		bitmap->size[page] = bitmap_size;
 	}

@@ -192,12 +192,12 @@

 HG_INLINE_FUNC hg_quark_t
 _hg_allocator_bitmap_alloc(hg_allocator_bitmap_t *bitmap,
-			   gsize                  size)
-{
-	gsize aligned_size;
-	gint32 page;
-	guint32 i, j, idx = 0;
-	gboolean retry = FALSE;
+			   hg_usize_t             size)
+{
+	hg_usize_t aligned_size;
+	hg_int_t page;
+	hg_uint_t i, j, idx = 0;
+	hg_bool_t retry = FALSE;

 	aligned_size = HG_ALIGNED_TO (size, BLOCK_SIZE) / BLOCK_SIZE;
 	page = bitmap->last_page;
@@ -246,13 +246,13 @@
 HG_INLINE_FUNC hg_quark_t
 _hg_allocator_bitmap_realloc(hg_allocator_bitmap_t *bitmap,
 			     hg_quark_t             index_,
-			     gsize                  old_size,
-			     gsize                  size)
+			     hg_usize_t             old_size,
+			     hg_usize_t             size)
 {
 	hg_quark_t i;
-	gssize aligned_size, old_aligned_size, required_size;
-	gint32 page;
-	guint32 idx;
+	hg_size_t aligned_size, old_aligned_size, required_size;
+	hg_int_t page;
+	hg_uint_t idx;

 	hg_return_val_if_fail (index_ != Qnil, Qnil);
 	hg_return_val_if_fail (size > 0, Qnil);
@@ -306,12 +306,12 @@
 HG_INLINE_FUNC void
 _hg_allocator_bitmap_free(hg_allocator_bitmap_t *bitmap,
 			  hg_quark_t             index_,
-			  gsize                  size)
+			  hg_usize_t             size)
 {
 	hg_quark_t i;
-	gsize aligned_size;
-	gint32 page;
-	guint32 idx;
+	hg_usize_t aligned_size;
+	hg_int_t page;
+	hg_uint_t idx;

 	hg_return_if_fail (index_ > 0);
 	hg_return_if_fail (size > 0);
@@ -338,45 +338,45 @@

 HG_INLINE_FUNC void
 _hg_allocator_bitmap_mark(hg_allocator_bitmap_t *bitmap,
-			  gint32                 page,
-			  guint32                index_)
+			  hg_int_t               page,
+			  hg_uint_t              index_)
 {
 	hg_return_if_fail (page >= 0 && page < hg_allocator_get_max_page());
 	hg_return_if_fail (index_ > 0 && index_ <= bitmap->size[page]);
 	hg_return_if_fail (!_hg_allocator_bitmap_is_marked(bitmap, page, index_));

-	bitmap->bitmaps[page][(index_ - 1) / sizeof (guint32)] |= 1 << ((index_ - 1) % sizeof (guint32));
+	bitmap->bitmaps[page][(index_ - 1) / sizeof (hg_uint_t)] |= 1 << ((index_ - 1) % sizeof (hg_uint_t));
 }

 HG_INLINE_FUNC void
 _hg_allocator_bitmap_clear(hg_allocator_bitmap_t *bitmap,
-			   gint32                 page,
-			   guint32                index_)
+			   hg_int_t               page,
+			   hg_uint_t              index_)
 {
 	hg_return_if_fail (page >= 0 && page < hg_allocator_get_max_page());
 	hg_return_if_fail (index_ > 0 && index_ <= bitmap->size[page]);

-	bitmap->bitmaps[page][(index_ - 1) / sizeof (guint32)] &= ~(1 << ((index_ - 1) % sizeof (guint32)));
-}
-
-HG_INLINE_FUNC gboolean
+	bitmap->bitmaps[page][(index_ - 1) / sizeof (hg_uint_t)] &= ~(1 << ((index_ - 1) % sizeof (hg_uint_t)));
+}
+
+HG_INLINE_FUNC hg_bool_t
 _hg_allocator_bitmap_is_marked(hg_allocator_bitmap_t *bitmap,
-			       gint32                 page,
-			       guint32                index_)
+			       hg_int_t               page,
+			       hg_uint_t              index_)
 {
 	hg_return_val_if_fail (page >= 0 && page < hg_allocator_get_max_page(), FALSE);
 	hg_return_val_if_fail (index_ > 0 && index_ <= bitmap->size[page], FALSE);

-	return bitmap->bitmaps[page][(index_ - 1) / sizeof (guint32)] & 1 << ((index_ - 1) % sizeof (guint32));
-}
-
-HG_INLINE_FUNC gboolean
+	return bitmap->bitmaps[page][(index_ - 1) / sizeof (hg_uint_t)] & 1 << ((index_ - 1) % sizeof (hg_uint_t));
+}
+
+HG_INLINE_FUNC hg_bool_t
 _hg_allocator_bitmap_range_mark(hg_allocator_bitmap_t *bitmap,
-				gint32                 page,
-				guint32               *index_,
-				gsize                  size)
-{
-	gsize required_size = size, j;
+				hg_int_t               page,
+				hg_uint_t             *index_,
+				hg_usize_t             size)
+{
+	hg_usize_t required_size = size, j;

 	if (!_hg_allocator_bitmap_is_marked(bitmap, page, *index_)) {
 		required_size--;
@@ -410,7 +410,7 @@
 _hg_allocator_bitmap_copy(hg_allocator_bitmap_t *bitmap)
 {
 	hg_allocator_bitmap_t *retval = _hg_allocator_bitmap_new(bitmap->size[0] * BLOCK_SIZE);
-	gsize i, max_page = hg_allocator_get_max_page();
+	hg_usize_t i, max_page = hg_allocator_get_max_page();

 	G_LOCK (bitmap);

@@ -433,9 +433,9 @@

 HG_INLINE_FUNC void
 _hg_allocator_bitmap_dump(hg_allocator_bitmap_t *bitmap,
-			  gint32                 page)
-{
-	gsize i;
+			  hg_int_t               page)
+{
+	hg_usize_t i;

 	if (hg_message_is_enabled(HG_MSGCAT_BITMAP)) {
 		hg_debug(HG_MSGCAT_BITMAP, "bitmap[%d]: %ld blocks allocated", page, bitmap->size[page]);
@@ -461,7 +461,7 @@
 }

 /** allocator **/
-static gpointer
+static hg_pointer_t
 _hg_allocator_initialize(void)
 {
 	hg_allocator_private_t *retval;
@@ -475,7 +475,7 @@
 _hg_allocator_finalize(hg_allocator_data_t *data)
 {
 	hg_allocator_private_t *priv;
-	gsize i, max_page = hg_allocator_get_max_page();
+	hg_usize_t i, max_page = hg_allocator_get_max_page();

 	if (!data)
 		return;
@@ -492,15 +492,15 @@
 	g_free(priv);
 }

-static gboolean
+static hg_bool_t
 _hg_allocator_expand_heap(hg_allocator_data_t *data,
-			  gsize                size)
+			  hg_usize_t           size)
 {
 	hg_allocator_private_t *priv = (hg_allocator_private_t *)data;
-	gint32 page = 0;
+	hg_int_t page = 0;

 	if (!priv->heaps) {
-		priv->heaps = g_new0(gpointer, hg_allocator_get_max_page());
+		priv->heaps = g_new0(hg_pointer_t, hg_allocator_get_max_page());
 		if (!priv->heaps)
 			return FALSE;
 	}
@@ -520,11 +520,11 @@
 	return TRUE;
 }

-static gsize
+static hg_usize_t
 _hg_allocator_get_max_heap_size(hg_allocator_data_t *data)
 {
 	hg_allocator_private_t *priv = (hg_allocator_private_t *)data;
-	gsize retval = 0, i, max_page = hg_allocator_get_max_page();
+	hg_usize_t retval = 0, i, max_page = hg_allocator_get_max_page();

 	for (i = 0; i < max_page; i++) {
 		retval = MAX (retval, priv->bitmap->size[i]);
@@ -535,13 +535,13 @@

 static hg_quark_t
 _hg_allocator_alloc(hg_allocator_data_t *data,
-		    gsize                size,
-		    guint                flags,
-		    gpointer            *ret)
+		    hg_usize_t           size,
+		    hg_uint_t            flags,
+		    hg_pointer_t        *ret)
 {
 	hg_allocator_private_t *priv;
 	hg_allocator_block_t *block;
-	gsize obj_size;
+	hg_usize_t obj_size;
 	hg_quark_t index_, retval = Qnil;

 	priv = (hg_allocator_private_t *)data;
@@ -574,12 +574,12 @@
 static hg_quark_t
 _hg_allocator_realloc(hg_allocator_data_t *data,
 		      hg_quark_t           qdata,
-		      gsize                size,
-		      gpointer            *ret)
+		      hg_usize_t           size,
+		      hg_pointer_t        *ret)
 {
 	hg_allocator_private_t *priv;
 	hg_allocator_block_t *block, *new_block;
-	gsize obj_size;
+	hg_usize_t obj_size;
 	hg_quark_t index_ = Qnil, retval = Qnil;

 	G_LOCK (allocator);
@@ -588,7 +588,7 @@

 	obj_size = HG_ALIGNED_TO_POINTER (sizeof (hg_allocator_block_t) + size);
 	block = _hg_allocator_real_lock_object(data, qdata);
-	if (G_LIKELY (block)) {
+	if (HG_LIKELY (block)) {
 		volatile gint make_sure_if_no_referrer;

 		make_sure_if_no_referrer = g_atomic_int_get(&block->lock_count);
@@ -637,7 +637,7 @@

 	priv = (hg_allocator_private_t *)data;
 	block = _hg_allocator_real_lock_object(data, index_);
-	if (G_LIKELY (block)) {
+	if (HG_LIKELY (block)) {
 		/* Update the used size */
 		data->used_size -= block->size;

@@ -649,13 +649,13 @@
 	}
 }

-HG_INLINE_FUNC gpointer
+HG_INLINE_FUNC hg_pointer_t
 _hg_allocator_get_internal_block(hg_allocator_private_t *priv,
 				 hg_quark_t              index_,
-				 gboolean                initialize)
-{
-	gint32 page;
-	guint32 idx;
+				 hg_bool_t               initialize)
+{
+	hg_int_t page;
+	hg_uint_t idx;

 	page = _hg_allocator_quark_get_page(index_);
 	idx = _hg_allocator_quark_get_index(index_);
@@ -663,11 +663,11 @@
 	return _hg_allocator_get_internal_block_from_page_and_index(priv, page, idx, initialize);
 }

-HG_INLINE_FUNC gpointer
+HG_INLINE_FUNC hg_pointer_t
 _hg_allocator_get_internal_block_from_page_and_index(hg_allocator_private_t *priv,
-						     gint32                  page,
-						     guint32                 idx,
-						     gboolean                initialize)
+						     hg_int_t                page,
+						     hg_uint_t               idx,
+						     hg_bool_t               initialize)
 {
 	hg_allocator_block_t *retval;

@@ -676,7 +676,7 @@
 		hg_warning("Invalid quark to access: [page: %d, index: %d]", page, idx);
 		return NULL;
 	}
-	retval = (hg_allocator_block_t *)((gulong)priv->heaps[page] + ((idx - 1) * BLOCK_SIZE));
+	retval = (hg_allocator_block_t *)((hg_quark_t)priv->heaps[page] + ((idx - 1) * BLOCK_SIZE));
 	if (initialize) {
 		memset(retval, 0, sizeof (hg_allocator_block_t));
 		retval->lock_count = 1;
@@ -685,15 +685,15 @@
 	return retval;
 }

-HG_INLINE_FUNC gpointer
+HG_INLINE_FUNC hg_pointer_t
 _hg_allocator_real_lock_object(hg_allocator_data_t *data,
 			       hg_quark_t           index_)
 {
 	hg_allocator_private_t *priv;
 	hg_allocator_block_t *retval = NULL;
-	gint old_val;
-	gint32 page;
-	guint32 idx;
+	hg_int_t old_val;
+	hg_int_t page;
+	hg_uint_t idx;

 	page = _hg_allocator_quark_get_page(index_);
 	idx = _hg_allocator_quark_get_index(index_);
@@ -709,7 +709,7 @@
 	return retval;
 }

-static gpointer
+static hg_pointer_t
 _hg_allocator_lock_object(hg_allocator_data_t *data,
 			  hg_quark_t           index_)
 {
@@ -729,7 +729,7 @@
 HG_INLINE_FUNC void
 _hg_allocator_real_unlock_object(hg_allocator_block_t *block)
 {
-	gint old_val;
+	hg_int_t old_val;

 	hg_return_if_fail (block != NULL);
 	hg_return_if_fail (block->lock_count > 0);
@@ -746,8 +746,8 @@
 {
 	hg_allocator_private_t *priv;
 	hg_allocator_block_t *retval = NULL;
-	gint32 page;
-	guint32 idx;
+	hg_int_t page;
+	hg_uint_t idx;

 	priv = (hg_allocator_private_t *)data;

@@ -761,13 +761,13 @@
 	}
 }

-static gboolean
+static hg_bool_t
 _hg_allocator_gc_init(hg_allocator_data_t *data)
 {
 	hg_allocator_private_t *priv = (hg_allocator_private_t *)data;
-	gsize i, max_page = hg_allocator_get_max_page();
-
-	if (G_UNLIKELY (priv->slave_bitmap)) {
+	hg_usize_t i, max_page = hg_allocator_get_max_page();
+
+	if (HG_UNLIKELY (priv->slave_bitmap)) {
 		hg_warning("GC is already ongoing.");
 		return FALSE;
 	}
@@ -791,9 +791,9 @@
 {
 	hg_allocator_private_t *priv = (hg_allocator_private_t *)data;
 	hg_allocator_block_t *block;
-	gint32 page;
-	guint32 idx;
-	gsize aligned_size;
+	hg_int_t page;
+	hg_uint_t idx;
+	hg_usize_t aligned_size;

 	/* this isn't the object in the targeted spool */
 	if (!priv->slave_bitmap)
@@ -829,7 +829,7 @@
 {
 	hg_allocator_private_t *priv = (hg_allocator_private_t *)data;

-	if (G_UNLIKELY (!priv->slave_bitmap)) {
+	if (HG_UNLIKELY (!priv->slave_bitmap)) {
 		hg_warning("GC isn't yet started.");
 		return HG_ERROR_ (HG_STATUS_FAILED, HG_e_VMerror);
 	}
@@ -838,8 +838,8 @@

 	/* XXX: this has to be dropped in the future */
 	if (HG_ERROR_IS_SUCCESS (error)) {
-		gsize used_size;
-		guint32 i, j, max_page = hg_allocator_get_max_page();
+		hg_usize_t used_size;
+		hg_uint_t i, j, max_page = hg_allocator_get_max_page();

 		used_size = data->used_size - priv->slave.used_size;

@@ -850,7 +850,7 @@
 			for (j = 0; used_size > 0 && j < priv->bitmap->size[i]; j++) {
 				if (_hg_allocator_bitmap_is_marked(priv->bitmap, i, j + 1)) {
 					hg_allocator_block_t *block;
-					gsize aligned_size;
+					hg_usize_t aligned_size;

 					block = _hg_allocator_get_internal_block_from_page_and_index((hg_allocator_private_t *)data,
 												     i, j + 1, FALSE);
@@ -904,7 +904,7 @@
 {
 	hg_allocator_private_t *priv = (hg_allocator_private_t *)data;
 	hg_allocator_snapshot_private_t *snapshot;
-	gsize i, max_page = hg_allocator_get_max_page();
+	hg_usize_t i, max_page = hg_allocator_get_max_page();

 	G_LOCK (allocator);

@@ -933,8 +933,8 @@
 {
 	hg_allocator_private_t *priv = (hg_allocator_private_t *)data;
 	hg_allocator_snapshot_private_t *spriv = (hg_allocator_snapshot_private_t *)snapshot;
-	guint32 i, j, max_page = hg_allocator_get_max_page();
-	gboolean retval = FALSE;
+	hg_uint_t i, j, max_page = hg_allocator_get_max_page();
+	hg_bool_t retval = FALSE;

 	if (spriv->age >= priv->snapshot_age)
 		return FALSE;
@@ -943,17 +943,17 @@

 	for (i = 0; i < max_page; i++) {
 		for (j = 0; j < priv->bitmap->size[i]; j++) {
-			gboolean f1, f2;
-			gsize aligned_size;
+			hg_bool_t f1, f2;
+			hg_usize_t aligned_size;

 			f1 = _hg_allocator_bitmap_is_marked(priv->bitmap, i, j + 1);
 			f2 = j >= spriv->bitmap->size[i] ? FALSE : _hg_allocator_bitmap_is_marked(spriv->bitmap, i, j + 1);
 			if (f1 && f2) {
 				hg_allocator_block_t *b1, *b2;
-				gsize idx = j * BLOCK_SIZE;
+				hg_usize_t idx = j * BLOCK_SIZE;

 				b1 = _hg_allocator_get_internal_block_from_page_and_index(priv, i, j + 1, FALSE);
-				b2 = (hg_allocator_block_t *)((gulong)spriv->heaps[i] + idx);
+				b2 = (hg_allocator_block_t *)((hg_quark_t)spriv->heaps[i] + idx);
 				if (b1->size != b2->size ||
 				    b1->age != b2->age) {
 					if (g_hash_table_lookup_extended(references,
@@ -984,10 +984,10 @@
 				j += aligned_size - 1;
 			} else if (!f1 && f2) {
 				hg_allocator_block_t *b2;
-				gsize k, check_size;
-				gsize idx = j * BLOCK_SIZE;
-
-				b2 = (hg_allocator_block_t *)((gulong)spriv->heaps[i] + idx);
+				hg_usize_t k, check_size;
+				hg_usize_t idx = j * BLOCK_SIZE;
+
+				b2 = (hg_allocator_block_t *)((hg_quark_t)spriv->heaps[i] + idx);
 				check_size = aligned_size = HG_ALIGNED_TO (b2->size, BLOCK_SIZE) / BLOCK_SIZE;
 				check_size--;
 				for (k = j + 1; check_size > 0 && k < priv->bitmap->size[i]; k++) {
@@ -1011,14 +1011,14 @@
 		for (j = 0; j < spriv->bitmap->size[i]; j++) {
 			if (_hg_allocator_bitmap_is_marked(spriv->bitmap, i, j + 1)) {
 				hg_allocator_block_t *block;
-				gsize aligned_size;
+				hg_usize_t aligned_size;

 				block = _hg_allocator_get_internal_block_from_page_and_index(priv, i, j + 1, FALSE);
 				if (block == NULL)
 					goto error;
 				if (block->is_restorable) {
-					memcpy((((gchar *)priv->heaps[i]) + j * BLOCK_SIZE),
-					       (((gchar *)spriv->heaps[i]) + j * BLOCK_SIZE),
+					memcpy((((hg_char_t *)priv->heaps[i]) + j * BLOCK_SIZE),
+					       (((hg_char_t *)spriv->heaps[i]) + j * BLOCK_SIZE),
 					       block->size);
 				}
 				aligned_size = HG_ALIGNED_TO (block->size, BLOCK_SIZE) / BLOCK_SIZE;
@@ -1045,11 +1045,11 @@
 }

 static void
-_hg_allocator_destroy_snapshot(hg_allocator_data_t    *data,
+_hg_allocator_destroy_snapshot(hg_allocator_data_t          *data,
 			       hg_allocator_snapshot_data_t *snapshot)
 {
 	hg_allocator_snapshot_private_t *spriv = (hg_allocator_snapshot_private_t *)snapshot;
-	gsize i, max_page = hg_allocator_get_max_page();
+	hg_usize_t i, max_page = hg_allocator_get_max_page();

 	_hg_allocator_bitmap_destroy(spriv->bitmap);
 	for (i = 0; i < max_page; i++) {


Fixed a few more issues with the _ec() calls.

--- libcelt/celt.c
+++ libcelt/celt.c
@@ -467,9 +467,13 @@
    if (i<2)
       ec_enc_uint(enc, flag_bits, 4);
    else if (i<6)
-      ec_enc_uint(enc, flag_bits, 16);
-   else
-      ec_enc_uint(enc, flag_bits, 8);
+   {
+      ec_enc_uint(enc, flag_bits>>2, 4);
+      ec_enc_uint(enc, flag_bits&0x3, 4);
+   } else {
+      ec_enc_uint(enc, flag_bits>>1, 4);
+      ec_enc_uint(enc, flag_bits&0x1, 2);
+   }
 }

 static void decode_flags(ec_dec *dec, int *intra_ener, int *has_pitch, int *shortBlocks, int *has_fold)
@@ -748,7 +752,7 @@
       enc = &_enc;
       nbFilledBytes=0;
    } else {
-      nbFilledBytes=ec_enc_tell(enc, 0);
+      nbFilledBytes=(ec_enc_tell(enc, 0)+4)>>3;
    }
    nbAvailableBytes = nbCompressedBytes - nbFilledBytes;

@@ -1700,7 +1704,7 @@
       dec = &_dec;
       nbFilledBytes = 0;
    } else {
-      nbFilledBytes = ec_dec_tell(dec, 0);
+      nbFilledBytes = (ec_dec_tell(dec, 0)+4)>>3;
    }
    nbAvailableBytes = len-nbFilledBytes;


Updated the CellML API to version 1.11 RC1 on Windows x86.

--- src/plugins/api/CellMLAPI/src/cda_compiler_support.h
+++ src/plugins/api/CellMLAPI/src/cda_compiler_support.h
@@ -46,17 +46,6 @@
 private:
   T* mPtr;
 };
-
-static void
-operator<<(std::ostream& data, const std::wstring& str)
-{
-  size_t n = wcstombs(NULL, str.c_str(), 0);
-  char* buf = new char[n + 1];
-  wcstombs(buf, str.c_str(), n + 1);
-  data << buf;
-  delete [] buf;
-}
-

 #ifdef _MSC_VER
 #undef WIN32


changing probability of first tf resolution symbol

--- libcelt/celt.c
+++ libcelt/celt.c
@@ -579,8 +579,10 @@
    for (i=1;i<len-1;i++)
       if (tf_res[i] != tf_res[i-1] && tf_res[i] != tf_res[i+1])
          tf_res[i] = tf_res[i+1];
-   curr = 0;
-   for (i=0;i<len;i++)
+
+   ec_enc_bit_prob(enc, tf_res[0], isTransient ? 64 : 16);
+   curr = tf_res[0];
+   for (i=1;i<len;i++)
    {
       ec_enc_bit_prob(enc, tf_res[i], curr ? 240: 16);
       curr = tf_res[i];
@@ -591,13 +593,14 @@
 static void tf_decode(int len, int C, int isTransient, int *tf_res, ec_dec *dec)
 {
    int i, curr;
-   curr = 0;
-   for (i=0;i<len;i++)
+
+   tf_res[0] = ec_dec_bit_prob(dec, isTransient ? 64 : 16);
+   curr = tf_res[0];
+   for (i=1;i<len;i++)
    {
       tf_res[i] = ec_dec_bit_prob(dec, curr ? 240: 16);
       curr = tf_res[i];
    }
-
 }

 #ifdef FIXED_POINT


Update writer release to use revamped locking macros

--- source/adios2/toolkit/sst/cp/cp_writer.c
+++ source/adios2/toolkit/sst/cp/cp_writer.c
@@ -1491,13 +1491,13 @@
     if ((Stream->ConfigParams->CPCommPattern == SstCPCommPeer) ||
         (Stream->Rank == 0))
     {
-        PTHREAD_MUTEX_LOCK(&Stream->DataLock);
+        STREAM_MUTEX_LOCK(Stream)
         if (Stream->ReleaseCount > 0)
         {
-            SMPI_Bcast(&Stream->ReleaseCount, 1, MPI_INT, 0, Stream->mpiComm);
+            SMPI_Bcast(&Stream->ReleaseCount, 1, SMPI_INT, 0, Stream->mpiComm);
             SMPI_Bcast(Stream->ReleaseList,
                        Stream->ReleaseCount * sizeof(*(Stream->ReleaseList)),
-                       MPI_BYTE, 0, Stream->mpiComm);
+                       SMPI_BYTE, 0, Stream->mpiComm);
             Stream->ReleaseCount = 0;
             free(Stream->ReleaseList);
             Stream->ReleaseList = NULL;
@@ -1540,23 +1540,22 @@
             }
             /* NEED TO HANDLE FAILURE HERE */
             STREAM_CONDITION_WAIT(Stream);
-            SST_REAFFIRM_LOCKED_AFTER_CONDITION();
-            SMPI_Bcast(&Stream->ReleaseCount, 1, MPI_INT, 0, Stream->mpiComm);
+            SMPI_Bcast(&Stream->ReleaseCount, 1, SMPI_INT, 0, Stream->mpiComm);
             if (Stream->ReleaseCount > 0)
             {
                 SMPI_Bcast(Stream->ReleaseList,
                            Stream->ReleaseCount *
                                sizeof(*(Stream->ReleaseList)),
-                           MPI_BYTE, 0, Stream->mpiComm);
+                           SMPI_BYTE, 0, Stream->mpiComm);
                 Stream->ReleaseCount = 0;
                 free(Stream->ReleaseList);
                 Stream->ReleaseList = NULL;
             }
         }
         Stream->ReleaseCount = -1;
-        SMPI_Bcast(&Stream->ReleaseCount, 1, MPI_INT, 0, Stream->mpiComm);
+        SMPI_Bcast(&Stream->ReleaseCount, 1, SMPI_INT, 0, Stream->mpiComm);
         Stream->ReleaseCount = 0;
-        PTHREAD_MUTEX_UNLOCK(&Stream->DataLock);
+        STREAM_MUTEX_UNLOCK(Stream);
     }

     if (Stream->ConfigParams->CPCommPattern == SstCPCommMin)
@@ -1566,7 +1565,7 @@
             ReleaseData = malloc(sizeof(*ReleaseData));
             while (1)
             {
-                SMPI_Bcast(&ReleaseData->ReleaseCount, 1, MPI_INT, 0,
+                SMPI_Bcast(&ReleaseData->ReleaseCount, 1, SMPI_INT, 0,
                            Stream->mpiComm);
                 if (ReleaseData->ReleaseCount == -1)
                 {
@@ -1580,7 +1579,7 @@
                     SMPI_Bcast(ReleaseData->ReleaseList,
                                ReleaseData->ReleaseCount *
                                    sizeof(*(ReleaseData->ReleaseList)),
-                               MPI_BYTE, 0, Stream->mpiComm);
+                               SMPI_BYTE, 0, Stream->mpiComm);
                     ProcessReleaseList(Stream, ReleaseData);
                     free(ReleaseData->ReleaseList);
                     ReleaseData->ReleaseList = NULL;


Remove useless ec_dec_tell() call.

Remove useless ec_dec_tell() call.

--- libcelt/celt.c
+++ libcelt/celt.c
@@ -1987,7 +1987,6 @@
          qg = ec_dec_bits(dec, 2);
          postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
          postfilter_gain = QCONST16(.125f,15)*(qg+2);
-         tell = ec_dec_tell(dec, 0);
 #else /* ENABLE_POSTFILTER */
          RESTORE_STACK;
          return CELT_CORRUPTED_DATA;


- Bug, Don't crash is the assoc_apps is not initialized

SVN revision: 17958

--- src/bin/e_fileman_file.c
+++ src/bin/e_fileman_file.c
@@ -20,8 +20,8 @@
 static void _e_fm_file_free(E_Fm_File *file);

 /* TODO Make init and shutdown func that populates the assoc */
-static E_Config_DD *assoc_app_edd;
-static Evas_List   *assoc_apps;
+static E_Config_DD *assoc_app_edd = NULL;
+static Evas_List   *assoc_apps = NULL;

 #if 0
 	{
@@ -380,6 +380,8 @@
    E_Fm_Assoc_App *assoc;
    Ecore_Exe *exe;

+   if (!assoc_apps) return 0;
+
    for (l = assoc_apps; l; l = l->next)
      {
 	char *ext;


More fixed-point work on the time window -- including conversion of the gain to power-of-two.

--- libcelt/celt.c
+++ libcelt/celt.c
@@ -55,7 +55,17 @@
 static const float gainWindow[16] = {
    0.0085135, 0.0337639, 0.0748914, 0.1304955, 0.1986827, 0.2771308, 0.3631685, 0.4538658,
    0.5461342, 0.6368315, 0.7228692, 0.8013173, 0.8695045, 0.9251086, 0.9662361, 0.9914865};
-
+
+#ifdef FIXED_POINT
+static const celt_word16_t transientWindow[16] = {
+     279,  1106,  2454,  4276,  6510,  9081, 11900, 14872,
+   17896, 20868, 23687, 26258, 28492, 30314, 31662, 32489};
+#else
+static const float transientWindow[16] = {
+   0.0085135, 0.0337639, 0.0748914, 0.1304955, 0.1986827, 0.2771308, 0.3631685, 0.4538658,
+   0.5461342, 0.6368315, 0.7228692, 0.8013173, 0.8695045, 0.9251086, 0.9662361, 0.9914865};
+#endif
+
 /** Encoder state
  @brief Encoder state
  */
@@ -186,7 +196,7 @@
       float num, den;
       num = end[i]*i;
       den = (1000+begin[i])*(len-i)+.01*end[i]*len;
-      if (num*maxD > den*maxN && end[i] > .05*begin[i])
+      if ((num*maxD > den*maxN) && (end[i] > .05*begin[i]))
       {
          maxN = num;
          maxD = den;
@@ -262,7 +272,7 @@
 }

 /** Compute the IMDCT and apply window for all sub-frames and all channels in a frame */
-static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t *X, int transient_time, float transient_gain, celt_sig_t * restrict out_mem)
+static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t *X, int transient_time, int transient_shift, celt_sig_t * restrict out_mem)
 {
    int c, N4;
    const int C = CHANNELS(mode);
@@ -272,7 +282,7 @@
    for (c=0;c<C;c++)
    {
       int j;
-      if (transient_time<0 && C==1 && !shortBlocks) {
+      if (transient_shift==0 && C==1 && !shortBlocks) {
          const mdct_lookup *lookup = MDCT(mode);
          mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap);
       } else if (!shortBlocks) {
@@ -288,12 +298,19 @@
          /* Prevents problems from the imdct doing the overlap-add */
          CELT_MEMSET(x+N4, 0, overlap);
          mdct_backward(lookup, tmp, x, mode->window, overlap);
-         if (transient_time >= 0)
+         if (transient_shift > 0)
          {
+#ifdef FIXED_POINT
             for (j=0;j<16;j++)
-               x[N4+transient_time+j-16] *= 1+gainWindow[j]*(transient_gain-1);
+               x[N4+transient_time+j-16] *= 1-gainWindow[j]+gainWindow[j]*(1<<transient_shift);
             for (j=transient_time;j<N+overlap;j++)
-               x[N4+j] *= transient_gain;
+               x[N4+j] = SHL32(x[N4+j], transient_shift);
+#else
+            for (j=0;j<16;j++)
+               x[N4+transient_time+j-16] *= 1+gainWindow[j]*((1<<transient_shift)-1);
+            for (j=transient_time;j<N+overlap;j++)
+               x[N4+j] *= 1<<transient_shift;
+#endif
          }
          /* The first and last part would need to be set to zero if we actually
          wanted to use them. */
@@ -323,12 +340,19 @@
                tmp[j] = X[C*(j*B+b)+c];
             mdct_backward(lookup, tmp, x+N4+N2*b, mode->window, overlap);
          }
-         if (transient_time >= 0)
+         if (transient_shift > 0)
          {
+#ifdef FIXED_POINT
             for (j=0;j<16;j++)
-               x[N4+transient_time+j-16] *= 1+gainWindow[j]*(transient_gain-1);
+               x[N4+transient_time+j-16] = MULT16_32_Q15(SHR16(Q15_ONE-transientWindow[j],transient_shift)+transientWindow[j], SHL32(x[N4+transient_time+j-16],transient_shift));
             for (j=transient_time;j<N+overlap;j++)
-               x[N4+j] *= transient_gain;
+               x[N4+j] = SHL32(x[N4+j], transient_shift);
+#else
+            for (j=0;j<16;j++)
+               x[N4+transient_time+j-16] *= 1+gainWindow[j]*((1<<transient_shift)-1);
+            for (j=transient_time;j<N+overlap;j++)
+               x[N4+j] *= 1<<transient_shift;
+#endif
          }
          /* The first and last part would need to be set to zero if we actually
          wanted to use them. */
@@ -361,7 +385,7 @@
 #endif
    int shortBlocks=0;
    int transient_time;
-   float transient_gain;
+   int transient_shift;
    float maxR;
    const int C = CHANNELS(st->mode);
    SAVE_STACK;
@@ -397,35 +421,41 @@
       ec_enc_bits(&st->enc, 1, 1);
       if (maxR < 30)
       {
-         transient_time = 16;
-         transient_gain = 1;
-         ec_enc_bits(&st->enc, 0, 2);
+         transient_shift = 0;
       } else if (maxR < 100)
       {
-         transient_gain = 2;
-         ec_enc_bits(&st->enc, 1, 2);
+         transient_shift = 1;
       } else if (maxR < 500)
       {
-         transient_gain = 4;
-         ec_enc_bits(&st->enc, 2, 2);
+         transient_shift = 2;
       } else
       {
-         transient_gain = 8;
-         ec_enc_bits(&st->enc, 3, 2);
-      }
-      ec_enc_uint(&st->enc, transient_time, N+st->overlap);
-      for (c=0;c<C;c++)
-         for (i=0;i<16;i++)
-            in[C*(transient_time+i-16)+c] /= 1+gainWindow[i]*(transient_gain-1);
-      gain_1 = 1./transient_gain;
-      for (c=0;c<C;c++)
-         for (i=transient_time;i<N+st->overlap;i++)
-            in[C*i+c] *= gain_1;
+         transient_shift = 3;
+      }
+      ec_enc_bits(&st->enc, transient_shift, 2);
+      if (transient_shift)
+         ec_enc_uint(&st->enc, transient_time, N+st->overlap);
+      if (transient_shift)
+      {
+         for (c=0;c<C;c++)
+            for (i=0;i<16;i++)
+               in[C*(transient_time+i-16)+c] /= 1+gainWindow[i]*((1<<transient_shift)-1);
+#ifdef FIXED_POINT
+         for (c=0;c<C;c++)
+            for (i=transient_time;i<N+st->overlap;i++)
+               in[C*i+c] = SHR32(in[C*i+c], transient_shift);
+#else
+         gain_1 = 1./(1<<transient_shift);
+         for (c=0;c<C;c++)
+            for (i=transient_time;i<N+st->overlap;i++)
+               in[C*i+c] *= gain_1;
+#endif
+      }
       shortBlocks = 1;
    } else {
       ec_enc_bits(&st->enc, 0, 1);
       transient_time = -1;
-      transient_gain = 1;
+      transient_shift = 0;
       shortBlocks = 0;
    }
    /* Pitch analysis: we do it early to save on the peak stack space */
@@ -531,7 +561,7 @@

    CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));

-   compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_gain, st->out_mem);
+   compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem);
    /* De-emphasis and put everything back at the right place in the synthesis history */
 #ifndef SHORTCUTS
    for (c=0;c<C;c++)
@@ -729,7 +759,7 @@
    VARDECL(int, stereo_mode);
    int shortBlocks;
    int transient_time;
-   float transient_gain;
+   int transient_shift;
    const int C = CHANNELS(st->mode);
    SAVE_STACK;

@@ -763,26 +793,14 @@
    shortBlocks = ec_dec_bits(&dec, 1);
    if (shortBlocks)
    {
-      int gainid = ec_dec_bits(&dec, 2);
-      switch(gainid) {
-         case 0:
-            transient_gain = 1;
-            break;
-         case 1:
-            transient_gain = 2;
-            break;
-         case 2:
-            transient_gain = 4;
-            break;
-         case 3:
-         default:
-            transient_gain = 8;
-            break;
-      }
-      transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
+      transient_shift = ec_dec_bits(&dec, 2);
+      if (transient_shift)
+         transient_time = ec_dec_uint(&dec, N+st->mode->overlap);
+      else
+         transient_time = 0;
    } else {
       transient_time = -1;
-      transient_gain = 1;
+      transient_shift = 0;
    }
    /* Get the pitch gains */
    has_pitch = unquant_pitch(gains, st->mode->nbPBands, &dec);
@@ -828,7 +846,7 @@

    CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
    /* Compute inverse MDCTs */
-   compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_gain, st->out_mem);
+   compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem);

    for (c=0;c<C;c++)
    {


Add cast to char ** for wd->value to cleanup compiler warning.

SVN revision: 41440

--- src/bin/e_widget_ilist.c
+++ src/bin/e_widget_ilist.c
@@ -267,7 +267,7 @@
    e_widget_focus_hook_set(obj, _e_wid_focus_hook);
    e_widget_data_set(obj, wd);

-   wd->value = value;
+   wd->value = (char **)value;

    o = e_scrollframe_add(evas);
    wd->o_scrollframe = o;


Made twiddle pointer in mdct more explicit

--- libcelt/mdct.c
+++ libcelt/mdct.c
@@ -104,6 +104,7 @@
       const kiss_fft_scalar * restrict xp1 = in+N4;
       const kiss_fft_scalar * restrict xp2 = in+N2+N4-1;
       kiss_fft_scalar * restrict yp = out;
+      kiss_fft_scalar *t = &l->trig[0];
       for(i=0;i<N/8;i++)
       {
          kiss_fft_scalar re, im;
@@ -114,8 +115,9 @@
          xp2-=2;
          /* We could remove the HALF32 above and just use MULT16_32_Q16 below
             (MIXED_PRECISION only) */
-         *yp++ = S_MUL(re,l->trig[i])  -  S_MUL(im,l->trig[i+N4]);
-         *yp++ = S_MUL(im,l->trig[i])  +  S_MUL(re,l->trig[i+N4]);
+         *yp++ = S_MUL(re,t[0])  -  S_MUL(im,t[N4]);
+         *yp++ = S_MUL(im,t[0])  +  S_MUL(re,t[N4]);
+	 t++;
       }
       for(;i<N4;i++)
       {
@@ -127,8 +129,9 @@
          xp2-=2;
          /* We could remove the HALF32 above and just use MULT16_32_Q16 below
             (MIXED_PRECISION only) */
-         *yp++ = S_MUL(re,l->trig[i])  -  S_MUL(im,l->trig[i+N4]);
-         *yp++ = S_MUL(im,l->trig[i])  +  S_MUL(re,l->trig[i+N4]);
+         *yp++ = S_MUL(re,t[0])  -  S_MUL(im,t[N4]);
+         *yp++ = S_MUL(im,t[0])  +  S_MUL(re,t[N4]);
+	 t++;
       }
    }

@@ -141,14 +144,16 @@
       const kiss_fft_scalar * restrict fp = f;
       kiss_fft_scalar * restrict yp1 = out;
       kiss_fft_scalar * restrict yp2 = out+N2-1;
+      kiss_fft_scalar *t = &l->trig[0];
       /* Temp pointers to make it really clear to the compiler what we're doing */
       for(i=0;i<N4;i++)
       {
-         *yp1 = -S_MUL(fp[1],l->trig[i+N4]) + S_MUL(fp[0],l->trig[i]);
-         *yp2 = -S_MUL(fp[0],l->trig[i+N4]) - S_MUL(fp[1],l->trig[i]);
+         *yp1 = -S_MUL(fp[1],t[N4]) + S_MUL(fp[0],t[0]);
+         *yp2 = -S_MUL(fp[0],t[N4]) - S_MUL(fp[1],t[0]);
          fp += 2;
          yp1 += 2;
          yp2 -= 2;
+	 t++;
       }
    }
    RESTORE_STACK;
@@ -172,12 +177,14 @@
       const kiss_fft_scalar * restrict xp1 = in;
       const kiss_fft_scalar * restrict xp2 = in+N2-1;
       kiss_fft_scalar * restrict yp = out;
+      kiss_fft_scalar *t = &l->trig[0];
       for(i=0;i<N4;i++)
       {
-         *yp++ = -S_MUL(*xp2, l->trig[i])    - S_MUL(*xp1,l->trig[i+N4]);
-         *yp++ =  S_MUL(*xp2, l->trig[i+N4]) - S_MUL(*xp1,l->trig[i]);
+         *yp++ = -S_MUL(*xp2, t[0])  - S_MUL(*xp1,t[N4]);
+         *yp++ =  S_MUL(*xp2, t[N4]) - S_MUL(*xp1,t[0]);
          xp1+=2;
          xp2-=2;
+	 t++;
       }
    }


Custom modes fixes (got broken by the s/celt_alloc/opus_alloc/)

--- libcelt/rate.c
+++ libcelt/rate.c
@@ -84,7 +84,7 @@
    unsigned char *bits;
    unsigned char *cap;

-   cindex = celt_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2));
+   cindex = opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2));
    cache->index = cindex;

    /* Scan for all unique band sizes */
@@ -124,7 +124,7 @@
          }
       }
    }
-   bits = celt_alloc(sizeof(unsigned char)*curr);
+   bits = opus_alloc(sizeof(unsigned char)*curr);
    cache->bits = bits;
    cache->size = curr;
    /* Compute the cache for all unique sizes */
@@ -140,7 +140,7 @@

    /* Compute the maximum rate for each band at which we'll reliably use as
        many bits as we ask for. */
-   cache->caps = cap = celt_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands);
+   cache->caps = cap = opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands);
    for (i=0;i<=LM;i++)
    {
       for (C=1;C<=2;C++)


Added declarations for 3D API functions.

Signed-off-by: Alastair Lynn <4665d361aaf271b139147017031ea99df777ca5a@gmail.com>

--- Engine/Graphics/Graphics.h
+++ Engine/Graphics/Graphics.h
@@ -109,6 +109,45 @@
  * @param depth The depth of the star-field, for parallax
  */
 void DrawStarfield ( float depth );
+/**
+ * Draws a 3D object for ambient lighting
+ * @param centre The centre of the object
+ * @param ambient The ambient colour
+ * @param scale The scale of the object
+ * @param angle The angle of the object
+ * @param bank The bank of the object
+ */
+void DrawObject3DAmbient ( vec2 centre, colour ambient, float scale, float angle, float bank = 0.0f );
+/**
+ * Draws a 3D object for directional lighting
+ * @param centre The centre of the object
+ * @param light The light colour
+ * @param lightAngle The angle of the light
+ * @param scale The scale of the object
+ * @param angle The angle of the object
+ * @param bank The bank of the object
+ */
+void DrawObject3DDirectional ( vec2 centre, colour light, float lightAngle, float scale, float angle, float bank = 0.0f );
+/**
+ * Draws a 3D object for directional lighting
+ * @param centre The centre of the object
+ * @param light The light colour
+ * @param lightCentre The origin of the light
+ * @param lightRadius The radius of this light
+ * @param scale The scale of the object
+ * @param angle The angle of the object
+ * @param bank The bank of the object
+ */
+void DrawObject3DSpot ( vec2 centre, colour light, vec2 lightCentre, float lightRadius, float scale, float angle, float bank = 0.0f );
+/**
+ * Draws a 3D object for glow lighting
+ * @param centre The centre of the object
+ * @param glow The scale of the glow on the lighting
+ * @param scale The scale of the object
+ * @param angle The angle of the object
+ * @param bank The bank of the object
+ */
+void DrawObject3DAmbient ( vec2 centre, float glow, float scale, float angle, float bank = 0.0f );

 /**
  * Gives the aspect ratio of the screen


Update fprime.c

Update fprime.c

--- exam/fprime.c
+++ exam/fprime.c
@@ -43,5 +43,8 @@
     return 0;
   }
   // to be continued
+  int i;

+  i = atoi(argv[1]);
+  prime_factor(i);
 }


Mark FastPathStrongRelationLocks volatile.

Otherwise, the compiler might decide to move modifications to data
within this structure outside the enclosing SpinLockAcquire /
SpinLockRelease pair, leading to shared memory corruption.

This may or may not explain a recent lmgr-related buildfarm failure
on prairiedog, but it needs to be fixed either way.

--- src/backend/storage/lmgr/lock.c
+++ src/backend/storage/lmgr/lock.c
@@ -238,7 +238,7 @@
 	uint32		count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS];
 } FastPathStrongRelationLockData;

-static FastPathStrongRelationLockData *FastPathStrongRelationLocks;
+static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks;

 /*


allow ping

allow ping

--- libjl777/api.h
+++ libjl777/api.h
@@ -1828,7 +1828,7 @@
     static char *cosigned[] = { (char *)cosigned_func, "cosigned", "V", "seed", "result", "privacct", "pubacct", 0 };

     // IP comms
-    static char *ping[] = { (char *)ping_func, "ping", "V", "pubkey", "ipaddr", "port", "destip", "MMatrix", 0 };
+    static char *ping[] = { (char *)ping_func, "ping", "", "pubkey", "ipaddr", "port", "destip", "MMatrix", 0 };
     static char *pong[] = { (char *)pong_func, "pong", "V", "pubkey", "ipaddr", "port", "yourip", "yourport", "tag", "MMatrix", 0 };
     static char *sendfrag[] = { (char *)sendfrag_func, "sendfrag", "V", "pubkey", "name", "fragi", "numfrags", "ipaddr", "totalcrc", "datacrc", "data", "totallen", "blocksize", "handler", "syncmem", 0 };
     static char *gotfrag[] = { (char *)gotfrag_func, "gotfrag", "V", "pubkey", "name", "fragi", "numfrags", "ipaddr", "totalcrc", "datacrc", "totallen", "blocksize", "count", "handler", "syncmem", "snapshotcrc", 0 };


Sorting for the inet data type randomly returns the wrong result
when you have networks with the same prefix, but different netmasks.

This is due to the fact that occassionally there is random
(uninitialized?)
data in the extra bits past the point where the netmask cares about
them.

ie (real data from a real live database):

  10.0/10 == 00001010.00100000.00100000.00011000
  10.0/11 == 00001010.00000000.00000000.00000000
                        ^ Bad data, normally never seen

The v4bitncmp() function was only taking one bit length argument so
it would determine that the networks were different, even though
they really aren't (and the netmask test wouldn't be used).  This
ONLY happens if the tuple with the longer bit length is used as the
ip_bits() for the v4bitncmp call AND there happens to be junk data
in place in the shorter tuple.  Odd and random, but I saw it happen
a couple times so...

Ryan Mooney

--- src/backend/utils/adt/network.c
+++ src/backend/utils/adt/network.c
@@ -3,7 +3,7 @@
  *	is for IP V4 CIDR notation, but prepared for V6: just
  *	add the necessary bits where the comments indicate.
  *
- *	$Id: network.c,v 1.18 2000/02/21 18:49:54 tgl Exp $
+ *	$Id: network.c,v 1.19 2000/03/07 23:01:43 momjian Exp $
  *	Jon Postel RIP 16 Oct 1998
  */

@@ -18,7 +18,7 @@
 #include "postgres.h"
 #include "utils/builtins.h"

-static int	v4bitncmp(unsigned int a1, unsigned int a2, int bits);
+static int	v4bitncmp(unsigned int a1, unsigned int a2, int bits1, int bits2);

 /*
  *	Access macros.	Add IPV6 support.
@@ -137,7 +137,7 @@
 		return FALSE;
 	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
 	{
-		int			order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
+		int			order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1), ip_bits(a2));

 		return ((order < 0) || ((order == 0) && (ip_bits(a1) < ip_bits(a2))));
 	}
@@ -166,7 +166,7 @@
 	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
 	{
 		return ((ip_bits(a1) == ip_bits(a2))
-		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
+		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1), ip_bits(a2)) == 0));
 	}
 	else
 	{
@@ -192,7 +192,7 @@
 		return FALSE;
 	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
 	{
-		int			order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
+		int			order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1), ip_bits(a2));

 		return ((order > 0) || ((order == 0) && (ip_bits(a1) > ip_bits(a2))));
 	}
@@ -222,7 +222,7 @@
 	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
 	{
 		return ((ip_bits(a1) > ip_bits(a2))
-		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
+		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1), ip_bits(a2)) == 0));
 	}
 	else
 	{
@@ -242,7 +242,7 @@
 	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
 	{
 		return ((ip_bits(a1) >= ip_bits(a2))
-		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
+		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1), ip_bits(a2)) == 0));
 	}
 	else
 	{
@@ -262,7 +262,7 @@
 	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
 	{
 		return ((ip_bits(a1) < ip_bits(a2))
-		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
+		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1), ip_bits(a2)) == 0));
 	}
 	else
 	{
@@ -282,7 +282,7 @@
 	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
 	{
 		return ((ip_bits(a1) <= ip_bits(a2))
-		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
+		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1), ip_bits(a2)) == 0));
 	}
 	else
 	{
@@ -476,13 +476,16 @@
  */

 static int
-v4bitncmp(unsigned int a1, unsigned int a2, int bits)
+v4bitncmp(unsigned int a1, unsigned int a2, int bits1, int bits2)
 {
 	unsigned long mask = 0;
-	int			i;
+	int			i, bits;
+
+	bits=(bits1 < bits2) ? bits1 : bits2;

 	for (i = 0; i < bits; i++)
 		mask = (mask >> 1) | 0x80000000;
+
 	a1 = ntohl(a1);
 	a2 = ntohl(a2);
 	if ((a1 & mask) < (a2 & mask))