Motr  M0
kemd.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2019-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/fs.h>
26 #include <linux/cdev.h>
27 #include <linux/smp.h>
28 #include <linux/types.h>
29 #include <linux/time.h>
30 #include <linux/uaccess.h>
31 #include <linux/device.h>
32 #include <linux/slab.h>
33 
36 
43 #define NUM(dev) (MINOR(dev) & 0xf)
44 
45 static int kemd_major = KEMD_MAJOR;
46 static int kemd_minor = KEMD_MINOR;
47 static int kemd_nr_cpus;
48 
49 struct kem_rb *kemd_rbs;
50 
51 static struct kem_dev *kemd_devices;
52 
53 static int kemd_init_module(void);
54 static void kemd_cleanup_module(void);
55 static int kemd_open(struct inode *inode, struct file *filp);
56 static int kemd_release(struct inode *inode, struct file *filp);
57 static ssize_t kemd_read(struct file *filp, char *buf,
58  size_t len, loff_t *offset);
59 static ssize_t kemd_write(struct file *filp, const char *buf,
60  size_t len, loff_t *offset);
61 
62 static struct file_operations kemd_fops = {
63  .owner = THIS_MODULE,
64  .read = kemd_read,
65  .write = kemd_write,
66  .open = kemd_open,
67  .release = kemd_release
68 };
69 
70 static void kemd_dev_destroy(int i)
71 {
72  cdev_del(&kemd_devices[i].kd_cdev);
73 }
74 
75 static int kemd_dev_create(int i)
76 {
77  dev_t devno;
78 
79  devno = MKDEV(kemd_major, kemd_minor + i);
80  cdev_init(&kemd_devices[i].kd_cdev, &kemd_fops);
81  kemd_devices[i].kd_cdev.owner = THIS_MODULE;
85  atomic_set(&kemd_devices[i].kd_busy, 0);
86 
87  return cdev_add(&kemd_devices[i].kd_cdev, devno, 1);
88 }
89 
90 static int kemd_devs_create(void)
91 {
92  int err = 0;
93  int i;
94 
95  for (i = 0; i < kemd_nr_cpus; i++) {
96  err = kemd_dev_create(i);
97  if (err < 0)
98  break;
99  }
100 
101  if (err < 0) {
102  printk(KERN_WARNING "Can't create cdev for kemd%d.\n", i);
103  for (i -= 1; i > 0; i--)
105  }
106 
107  return err;
108 }
109 
110 static void kemd_devs_destroy(void)
111 {
112  int i;
113 
114  for (i = 0; i < kemd_nr_cpus; i++) {
116  }
117 }
118 
119 void kemd_rbs_free(struct kem_rb *rbs)
120 {
121  int i;
122 
123  for (i = 0; i < kemd_nr_cpus; i++) {
124  kfree(rbs[i].kr_buf);
125  }
126 }
127 
128 int kemd_rbs_init(struct kem_rb *rbs)
129 {
130  struct ke_msg *ptr;
131  int i;
132  int j;
133 
134  for (i = 0; i < kemd_nr_cpus; i++) {
135  ptr = kzalloc(KEMD_BUFFER_SIZE * sizeof(struct ke_msg),
136  GFP_KERNEL);
137  if (ptr == NULL)
138  goto err;
139  rbs[i].kr_buf = ptr;
140  rbs[i].kr_size = KEMD_BUFFER_SIZE;
141  }
142  return 0;
143 err:
144  printk(KERN_WARNING "Can't allocate buffers %dth obj.\n", i);
145  for (j = 0; j < i; j++)
146  kfree(rbs[j].kr_buf);
147  return -ENOMEM;
148 }
149 
150 static int kemd_init_module(void)
151 {
152  dev_t devno;
153  int err = 0;
154 
155  kemd_nr_cpus = num_online_cpus();
156 
157  printk(KERN_INFO "Number of CPUs: %d.\n", kemd_nr_cpus);
158 
159  kemd_rbs = kzalloc(kemd_nr_cpus * sizeof(*kemd_rbs), GFP_KERNEL);
160  if (kemd_rbs == NULL) {
161  printk(KERN_WARNING "Can't allocate kemd_rbs.\n");
162  return -ENOMEM;
163  }
164  err = kemd_rbs_init(kemd_rbs);
165  if(err != 0) {
166  printk(KERN_WARNING "Can't allocate kemd_rbs.\n");
167  goto out_rbs;
168  }
169  kemd_devices = kzalloc(kemd_nr_cpus * sizeof(*kemd_devices),
170  GFP_KERNEL);
171  if (kemd_devices == NULL) {
172  printk(KERN_WARNING "Can't allocate mem for kemd_devices.\n");
173  goto out_rbs_inited;
174  }
175 
176  if (kemd_major) {
177  devno = MKDEV(kemd_major, kemd_minor);
178  err = register_chrdev_region(devno, kemd_nr_cpus,
179  KEMD_DEV_NAME);
180  } else {
181  err = alloc_chrdev_region(&devno, kemd_minor,
183  kemd_major = MAJOR(devno);
184  }
185 
186  printk(KERN_INFO "Init devno: %d.\n", devno);
187 
188  if (err < 0) {
189  printk(KERN_WARNING "Can't get major %d.\n", kemd_major);
190  goto out_devs;
191  }
192 
193  err = kemd_devs_create();
194  if (err < 0) {
195  printk(KERN_WARNING "Can't init kemd chrdevs.\n");
196  goto out_chrdev;
197  }
198 
199  printk(KERN_INFO KEMD_DEV_NAME " major %d inited.\n", kemd_major);
200 
201  return 0;
202 
203  out_chrdev:
204  unregister_chrdev_region(devno, kemd_nr_cpus);
205  out_devs:
206  kfree(kemd_devices);
207  out_rbs_inited:
209  out_rbs:
210  kfree(kemd_rbs);
211 
212  return err;
213 }
214 
215 static void kemd_cleanup_module(void)
216 {
217  dev_t devno;
218 
219  devno = MKDEV(kemd_major, kemd_minor);
220 
221  printk(KERN_INFO "kemd cleanup.\n");
222 
224  printk(KERN_INFO "devs destroyed.\n");
225 
226  unregister_chrdev_region(devno, kemd_nr_cpus);
227  printk(KERN_INFO "chrdev unreg.\n");
228 
229  kfree(kemd_devices);
230  printk(KERN_INFO "kfree kemd_devices.\n");
231 
233  kfree(kemd_rbs);
234  printk(KERN_INFO "kfree kemd_rbs.\n");
235 }
236 
237 static int kemd_open(struct inode *inode, struct file *filp)
238 {
239  int num;
240  struct kem_dev *kemd_dev;
241 
242  num = NUM(inode->i_rdev);
243  kemd_dev = &kemd_devices[num];
244 
245  if (atomic_read(&kemd_dev->kd_busy) != 0)
246  return -EBUSY;
247 
248  filp->private_data = &kemd_devices[num];
249  atomic_inc(&kemd_dev->kd_busy);
250 
251  return 0;
252 }
253 
254 static int kemd_release(struct inode *inode, struct file *filp)
255 {
256  int num;
257  struct kem_dev *kemd_dev;
258 
259  num = NUM(inode->i_rdev);
260  kemd_dev = &kemd_devices[num];
261  atomic_dec(&kemd_dev->kd_busy);
262 
263  return 0;
264 }
265 
266 static ssize_t kemd_read(struct file *filp, char *buf,
267  size_t len, loff_t *offset)
268 {
269  int bytes_read = 0;
270  struct kem_dev *kemd_dev;
271  struct kem_rb *rb;
272  struct ke_msg *ent;
273  unsigned int nr_ents;
274  unsigned int nr_written;
275  int i;
276  int err;
277 
278  kemd_dev = (struct kem_dev *)filp->private_data;
279  rb = kemd_dev->kd_rb;
280 
281  nr_ents = len / sizeof(*ent);
282 
283  nr_written = atomic_read(&rb->kr_written);
284  if (nr_ents > nr_written)
285  nr_ents = nr_written;
286 
287  if (nr_ents > KEMD_READ_PORTION)
288  nr_ents = KEMD_READ_PORTION;
289 
290  for (i = 0; i < nr_ents; i++) {
291  ent = &rb->kr_buf[rb->kr_read_idx];
292  err = copy_to_user(buf, ent, sizeof(*ent));
293  if (err) {
294  bytes_read = -EFAULT;
295  break;
296  }
297 
298  bytes_read += sizeof(*ent);
299 
300  rb->kr_read_idx = (rb->kr_read_idx + 1) % KEMD_BUFFER_SIZE;
301  atomic_dec(&rb->kr_written);
302  nr_written--;
303  }
304 
305  return bytes_read;
306 }
307 
308 static ssize_t kemd_write(struct file *filp, const char *buf,
309  size_t len, loff_t *off)
310 {
311  return -EINVAL;
312 }
313 
315 
318 
321 /*
322  * Local variables:
323  * c-indentation-style: "K&R"
324  * c-basic-offset: 8
325  * tab-width: 8
326  * fill-column: 80
327  * scroll-step: 1
328  * End:
329  */
330 /*
331  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
332  */
static void ptr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:440
#define KEMD_READ_PORTION
Definition: kem_dev.h:33
#define NULL
Definition: misc.h:38
static void kemd_cleanup_module(void)
Definition: kemd.c:215
struct m0_file file
Definition: di.c:36
static int kemd_release(struct inode *inode, struct file *filp)
Definition: kemd.c:254
module_init(kemd_init_module)
#define KEMD_DEV_NAME
Definition: kem.h:37
struct kem_rb * kd_rb
Definition: kem_dev.h:64
struct kem_rb * kemd_rbs
Definition: kemd.c:49
Definition: sock.c:887
struct inode * inode
Definition: dir.c:624
module_exit(kemd_cleanup_module)
#define KEMD_BUFFER_SIZE
Definition: kem_dev.h:32
int i
Definition: dir.c:1033
struct reqh_ut_balloc rb
Definition: reqh_fom_ut.c:159
struct cdev kd_cdev
Definition: kem_dev.h:61
static int kemd_open(struct inode *inode, struct file *filp)
Definition: kemd.c:237
static ssize_t kemd_read(struct file *filp, char *buf, size_t len, loff_t *offset)
Definition: kemd.c:266
static void kemd_dev_destroy(int i)
Definition: kemd.c:70
struct ke_msg * kr_buf
Definition: kem_dev.h:51
EXPORT_SYMBOL(kemd_rbs)
Definition: kem.h:70
#define KEMD_MINOR
Definition: kem_dev.h:42
static struct file_operations kemd_fops
Definition: kemd.c:62
static m0_bindex_t offset
Definition: dump.c:173
static int kemd_major
Definition: kemd.c:45
static void kemd_devs_destroy(void)
Definition: kemd.c:110
static struct kem_dev * kemd_devices
Definition: kemd.c:51
static int kemd_init_module(void)
Definition: kemd.c:150
static int kemd_devs_create(void)
Definition: kemd.c:90
int kd_num
Definition: kem_dev.h:63
atomic_t kd_busy
Definition: kem_dev.h:62
#define NUM(dev)
Definition: kemd.c:43
static ssize_t kemd_write(struct file *filp, const char *buf, size_t len, loff_t *offset)
Definition: kemd.c:308
int kemd_rbs_init(struct kem_rb *rbs)
Definition: kemd.c:128
Definition: kem_dev.h:50
#define KEMD_MAJOR
Definition: kem_dev.h:41
unsigned int kr_size
Definition: kem_dev.h:52
static int kemd_nr_cpus
Definition: kemd.c:47
struct m0_dirent * ent
Definition: dir.c:1029
int num
Definition: bulk_if.c:54
static int kemd_minor
Definition: kemd.c:46
void kemd_rbs_free(struct kem_rb *rbs)
Definition: kemd.c:119
static int kemd_dev_create(int i)
Definition: kemd.c:75