/* * cuse_info is populated and used to register the cuse device. vhost_net_device_ops are * also passed when the device is registered in main.c. */ int register_cuse_device(const char *base_name, int index, struct vhost_net_device_ops const * const pops) { struct cuse_info cuse_info; char device_name[PATH_MAX] = ""; char char_device_name[PATH_MAX] = ""; const char *device_argv[] = { device_name }; char fuse_opt_dummy[] = FUSE_OPT_DUMMY; char fuse_opt_fore[] = FUSE_OPT_FORE; char fuse_opt_nomulti[] = FUSE_OPT_NOMULTI; char *fuse_argv[] = {fuse_opt_dummy, fuse_opt_fore, fuse_opt_nomulti}; if (access(cuse_device_name, R_OK | W_OK) < 0) { RTE_LOG(ERR, CONFIG, "Character device %s can't be accessed, maybe not exist\n", cuse_device_name); return -1; } /* * The device name is created. This is passed to QEMU so that it can register * the device with our application. The index allows us to have multiple instances * of userspace vhost which we can then add devices to separately. */ if (strncmp(base_name, default_cdev, PATH_MAX)!=0) { rte_snprintf(device_name, PATH_MAX, "DEVNAME=%s-%d", base_name, index); rte_snprintf(char_device_name, PATH_MAX, "/dev/%s-%d", base_name, index); } else { rte_snprintf(device_name, PATH_MAX, "DEVNAME=%s", base_name); rte_snprintf(char_device_name, PATH_MAX, "/dev/%s", base_name); } /* Check if device already exists. */ if (access(char_device_name, F_OK) != -1) { RTE_LOG(ERR, CONFIG, "Character device %s already exists\n", char_device_name); return -1; } memset(&cuse_info, 0, sizeof(cuse_info)); cuse_info.dev_major = default_major; cuse_info.dev_minor = default_minor + index; cuse_info.dev_info_argc = 1; cuse_info.dev_info_argv = device_argv; cuse_info.flags = CUSE_UNRESTRICTED_IOCTL; ops = pops; session = cuse_lowlevel_setup(3, fuse_argv, &cuse_info, &vhost_net_ops, 0, NULL); if (session == NULL) return -1; return 0; }
/* * cuse_info is populated and used to register the cuse device. * vhost_net_device_ops are also passed when the device is registered in app. */ int rte_vhost_driver_register(const char *dev_name) { struct cuse_info cuse_info; char device_name[PATH_MAX] = ""; char char_device_name[PATH_MAX] = ""; const char *device_argv[] = { device_name }; char fuse_opt_dummy[] = FUSE_OPT_DUMMY; char fuse_opt_fore[] = FUSE_OPT_FORE; char fuse_opt_nomulti[] = FUSE_OPT_NOMULTI; char *fuse_argv[] = {fuse_opt_dummy, fuse_opt_fore, fuse_opt_nomulti}; if (access(cuse_device_name, R_OK | W_OK) < 0) { RTE_LOG(ERR, VHOST_CONFIG, "char device %s can't be accessed, maybe not exist\n", cuse_device_name); return -1; } if (eventfd_init() < 0) return -1; /* * The device name is created. This is passed to QEMU so that it can * register the device with our application. */ snprintf(device_name, PATH_MAX, "DEVNAME=%s", dev_name); snprintf(char_device_name, PATH_MAX, "/dev/%s", dev_name); /* Check if device already exists. */ if (access(char_device_name, F_OK) != -1) { RTE_LOG(ERR, VHOST_CONFIG, "char device %s already exists\n", char_device_name); return -1; } memset(&cuse_info, 0, sizeof(cuse_info)); cuse_info.dev_major = default_major; cuse_info.dev_minor = default_minor; cuse_info.dev_info_argc = 1; cuse_info.dev_info_argv = device_argv; cuse_info.flags = CUSE_UNRESTRICTED_IOCTL; session = cuse_lowlevel_setup(3, fuse_argv, &cuse_info, &vhost_net_ops, 0, NULL); if (session == NULL) return -1; return 0; }
int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci, const struct cuse_lowlevel_ops *clop, void *userdata) { struct fuse_session *se; int multithreaded; int res; se = cuse_lowlevel_setup(argc, argv, ci, clop, &multithreaded, userdata); if (se == NULL) return 1; if (multithreaded) res = fuse_session_loop_mt(se); else res = fuse_session_loop(se); cuse_lowlevel_teardown(se); if (res == -1) return 1; return 0; }