staticint rnbd_clt_parse_map_options(constchar *buf, size_t max_path_cnt, struct rnbd_map_options *opt)
{ char *options, *sep_opt; char *p;
substring_t args[MAX_OPT_ARGS]; int opt_mask = 0; int token; int ret = -EINVAL; int nr_poll_queues = 0; int dest_port = 0; int p_cnt = 0; int i;
options = kstrdup(buf, GFP_KERNEL); if (!options) return -ENOMEM;
sep_opt = strstrip(options); while ((p = strsep(&sep_opt, " ")) != NULL) { if (!*p) continue;
switch (token) { case RNBD_OPT_SESSNAME:
p = match_strdup(args); if (!p) {
ret = -ENOMEM; goto out;
} if (strlen(p) > NAME_MAX) {
pr_err("map_device: sessname too long\n");
ret = -EINVAL;
kfree(p); goto out;
}
strscpy(opt->sessname, p, NAME_MAX);
kfree(p); break;
case RNBD_OPT_PATH: if (p_cnt >= max_path_cnt) {
pr_err("map_device: too many (> %zu) paths provided\n",
max_path_cnt);
ret = -ENOMEM; goto out;
}
p = match_strdup(args); if (!p) {
ret = -ENOMEM; goto out;
}
ret = rtrs_addr_to_sockaddr(p, strlen(p),
*opt->dest_port,
&opt->paths[p_cnt]); if (ret) {
pr_err("Can't parse path %s: %d\n", p, ret);
kfree(p); goto out;
}
p_cnt++;
kfree(p); break;
case RNBD_OPT_DEV_PATH:
p = match_strdup(args); if (!p) {
ret = -ENOMEM; goto out;
} if (strlen(p) > NAME_MAX) {
pr_err("map_device: Device path too long\n");
ret = -EINVAL;
kfree(p); goto out;
}
strscpy(opt->pathname, p, NAME_MAX);
kfree(p); break;
case RNBD_OPT_DEST_PORT: if (match_int(args, &dest_port) || dest_port < 0 ||
dest_port > 65535) {
pr_err("bad destination port number parameter '%d'\n",
dest_port);
ret = -EINVAL; goto out;
}
*opt->dest_port = dest_port; break;
case RNBD_OPT_ACCESS_MODE:
p = match_strdup(args); if (!p) {
ret = -ENOMEM; goto out;
}
case RNBD_OPT_NR_POLL_QUEUES: if (match_int(args, &nr_poll_queues) || nr_poll_queues < -1 ||
nr_poll_queues > (int)nr_cpu_ids) {
pr_err("bad nr_poll_queues parameter '%d'\n",
nr_poll_queues);
ret = -EINVAL; goto out;
} if (nr_poll_queues == -1)
nr_poll_queues = nr_cpu_ids;
*opt->nr_poll_queues = nr_poll_queues; break;
default:
pr_err("map_device: Unknown parameter or missing value '%s'\n",
p);
ret = -EINVAL; goto out;
}
}
for (i = 0; i < ARRAY_SIZE(rnbd_opt_mandatory); i++) { if ((opt_mask & rnbd_opt_mandatory[i])) {
ret = 0;
} else {
pr_err("map_device: Parameters missing\n");
ret = -EINVAL; break;
}
}
dev = container_of(kobj, struct rnbd_clt_dev, kobj);
switch (dev->dev_state) { case DEV_STATE_INIT: return sysfs_emit(page, "init\n"); case DEV_STATE_MAPPED: /* TODO fix cli tool before changing to proper state */ return sysfs_emit(page, "open\n"); case DEV_STATE_MAPPED_DISCONNECTED: /* TODO fix cli tool before changing to proper state */ return sysfs_emit(page, "closed\n"); case DEV_STATE_UNMAPPED: return sysfs_emit(page, "unmapped\n"); default: return sysfs_emit(page, "unknown\n");
}
}
opt = kstrdup(buf, GFP_KERNEL); if (!opt) return -ENOMEM;
options = strstrip(opt);
dev = container_of(kobj, struct rnbd_clt_dev, kobj); if (sysfs_streq(options, "normal")) {
force = false;
} elseif (sysfs_streq(options, "force")) {
force = true;
} else {
rnbd_clt_err(dev, "unmap_device: Invalid value: %s\n",
options);
err = -EINVAL; goto out;
}
rnbd_clt_info(dev, "Unmapping device, option: %s.\n",
force ? "force" : "normal");
/* * We take explicit module reference only for one reason: do not * race with lockless rnbd_destroy_sessions().
*/ if (!try_module_get(THIS_MODULE)) {
err = -ENODEV; goto out;
}
err = rnbd_clt_unmap_device(dev, force, &attr->attr); if (err) { if (err != -EALREADY)
rnbd_clt_err(dev, "unmap_device: %d\n", err); goto module_put;
}
void rnbd_clt_remove_dev_symlink(struct rnbd_clt_dev *dev)
{ /* * The module unload rnbd_client_exit path is racing with unmapping of * the last single device from the sysfs manually * i.e. rnbd_clt_unmap_dev_store() leading to a sysfs warning because * of sysfs link already was removed already.
*/ if (dev->blk_symlink_name) { if (try_module_get(THIS_MODULE)) {
sysfs_remove_link(rnbd_devs_kobj, dev->blk_symlink_name);
module_put(THIS_MODULE);
} /* It should be freed always. */
kfree(dev->blk_symlink_name);
dev->blk_symlink_name = NULL;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.