node = node_get(qrtr_ns.local_node); if (!node) return0;
/* 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;
}
} return0;
}
/* 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.Neighbourswould'vealreadyremovedtheserverbelonging *tothisportduetotheDEL_CLIENTbroadcastfromqrtr_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) return0;
/* 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 *todecreasetheqrtrmodulereferencecounttoguaranteethatit *remainszeroafterthenssocketiscreated,otherwise,executing *"rmmod"commandisunabletomaketheqrtrmoduledeletedafterthe *qrtrmoduleisinsertedsuccessfully. * *However,thereferencecountisincreasedtwicein *sock_create_kern():oneistoincreasethereferencecountofowner *ofqrtrsocket'sproto_opsstruct;anotheristoincrementthe *referencecountofownerofqrtrprotostruct.Therefore,wemust *decrementthemodulereferencecounttwicetoensurethatitkeeps *zeroafterserver'slisteningsocketiscreated.Ofcourse,we *mustbumpthemodulereferencecounttwiceaswellbeforethesocket *isclosed.
*/
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().Thisfunctionisonlycalledduringmoduleremove, *sotry_stop_module()hasalreadysettherefcntto0.Use *__module_get()insteadoftry_module_get()tosuccessfullytaketwo *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.