1*a8089ea5SJohn Baldwin /*- 2*a8089ea5SJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause 3*a8089ea5SJohn Baldwin * 4*a8089ea5SJohn Baldwin * Copyright (c) 2023-2024 Chelsio Communications, Inc. 5*a8089ea5SJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 6*a8089ea5SJohn Baldwin */ 7*a8089ea5SJohn Baldwin 8*a8089ea5SJohn Baldwin #include <sys/disk.h> 9*a8089ea5SJohn Baldwin #include <sys/gsb_crc32.h> 10*a8089ea5SJohn Baldwin #include <sys/ioctl.h> 11*a8089ea5SJohn Baldwin #include <sys/stat.h> 12*a8089ea5SJohn Baldwin #include <net/ieee_oui.h> 13*a8089ea5SJohn Baldwin #include <err.h> 14*a8089ea5SJohn Baldwin #include <errno.h> 15*a8089ea5SJohn Baldwin #include <fcntl.h> 16*a8089ea5SJohn Baldwin #include <libnvmf.h> 17*a8089ea5SJohn Baldwin #include <libutil.h> 18*a8089ea5SJohn Baldwin #include <stdlib.h> 19*a8089ea5SJohn Baldwin #include <string.h> 20*a8089ea5SJohn Baldwin #include <unistd.h> 21*a8089ea5SJohn Baldwin 22*a8089ea5SJohn Baldwin #include "internal.h" 23*a8089ea5SJohn Baldwin 24*a8089ea5SJohn Baldwin #define RAMDISK_PREFIX "ramdisk:" 25*a8089ea5SJohn Baldwin 26*a8089ea5SJohn Baldwin struct backing_device { 27*a8089ea5SJohn Baldwin enum { RAMDISK, FILE, CDEV } type; 28*a8089ea5SJohn Baldwin union { 29*a8089ea5SJohn Baldwin int fd; /* FILE, CDEV */ 30*a8089ea5SJohn Baldwin void *mem; /* RAMDISK */ 31*a8089ea5SJohn Baldwin }; 32*a8089ea5SJohn Baldwin u_int sector_size; 33*a8089ea5SJohn Baldwin uint64_t nlbas; 34*a8089ea5SJohn Baldwin uint64_t eui64; 35*a8089ea5SJohn Baldwin }; 36*a8089ea5SJohn Baldwin 37*a8089ea5SJohn Baldwin static struct backing_device *devices; 38*a8089ea5SJohn Baldwin static u_int ndevices; 39*a8089ea5SJohn Baldwin 40*a8089ea5SJohn Baldwin static uint64_t 41*a8089ea5SJohn Baldwin generate_eui64(uint32_t low) 42*a8089ea5SJohn Baldwin { 43*a8089ea5SJohn Baldwin return (OUI_FREEBSD_NVME_LOW << 16 | low); 44*a8089ea5SJohn Baldwin } 45*a8089ea5SJohn Baldwin 46*a8089ea5SJohn Baldwin static uint32_t 47*a8089ea5SJohn Baldwin crc32(const void *buf, size_t len) 48*a8089ea5SJohn Baldwin { 49*a8089ea5SJohn Baldwin return (calculate_crc32c(0xffffffff, buf, len) ^ 0xffffffff); 50*a8089ea5SJohn Baldwin } 51*a8089ea5SJohn Baldwin 52*a8089ea5SJohn Baldwin static void 53*a8089ea5SJohn Baldwin init_ramdisk(const char *config, struct backing_device *dev) 54*a8089ea5SJohn Baldwin { 55*a8089ea5SJohn Baldwin static uint32_t ramdisk_idx = 1; 56*a8089ea5SJohn Baldwin uint64_t num; 57*a8089ea5SJohn Baldwin 58*a8089ea5SJohn Baldwin dev->type = RAMDISK; 59*a8089ea5SJohn Baldwin dev->sector_size = 512; 60*a8089ea5SJohn Baldwin if (expand_number(config, &num)) 61*a8089ea5SJohn Baldwin errx(1, "Invalid ramdisk specification: %s", config); 62*a8089ea5SJohn Baldwin if ((num % dev->sector_size) != 0) 63*a8089ea5SJohn Baldwin errx(1, "Invalid ramdisk size %ju", (uintmax_t)num); 64*a8089ea5SJohn Baldwin dev->mem = calloc(num, 1); 65*a8089ea5SJohn Baldwin dev->nlbas = num / dev->sector_size; 66*a8089ea5SJohn Baldwin dev->eui64 = generate_eui64('M' << 24 | ramdisk_idx++); 67*a8089ea5SJohn Baldwin } 68*a8089ea5SJohn Baldwin 69*a8089ea5SJohn Baldwin static void 70*a8089ea5SJohn Baldwin init_filedevice(const char *config, int fd, struct stat *sb, 71*a8089ea5SJohn Baldwin struct backing_device *dev) 72*a8089ea5SJohn Baldwin { 73*a8089ea5SJohn Baldwin dev->type = FILE; 74*a8089ea5SJohn Baldwin dev->fd = fd; 75*a8089ea5SJohn Baldwin dev->sector_size = 512; 76*a8089ea5SJohn Baldwin if ((sb->st_size % dev->sector_size) != 0) 77*a8089ea5SJohn Baldwin errx(1, "File size is not a multiple of 512: %s", config); 78*a8089ea5SJohn Baldwin dev->nlbas = sb->st_size / dev->sector_size; 79*a8089ea5SJohn Baldwin dev->eui64 = generate_eui64('F' << 24 | 80*a8089ea5SJohn Baldwin (crc32(config, strlen(config)) & 0xffffff)); 81*a8089ea5SJohn Baldwin } 82*a8089ea5SJohn Baldwin 83*a8089ea5SJohn Baldwin static void 84*a8089ea5SJohn Baldwin init_chardevice(const char *config, int fd, struct backing_device *dev) 85*a8089ea5SJohn Baldwin { 86*a8089ea5SJohn Baldwin off_t len; 87*a8089ea5SJohn Baldwin 88*a8089ea5SJohn Baldwin dev->type = CDEV; 89*a8089ea5SJohn Baldwin dev->fd = fd; 90*a8089ea5SJohn Baldwin if (ioctl(fd, DIOCGSECTORSIZE, &dev->sector_size) != 0) 91*a8089ea5SJohn Baldwin err(1, "Failed to fetch sector size for %s", config); 92*a8089ea5SJohn Baldwin if (ioctl(fd, DIOCGMEDIASIZE, &len) != 0) 93*a8089ea5SJohn Baldwin err(1, "Failed to fetch sector size for %s", config); 94*a8089ea5SJohn Baldwin dev->nlbas = len / dev->sector_size; 95*a8089ea5SJohn Baldwin dev->eui64 = generate_eui64('C' << 24 | 96*a8089ea5SJohn Baldwin (crc32(config, strlen(config)) & 0xffffff)); 97*a8089ea5SJohn Baldwin } 98*a8089ea5SJohn Baldwin 99*a8089ea5SJohn Baldwin static void 100*a8089ea5SJohn Baldwin init_device(const char *config, struct backing_device *dev) 101*a8089ea5SJohn Baldwin { 102*a8089ea5SJohn Baldwin struct stat sb; 103*a8089ea5SJohn Baldwin int fd; 104*a8089ea5SJohn Baldwin 105*a8089ea5SJohn Baldwin /* Check for a RAM disk. */ 106*a8089ea5SJohn Baldwin if (strncmp(RAMDISK_PREFIX, config, strlen(RAMDISK_PREFIX)) == 0) { 107*a8089ea5SJohn Baldwin init_ramdisk(config + strlen(RAMDISK_PREFIX), dev); 108*a8089ea5SJohn Baldwin return; 109*a8089ea5SJohn Baldwin } 110*a8089ea5SJohn Baldwin 111*a8089ea5SJohn Baldwin fd = open(config, O_RDWR); 112*a8089ea5SJohn Baldwin if (fd == -1) 113*a8089ea5SJohn Baldwin err(1, "Failed to open %s", config); 114*a8089ea5SJohn Baldwin if (fstat(fd, &sb) == -1) 115*a8089ea5SJohn Baldwin err(1, "fstat"); 116*a8089ea5SJohn Baldwin switch (sb.st_mode & S_IFMT) { 117*a8089ea5SJohn Baldwin case S_IFCHR: 118*a8089ea5SJohn Baldwin init_chardevice(config, fd, dev); 119*a8089ea5SJohn Baldwin break; 120*a8089ea5SJohn Baldwin case S_IFREG: 121*a8089ea5SJohn Baldwin init_filedevice(config, fd, &sb, dev); 122*a8089ea5SJohn Baldwin break; 123*a8089ea5SJohn Baldwin default: 124*a8089ea5SJohn Baldwin errx(1, "Invalid file type for %s", config); 125*a8089ea5SJohn Baldwin } 126*a8089ea5SJohn Baldwin } 127*a8089ea5SJohn Baldwin 128*a8089ea5SJohn Baldwin void 129*a8089ea5SJohn Baldwin register_devices(int ac, char **av) 130*a8089ea5SJohn Baldwin { 131*a8089ea5SJohn Baldwin ndevices = ac; 132*a8089ea5SJohn Baldwin devices = calloc(ndevices, sizeof(*devices)); 133*a8089ea5SJohn Baldwin 134*a8089ea5SJohn Baldwin for (int i = 0; i < ac; i++) 135*a8089ea5SJohn Baldwin init_device(av[i], &devices[i]); 136*a8089ea5SJohn Baldwin } 137*a8089ea5SJohn Baldwin 138*a8089ea5SJohn Baldwin u_int 139*a8089ea5SJohn Baldwin device_count(void) 140*a8089ea5SJohn Baldwin { 141*a8089ea5SJohn Baldwin return (ndevices); 142*a8089ea5SJohn Baldwin } 143*a8089ea5SJohn Baldwin 144*a8089ea5SJohn Baldwin static struct backing_device * 145*a8089ea5SJohn Baldwin lookup_device(uint32_t nsid) 146*a8089ea5SJohn Baldwin { 147*a8089ea5SJohn Baldwin if (nsid == 0 || nsid > ndevices) 148*a8089ea5SJohn Baldwin return (NULL); 149*a8089ea5SJohn Baldwin return (&devices[nsid - 1]); 150*a8089ea5SJohn Baldwin } 151*a8089ea5SJohn Baldwin 152*a8089ea5SJohn Baldwin void 153*a8089ea5SJohn Baldwin device_active_nslist(uint32_t nsid, struct nvme_ns_list *nslist) 154*a8089ea5SJohn Baldwin { 155*a8089ea5SJohn Baldwin u_int count; 156*a8089ea5SJohn Baldwin 157*a8089ea5SJohn Baldwin memset(nslist, 0, sizeof(*nslist)); 158*a8089ea5SJohn Baldwin count = 0; 159*a8089ea5SJohn Baldwin nsid++; 160*a8089ea5SJohn Baldwin while (nsid <= ndevices) { 161*a8089ea5SJohn Baldwin nslist->ns[count] = htole32(nsid); 162*a8089ea5SJohn Baldwin count++; 163*a8089ea5SJohn Baldwin if (count == nitems(nslist->ns)) 164*a8089ea5SJohn Baldwin break; 165*a8089ea5SJohn Baldwin nsid++; 166*a8089ea5SJohn Baldwin } 167*a8089ea5SJohn Baldwin } 168*a8089ea5SJohn Baldwin 169*a8089ea5SJohn Baldwin bool 170*a8089ea5SJohn Baldwin device_identification_descriptor(uint32_t nsid, void *buf) 171*a8089ea5SJohn Baldwin { 172*a8089ea5SJohn Baldwin struct backing_device *dev; 173*a8089ea5SJohn Baldwin char *p; 174*a8089ea5SJohn Baldwin 175*a8089ea5SJohn Baldwin dev = lookup_device(nsid); 176*a8089ea5SJohn Baldwin if (dev == NULL) 177*a8089ea5SJohn Baldwin return (false); 178*a8089ea5SJohn Baldwin 179*a8089ea5SJohn Baldwin memset(buf, 0, 4096); 180*a8089ea5SJohn Baldwin 181*a8089ea5SJohn Baldwin p = buf; 182*a8089ea5SJohn Baldwin 183*a8089ea5SJohn Baldwin /* EUI64 */ 184*a8089ea5SJohn Baldwin *p++ = 1; 185*a8089ea5SJohn Baldwin *p++ = 8; 186*a8089ea5SJohn Baldwin p += 2; 187*a8089ea5SJohn Baldwin be64enc(p, dev->eui64); 188*a8089ea5SJohn Baldwin return (true); 189*a8089ea5SJohn Baldwin } 190*a8089ea5SJohn Baldwin 191*a8089ea5SJohn Baldwin bool 192*a8089ea5SJohn Baldwin device_namespace_data(uint32_t nsid, struct nvme_namespace_data *nsdata) 193*a8089ea5SJohn Baldwin { 194*a8089ea5SJohn Baldwin struct backing_device *dev; 195*a8089ea5SJohn Baldwin 196*a8089ea5SJohn Baldwin dev = lookup_device(nsid); 197*a8089ea5SJohn Baldwin if (dev == NULL) 198*a8089ea5SJohn Baldwin return (false); 199*a8089ea5SJohn Baldwin 200*a8089ea5SJohn Baldwin memset(nsdata, 0, sizeof(*nsdata)); 201*a8089ea5SJohn Baldwin nsdata->nsze = htole64(dev->nlbas); 202*a8089ea5SJohn Baldwin nsdata->ncap = nsdata->nsze; 203*a8089ea5SJohn Baldwin nsdata->nuse = nsdata->ncap; 204*a8089ea5SJohn Baldwin nsdata->nlbaf = 1 - 1; 205*a8089ea5SJohn Baldwin nsdata->flbas = NVMEF(NVME_NS_DATA_FLBAS_FORMAT, 0); 206*a8089ea5SJohn Baldwin nsdata->lbaf[0] = NVMEF(NVME_NS_DATA_LBAF_LBADS, 207*a8089ea5SJohn Baldwin ffs(dev->sector_size) - 1); 208*a8089ea5SJohn Baldwin 209*a8089ea5SJohn Baldwin be64enc(nsdata->eui64, dev->eui64); 210*a8089ea5SJohn Baldwin return (true); 211*a8089ea5SJohn Baldwin } 212*a8089ea5SJohn Baldwin 213*a8089ea5SJohn Baldwin static bool 214*a8089ea5SJohn Baldwin read_buffer(int fd, void *buf, size_t len, off_t offset) 215*a8089ea5SJohn Baldwin { 216*a8089ea5SJohn Baldwin ssize_t nread; 217*a8089ea5SJohn Baldwin char *dst; 218*a8089ea5SJohn Baldwin 219*a8089ea5SJohn Baldwin dst = buf; 220*a8089ea5SJohn Baldwin while (len > 0) { 221*a8089ea5SJohn Baldwin nread = pread(fd, dst, len, offset); 222*a8089ea5SJohn Baldwin if (nread == -1 && errno == EINTR) 223*a8089ea5SJohn Baldwin continue; 224*a8089ea5SJohn Baldwin if (nread <= 0) 225*a8089ea5SJohn Baldwin return (false); 226*a8089ea5SJohn Baldwin dst += nread; 227*a8089ea5SJohn Baldwin len -= nread; 228*a8089ea5SJohn Baldwin offset += nread; 229*a8089ea5SJohn Baldwin } 230*a8089ea5SJohn Baldwin return (true); 231*a8089ea5SJohn Baldwin } 232*a8089ea5SJohn Baldwin 233*a8089ea5SJohn Baldwin void 234*a8089ea5SJohn Baldwin device_read(uint32_t nsid, uint64_t lba, u_int nlb, 235*a8089ea5SJohn Baldwin const struct nvmf_capsule *nc) 236*a8089ea5SJohn Baldwin { 237*a8089ea5SJohn Baldwin struct backing_device *dev; 238*a8089ea5SJohn Baldwin char *p, *src; 239*a8089ea5SJohn Baldwin off_t off; 240*a8089ea5SJohn Baldwin size_t len; 241*a8089ea5SJohn Baldwin 242*a8089ea5SJohn Baldwin dev = lookup_device(nsid); 243*a8089ea5SJohn Baldwin if (dev == NULL) { 244*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, 245*a8089ea5SJohn Baldwin NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 246*a8089ea5SJohn Baldwin return; 247*a8089ea5SJohn Baldwin } 248*a8089ea5SJohn Baldwin 249*a8089ea5SJohn Baldwin if (lba + nlb < lba || lba + nlb > dev->nlbas) { 250*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, NVME_SC_LBA_OUT_OF_RANGE); 251*a8089ea5SJohn Baldwin return; 252*a8089ea5SJohn Baldwin } 253*a8089ea5SJohn Baldwin 254*a8089ea5SJohn Baldwin off = lba * dev->sector_size; 255*a8089ea5SJohn Baldwin len = nlb * dev->sector_size; 256*a8089ea5SJohn Baldwin if (nvmf_capsule_data_len(nc) != len) { 257*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD); 258*a8089ea5SJohn Baldwin return; 259*a8089ea5SJohn Baldwin } 260*a8089ea5SJohn Baldwin 261*a8089ea5SJohn Baldwin if (dev->type == RAMDISK) { 262*a8089ea5SJohn Baldwin p = NULL; 263*a8089ea5SJohn Baldwin src = (char *)dev->mem + off; 264*a8089ea5SJohn Baldwin } else { 265*a8089ea5SJohn Baldwin p = malloc(len); 266*a8089ea5SJohn Baldwin if (!read_buffer(dev->fd, p, len, off)) { 267*a8089ea5SJohn Baldwin free(p); 268*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, 269*a8089ea5SJohn Baldwin NVME_SC_INTERNAL_DEVICE_ERROR); 270*a8089ea5SJohn Baldwin return; 271*a8089ea5SJohn Baldwin } 272*a8089ea5SJohn Baldwin src = p; 273*a8089ea5SJohn Baldwin } 274*a8089ea5SJohn Baldwin 275*a8089ea5SJohn Baldwin nvmf_send_controller_data(nc, src, len); 276*a8089ea5SJohn Baldwin free(p); 277*a8089ea5SJohn Baldwin } 278*a8089ea5SJohn Baldwin 279*a8089ea5SJohn Baldwin static bool 280*a8089ea5SJohn Baldwin write_buffer(int fd, const void *buf, size_t len, off_t offset) 281*a8089ea5SJohn Baldwin { 282*a8089ea5SJohn Baldwin ssize_t nwritten; 283*a8089ea5SJohn Baldwin const char *src; 284*a8089ea5SJohn Baldwin 285*a8089ea5SJohn Baldwin src = buf; 286*a8089ea5SJohn Baldwin while (len > 0) { 287*a8089ea5SJohn Baldwin nwritten = pwrite(fd, src, len, offset); 288*a8089ea5SJohn Baldwin if (nwritten == -1 && errno == EINTR) 289*a8089ea5SJohn Baldwin continue; 290*a8089ea5SJohn Baldwin if (nwritten <= 0) 291*a8089ea5SJohn Baldwin return (false); 292*a8089ea5SJohn Baldwin src += nwritten; 293*a8089ea5SJohn Baldwin len -= nwritten; 294*a8089ea5SJohn Baldwin offset += nwritten; 295*a8089ea5SJohn Baldwin } 296*a8089ea5SJohn Baldwin return (true); 297*a8089ea5SJohn Baldwin } 298*a8089ea5SJohn Baldwin 299*a8089ea5SJohn Baldwin void 300*a8089ea5SJohn Baldwin device_write(uint32_t nsid, uint64_t lba, u_int nlb, 301*a8089ea5SJohn Baldwin const struct nvmf_capsule *nc) 302*a8089ea5SJohn Baldwin { 303*a8089ea5SJohn Baldwin struct backing_device *dev; 304*a8089ea5SJohn Baldwin char *p, *dst; 305*a8089ea5SJohn Baldwin off_t off; 306*a8089ea5SJohn Baldwin size_t len; 307*a8089ea5SJohn Baldwin int error; 308*a8089ea5SJohn Baldwin 309*a8089ea5SJohn Baldwin dev = lookup_device(nsid); 310*a8089ea5SJohn Baldwin if (dev == NULL) { 311*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, 312*a8089ea5SJohn Baldwin NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 313*a8089ea5SJohn Baldwin return; 314*a8089ea5SJohn Baldwin } 315*a8089ea5SJohn Baldwin 316*a8089ea5SJohn Baldwin if (lba + nlb < lba || lba + nlb > dev->nlbas) { 317*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, NVME_SC_LBA_OUT_OF_RANGE); 318*a8089ea5SJohn Baldwin return; 319*a8089ea5SJohn Baldwin } 320*a8089ea5SJohn Baldwin 321*a8089ea5SJohn Baldwin off = lba * dev->sector_size; 322*a8089ea5SJohn Baldwin len = nlb * dev->sector_size; 323*a8089ea5SJohn Baldwin if (nvmf_capsule_data_len(nc) != len) { 324*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD); 325*a8089ea5SJohn Baldwin return; 326*a8089ea5SJohn Baldwin } 327*a8089ea5SJohn Baldwin 328*a8089ea5SJohn Baldwin if (dev->type == RAMDISK) { 329*a8089ea5SJohn Baldwin p = NULL; 330*a8089ea5SJohn Baldwin dst = (char *)dev->mem + off; 331*a8089ea5SJohn Baldwin } else { 332*a8089ea5SJohn Baldwin p = malloc(len); 333*a8089ea5SJohn Baldwin dst = p; 334*a8089ea5SJohn Baldwin } 335*a8089ea5SJohn Baldwin 336*a8089ea5SJohn Baldwin error = nvmf_receive_controller_data(nc, 0, dst, len); 337*a8089ea5SJohn Baldwin if (error != 0) { 338*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, NVME_SC_TRANSIENT_TRANSPORT_ERROR); 339*a8089ea5SJohn Baldwin free(p); 340*a8089ea5SJohn Baldwin return; 341*a8089ea5SJohn Baldwin } 342*a8089ea5SJohn Baldwin 343*a8089ea5SJohn Baldwin if (dev->type != RAMDISK) { 344*a8089ea5SJohn Baldwin if (!write_buffer(dev->fd, p, len, off)) { 345*a8089ea5SJohn Baldwin free(p); 346*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, 347*a8089ea5SJohn Baldwin NVME_SC_INTERNAL_DEVICE_ERROR); 348*a8089ea5SJohn Baldwin return; 349*a8089ea5SJohn Baldwin } 350*a8089ea5SJohn Baldwin } 351*a8089ea5SJohn Baldwin free(p); 352*a8089ea5SJohn Baldwin nvmf_send_success(nc); 353*a8089ea5SJohn Baldwin } 354*a8089ea5SJohn Baldwin 355*a8089ea5SJohn Baldwin void 356*a8089ea5SJohn Baldwin device_flush(uint32_t nsid, const struct nvmf_capsule *nc) 357*a8089ea5SJohn Baldwin { 358*a8089ea5SJohn Baldwin struct backing_device *dev; 359*a8089ea5SJohn Baldwin 360*a8089ea5SJohn Baldwin dev = lookup_device(nsid); 361*a8089ea5SJohn Baldwin if (dev == NULL) { 362*a8089ea5SJohn Baldwin nvmf_send_generic_error(nc, 363*a8089ea5SJohn Baldwin NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 364*a8089ea5SJohn Baldwin return; 365*a8089ea5SJohn Baldwin } 366*a8089ea5SJohn Baldwin 367*a8089ea5SJohn Baldwin switch (dev->type) { 368*a8089ea5SJohn Baldwin case RAMDISK: 369*a8089ea5SJohn Baldwin break; 370*a8089ea5SJohn Baldwin case FILE: 371*a8089ea5SJohn Baldwin if (fdatasync(dev->fd) == -1) { 372*a8089ea5SJohn Baldwin nvmf_send_error(nc, NVME_SCT_MEDIA_ERROR, 373*a8089ea5SJohn Baldwin NVME_SC_WRITE_FAULTS); 374*a8089ea5SJohn Baldwin return; 375*a8089ea5SJohn Baldwin } 376*a8089ea5SJohn Baldwin break; 377*a8089ea5SJohn Baldwin case CDEV: 378*a8089ea5SJohn Baldwin if (ioctl(dev->fd, DIOCGFLUSH) == -1) { 379*a8089ea5SJohn Baldwin nvmf_send_error(nc, NVME_SCT_MEDIA_ERROR, 380*a8089ea5SJohn Baldwin NVME_SC_WRITE_FAULTS); 381*a8089ea5SJohn Baldwin return; 382*a8089ea5SJohn Baldwin } 383*a8089ea5SJohn Baldwin } 384*a8089ea5SJohn Baldwin 385*a8089ea5SJohn Baldwin nvmf_send_success(nc); 386*a8089ea5SJohn Baldwin } 387