// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (c) 2015, Sony Mobile Communications Inc. * Copyright (c) 2013, The Linux Foundation. All rights reserved. * Copyright (c) 2020, Linaro Ltd.
*/
node = node_get(qrtr_ns.local_node); if (!node) return 0;
/* Announce the list of servers registered in this node */
xa_for_each(&node->servers, index, srv) {
ret = service_announce_new(sq, srv); if (ret < 0) { if (ret == -ENODEV) continue;
pr_err("failed to announce new service\n"); return ret;
}
} return 0;
}
/* Delete the old server on the same port */
old = xa_store(&node->servers, port, srv, GFP_KERNEL); if (old) { if (xa_is_err(old)) {
pr_err("failed to add server [0x%x:0x%x] ret:%d\n",
srv->service, srv->instance, xa_err(old)); goto err;
} else {
kfree(old);
}
}
/* Local DEL_CLIENT messages comes from the port being closed */ if (from->sq_node == qrtr_ns.local_node && from->sq_port != port) return -EINVAL;
/* Remove any lookups by this client */
list_for_each_safe(li, tmp, &qrtr_ns.lookups) {
lookup = container_of(li, struct qrtr_lookup, li); if (lookup->sq.sq_node != node_id) continue; if (lookup->sq.sq_port != port) continue;
list_del(&lookup->li);
kfree(lookup);
}
/* Remove the server belonging to this port but don't broadcast * DEL_SERVER. Neighbours would've already removed the server belonging * to this port due to the DEL_CLIENT broadcast from qrtr_port_remove().
*/
node = node_get(node_id); if (node)
server_del(node, port, false);
/* Advertise the removal of this client to all local servers */
local_node = node_get(qrtr_ns.local_node); if (!local_node) return 0;
/* Ignore specified node and port for local servers */ if (from->sq_node == qrtr_ns.local_node) {
node_id = from->sq_node;
port = from->sq_port;
}
srv = server_add(service, instance, node_id, port); if (!srv) return -EINVAL;
if (srv->node == qrtr_ns.local_node) {
ret = service_announce_new(&qrtr_ns.bcast_sq, srv); if (ret < 0) {
pr_err("failed to announce new service\n"); return ret;
}
}
/* Notify any potential lookups about the new server */
list_for_each(li, &qrtr_ns.lookups) {
lookup = container_of(li, struct qrtr_lookup, li); if (lookup->service && lookup->service != service) continue; if (lookup->instance && lookup->instance != instance) continue;
ret = 0; switch (cmd) { case QRTR_TYPE_HELLO:
ret = ctrl_cmd_hello(&sq); break; case QRTR_TYPE_BYE:
ret = ctrl_cmd_bye(&sq); break; case QRTR_TYPE_DEL_CLIENT:
ret = ctrl_cmd_del_client(&sq,
le32_to_cpu(pkt->client.node),
le32_to_cpu(pkt->client.port)); break; case QRTR_TYPE_NEW_SERVER:
ret = ctrl_cmd_new_server(&sq,
le32_to_cpu(pkt->server.service),
le32_to_cpu(pkt->server.instance),
le32_to_cpu(pkt->server.node),
le32_to_cpu(pkt->server.port)); break; case QRTR_TYPE_DEL_SERVER:
ret = ctrl_cmd_del_server(&sq,
le32_to_cpu(pkt->server.service),
le32_to_cpu(pkt->server.instance),
le32_to_cpu(pkt->server.node),
le32_to_cpu(pkt->server.port)); break; case QRTR_TYPE_EXIT: case QRTR_TYPE_PING: case QRTR_TYPE_RESUME_TX: break; case QRTR_TYPE_NEW_LOOKUP:
ret = ctrl_cmd_new_lookup(&sq,
le32_to_cpu(pkt->server.service),
le32_to_cpu(pkt->server.instance)); break; case QRTR_TYPE_DEL_LOOKUP:
ctrl_cmd_del_lookup(&sq,
le32_to_cpu(pkt->server.service),
le32_to_cpu(pkt->server.instance)); break;
}
if (ret < 0)
pr_err("failed while handling packet from %d:%d",
sq.sq_node, sq.sq_port);
}
ret = say_hello(&qrtr_ns.bcast_sq); if (ret < 0) goto err_wq;
/* As the qrtr ns socket owner and creator is the same module, we have * to decrease the qrtr module reference count to guarantee that it * remains zero after the ns socket is created, otherwise, executing * "rmmod" command is unable to make the qrtr module deleted after the * qrtr module is inserted successfully. * * However, the reference count is increased twice in * sock_create_kern(): one is to increase the reference count of owner * of qrtr socket's proto_ops struct; another is to increment the * reference count of owner of qrtr proto struct. Therefore, we must * decrement the module reference count twice to ensure that it keeps * zero after server's listening socket is created. Of course, we * must bump the module reference count twice as well before the socket * is closed.
*/
module_put(qrtr_ns.sock->ops->owner);
module_put(qrtr_ns.sock->sk->sk_prot_creator->owner);
/* sock_release() expects the two references that were put during * qrtr_ns_init(). This function is only called during module remove, * so try_stop_module() has already set the refcnt to 0. Use * __module_get() instead of try_module_get() to successfully take two * references.
*/
__module_get(qrtr_ns.sock->ops->owner);
__module_get(qrtr_ns.sock->sk->sk_prot_creator->owner);
sock_release(qrtr_ns.sock);
}
EXPORT_SYMBOL_GPL(qrtr_ns_remove);
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.