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 /* Single Netlink Message type to send all Lustre messages */
63 static struct sock *lnl_socket = NULL;
64 static atomic_t lnl_start_count = ATOMIC_INIT(0);
65 static spinlock_t lnl_lock = SPIN_LOCK_UNLOCKED;
67 /** Start the netlink socket for this transport
68 * @param transport lnl_transport
70 int libcfs_klnl_start(int transport)
75 /* If anyone needs it, we can add per-transport incoming message
76 callbacks. Add the callback as a param here. Store the transport
77 and callback in a table. Include a generalized incoming msg
78 callback here to dispatch messages to the appropriate
79 per-transport callback. */
82 if (atomic_inc_return(&lnl_start_count) > 1)
85 lnl_socket = netlink_kernel_create(
86 #ifdef HAVE_NETLINK_NS
89 LNL_SOCKET, LNL_GRP_CNT,
90 NULL /* incoming cb */,
91 #ifdef HAVE_NETLINK_CBMUTEX
95 if (lnl_socket == NULL) {
96 CERROR("Cannot open socket %d\n", LNL_SOCKET);
97 atomic_dec(&lnl_start_count);
98 GOTO(out, rc = -ENODEV);
102 spin_unlock(&lnl_lock);
105 EXPORT_SYMBOL(libcfs_klnl_start);
107 static void send_shutdown_msg(int transport, int group) {
110 lh.lnl_magic = LNL_MAGIC;
111 lh.lnl_transport = LNL_TRANSPORT_GENERIC;
112 lh.lnl_msgtype = LNL_MSG_SHUTDOWN;
113 lh.lnl_msglen = sizeof(lh);
115 libcfs_klnl_msg_put(0, group, &lh);
118 /* This should be called once per (started) transport
119 * @param transport lnl_transport
120 * @param group Broadcast group for shutdown message */
121 int libcfs_klnl_stop(int transport, int group)
124 send_shutdown_msg(transport, group);
126 spin_lock(&lnl_lock);
128 if (atomic_dec_and_test(&lnl_start_count)) {
129 sock_release(lnl_socket->sk_socket);
133 spin_unlock(&lnl_lock);
136 EXPORT_SYMBOL(libcfs_klnl_stop);
138 static struct sk_buff *netlink_make_msg(int pid, int seq, void *payload,
142 struct nlmsghdr *nlh;
143 int len = NLMSG_SPACE(size);
146 #ifdef HAVE_NETLINK_NL2
147 skb = nlmsg_new(len, GFP_KERNEL);
149 skb = nlmsg_new(len);
155 nlh = nlmsg_put(skb, pid, seq, LNL_MSG, size, 0);
161 data = nlmsg_data(nlh);
162 memcpy(data, payload, size);
167 * libcfs_klnl_msg_put - send an message from kernel to userspace
168 * @param pid Process id to send message to for unicast messages; must be 0 for
170 * @param group Broadcast group; 0 for unicast messages
171 * @param payload Payload data. First field of payload is always struct lnl_hdr
173 * Allocates an skb, builds the netlink message, and sends it to the pid.
175 int libcfs_klnl_msg_put(int pid, int group, void *payload)
177 struct lnl_hdr *lnlh = (struct lnl_hdr *)payload;
181 if (lnl_socket == NULL) {
182 CERROR("LustreNetLink: not running\n");
186 if (lnlh->lnl_magic != LNL_MAGIC) {
187 CERROR("LustreNetLink: bad magic %x\n", lnlh->lnl_magic);
191 if ((pid != 0) && (group != 0)) {
192 CERROR("LustreNetLink: pid=%d or group=%d must be 0\n",
197 skb = netlink_make_msg(pid, 0, payload, lnlh->lnl_msglen);
202 rc = netlink_unicast(lnl_socket, skb, pid,
203 lnlh->lnl_flags & LNL_FL_BLOCK ? 0 : MSG_DONTWAIT);
207 #ifdef HAVE_NLMSG_MULTICAST_5ARGS
208 rc = nlmsg_multicast(lnl_socket, skb, 0, group, GFP_KERNEL);
210 rc = nlmsg_multicast(lnl_socket, skb, 0, group);
214 CDEBUG(0, "Sent message pid=%d, group=%d, rc=%d\n", pid, group, rc);
217 CWARN("message send failed (%d) [pid=%d,group=%d]\n", rc,
222 EXPORT_SYMBOL(libcfs_klnl_msg_put);