Whamcloud - gitweb
LU-17705 ptlrpc: replace synchronize_rcu() with rcu_barrier()
[fs/lustre-release.git] / lustre / ofd / ofd_access_log.c
1 #include <linux/cdev.h>
2 #include <linux/circ_buf.h>
3 #include <linux/device.h>
4 #include <linux/fs.h>
5 #include <linux/idr.h>
6 #include <linux/kernel.h>
7 #include <linux/miscdevice.h>
8 #include <linux/module.h>
9 #include <linux/poll.h>
10 #include <linux/slab.h>
11 #include <linux/types.h>
12 #include <linux/uaccess.h>
13 #include <uapi/linux/lustre/lustre_idl.h>
14 #include <uapi/linux/lustre/lustre_access_log.h>
15 #include "ofd_internal.h"
16
17 /* OFD access logs: OST (OFD) RPC handlers log accesses by FID and
18  * PFID which are read from userspace through character device files
19  * (/dev/lustre-access-log/scratch-OST0000). Accesses are described by
20  * struct ofd_access_entry_v1. The char device implements read()
21  * (blocking and nonblocking) and poll(), along with an ioctl that
22  * returns diagnostic information on an oal device.
23  *
24  * A control device (/dev/lustre-access-log/control) supports an ioctl()
25  * plus poll() method to for oal discovery. See uses of
26  * oal_control_event_count and oal_control_wait_queue for details.
27  *
28  * oal log size and entry size are restricted to powers of 2 to
29  * support circ_buf methods. See Documentation/core-api/circular-buffers.rst
30  * in the linux tree for more information.
31  *
32  * The associated struct device (*oal_device) owns the oal. The
33  * release() method of oal_device frees the oal and releases its
34  * minor. This may seem slightly more complicated than necessary but
35  * it allows the OST to be unmounted while the oal still has open file
36  * descriptors.
37  */
38
39 enum {
40         OAL_DEV_COUNT = 1 << MINORBITS,
41 };
42
43 struct ofd_access_log {
44         char oal_name[128]; /* lustre-OST0000 */
45         struct device oal_device;
46         struct cdev oal_cdev;
47         struct rw_semaphore oal_buf_list_sem;
48         struct list_head oal_circ_buf_list;
49         unsigned int oal_is_closed;
50         unsigned int oal_log_size;
51         unsigned int oal_entry_size;
52 };
53
54 struct oal_circ_buf {
55         struct list_head ocb_list;
56         spinlock_t ocb_write_lock;
57         spinlock_t ocb_read_lock;
58         struct ofd_access_log *ocb_access_log;
59         __u32 ocb_filter;
60         wait_queue_head_t ocb_read_wait_queue;
61         unsigned int ocb_drop_count;
62         struct circ_buf ocb_circ;
63 };
64
65 static atomic_t oal_control_event_count = ATOMIC_INIT(0);
66 static DECLARE_WAIT_QUEUE_HEAD(oal_control_wait_queue);
67
68 static struct class *oal_log_class;
69 static unsigned int oal_log_major;
70 static DEFINE_IDR(oal_log_minor_idr); /* TODO Use ida instead. */
71 static DEFINE_SPINLOCK(oal_log_minor_lock);
72
73 bool ofd_access_log_size_is_valid(unsigned int size)
74 {
75         const unsigned int size_min = 2 * sizeof(struct ofd_access_entry_v1);
76         const unsigned int size_max = 1U << 30;
77
78         if (size == 0)
79                 return true;
80
81         return is_power_of_2(size) && size_min <= size && size <= size_max;
82 }
83
84 static void oal_control_event_inc(void)
85 {
86         atomic_inc(&oal_control_event_count);
87         wake_up(&oal_control_wait_queue);
88 }
89
90 static int oal_log_minor_alloc(int *pminor)
91 {
92         void *OAL_LOG_MINOR_ALLOCED = (void *)-1;
93         int minor;
94
95         idr_preload(GFP_KERNEL);
96         spin_lock(&oal_log_minor_lock);
97         minor = idr_alloc(&oal_log_minor_idr, OAL_LOG_MINOR_ALLOCED, 0,
98                         OAL_DEV_COUNT, GFP_NOWAIT);
99         spin_unlock(&oal_log_minor_lock);
100         idr_preload_end();
101
102         if (minor < 0)
103                 return minor;
104
105         *pminor = minor;
106
107         return 0;
108 }
109
110 static void oal_log_minor_free(int minor)
111 {
112         spin_lock(&oal_log_minor_lock);
113         idr_remove(&oal_log_minor_idr, minor);
114         spin_unlock(&oal_log_minor_lock);
115 }
116
117 static bool oal_is_empty(struct oal_circ_buf *ocb)
118 {
119         struct ofd_access_log *oal = ocb->ocb_access_log;
120
121         return CIRC_CNT(ocb->ocb_circ.head,
122                         ocb->ocb_circ.tail,
123                         oal->oal_log_size) < oal->oal_entry_size;
124 }
125
126 static ssize_t oal_write_entry(struct oal_circ_buf *ocb,
127                         const void *entry, size_t entry_size)
128 {
129         struct ofd_access_log *oal = ocb->ocb_access_log;
130         struct circ_buf *circ = &ocb->ocb_circ;
131         unsigned int head;
132         unsigned int tail;
133         ssize_t rc;
134
135         if (entry_size != oal->oal_entry_size)
136                 return -EINVAL;
137
138         spin_lock(&ocb->ocb_write_lock);
139         head = circ->head;
140         tail = READ_ONCE(circ->tail);
141
142         /* CIRC_SPACE() return space available, 0..oal_log_size -
143          * 1. It always leaves one free char, since a completely full
144          * buffer would have head == tail, which is the same as empty. */
145         if (CIRC_SPACE(head, tail, oal->oal_log_size) < oal->oal_entry_size) {
146                 ocb->ocb_drop_count++;
147                 rc = -EAGAIN;
148                 goto out_write_lock;
149         }
150
151         memcpy(&circ->buf[head], entry, entry_size);
152         rc = entry_size;
153
154         /* Ensure the entry is stored before we update the head. */
155         smp_store_release(&circ->head,
156                         (head + oal->oal_entry_size) & (oal->oal_log_size - 1));
157
158         wake_up(&ocb->ocb_read_wait_queue);
159 out_write_lock:
160         spin_unlock(&ocb->ocb_write_lock);
161
162         return rc;
163 }
164
165 /* Read one entry from the log and return its size. Non-blocking.
166  * When the log is empty we return -EAGAIN if the OST is still mounted
167  * and 0 otherwise.
168  */
169 static ssize_t oal_read_entry(struct oal_circ_buf *ocb,
170                         void *entry_buf, size_t entry_buf_size)
171 {
172         struct ofd_access_log *oal = ocb->ocb_access_log;
173         struct circ_buf *circ = &ocb->ocb_circ;
174         unsigned int head;
175         unsigned int tail;
176         ssize_t rc;
177
178         /* XXX This method may silently truncate entries when
179          * entry_buf_size is less than oal_entry_size. But that's OK
180          * because you know what you are doing. */
181         spin_lock(&ocb->ocb_read_lock);
182
183         /* Memory barrier usage follows circular-buffers.txt. */
184         head = smp_load_acquire(&circ->head);
185         tail = circ->tail;
186
187         if (!CIRC_CNT(head, tail, oal->oal_log_size)) {
188                 rc = oal->oal_is_closed ? 0 : -EAGAIN;
189                 goto out_read_lock;
190         }
191
192         BUG_ON(CIRC_CNT(head, tail, oal->oal_log_size) < oal->oal_entry_size);
193
194         /* Extract one entry from the buffer. */
195         rc = min_t(size_t, oal->oal_entry_size, entry_buf_size);
196         memcpy(entry_buf, &circ->buf[tail], rc);
197
198         /* Memory barrier usage follows circular-buffers.txt. */
199         smp_store_release(&circ->tail,
200                         (tail + oal->oal_entry_size) & (oal->oal_log_size - 1));
201
202 out_read_lock:
203         spin_unlock(&ocb->ocb_read_lock);
204
205         return rc;
206 }
207
208 static int oal_file_open(struct inode *inode, struct file *filp)
209 {
210         struct ofd_access_log *oal;
211         struct oal_circ_buf *ocb;
212
213         oal = container_of(inode->i_cdev, struct ofd_access_log, oal_cdev);
214
215         ocb = kzalloc(sizeof(*ocb), GFP_KERNEL);
216         if (!ocb)
217                 return -ENOMEM;
218         ocb->ocb_circ.buf = vmalloc(oal->oal_log_size);
219         if (!ocb->ocb_circ.buf) {
220                 kfree(ocb);
221                 return -ENOMEM;
222         }
223
224         spin_lock_init(&ocb->ocb_write_lock);
225         spin_lock_init(&ocb->ocb_read_lock);
226         ocb->ocb_access_log = oal;
227         init_waitqueue_head(&ocb->ocb_read_wait_queue);
228
229         down_write(&oal->oal_buf_list_sem);
230         list_add(&ocb->ocb_list, &oal->oal_circ_buf_list);
231         up_write(&oal->oal_buf_list_sem);
232
233         filp->private_data = ocb;
234
235         return nonseekable_open(inode, filp);
236 }
237
238 /* User buffer size must be a multiple of ofd access entry size. */
239 static ssize_t oal_file_read(struct file *filp, char __user *buf, size_t count,
240                         loff_t *ppos)
241 {
242         struct oal_circ_buf *ocb = filp->private_data;
243         struct ofd_access_log *oal = ocb->ocb_access_log;
244         void *entry;
245         size_t size = 0;
246         int rc = 0;
247
248         if (!count)
249                 return 0;
250
251         if (count & (oal->oal_entry_size - 1))
252                 return -EINVAL;
253
254         entry = kzalloc(oal->oal_entry_size, GFP_KERNEL);
255         if (!entry)
256                 return -ENOMEM;
257
258         while (size < count) {
259                 rc = oal_read_entry(ocb, entry, oal->oal_entry_size);
260                 if (rc == -EAGAIN) {
261                         if (filp->f_flags & O_NONBLOCK)
262                                 break;
263
264                         rc = wait_event_interruptible(ocb->ocb_read_wait_queue,
265                                 !oal_is_empty(ocb) || oal->oal_is_closed);
266                         if (rc)
267                                 break;
268                 } else if (rc <= 0) {
269                         break; /* cloed or error */
270                 } else {
271                         if (copy_to_user(buf, entry, oal->oal_entry_size)) {
272                                 rc = -EFAULT;
273                                 break;
274                         }
275
276                         buf += oal->oal_entry_size;
277                         size += oal->oal_entry_size;
278                 }
279         }
280
281         kfree(entry);
282
283         return size ? size : rc;
284 }
285
286 /* Included for test purposes. User buffer size must be a multiple of
287  * ofd access entry size. */
288 static ssize_t oal_file_write(struct file *filp, const char __user *buf,
289                         size_t count, loff_t *ppos)
290 {
291         struct oal_circ_buf *ocb = filp->private_data;
292         struct ofd_access_log *oal = ocb->ocb_access_log;
293         void *entry;
294         size_t size = 0;
295         ssize_t rc = 0;
296
297         if (!count)
298                 return 0;
299
300         if (count & (oal->oal_entry_size - 1))
301                 return -EINVAL;
302
303         entry = kzalloc(oal->oal_entry_size, GFP_KERNEL);
304         if (!entry)
305                 return -ENOMEM;
306
307         while (size < count) {
308                 if (copy_from_user(entry, buf, oal->oal_entry_size)) {
309                         rc = -EFAULT;
310                         break;
311                 }
312
313                 rc = oal_write_entry(ocb, entry, oal->oal_entry_size);
314                 if (rc <= 0)
315                         break;
316
317                 buf += oal->oal_entry_size;
318                 size += oal->oal_entry_size;
319         }
320
321         kfree(entry);
322
323         return size > 0 ? size : rc;
324 }
325
326 static unsigned int oal_file_poll(struct file *filp,
327                                   struct poll_table_struct *wait)
328 {
329         struct oal_circ_buf *ocb = filp->private_data;
330         struct ofd_access_log *oal = ocb->ocb_access_log;
331         unsigned int mask = 0;
332
333         poll_wait(filp, &ocb->ocb_read_wait_queue, wait);
334
335         spin_lock(&ocb->ocb_read_lock);
336
337         if (!oal_is_empty(ocb) || oal->oal_is_closed)
338                 mask |= POLLIN;
339
340         spin_unlock(&ocb->ocb_read_lock);
341
342         return mask;
343 }
344
345 static long oal_ioctl_info(struct oal_circ_buf *ocb, void __user *uarg)
346 {
347         struct ofd_access_log *oal = ocb->ocb_access_log;
348         struct lustre_access_log_info_v1 __user *lali;
349         u32 entry_count = CIRC_CNT(ocb->ocb_circ.head,
350                                 ocb->ocb_circ.tail,
351                                 oal->oal_log_size) / oal->oal_entry_size;
352         u32 entry_space = CIRC_SPACE(ocb->ocb_circ.head,
353                                 ocb->ocb_circ.tail,
354                                 oal->oal_log_size) / oal->oal_entry_size;
355
356         lali = uarg;
357         BUILD_BUG_ON(sizeof(lali->lali_name) != sizeof(oal->oal_name));
358
359         if (put_user(LUSTRE_ACCESS_LOG_VERSION_1, &lali->lali_version))
360                 return -EFAULT;
361
362         if (put_user(LUSTRE_ACCESS_LOG_TYPE_OFD, &lali->lali_type))
363                 return -EFAULT;
364
365         if (copy_to_user(lali->lali_name, oal->oal_name, sizeof(oal->oal_name)))
366                 return -EFAULT;
367
368         if (put_user(oal->oal_log_size, &lali->lali_log_size))
369                 return -EFAULT;
370
371         if (put_user(oal->oal_entry_size, &lali->lali_entry_size))
372                 return -EFAULT;
373
374         if (put_user(ocb->ocb_circ.head, &lali->_lali_head))
375                 return -EFAULT;
376
377         if (put_user(ocb->ocb_circ.tail, &lali->_lali_tail))
378                 return -EFAULT;
379
380         if (put_user(entry_space, &lali->_lali_entry_space))
381                 return -EFAULT;
382
383         if (put_user(entry_count, &lali->_lali_entry_count))
384                 return -EFAULT;
385
386         if (put_user(ocb->ocb_drop_count, &lali->_lali_drop_count))
387                 return -EFAULT;
388
389         if (put_user(oal->oal_is_closed, &lali->_lali_is_closed))
390                 return -EFAULT;
391
392         return 0;
393 }
394
395 static long oal_file_ioctl(struct file *filp, unsigned int cmd,
396                            unsigned long arg)
397 {
398         struct oal_circ_buf *ocb = filp->private_data;
399
400         switch (cmd) {
401         case LUSTRE_ACCESS_LOG_IOCTL_VERSION:
402                 return LUSTRE_ACCESS_LOG_VERSION_1;
403         case LUSTRE_ACCESS_LOG_IOCTL_INFO:
404                 return oal_ioctl_info(ocb, (void __user *)arg);
405         case LUSTRE_ACCESS_LOG_IOCTL_FILTER:
406                 ocb->ocb_filter = arg;
407                 return 0;
408         default:
409                 return -ENOTTY;
410         }
411 }
412
413 static int oal_file_release(struct inode *inode, struct file *filp)
414 {
415         struct oal_circ_buf *ocb = filp->private_data;
416         struct ofd_access_log *oal = ocb->ocb_access_log;
417
418         down_write(&oal->oal_buf_list_sem);
419         list_del(&ocb->ocb_list);
420         up_write(&oal->oal_buf_list_sem);
421
422         vfree(ocb->ocb_circ.buf);
423         kfree(ocb);
424
425         return 0;
426 }
427
428 static const struct file_operations oal_fops = {
429         .owner = THIS_MODULE,
430         .open = &oal_file_open,
431         .release = &oal_file_release,
432         .unlocked_ioctl = &oal_file_ioctl,
433         .read = &oal_file_read,
434         .write = &oal_file_write,
435         .poll = &oal_file_poll,
436 #ifdef HAVE_NO_LLSEEK
437         .llseek = &no_llseek,
438 #endif
439 };
440
441 static void oal_device_release(struct device *dev)
442 {
443         struct ofd_access_log *oal = dev_get_drvdata(dev);
444
445         oal_log_minor_free(MINOR(oal->oal_device.devt));
446         BUG_ON(!list_empty(&oal->oal_circ_buf_list));
447         kfree(oal);
448 }
449
450 struct ofd_access_log *ofd_access_log_create(const char *ofd_name, size_t size)
451 {
452         const size_t entry_size = sizeof(struct ofd_access_entry_v1);
453         struct ofd_access_log *oal;
454         int minor;
455         int rc;
456
457         BUILD_BUG_ON(sizeof(oal->oal_name) != MAX_OBD_NAME);
458         BUILD_BUG_ON(!is_power_of_2(entry_size));
459
460         if (!size)
461                 return NULL;
462
463         if (!is_power_of_2(size) || (size & (entry_size - 1)) ||
464             (unsigned int)size != size)
465                 return ERR_PTR(-EINVAL);
466
467         oal = kzalloc(sizeof(*oal), GFP_KERNEL);
468         if (!oal)
469                 return ERR_PTR(-ENOMEM);
470
471         strscpy(oal->oal_name, ofd_name, sizeof(oal->oal_name));
472         oal->oal_log_size = size;
473         oal->oal_entry_size = entry_size;
474         INIT_LIST_HEAD(&oal->oal_circ_buf_list);
475         init_rwsem(&oal->oal_buf_list_sem);
476
477         rc = oal_log_minor_alloc(&minor);
478         if (rc < 0)
479                 goto out_free;
480
481         device_initialize(&oal->oal_device);
482         oal->oal_device.devt = MKDEV(oal_log_major, minor);
483         oal->oal_device.class = oal_log_class;
484         oal->oal_device.release = &oal_device_release;
485         dev_set_drvdata(&oal->oal_device, oal);
486         rc = dev_set_name(&oal->oal_device,
487                         "%s!%s", LUSTRE_ACCESS_LOG_DIR_NAME, oal->oal_name);
488         if (rc < 0)
489                 goto out_minor;
490
491         cdev_init(&oal->oal_cdev, &oal_fops);
492         oal->oal_cdev.owner = THIS_MODULE;
493         rc = cdev_device_add(&oal->oal_cdev, &oal->oal_device);
494         if (rc < 0)
495                 goto out_device_name;
496
497         oal_control_event_inc();
498
499         return oal;
500
501 out_device_name:
502         kfree_const(oal->oal_device.kobj.name);
503 out_minor:
504         oal_log_minor_free(minor);
505 out_free:
506         kfree(oal);
507
508         return ERR_PTR(rc);
509 }
510
511 void ofd_access(const struct lu_env *env,
512                 struct ofd_device *m,
513                 const struct lu_fid *parent_fid,
514                 __u64 begin, __u64 end,
515                 unsigned int size,
516                 unsigned int segment_count,
517                 int rw)
518 {
519         unsigned int flags = (rw == READ) ? OFD_ACCESS_READ : OFD_ACCESS_WRITE;
520         struct ofd_access_log *oal = m->ofd_access_log;
521
522         /* obdfilter-survey does not set parent FIDs. */
523         if (fid_is_zero(parent_fid))
524                 return;
525
526         if (oal && (flags & m->ofd_access_log_mask)) {
527                 struct ofd_access_entry_v1 oae = {
528                         .oae_parent_fid = *parent_fid,
529                         .oae_begin = begin,
530                         .oae_end = end,
531                         .oae_time = ktime_get_real_seconds(),
532                         .oae_size = size,
533                         .oae_segment_count = segment_count,
534                         .oae_flags = flags,
535                 };
536                 struct lu_seq_range range = {
537                         .lsr_flags = LU_SEQ_RANGE_ANY,
538                 };
539                 struct oal_circ_buf *ocb;
540                 int rc;
541
542                 /* learn target MDT from FID's sequence */
543                 rc = fld_server_lookup(env, m->ofd_seq_site.ss_server_fld,
544                                        fid_seq(parent_fid), &range);
545                 if (unlikely(rc))
546                         CERROR("%s: can't resolve "DFID": rc=%d\n",
547                                ofd_name(m), PFID(parent_fid), rc);
548
549                 down_read(&oal->oal_buf_list_sem);
550                 list_for_each_entry(ocb, &oal->oal_circ_buf_list, ocb_list) {
551                         /* filter by MDT index if requested */
552                         if (ocb->ocb_filter == 0xffffffff ||
553                             range.lsr_index == ocb->ocb_filter)
554                                 oal_write_entry(ocb, &oae, sizeof(oae));
555                 }
556                 up_read(&oal->oal_buf_list_sem);
557         }
558 }
559
560 /* Called on OST umount to:
561  * - Close the write end of the oal. The wakes any tasks sleeping in
562  *   read or poll and makes all reads return zero once the log
563  *   becomes empty.
564  * - Delete the associated stuct device and cdev, preventing new
565  *   opens. Existing opens retain a reference on the oal through
566  *   their reference on oal_device.
567  * The oal will be freed when the last open file handle is closed. */
568 void ofd_access_log_delete(struct ofd_access_log *oal)
569 {
570         struct oal_circ_buf *ocb;
571
572         if (!oal)
573                 return;
574
575         oal->oal_is_closed = 1;
576         down_read(&oal->oal_buf_list_sem);
577         list_for_each_entry(ocb, &oal->oal_circ_buf_list, ocb_list)
578                 wake_up(&ocb->ocb_read_wait_queue);
579         up_read(&oal->oal_buf_list_sem);
580         cdev_device_del(&oal->oal_cdev, &oal->oal_device);
581 }
582
583 /* private_data for control device file. */
584 struct oal_control_file {
585         int ccf_event_count;
586 };
587
588 /* Control file usage:
589  * Open /dev/lustre-access-log/control.
590  * while (1)
591  *   Poll for readable on control FD.
592  *   Call ioctl(FD, LUSTRE_ACCESS_LOG_IOCTL_PRESCAN) to fetch event count.
593  *   Scan /dev/ or /sys/class/... for new devices.
594  */
595 static int oal_control_file_open(struct inode *inode, struct file *filp)
596 {
597         struct oal_control_file *ccf;
598         int rc;
599
600         rc = nonseekable_open(inode, filp);
601         if (rc)
602                 return rc;
603
604         /* ccf->ccf_event_count = 0 on open */
605         ccf = kzalloc(sizeof(*ccf), GFP_KERNEL);
606         if (!ccf)
607                 return -ENOMEM;
608
609         filp->private_data = ccf;
610
611         return 0;
612 }
613
614 static int oal_control_file_release(struct inode *inode, struct file *filp)
615 {
616         kfree(filp->private_data);
617         return 0;
618 }
619
620 static unsigned int oal_control_file_poll(struct file *filp, poll_table *wait)
621 {
622         struct oal_control_file *ccf = filp->private_data;
623         unsigned int mask = 0;
624
625         poll_wait(filp, &oal_control_wait_queue, wait);
626
627         if (atomic_read(&oal_control_event_count) != ccf->ccf_event_count)
628                 mask |= POLLIN;
629
630         return mask;
631 }
632
633 static long oal_control_file_ioctl(struct file *filp, unsigned int cmd,
634                                    unsigned long arg)
635 {
636         struct oal_control_file *ccf = filp->private_data;
637
638         switch (cmd) {
639         case LUSTRE_ACCESS_LOG_IOCTL_VERSION:
640                 return LUSTRE_ACCESS_LOG_VERSION_1;
641         case LUSTRE_ACCESS_LOG_IOCTL_MAJOR:
642                 return oal_log_major;
643         case LUSTRE_ACCESS_LOG_IOCTL_PRESCAN:
644                 ccf->ccf_event_count = atomic_read(&oal_control_event_count);
645                 return 0;
646         default:
647                 return -ENOTTY;
648         }
649 }
650
651 static const struct file_operations oal_control_fops = {
652         .owner = THIS_MODULE,
653         .open = &oal_control_file_open,
654         .release = &oal_control_file_release,
655         .poll = &oal_control_file_poll,
656         .unlocked_ioctl = &oal_control_file_ioctl,
657         .llseek = &noop_llseek,
658 };
659
660 static struct miscdevice oal_control_misc = {
661         .minor = MISC_DYNAMIC_MINOR,
662         .name = LUSTRE_ACCESS_LOG_DIR_NAME"!control",
663         .fops = &oal_control_fops,
664 };
665
666 int ofd_access_log_module_init(void)
667 {
668         dev_t dev;
669         int rc;
670
671         BUILD_BUG_ON(!is_power_of_2(sizeof(struct ofd_access_entry_v1)));
672
673         rc = misc_register(&oal_control_misc);
674         if (rc)
675                 return rc;
676
677         rc = alloc_chrdev_region(&dev, 0, OAL_DEV_COUNT,
678                                 LUSTRE_ACCESS_LOG_DIR_NAME);
679         if (rc)
680                 goto out_oal_control_misc;
681
682         oal_log_major = MAJOR(dev);
683
684         oal_log_class = ll_class_create(LUSTRE_ACCESS_LOG_DIR_NAME);
685         if (IS_ERR(oal_log_class)) {
686                 rc = PTR_ERR(oal_log_class);
687                 goto out_dev;
688         }
689
690         return 0;
691 out_dev:
692         unregister_chrdev_region(dev, OAL_DEV_COUNT);
693 out_oal_control_misc:
694         misc_deregister(&oal_control_misc);
695
696         return rc;
697 }
698
699 void ofd_access_log_module_exit(void)
700 {
701         class_destroy(oal_log_class);
702         unregister_chrdev_region(MKDEV(oal_log_major, 0), OAL_DEV_COUNT);
703         idr_destroy(&oal_log_minor_idr);
704         misc_deregister(&oal_control_misc);
705 }