1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2009 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * Author: Nathan Rutman <nathan.rutman@sun.com>
38 * Kernel <-> userspace communication routines. We'll use a shorthand term
39 * "lnl" (Lustre NetLink) for the interface names for all arches (even though
40 * implemtation may not use NetLink).
41 * For Linux, we use Netlink sockets.
44 #define DEBUG_SUBSYSTEM S_CLASS
47 /* This is the kernel side.
48 * See libcfs/ulinux/ulinux-kernelcomm.c for the user side.
51 #if defined(HAVE_NETLINK) && defined(__KERNEL__)
53 #include <linux/module.h>
54 #include <linux/socket.h>
55 #include <linux/skbuff.h>
56 #include <net/netlink.h>
58 #include <libcfs/libcfs.h>
60 /* OFED backport #defines netlink_kernel_create with 6 args.
61 I haven't a clue why that header file gets included here,
62 but we must undo its mischief. */
63 #ifdef BACKPORT_LINUX_NETLINK_H
64 #undef netlink_kernel_create
68 /* Single Netlink Message type to send all Lustre messages */
71 static struct sock *lnl_socket = NULL;
72 static atomic_t lnl_start_count = ATOMIC_INIT(0);
73 static spinlock_t lnl_lock = SPIN_LOCK_UNLOCKED;
75 /** Start the netlink socket for this transport
76 * @param transport lnl_transport
78 int libcfs_klnl_start(int transport)
83 /* If anyone needs it, we can add per-transport incoming message
84 callbacks. Add the callback as a param here. Store the transport
85 and callback in a table. Include a generalized incoming msg
86 callback here to dispatch messages to the appropriate
87 per-transport callback. */
90 if (atomic_inc_return(&lnl_start_count) > 1)
93 lnl_socket = netlink_kernel_create(LNL_SOCKET, LNL_GRP_CNT,
94 NULL /* incoming cb */,
96 if (lnl_socket == NULL) {
97 CERROR("Cannot open socket %d\n", LNL_SOCKET);
98 atomic_dec(&lnl_start_count);
99 GOTO(out, rc = -ENODEV);
103 spin_unlock(&lnl_lock);
106 EXPORT_SYMBOL(libcfs_klnl_start);
108 static void send_shutdown_msg(int transport, int group) {
111 lh.lnl_magic = LNL_MAGIC;
112 lh.lnl_transport = LNL_TRANSPORT_GENERIC;
113 lh.lnl_msgtype = LNL_MSG_SHUTDOWN;
114 lh.lnl_msglen = sizeof(lh);
116 libcfs_klnl_msg_put(0, group, &lh);
119 /* This should be called once per (started) transport
120 * @param transport lnl_transport
121 * @param group Broadcast group for shutdown message */
122 int libcfs_klnl_stop(int transport, int group)
125 send_shutdown_msg(transport, group);
127 spin_lock(&lnl_lock);
129 if (atomic_dec_and_test(&lnl_start_count)) {
130 sock_release(lnl_socket->sk_socket);
134 spin_unlock(&lnl_lock);
137 EXPORT_SYMBOL(libcfs_klnl_stop);
139 static struct sk_buff *netlink_make_msg(int pid, int seq, void *payload,
143 struct nlmsghdr *nlh;
144 int len = NLMSG_SPACE(size);
147 skb = nlmsg_new(len, GFP_KERNEL);
151 nlh = nlmsg_put(skb, pid, seq, LNL_MSG, size, 0);
157 data = nlmsg_data(nlh);
158 memcpy(data, payload, size);
163 * libcfs_klnl_msg_put - send an message from kernel to userspace
164 * @param pid Process id to send message to for unicast messages; must be 0 for
166 * @param group Broadcast group; 0 for unicast messages
167 * @param payload Payload data. First field of payload is always struct lnl_hdr
169 * Allocates an skb, builds the netlink message, and sends it to the pid.
171 int libcfs_klnl_msg_put(int pid, int group, void *payload)
173 struct lnl_hdr *lnlh = (struct lnl_hdr *)payload;
177 if (lnl_socket == NULL) {
178 CERROR("LustreNetLink: not running\n");
182 if (lnlh->lnl_magic != LNL_MAGIC) {
183 CERROR("LustreNetLink: bad magic %x\n", lnlh->lnl_magic);
187 if ((pid != 0) && (group != 0)) {
188 CERROR("LustreNetLink: pid=%d or group=%d must be 0\n",
193 skb = netlink_make_msg(pid, 0, payload, lnlh->lnl_msglen);
198 rc = nlmsg_unicast(lnl_socket, skb, pid);
200 rc = nlmsg_multicast(lnl_socket, skb, 0, group);
202 CDEBUG(0, "Sent message pid=%d, group=%d, rc=%d\n", pid, group, rc);
205 CWARN("message send failed (%d) [pid=%d,group=%d]\n", rc,
210 EXPORT_SYMBOL(libcfs_klnl_msg_put);