Whamcloud - gitweb
LU-16859 lnet: incorrect check for duplicate NI
[fs/lustre-release.git] / lnet / lnet / lib-mem.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * GPL HEADER END
17  */
18 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
19  * Copyright (c) 2012, Intel Corporation.
20  */
21 /* This file is part of Lustre, http://www.lustre.org/
22  *
23  * Author: liang@whamcloud.com
24  */
25
26 #define DEBUG_SUBSYSTEM S_LNET
27
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <libcfs/libcfs.h>
31 #include <libcfs/libcfs_cpu.h>
32 #include <linux/slab.h>
33 #include <linux/mm.h>
34
35 struct cfs_var_array {
36         unsigned int            va_count;       /* # of buffers */
37         unsigned int            va_size;        /* size of each var */
38         struct cfs_cpt_table    *va_cptab;      /* cpu partition table */
39         void                    *va_ptrs[0];    /* buffer addresses */
40 };
41
42 /* free per-cpu data, see more detail in cfs_percpt_free
43  */
44 void
45 cfs_percpt_free(void *vars)
46 {
47         struct cfs_var_array *arr;
48         int i;
49
50         arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
51
52         for (i = 0; i < arr->va_count; i++) {
53                 if (arr->va_ptrs[i] != NULL)
54                         LIBCFS_FREE(arr->va_ptrs[i], arr->va_size);
55         }
56
57         LIBCFS_FREE(arr, offsetof(struct cfs_var_array,
58                                   va_ptrs[arr->va_count]));
59 }
60 EXPORT_SYMBOL(cfs_percpt_free);
61
62 /* allocate per cpu-partition variables, returned value is an array of pointers,
63  * variable can be indexed by CPU partition ID, i.e:
64  *
65  *      arr = cfs_percpt_alloc(cfs_cpu_pt, size);
66  *      then caller can access memory block for CPU 0 by arr[0],
67  *      memory block for CPU 1 by arr[1]...
68  *      memory block for CPU N by arr[N]...
69  *
70  * cacheline aligned.
71  */
72 void *
73 cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size)
74 {
75         struct cfs_var_array *arr;
76         int count;
77         int i;
78
79         count = cfs_cpt_number(cptab);
80
81         LIBCFS_ALLOC(arr, offsetof(struct cfs_var_array, va_ptrs[count]));
82         if (!arr)
83                 return NULL;
84
85         size = L1_CACHE_ALIGN(size);
86         arr->va_size = size;
87         arr->va_count = count;
88         arr->va_cptab = cptab;
89
90         for (i = 0; i < count; i++) {
91                 LIBCFS_CPT_ALLOC(arr->va_ptrs[i], cptab, i, size);
92                 if (!arr->va_ptrs[i]) {
93                         cfs_percpt_free((void *)&arr->va_ptrs[0]);
94                         return NULL;
95                 }
96         }
97
98         return (void *)&arr->va_ptrs[0];
99 }
100 EXPORT_SYMBOL(cfs_percpt_alloc);
101
102 /* return number of CPUs (or number of elements in per-cpu data)
103  * according to cptab of @vars
104  */
105 int
106 cfs_percpt_number(void *vars)
107 {
108         struct cfs_var_array *arr;
109
110         arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
111
112         return arr->va_count;
113 }
114 EXPORT_SYMBOL(cfs_percpt_number);