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
generate_eui64(uint32_t low)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
crc32(const void * buf,size_t len)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
init_ramdisk(const char * config,struct backing_device * dev)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
init_filedevice(const char * config,int fd,struct stat * sb,struct backing_device * dev)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
init_chardevice(const char * config,int fd,struct backing_device * dev)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
init_device(const char * config,struct backing_device * dev)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
register_devices(int ac,char ** av)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
device_count(void)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 *
lookup_device(uint32_t nsid)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
device_active_nslist(uint32_t nsid,struct nvme_ns_list * nslist)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
device_identification_descriptor(uint32_t nsid,void * buf)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
device_namespace_data(uint32_t nsid,struct nvme_namespace_data * nsdata)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
read_buffer(int fd,void * buf,size_t len,off_t offset)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
device_read(uint32_t nsid,uint64_t lba,u_int nlb,const struct nvmf_capsule * nc)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
write_buffer(int fd,const void * buf,size_t len,off_t offset)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
device_write(uint32_t nsid,uint64_t lba,u_int nlb,const struct nvmf_capsule * nc)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
device_flush(uint32_t nsid,const struct nvmf_capsule * nc)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