module_param_named(port_nr, port_nr, ushort, 0444);
MODULE_PARM_DESC(port_nr, "The port number the server is listening on (default: "
__stringify(RTRS_PORT)")");
module_param_cb(dev_search_path, &dev_search_path_ops,
&dev_search_path_kparam_str, 0444);
MODULE_PARM_DESC(dev_search_path, "Sets the dev_search_path. When a device is mapped this path is prepended to the device path from the map device operation. If %SESSNAME% is specified in a path, then device will be searched in a session namespace. (default: "
DEFAULT_DEV_SEARCH_PATH ")");
mutex_destroy(&dev->lock); if (dev->dev_kobj.state_in_sysfs) /* * Destroy kobj only if it was really created.
*/
rnbd_srv_destroy_dev_sysfs(dev); else
kfree(dev);
}
if (keep_id) /* free the resources for the id but don't */ /* allow to re-use the id itself because it */ /* is still used by the client */
xa_cmpxchg(&sess_dev->sess->index_idr, sess_dev->device_id,
sess_dev, NULL, 0); else
xa_erase(&sess_dev->sess->index_idr, sess_dev->device_id);
synchronize_rcu();
sess_dev->destroy_comp = &dc;
rnbd_put_sess_dev(sess_dev);
wait_for_completion(&dc); /* wait for inflights to drop to zero */
fput(sess_dev->bdev_file);
mutex_lock(&sess_dev->dev->lock);
list_del(&sess_dev->dev_list); if (!sess_dev->readonly)
sess_dev->dev->open_write_cnt--;
mutex_unlock(&sess_dev->dev->lock);
switch (type) { case RNBD_MSG_IO: return process_rdma(srv_sess, id, data, datalen, usr, usrlen); case RNBD_MSG_CLOSE:
process_msg_close(srv_sess, data, datalen, usr, usrlen); break; case RNBD_MSG_OPEN:
ret = process_msg_open(srv_sess, usr, usrlen, data, datalen); break; case RNBD_MSG_SESS_INFO:
process_msg_sess_info(srv_sess, usr, usrlen, data, datalen); break; default:
pr_warn("Received unexpected message type %d from session %s\n",
type, srv_sess->sessname); return -EINVAL;
}
/* * Since ret is passed to rtrs to handle the failure case, we * just return 0 at the end otherwise callers in rtrs would call * send_io_resp_imm again to print redundant err message.
*/
rtrs_srv_resp_rdma(id, ret); return 0;
}
spin_lock(&dev_lock);
list_for_each_entry(dev, &dev_list, list) { if (!strncmp(dev->name, new_dev->name, sizeof(dev->name))) { if (!kref_get_unless_zero(&dev->kref)) /* * We lost the race, device is almost dead. * Continue traversing to find a valid one.
*/ continue;
spin_unlock(&dev_lock); return dev;
}
}
list_add(&new_dev->list, &dev_list);
spin_unlock(&dev_lock);
return new_dev;
}
staticint rnbd_srv_check_update_open_perm(struct rnbd_srv_dev *srv_dev, struct rnbd_srv_session *srv_sess, enum rnbd_access_mode access_mode)
{ int ret = 0;
mutex_lock(&srv_dev->lock);
switch (access_mode) { case RNBD_ACCESS_RO: break; case RNBD_ACCESS_RW: if (srv_dev->open_write_cnt == 0) {
srv_dev->open_write_cnt++;
} else {
pr_err("Mapping device '%s' for session %s with RW permissions failed. Device already opened as 'RW' by %d client(s), access mode %s.\n",
srv_dev->name, srv_sess->sessname,
srv_dev->open_write_cnt,
rnbd_access_modes[access_mode].str);
ret = -EPERM;
} break; case RNBD_ACCESS_MIGRATION: if (srv_dev->open_write_cnt < 2) {
srv_dev->open_write_cnt++;
} else {
pr_err("Mapping device '%s' for session %s with migration permissions failed. Device already opened as 'RW' by %d client(s), access mode %s.\n",
srv_dev->name, srv_sess->sessname,
srv_dev->open_write_cnt,
rnbd_access_modes[access_mode].str);
ret = -EPERM;
} break; default:
pr_err("Received mapping request for device '%s' on session %s with invalid access mode: %d\n",
srv_dev->name, srv_sess->sessname, access_mode);
ret = -EINVAL;
}
full_path = kmalloc(PATH_MAX, GFP_KERNEL); if (!full_path) return ERR_PTR(-ENOMEM);
/* * Replace %SESSNAME% with a real session name in order to * create device namespace.
*/
a = strnstr(dev_search_path, "%SESSNAME%", sizeof(dev_search_path)); if (a) {
len = a - dev_search_path;
len = snprintf(full_path, PATH_MAX, "%.*s/%s/%s", len,
dev_search_path, srv_sess->sessname, dev_name);
} else {
len = snprintf(full_path, PATH_MAX, "%s/%s",
dev_search_path, dev_name);
} if (len >= PATH_MAX) {
pr_err("Too long path: %s, %s, %s\n",
dev_search_path, srv_sess->sessname, dev_name);
kfree(full_path); return ERR_PTR(-EINVAL);
}
/** * find_srv_sess_dev() - a dev is already opened by this name * @srv_sess: the session to search. * @dev_name: string containing the name of the device. * * Return struct rnbd_srv_sess_dev if srv_sess already opened the dev_name * NULL if the session didn't open the device yet.
*/ staticstruct rnbd_srv_sess_dev *
find_srv_sess_dev(struct rnbd_srv_session *srv_sess, constchar *dev_name)
{ struct rnbd_srv_sess_dev *sess_dev; unsignedlong index;
if (xa_empty(&srv_sess->index_idr)) return NULL;
xa_for_each(&srv_sess->index_idr, index, sess_dev) if (!strcmp(sess_dev->pathname, dev_name)) return sess_dev;
/* Create the srv_dev sysfs files if they haven't been created yet. The * reason to delay the creation is not to create the sysfs files before * we are sure the device can be opened.
*/
mutex_lock(&srv_dev->lock); if (!srv_dev->dev_kobj.state_in_sysfs) {
ret = rnbd_srv_create_dev_sysfs(srv_dev, file_bdev(bdev_file)); if (ret) {
mutex_unlock(&srv_dev->lock);
rnbd_srv_err(srv_sess_dev, "Opening device failed, failed to create device sysfs files, err: %d\n",
ret); goto free_srv_sess_dev;
}
}
ret = rnbd_srv_create_dev_session_sysfs(srv_sess_dev); if (ret) {
mutex_unlock(&srv_dev->lock);
rnbd_srv_err(srv_sess_dev, "Opening device failed, failed to create dev client sysfs files, err: %d\n",
ret); goto free_srv_sess_dev;
}
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.