1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42#define DEBUG_SUBSYSTEM S_CLASS
43#define D_KUC D_OTHER
44
45#include "../include/obd_support.h"
46#include "../include/lustre_kernelcomm.h"
47
48
49
50
51
52
53
54int libcfs_kkuc_msg_put(struct file *filp, void *payload)
55{
56 struct kuc_hdr *kuch = (struct kuc_hdr *)payload;
57 ssize_t count = kuch->kuc_msglen;
58 loff_t offset = 0;
59 mm_segment_t fs;
60 int rc = -ENXIO;
61
62 if (IS_ERR_OR_NULL(filp))
63 return -EBADF;
64
65 if (kuch->kuc_magic != KUC_MAGIC) {
66 CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic);
67 return rc;
68 }
69
70 fs = get_fs();
71 set_fs(KERNEL_DS);
72 while (count > 0) {
73 rc = vfs_write(filp, (void __force __user *)payload,
74 count, &offset);
75 if (rc < 0)
76 break;
77 count -= rc;
78 payload += rc;
79 rc = 0;
80 }
81 set_fs(fs);
82
83 if (rc < 0)
84 CWARN("message send failed (%d)\n", rc);
85 else
86 CDEBUG(D_KUC, "Sent message rc=%d, fp=%p\n", rc, filp);
87
88 return rc;
89}
90EXPORT_SYMBOL(libcfs_kkuc_msg_put);
91
92
93
94
95
96
97
98struct kkuc_reg {
99 struct list_head kr_chain;
100 int kr_uid;
101 struct file *kr_fp;
102 char kr_data[0];
103};
104
105static struct list_head kkuc_groups[KUC_GRP_MAX + 1] = {};
106
107static DECLARE_RWSEM(kg_sem);
108
109
110
111
112
113
114
115int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group,
116 void *data, size_t data_len)
117{
118 struct kkuc_reg *reg;
119
120 if (group > KUC_GRP_MAX) {
121 CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group);
122 return -EINVAL;
123 }
124
125
126 if (!filp)
127 return -EBADF;
128
129
130 reg = kmalloc(sizeof(*reg) + data_len, 0);
131 if (!reg)
132 return -ENOMEM;
133
134 reg->kr_fp = filp;
135 reg->kr_uid = uid;
136 memcpy(reg->kr_data, data, data_len);
137
138 down_write(&kg_sem);
139 if (!kkuc_groups[group].next)
140 INIT_LIST_HEAD(&kkuc_groups[group]);
141 list_add(®->kr_chain, &kkuc_groups[group]);
142 up_write(&kg_sem);
143
144 CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group);
145
146 return 0;
147}
148EXPORT_SYMBOL(libcfs_kkuc_group_add);
149
150int libcfs_kkuc_group_rem(int uid, unsigned int group)
151{
152 struct kkuc_reg *reg, *next;
153
154 if (!kkuc_groups[group].next)
155 return 0;
156
157 if (!uid) {
158
159 struct kuc_hdr lh;
160
161 lh.kuc_magic = KUC_MAGIC;
162 lh.kuc_transport = KUC_TRANSPORT_GENERIC;
163 lh.kuc_msgtype = KUC_MSG_SHUTDOWN;
164 lh.kuc_msglen = sizeof(lh);
165 libcfs_kkuc_group_put(group, &lh);
166 }
167
168 down_write(&kg_sem);
169 list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) {
170 if (!uid || (uid == reg->kr_uid)) {
171 list_del(®->kr_chain);
172 CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n",
173 reg->kr_uid, reg->kr_fp, group);
174 if (reg->kr_fp)
175 fput(reg->kr_fp);
176 kfree(reg);
177 }
178 }
179 up_write(&kg_sem);
180
181 return 0;
182}
183EXPORT_SYMBOL(libcfs_kkuc_group_rem);
184
185int libcfs_kkuc_group_put(unsigned int group, void *payload)
186{
187 struct kkuc_reg *reg;
188 int rc = 0;
189 int one_success = 0;
190
191 down_write(&kg_sem);
192 list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
193 if (reg->kr_fp) {
194 rc = libcfs_kkuc_msg_put(reg->kr_fp, payload);
195 if (!rc) {
196 one_success = 1;
197 } else if (rc == -EPIPE) {
198 fput(reg->kr_fp);
199 reg->kr_fp = NULL;
200 }
201 }
202 }
203 up_write(&kg_sem);
204
205
206
207
208
209 if (one_success)
210 rc = 0;
211
212 return rc;
213}
214EXPORT_SYMBOL(libcfs_kkuc_group_put);
215
216
217
218
219
220
221
222int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func,
223 void *cb_arg)
224{
225 struct kkuc_reg *reg;
226 int rc = 0;
227
228 if (group > KUC_GRP_MAX) {
229 CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group);
230 return -EINVAL;
231 }
232
233
234 if (!kkuc_groups[group].next)
235 return 0;
236
237 down_read(&kg_sem);
238 list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
239 if (reg->kr_fp)
240 rc = cb_func(reg->kr_data, cb_arg);
241 }
242 up_read(&kg_sem);
243
244 return rc;
245}
246EXPORT_SYMBOL(libcfs_kkuc_group_foreach);
247