module_param_named(zone_max_active, g_zone_max_active, uint, 0444);
 MODULE_PARM_DESC(zone_max_active, "Maximum number of active zones when block device is zoned. Default: 0 (no limit)");
 
+static int g_zone_append_max_sectors = INT_MAX;
+module_param_named(zone_append_max_sectors, g_zone_append_max_sectors, int, 0444);
+MODULE_PARM_DESC(zone_append_max_sectors,
+                "Maximum size of a zone append command (in 512B sectors). Specify 0 for zone append emulation");
+
 static struct nullb_device *null_alloc_dev(void);
 static void null_free_dev(struct nullb_device *dev);
 static void null_del_dev(struct nullb *nullb);
 NULLB_DEVICE_ATTR(zone_nr_conv, uint, NULL);
 NULLB_DEVICE_ATTR(zone_max_open, uint, NULL);
 NULLB_DEVICE_ATTR(zone_max_active, uint, NULL);
+NULLB_DEVICE_ATTR(zone_append_max_sectors, uint, NULL);
 NULLB_DEVICE_ATTR(virt_boundary, bool, NULL);
 NULLB_DEVICE_ATTR(no_sched, bool, NULL);
 NULLB_DEVICE_ATTR(shared_tags, bool, NULL);
        &nullb_device_attr_zone_nr_conv,
        &nullb_device_attr_zone_max_open,
        &nullb_device_attr_zone_max_active,
+       &nullb_device_attr_zone_append_max_sectors,
        &nullb_device_attr_zone_readonly,
        &nullb_device_attr_zone_offline,
        &nullb_device_attr_virt_boundary,
                        "shared_tags,size,submit_queues,use_per_node_hctx,"
                        "virt_boundary,zoned,zone_capacity,zone_max_active,"
                        "zone_max_open,zone_nr_conv,zone_offline,zone_readonly,"
-                       "zone_size\n");
+                       "zone_size,zone_append_max_sectors\n");
 }
 
 CONFIGFS_ATTR_RO(memb_group_, features);
        dev->zone_nr_conv = g_zone_nr_conv;
        dev->zone_max_open = g_zone_max_open;
        dev->zone_max_active = g_zone_max_active;
+       dev->zone_append_max_sectors = g_zone_append_max_sectors;
        dev->virt_boundary = g_virt_boundary;
        dev->no_sched = g_no_sched;
        dev->shared_tags = g_shared_tags;
 
                        dev->zone_nr_conv);
        }
 
+       dev->zone_append_max_sectors =
+               min(ALIGN_DOWN(dev->zone_append_max_sectors,
+                              dev->blocksize >> SECTOR_SHIFT),
+                   zone_capacity_sects);
+
        /* Max active zones has to be < nbr of seq zones in order to be enforceable */
        if (dev->zone_max_active >= dev->nr_zones - dev->zone_nr_conv) {
                dev->zone_max_active = 0;
 
        lim->zoned = true;
        lim->chunk_sectors = dev->zone_size_sects;
-       lim->max_zone_append_sectors = dev->zone_size_sects;
+       lim->max_zone_append_sectors = dev->zone_append_max_sectors;
        lim->max_open_zones = dev->zone_max_open;
        lim->max_active_zones = dev->zone_max_active;
        return 0;
 int null_register_zoned_dev(struct nullb *nullb)
 {
        struct request_queue *q = nullb->q;
+       struct gendisk *disk = nullb->disk;
 
        blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
-       nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0);
-       return blk_revalidate_disk_zones(nullb->disk, NULL);
+       disk->nr_zones = bdev_nr_zones(disk->part0);
+
+       pr_info("%s: using %s zone append\n",
+               disk->disk_name,
+               queue_emulates_zone_append(q) ? "emulated" : "native");
+
+       return blk_revalidate_disk_zones(disk, NULL);
 }
 
 void null_free_zoned_dev(struct nullb_device *dev)
 
        trace_nullb_zone_op(cmd, zno, zone->cond);
 
+       if (WARN_ON_ONCE(append && !dev->zone_append_max_sectors))
+               return BLK_STS_IOERR;
+
        if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) {
                if (append)
                        return BLK_STS_IOERR;