Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 35032
b: refs/heads/master
c: 84314fd
h: refs/heads/master
v: v3
  • Loading branch information
James Smart authored and James Bottomley committed Sep 2, 2006
1 parent 41aaf0f commit 51e8716
Show file tree
Hide file tree
Showing 11 changed files with 613 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: deb81d80ba27da8dfabc29ccb5977db8f4942a0a
refs/heads/master: 84314fd4740ad73550c76dee4a9578979d84af48
6 changes: 6 additions & 0 deletions trunk/drivers/scsi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ config SCSI
However, do not compile this as a module if your root file system
(the one containing the directory /) is located on a SCSI device.

config SCSI_NETLINK
tristate
default n
select NET

config SCSI_PROC_FS
bool "legacy /proc/scsi/ support"
depends on SCSI && PROC_FS
Expand Down Expand Up @@ -222,6 +227,7 @@ config SCSI_SPI_ATTRS
config SCSI_FC_ATTRS
tristate "FiberChannel Transport Attributes"
depends on SCSI
select SCSI_NETLINK
help
If you wish to export transport-specific information about
each attached FiberChannel device to sysfs, say Y.
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/scsi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
scsicam.o scsi_error.o scsi_lib.o \
scsi_scan.o scsi_sysfs.o \
scsi_devinfo.o
scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o
scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o

Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/scsi/scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,8 @@ static int __init init_scsi(void)
for_each_possible_cpu(i)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));

scsi_netlink_init();

printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0;

Expand All @@ -1138,6 +1140,7 @@ static int __init init_scsi(void)

static void __exit exit_scsi(void)
{
scsi_netlink_exit();
scsi_sysfs_unregister();
scsi_exit_sysctl();
scsi_exit_hosts();
Expand Down
199 changes: 199 additions & 0 deletions trunk/drivers/scsi/scsi_netlink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/*
* scsi_netlink.c - SCSI Transport Netlink Interface
*
* Copyright (C) 2006 James Smart, Emulex Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/security.h>
#include <net/sock.h>
#include <net/netlink.h>

#include <scsi/scsi_netlink.h>
#include "scsi_priv.h"

struct sock *scsi_nl_sock = NULL;
EXPORT_SYMBOL_GPL(scsi_nl_sock);


/**
* scsi_nl_rcv_msg -
* Receive message handler. Extracts message from a receive buffer.
* Validates message header and calls appropriate transport message handler
*
* @skb: socket receive buffer
*
**/
static void
scsi_nl_rcv_msg(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
struct scsi_nl_hdr *hdr;
uint32_t rlen;
int err;

while (skb->len >= NLMSG_SPACE(0)) {
err = 0;

nlh = (struct nlmsghdr *) skb->data;
if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) ||
(skb->len < nlh->nlmsg_len)) {
printk(KERN_WARNING "%s: discarding partial skb\n",
__FUNCTION__);
return;
}

rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len)
rlen = skb->len;

if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
err = -EBADMSG;
goto next_msg;
}

hdr = NLMSG_DATA(nlh);
if ((hdr->version != SCSI_NL_VERSION) ||
(hdr->magic != SCSI_NL_MAGIC)) {
err = -EPROTOTYPE;
goto next_msg;
}

if (security_netlink_recv(skb, CAP_SYS_ADMIN)) {
err = -EPERM;
goto next_msg;
}

if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
printk(KERN_WARNING "%s: discarding partial message\n",
__FUNCTION__);
return;
}

/*
* We currently don't support anyone sending us a message
*/

next_msg:
if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
netlink_ack(skb, nlh, err);

skb_pull(skb, rlen);
}
}


/**
* scsi_nl_rcv_msg -
* Receive handler for a socket. Extracts a received message buffer from
* the socket, and starts message processing.
*
* @sk: socket
* @len: unused
*
**/
static void
scsi_nl_rcv(struct sock *sk, int len)
{
struct sk_buff *skb;

while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
scsi_nl_rcv_msg(skb);
kfree_skb(skb);
}
}


/**
* scsi_nl_rcv_event -
* Event handler for a netlink socket.
*
* @this: event notifier block
* @event: event type
* @ptr: event payload
*
**/
static int
scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct netlink_notify *n = ptr;

if (n->protocol != NETLINK_SCSITRANSPORT)
return NOTIFY_DONE;

/*
* Currently, we are not tracking PID's, etc. There is nothing
* to handle.
*/

return NOTIFY_DONE;
}

static struct notifier_block scsi_netlink_notifier = {
.notifier_call = scsi_nl_rcv_event,
};


/**
* scsi_netlink_init -
* Called by SCSI subsystem to intialize the SCSI transport netlink
* interface
*
**/
void
scsi_netlink_init(void)
{
int error;

error = netlink_register_notifier(&scsi_netlink_notifier);
if (error) {
printk(KERN_ERR "%s: register of event handler failed - %d\n",
__FUNCTION__, error);
return;
}

scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT,
SCSI_NL_GRP_CNT, scsi_nl_rcv, THIS_MODULE);
if (!scsi_nl_sock) {
printk(KERN_ERR "%s: register of recieve handler failed\n",
__FUNCTION__);
netlink_unregister_notifier(&scsi_netlink_notifier);
}

return;
}


/**
* scsi_netlink_exit -
* Called by SCSI subsystem to disable the SCSI transport netlink
* interface
*
**/
void
scsi_netlink_exit(void)
{
if (scsi_nl_sock) {
sock_release(scsi_nl_sock->sk_socket);
netlink_unregister_notifier(&scsi_netlink_notifier);
}

return;
}


11 changes: 11 additions & 0 deletions trunk/drivers/scsi/scsi_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct scsi_cmnd;
struct scsi_device;
struct scsi_host_template;
struct Scsi_Host;
struct scsi_nl_hdr;


/*
Expand Down Expand Up @@ -110,6 +111,16 @@ extern void __scsi_remove_device(struct scsi_device *);

extern struct bus_type scsi_bus_type;

/* scsi_netlink.c */
#ifdef CONFIG_SCSI_NETLINK
extern void scsi_netlink_init(void);
extern void scsi_netlink_exit(void);
extern struct sock *scsi_nl_sock;
#else
static inline void scsi_netlink_init(void) {}
static inline void scsi_netlink_exit(void) {}
#endif

/*
* internal scsi timeout functions: for use by mid-layer and transport
* classes.
Expand Down
Loading

0 comments on commit 51e8716

Please sign in to comment.