xref: /freebsd/usr.sbin/nvmfd/devices.c (revision a8089ea5aee578e08acab2438e82fc9a9ae50ed8)
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