Whamcloud - gitweb
LU-1481 build: quiet warnings due to := assignment
[fs/lustre-release.git] / libcfs / libcfs / libcfs_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  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 021110-1307, USA
20  *
21  * GPL HEADER END
22  */
23 /*
24  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
25  * Copyright (c) 2011, 2012, Whamcloud, Inc.
26  */
27 /*
28  * This file is part of Lustre, http://www.lustre.org/
29  * Lustre is a trademark of Sun Microsystems, Inc.
30  *
31  * Author: liang@whamcloud.com
32  */
33
34 #ifndef EXPORT_SYMTAB
35 # define EXPORT_SYMTAB
36 #endif
37 #define DEBUG_SUBSYSTEM S_LNET
38
39 #include <libcfs/libcfs.h>
40
41 struct cfs_var_array {
42         unsigned int            va_count;       /* # of buffers */
43         unsigned int            va_size;        /* size of each var */
44         struct cfs_cpt_table    *va_cptab;      /* cpu partition table */
45         void                    *va_ptrs[0];    /* buffer addresses */
46 };
47
48 /*
49  * free per-cpu data, see more detail in cfs_percpt_free
50  */
51 void
52 cfs_percpt_free(void *vars)
53 {
54         struct  cfs_var_array *arr;
55         int     i;
56
57         arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
58
59         for (i = 0; i < arr->va_count; i++) {
60                 if (arr->va_ptrs[i] != NULL)
61                         LIBCFS_FREE(arr->va_ptrs[i], arr->va_size);
62         }
63
64         LIBCFS_FREE(arr, offsetof(struct cfs_var_array,
65                                   va_ptrs[arr->va_count]));
66 }
67 EXPORT_SYMBOL(cfs_percpt_free);
68
69 /*
70  * allocate per cpu-partition variables, returned value is an array of pointers,
71  * variable can be indexed by CPU partition ID, i.e:
72  *
73  *      arr = cfs_percpt_alloc(cfs_cpu_pt, size);
74  *      then caller can access memory block for CPU 0 by arr[0],
75  *      memory block for CPU 1 by arr[1]...
76  *      memory block for CPU N by arr[N]...
77  *
78  * cacheline aligned.
79  */
80 void *
81 cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size)
82 {
83         struct cfs_var_array    *arr;
84         int                     count;
85         int                     i;
86
87         count = cfs_cpt_number(cptab);
88
89         LIBCFS_ALLOC(arr, offsetof(struct cfs_var_array, va_ptrs[count]));
90         if (arr == NULL)
91                 return NULL;
92
93         arr->va_size    = size = CFS_L1_CACHE_ALIGN(size);
94         arr->va_count   = count;
95         arr->va_cptab   = cptab;
96
97         for (i = 0; i < count; i++) {
98                 LIBCFS_CPT_ALLOC(arr->va_ptrs[i], cptab, i, size);
99                 if (arr->va_ptrs[i] == NULL) {
100                         cfs_percpt_free((void *)&arr->va_ptrs[0]);
101                         return NULL;
102                 }
103         }
104
105         return (void *)&arr->va_ptrs[0];
106 }
107 EXPORT_SYMBOL(cfs_percpt_alloc);
108
109 /*
110  * return number of CPUs (or number of elements in per-cpu data)
111  * according to cptab of @vars
112  */
113 int
114 cfs_percpt_number(void *vars)
115 {
116         struct cfs_var_array *arr;
117
118         arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
119
120         return arr->va_count;
121 }
122 EXPORT_SYMBOL(cfs_percpt_number);
123
124 /*
125  * return memory block shadowed from current CPU
126  */
127 void *
128 cfs_percpt_current(void *vars)
129 {
130         struct cfs_var_array *arr;
131         int    cpt;
132
133         arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
134         cpt = cfs_cpt_current(arr->va_cptab, 0);
135         if (cpt < 0)
136                 return NULL;
137
138         return arr->va_ptrs[cpt];
139 }
140 EXPORT_SYMBOL(cfs_percpt_current);
141
142 void *
143 cfs_percpt_index(void *vars, int idx)
144 {
145         struct cfs_var_array *arr;
146
147         arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
148
149         LASSERT(idx >= 0 && idx < arr->va_count);
150         return arr->va_ptrs[idx];
151 }
152 EXPORT_SYMBOL(cfs_percpt_index);
153
154 /*
155  * free variable array, see more detail in cfs_array_alloc
156  */
157 void
158 cfs_array_free(void *vars)
159 {
160         struct cfs_var_array    *arr;
161         int                     i;
162
163         arr = container_of(vars, struct cfs_var_array, va_ptrs[0]);
164
165         for (i = 0; i < arr->va_count; i++) {
166                 if (arr->va_ptrs[i] == NULL)
167                         continue;
168
169                 LIBCFS_FREE(arr->va_ptrs[i], arr->va_size);
170         }
171         LIBCFS_FREE(arr, offsetof(struct cfs_var_array,
172                                   va_ptrs[arr->va_count]));
173 }
174 EXPORT_SYMBOL(cfs_array_free);
175
176 /*
177  * allocate a variable array, returned value is an array of pointers.
178  * Caller can specify length of array by @count, @size is size of each
179  * memory block in array.
180  */
181 void *
182 cfs_array_alloc(int count, unsigned int size)
183 {
184         struct cfs_var_array    *arr;
185         int                     i;
186
187         LIBCFS_ALLOC(arr, offsetof(struct cfs_var_array, va_ptrs[count]));
188         if (arr == NULL)
189                 return NULL;
190
191         arr->va_count   = count;
192         arr->va_size    = size;
193
194         for (i = 0; i < count; i++) {
195                 LIBCFS_ALLOC(arr->va_ptrs[i], size);
196
197                 if (arr->va_ptrs[i] == NULL) {
198                         cfs_array_free((void *)&arr->va_ptrs[0]);
199                         return NULL;
200                 }
201         }
202
203         return (void *)&arr->va_ptrs[0];
204 }
205 EXPORT_SYMBOL(cfs_array_alloc);