]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | Subject: Netlink interface for SCSI sense codes |
2 | From: Hannes Reinecke <hare@suse.de> | |
3 | Date: Fri Nov 21 10:08:01 2008 +0100: | |
4 | Git: 97746dc5543ef9113c927022dc54ccd26915563d | |
5 | ||
6 | Inform the userspace about SCSI sense codes; some of them | |
7 | carry vital information where userspace should react to. | |
8 | ||
9 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
10 | ||
11 | diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c | |
12 | index 3863617..266e5a5 100644 | |
13 | --- a/drivers/scsi/scsi_error.c | |
14 | +++ b/drivers/scsi/scsi_error.c | |
15 | @@ -24,6 +24,8 @@ | |
16 | #include <linux/interrupt.h> | |
17 | #include <linux/blkdev.h> | |
18 | #include <linux/delay.h> | |
19 | +#include <linux/netlink.h> | |
20 | +#include <net/netlink.h> | |
21 | ||
22 | #include <scsi/scsi.h> | |
23 | #include <scsi/scsi_cmnd.h> | |
24 | @@ -33,6 +35,7 @@ | |
25 | #include <scsi/scsi_transport.h> | |
26 | #include <scsi/scsi_host.h> | |
27 | #include <scsi/scsi_ioctl.h> | |
28 | +#include <scsi/scsi_netlink_ml.h> | |
29 | ||
30 | #include "scsi_priv.h" | |
31 | #include "scsi_logging.h" | |
32 | @@ -224,6 +227,80 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, | |
33 | } | |
34 | #endif | |
35 | ||
36 | +#ifdef CONFIG_SCSI_NETLINK | |
37 | +/** | |
38 | + * scsi_post_sense_event - called to post a 'Sense Code' event | |
39 | + * | |
40 | + * @sdev: SCSI device the sense code occured on | |
41 | + * @sshdr: SCSI sense code | |
42 | + * | |
43 | + * Returns: | |
44 | + * 0 on succesful return | |
45 | + * otherwise, failing error code | |
46 | + * | |
47 | + */ | |
48 | +static void scsi_post_sense_event(struct scsi_device *sdev, | |
49 | + struct scsi_sense_hdr *sshdr) | |
50 | +{ | |
51 | + struct sk_buff *skb; | |
52 | + struct nlmsghdr *nlh; | |
53 | + struct scsi_nl_sense_msg *msg; | |
54 | + u32 len, skblen; | |
55 | + int err; | |
56 | + | |
57 | + if (!scsi_nl_sock) { | |
58 | + err = -ENOENT; | |
59 | + goto send_fail; | |
60 | + } | |
61 | + | |
62 | + len = SCSI_NL_MSGALIGN(sizeof(*msg)); | |
63 | + skblen = NLMSG_SPACE(len); | |
64 | + | |
65 | + skb = alloc_skb(skblen, GFP_ATOMIC); | |
66 | + if (!skb) { | |
67 | + err = -ENOBUFS; | |
68 | + goto send_fail; | |
69 | + } | |
70 | + | |
71 | + nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, | |
72 | + skblen - sizeof(*nlh), 0); | |
73 | + if (!nlh) { | |
74 | + err = -ENOBUFS; | |
75 | + goto send_fail_skb; | |
76 | + } | |
77 | + msg = NLMSG_DATA(nlh); | |
78 | + | |
79 | + INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT_ML, | |
80 | + ML_NL_SCSI_SENSE, len); | |
81 | + msg->host_no = sdev->host->host_no; | |
82 | + msg->channel = sdev->channel; | |
83 | + msg->id = sdev->id; | |
84 | + msg->lun = sdev->lun; | |
85 | + msg->sense = (sshdr->response_code << 24) | (sshdr->sense_key << 16) | | |
86 | + (sshdr->asc << 8) | sshdr->ascq; | |
87 | + | |
88 | + err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_ML_EVENTS, | |
89 | + GFP_ATOMIC); | |
90 | + if (err && (err != -ESRCH)) | |
91 | + /* nlmsg_multicast already kfree_skb'd */ | |
92 | + goto send_fail; | |
93 | + | |
94 | + return; | |
95 | + | |
96 | +send_fail_skb: | |
97 | + kfree_skb(skb); | |
98 | +send_fail: | |
99 | + sdev_printk(KERN_WARNING, sdev, | |
100 | + "Dropped SCSI Msg %02x/%02x/%02x/%02x: err %d\n", | |
101 | + sshdr->response_code, sshdr->sense_key, | |
102 | + sshdr->asc, sshdr->ascq, err); | |
103 | + return; | |
104 | +} | |
105 | +#else | |
106 | +static inline void scsi_post_sense_event(struct scsi_device *sdev, | |
107 | + struct scsi_sense_hdr *sshdr) {} | |
108 | +#endif | |
109 | + | |
110 | /** | |
111 | * scsi_check_sense - Examine scsi cmd sense | |
112 | * @scmd: Cmd to have sense checked. | |
113 | @@ -246,6 +323,8 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |
114 | if (scsi_sense_is_deferred(&sshdr)) | |
115 | return NEEDS_RETRY; | |
116 | ||
117 | + scsi_post_sense_event(sdev, &sshdr); | |
118 | + | |
119 | if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh && | |
120 | sdev->scsi_dh_data->scsi_dh->check_sense) { | |
121 | int rc; | |
122 | diff --git a/include/scsi/scsi_netlink.h b/include/scsi/scsi_netlink.h | |
123 | index 536752c..ac7c766 100644 | |
124 | --- a/include/scsi/scsi_netlink.h | |
125 | +++ b/include/scsi/scsi_netlink.h | |
126 | @@ -35,7 +35,8 @@ | |
127 | /* SCSI Transport Broadcast Groups */ | |
128 | /* leaving groups 0 and 1 unassigned */ | |
129 | #define SCSI_NL_GRP_FC_EVENTS (1<<2) /* Group 2 */ | |
130 | -#define SCSI_NL_GRP_CNT 3 | |
131 | +#define SCSI_NL_GRP_ML_EVENTS (1<<3) /* Group 3 */ | |
132 | +#define SCSI_NL_GRP_CNT 4 | |
133 | ||
134 | ||
135 | /* SCSI_TRANSPORT_MSG event message header */ | |
136 | @@ -56,7 +57,8 @@ struct scsi_nl_hdr { | |
137 | /* scsi_nl_hdr->transport value */ | |
138 | #define SCSI_NL_TRANSPORT 0 | |
139 | #define SCSI_NL_TRANSPORT_FC 1 | |
140 | -#define SCSI_NL_MAX_TRANSPORTS 2 | |
141 | +#define SCSI_NL_TRANSPORT_ML 2 | |
142 | +#define SCSI_NL_MAX_TRANSPORTS 3 | |
143 | ||
144 | /* Transport-based scsi_nl_hdr->msgtype values are defined in each transport */ | |
145 | ||
146 | diff --git a/include/scsi/scsi_netlink_ml.h b/include/scsi/scsi_netlink_ml.h | |
147 | new file mode 100644 | |
148 | index 0000000..c988458 | |
149 | --- /dev/null | |
150 | +++ b/include/scsi/scsi_netlink_ml.h | |
151 | @@ -0,0 +1,64 @@ | |
152 | +/* | |
153 | + * SCSI Midlayer Netlink Interface | |
154 | + * | |
155 | + * Copyright (C) 2008 Hannes Reinecke, SuSE Linux Products GmbH | |
156 | + * | |
157 | + * This program is free software; you can redistribute it and/or modify | |
158 | + * it under the terms of the GNU General Public License as published by | |
159 | + * the Free Software Foundation; either version 2 of the License, or | |
160 | + * (at your option) any later version. | |
161 | + * | |
162 | + * This program is distributed in the hope that it will be useful, | |
163 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
164 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
165 | + * GNU General Public License for more details. | |
166 | + * | |
167 | + * You should have received a copy of the GNU General Public License | |
168 | + * along with this program; if not, write to the Free Software | |
169 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
170 | + * | |
171 | + */ | |
172 | +#ifndef SCSI_NETLINK_ML_H | |
173 | +#define SCSI_NETLINK_ML_H | |
174 | + | |
175 | +#include <scsi/scsi_netlink.h> | |
176 | + | |
177 | +/* | |
178 | + * This file intended to be included by both kernel and user space | |
179 | + */ | |
180 | + | |
181 | +/* | |
182 | + * FC Transport Message Types | |
183 | + */ | |
184 | + /* kernel -> user */ | |
185 | +#define ML_NL_SCSI_SENSE 0x0100 | |
186 | + /* user -> kernel */ | |
187 | +/* none */ | |
188 | + | |
189 | + | |
190 | +/* | |
191 | + * Message Structures : | |
192 | + */ | |
193 | + | |
194 | +/* macro to round up message lengths to 8byte boundary */ | |
195 | +#define SCSI_NL_MSGALIGN(len) (((len) + 7) & ~7) | |
196 | + | |
197 | + | |
198 | +/* | |
199 | + * SCSI Midlayer SCSI Sense messages : | |
200 | + * SCSI_NL_SCSI_SENSE | |
201 | + * | |
202 | + */ | |
203 | +struct scsi_nl_sense_msg { | |
204 | + struct scsi_nl_hdr snlh; /* must be 1st element ! */ | |
205 | + uint64_t seconds; | |
206 | + u64 id; | |
207 | + u64 lun; | |
208 | + u16 host_no; | |
209 | + u16 channel; | |
210 | + u32 sense; | |
211 | +} __attribute__((aligned(sizeof(uint64_t)))); | |
212 | + | |
213 | + | |
214 | +#endif /* SCSI_NETLINK_ML_H */ | |
215 | + |