aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/nvmfd/devices.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/nvmfd/devices.c')
-rw-r--r--usr.sbin/nvmfd/devices.c386
1 files changed, 0 insertions, 386 deletions
diff --git a/usr.sbin/nvmfd/devices.c b/usr.sbin/nvmfd/devices.c
deleted file mode 100644
index fafc1077f207..000000000000
--- a/usr.sbin/nvmfd/devices.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2023-2024 Chelsio Communications, Inc.
- * Written by: John Baldwin <jhb@FreeBSD.org>
- */
-
-#include <sys/disk.h>
-#include <sys/gsb_crc32.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <net/ieee_oui.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libnvmf.h>
-#include <libutil.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "internal.h"
-
-#define RAMDISK_PREFIX "ramdisk:"
-
-struct backing_device {
- enum { RAMDISK, FILE, CDEV } type;
- union {
- int fd; /* FILE, CDEV */
- void *mem; /* RAMDISK */
- };
- u_int sector_size;
- uint64_t nlbas;
- uint64_t eui64;
-};
-
-static struct backing_device *devices;
-static u_int ndevices;
-
-static uint64_t
-generate_eui64(uint32_t low)
-{
- return (OUI_FREEBSD_NVME_LOW << 16 | low);
-}
-
-static uint32_t
-crc32(const void *buf, size_t len)
-{
- return (calculate_crc32c(0xffffffff, buf, len) ^ 0xffffffff);
-}
-
-static void
-init_ramdisk(const char *config, struct backing_device *dev)
-{
- static uint32_t ramdisk_idx = 1;
- uint64_t num;
-
- dev->type = RAMDISK;
- dev->sector_size = 512;
- if (expand_number(config, &num))
- errx(1, "Invalid ramdisk specification: %s", config);
- if ((num % dev->sector_size) != 0)
- errx(1, "Invalid ramdisk size %ju", (uintmax_t)num);
- dev->mem = calloc(num, 1);
- dev->nlbas = num / dev->sector_size;
- dev->eui64 = generate_eui64('M' << 24 | ramdisk_idx++);
-}
-
-static void
-init_filedevice(const char *config, int fd, struct stat *sb,
- struct backing_device *dev)
-{
- dev->type = FILE;
- dev->fd = fd;
- dev->sector_size = 512;
- if ((sb->st_size % dev->sector_size) != 0)
- errx(1, "File size is not a multiple of 512: %s", config);
- dev->nlbas = sb->st_size / dev->sector_size;
- dev->eui64 = generate_eui64('F' << 24 |
- (crc32(config, strlen(config)) & 0xffffff));
-}
-
-static void
-init_chardevice(const char *config, int fd, struct backing_device *dev)
-{
- off_t len;
-
- dev->type = CDEV;
- dev->fd = fd;
- if (ioctl(fd, DIOCGSECTORSIZE, &dev->sector_size) != 0)
- err(1, "Failed to fetch sector size for %s", config);
- if (ioctl(fd, DIOCGMEDIASIZE, &len) != 0)
- err(1, "Failed to fetch sector size for %s", config);
- dev->nlbas = len / dev->sector_size;
- dev->eui64 = generate_eui64('C' << 24 |
- (crc32(config, strlen(config)) & 0xffffff));
-}
-
-static void
-init_device(const char *config, struct backing_device *dev)
-{
- struct stat sb;
- int fd;
-
- /* Check for a RAM disk. */
- if (strncmp(RAMDISK_PREFIX, config, strlen(RAMDISK_PREFIX)) == 0) {
- init_ramdisk(config + strlen(RAMDISK_PREFIX), dev);
- return;
- }
-
- fd = open(config, O_RDWR);
- if (fd == -1)
- err(1, "Failed to open %s", config);
- if (fstat(fd, &sb) == -1)
- err(1, "fstat");
- switch (sb.st_mode & S_IFMT) {
- case S_IFCHR:
- init_chardevice(config, fd, dev);
- break;
- case S_IFREG:
- init_filedevice(config, fd, &sb, dev);
- break;
- default:
- errx(1, "Invalid file type for %s", config);
- }
-}
-
-void
-register_devices(int ac, char **av)
-{
- ndevices = ac;
- devices = calloc(ndevices, sizeof(*devices));
-
- for (int i = 0; i < ac; i++)
- init_device(av[i], &devices[i]);
-}
-
-u_int
-device_count(void)
-{
- return (ndevices);
-}
-
-static struct backing_device *
-lookup_device(uint32_t nsid)
-{
- if (nsid == 0 || nsid > ndevices)
- return (NULL);
- return (&devices[nsid - 1]);
-}
-
-void
-device_active_nslist(uint32_t nsid, struct nvme_ns_list *nslist)
-{
- u_int count;
-
- memset(nslist, 0, sizeof(*nslist));
- count = 0;
- nsid++;
- while (nsid <= ndevices) {
- nslist->ns[count] = htole32(nsid);
- count++;
- if (count == nitems(nslist->ns))
- break;
- nsid++;
- }
-}
-
-bool
-device_identification_descriptor(uint32_t nsid, void *buf)
-{
- struct backing_device *dev;
- char *p;
-
- dev = lookup_device(nsid);
- if (dev == NULL)
- return (false);
-
- memset(buf, 0, 4096);
-
- p = buf;
-
- /* EUI64 */
- *p++ = 1;
- *p++ = 8;
- p += 2;
- be64enc(p, dev->eui64);
- return (true);
-}
-
-bool
-device_namespace_data(uint32_t nsid, struct nvme_namespace_data *nsdata)
-{
- struct backing_device *dev;
-
- dev = lookup_device(nsid);
- if (dev == NULL)
- return (false);
-
- memset(nsdata, 0, sizeof(*nsdata));
- nsdata->nsze = htole64(dev->nlbas);
- nsdata->ncap = nsdata->nsze;
- nsdata->nuse = nsdata->ncap;
- nsdata->nlbaf = 1 - 1;
- nsdata->flbas = NVMEF(NVME_NS_DATA_FLBAS_FORMAT, 0);
- nsdata->lbaf[0] = NVMEF(NVME_NS_DATA_LBAF_LBADS,
- ffs(dev->sector_size) - 1);
-
- be64enc(nsdata->eui64, dev->eui64);
- return (true);
-}
-
-static bool
-read_buffer(int fd, void *buf, size_t len, off_t offset)
-{
- ssize_t nread;
- char *dst;
-
- dst = buf;
- while (len > 0) {
- nread = pread(fd, dst, len, offset);
- if (nread == -1 && errno == EINTR)
- continue;
- if (nread <= 0)
- return (false);
- dst += nread;
- len -= nread;
- offset += nread;
- }
- return (true);
-}
-
-void
-device_read(uint32_t nsid, uint64_t lba, u_int nlb,
- const struct nvmf_capsule *nc)
-{
- struct backing_device *dev;
- char *p, *src;
- off_t off;
- size_t len;
-
- dev = lookup_device(nsid);
- if (dev == NULL) {
- nvmf_send_generic_error(nc,
- NVME_SC_INVALID_NAMESPACE_OR_FORMAT);
- return;
- }
-
- if (lba + nlb < lba || lba + nlb > dev->nlbas) {
- nvmf_send_generic_error(nc, NVME_SC_LBA_OUT_OF_RANGE);
- return;
- }
-
- off = lba * dev->sector_size;
- len = nlb * dev->sector_size;
- if (nvmf_capsule_data_len(nc) != len) {
- nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD);
- return;
- }
-
- if (dev->type == RAMDISK) {
- p = NULL;
- src = (char *)dev->mem + off;
- } else {
- p = malloc(len);
- if (!read_buffer(dev->fd, p, len, off)) {
- free(p);
- nvmf_send_generic_error(nc,
- NVME_SC_INTERNAL_DEVICE_ERROR);
- return;
- }
- src = p;
- }
-
- nvmf_send_controller_data(nc, src, len);
- free(p);
-}
-
-static bool
-write_buffer(int fd, const void *buf, size_t len, off_t offset)
-{
- ssize_t nwritten;
- const char *src;
-
- src = buf;
- while (len > 0) {
- nwritten = pwrite(fd, src, len, offset);
- if (nwritten == -1 && errno == EINTR)
- continue;
- if (nwritten <= 0)
- return (false);
- src += nwritten;
- len -= nwritten;
- offset += nwritten;
- }
- return (true);
-}
-
-void
-device_write(uint32_t nsid, uint64_t lba, u_int nlb,
- const struct nvmf_capsule *nc)
-{
- struct backing_device *dev;
- char *p, *dst;
- off_t off;
- size_t len;
- int error;
-
- dev = lookup_device(nsid);
- if (dev == NULL) {
- nvmf_send_generic_error(nc,
- NVME_SC_INVALID_NAMESPACE_OR_FORMAT);
- return;
- }
-
- if (lba + nlb < lba || lba + nlb > dev->nlbas) {
- nvmf_send_generic_error(nc, NVME_SC_LBA_OUT_OF_RANGE);
- return;
- }
-
- off = lba * dev->sector_size;
- len = nlb * dev->sector_size;
- if (nvmf_capsule_data_len(nc) != len) {
- nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD);
- return;
- }
-
- if (dev->type == RAMDISK) {
- p = NULL;
- dst = (char *)dev->mem + off;
- } else {
- p = malloc(len);
- dst = p;
- }
-
- error = nvmf_receive_controller_data(nc, 0, dst, len);
- if (error != 0) {
- nvmf_send_generic_error(nc, NVME_SC_TRANSIENT_TRANSPORT_ERROR);
- free(p);
- return;
- }
-
- if (dev->type != RAMDISK) {
- if (!write_buffer(dev->fd, p, len, off)) {
- free(p);
- nvmf_send_generic_error(nc,
- NVME_SC_INTERNAL_DEVICE_ERROR);
- return;
- }
- }
- free(p);
- nvmf_send_success(nc);
-}
-
-void
-device_flush(uint32_t nsid, const struct nvmf_capsule *nc)
-{
- struct backing_device *dev;
-
- dev = lookup_device(nsid);
- if (dev == NULL) {
- nvmf_send_generic_error(nc,
- NVME_SC_INVALID_NAMESPACE_OR_FORMAT);
- return;
- }
-
- switch (dev->type) {
- case RAMDISK:
- break;
- case FILE:
- if (fdatasync(dev->fd) == -1) {
- nvmf_send_error(nc, NVME_SCT_MEDIA_ERROR,
- NVME_SC_WRITE_FAULTS);
- return;
- }
- break;
- case CDEV:
- if (ioctl(dev->fd, DIOCGFLUSH) == -1) {
- nvmf_send_error(nc, NVME_SCT_MEDIA_ERROR,
- NVME_SC_WRITE_FAULTS);
- return;
- }
- }
-
- nvmf_send_success(nc);
-}