Whamcloud - gitweb
Mass conversion of all copyright messages to Oracle.
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-mem.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #define DEBUG_SUBSYSTEM S_LNET
38
39 #include <libcfs/libcfs.h>
40
41
42 cfs_mem_cache_t *cfs_page_t_slab = NULL;
43 cfs_mem_cache_t *cfs_page_p_slab = NULL;
44
45 cfs_page_t * virt_to_page(void * addr)
46 {
47     cfs_page_t *pg;
48     pg = cfs_mem_cache_alloc(cfs_page_t_slab, 0);
49     
50     if (NULL == pg) {
51         cfs_enter_debugger();
52         return NULL;
53     }
54
55     memset(pg, 0, sizeof(cfs_page_t));
56     pg->addr = (void *)((__u64)addr & (~((__u64)PAGE_SIZE-1)));
57     pg->mapping = addr;
58     cfs_atomic_set(&pg->count, 1);
59     cfs_set_bit(PG_virt, &(pg->flags));
60     cfs_enter_debugger();
61     return pg;
62 }
63
64 /*
65  * cfs_alloc_page
66  *   To allocate the cfs_page_t and also 1 page of memory
67  *
68  * Arguments:
69  *   flags:  the allocation options
70  *
71  * Return Value:
72  *   pointer to the cfs_page_t strcture in success or
73  *   NULL in failure case
74  *
75  * Notes: 
76  *   N/A
77  */
78
79 cfs_atomic_t libcfs_total_pages;
80
81 cfs_page_t * cfs_alloc_page(int flags)
82 {
83     cfs_page_t *pg;
84     pg = cfs_mem_cache_alloc(cfs_page_t_slab, 0);
85     
86     if (NULL == pg) {
87         cfs_enter_debugger();
88         return NULL;
89     }
90
91     memset(pg, 0, sizeof(cfs_page_t));
92     pg->addr = cfs_mem_cache_alloc(cfs_page_p_slab, 0);
93     cfs_atomic_set(&pg->count, 1);
94
95     if (pg->addr) {
96         if (cfs_is_flag_set(flags, CFS_ALLOC_ZERO)) {
97             memset(pg->addr, 0, CFS_PAGE_SIZE);
98         }
99         cfs_atomic_inc(&libcfs_total_pages);
100     } else {
101         cfs_enter_debugger();
102         cfs_mem_cache_free(cfs_page_t_slab, pg);
103         pg = NULL;
104     }
105
106     return pg;
107 }
108
109 /*
110  * cfs_free_page
111  *   To free the cfs_page_t including the page
112  *
113  * Arguments:
114  *   pg:  pointer to the cfs_page_t strcture
115  *
116  * Return Value:
117  *   N/A
118  *
119  * Notes: 
120  *   N/A
121  */
122 void cfs_free_page(cfs_page_t *pg)
123 {
124     ASSERT(pg != NULL);
125     ASSERT(pg->addr  != NULL);
126     ASSERT(cfs_atomic_read(&pg->count) <= 1);
127
128     if (!cfs_test_bit(PG_virt, &pg->flags)) {
129         cfs_mem_cache_free(cfs_page_p_slab, pg->addr);
130         cfs_atomic_dec(&libcfs_total_pages);
131     } else {
132         cfs_enter_debugger();
133     }
134     cfs_mem_cache_free(cfs_page_t_slab, pg);
135 }
136
137 cfs_page_t *cfs_alloc_pages(unsigned int flags, unsigned int order)
138 {
139     cfs_page_t *pg;
140     pg = cfs_mem_cache_alloc(cfs_page_t_slab, 0);
141     
142     if (NULL == pg) {
143         cfs_enter_debugger();
144         return NULL;
145     }
146
147     memset(pg, 0, sizeof(cfs_page_t));
148     pg->addr = cfs_alloc((CFS_PAGE_SIZE << order),0);
149     cfs_atomic_set(&pg->count, 1);
150
151     if (pg->addr) {
152         if (cfs_is_flag_set(flags, CFS_ALLOC_ZERO)) {
153             memset(pg->addr, 0, CFS_PAGE_SIZE << order);
154         }
155         cfs_atomic_add(1 << order, &libcfs_total_pages);
156     } else {
157         cfs_enter_debugger();
158         cfs_mem_cache_free(cfs_page_t_slab, pg);
159         pg = NULL;
160     }
161
162     return pg;
163 }
164
165 void __cfs_free_pages(cfs_page_t *pg, unsigned int order)
166 {
167     ASSERT(pg != NULL);
168     ASSERT(pg->addr  != NULL);
169     ASSERT(cfs_atomic_read(&pg->count) <= 1);
170
171     cfs_atomic_sub(1 << order, &libcfs_total_pages);
172     cfs_free(pg->addr);
173     cfs_mem_cache_free(cfs_page_t_slab, pg);
174 }
175
176 int cfs_mem_is_in_cache(const void *addr, const cfs_mem_cache_t *kmem)
177 {
178     KdPrint(("cfs_mem_is_in_cache: not implemented. (should maintain a"
179               "chain to keep all allocations traced.)\n"));
180     return 1;
181 }
182
183 /*
184  * cfs_alloc
185  *   To allocate memory from system pool
186  *
187  * Arguments:
188  *   nr_bytes:  length in bytes of the requested buffer
189  *   flags:     flags indiction
190  *
191  * Return Value:
192  *   NULL: if there's no enough memory space in system
193  *   the address of the allocated memory in success.
194  *
195  * Notes: 
196  *   This operation can be treated as atomic.
197  */
198
199 void *
200 cfs_alloc(size_t nr_bytes, u_int32_t flags)
201 {
202     void *ptr;
203
204     /* Ignore the flags: always allcoate from NonPagedPool */
205     ptr = ExAllocatePoolWithTag(NonPagedPool, nr_bytes, 'Lufs');
206     if (ptr != NULL && (flags & CFS_ALLOC_ZERO)) {
207         memset(ptr, 0, nr_bytes);
208     }
209
210     if (!ptr) {
211         cfs_enter_debugger();
212     }
213
214     return ptr;
215 }
216
217 /*
218  * cfs_free
219  *   To free the sepcified memory to system pool
220  *
221  * Arguments:
222  *   addr:   pointer to the buffer to be freed
223  *
224  * Return Value:
225  *   N/A
226  *
227  * Notes: 
228  *    This operation can be treated as atomic.
229  */
230
231 void
232 cfs_free(void *addr)
233 {
234     ExFreePool(addr);
235 }
236
237 /*
238  * cfs_alloc_large
239  *   To allocate large block of memory from system pool
240  *
241  * Arguments:
242  *   nr_bytes:  length in bytes of the requested buffer
243  *
244  * Return Value:
245  *   NULL: if there's no enough memory space in system
246  *   the address of the allocated memory in success.
247  *
248  * Notes: 
249  *   N/A
250  */
251
252 void *
253 cfs_alloc_large(size_t nr_bytes)
254 {
255     return cfs_alloc(nr_bytes, 0);
256 }
257
258 /*
259  * cfs_free_large
260  *   To free the sepcified memory to system pool
261  *
262  * Arguments:
263  *   addr:   pointer to the buffer to be freed
264  *
265  * Return Value:
266  *   N/A
267  *
268  * Notes: 
269  *   N/A
270  */
271
272 void
273 cfs_free_large(void *addr)
274 {
275     cfs_free(addr);
276 }
277
278
279 /*
280  * cfs_mem_cache_create
281  *   To create a SLAB cache
282  *
283  * Arguments:
284  *   name:   name string of the SLAB cache to be created
285  *   size:   size in bytes of SLAB entry buffer
286  *   offset: offset in the page
287  *   flags:  SLAB creation flags
288 *
289  * Return Value:
290  *   The poitner of cfs_memory_cache structure in success.
291  *   NULL pointer in failure case.
292  *
293  * Notes: 
294  *   1, offset won't be used here.
295  *   2, it could be better to induce a lock to protect the access of the
296  *       SLAB structure on SMP if there's not outside lock protection.
297  *   3, parameters C/D are removed.
298  */
299
300 cfs_mem_cache_t *
301 cfs_mem_cache_create(
302     const char * name,
303     size_t size,
304     size_t offset,
305     unsigned long flags
306     )
307 {
308     cfs_mem_cache_t * kmc = NULL;
309
310     /*  The name of the SLAB could not exceed 20 chars */
311
312     if (name && strlen(name) >= 20) {
313         goto errorout;
314     }
315
316     /* Allocate and initialize the SLAB strcture */
317
318     kmc = cfs_alloc (sizeof(cfs_mem_cache_t), 0);
319
320     if (NULL == kmc) {
321         goto errorout;
322     }
323
324     memset(kmc, 0, sizeof(cfs_mem_cache_t));
325     kmc->flags = flags;
326
327     if (name) {
328         strcpy(&kmc->name[0], name);
329     }
330
331     /* Initialize the corresponding LookAside list */
332
333     ExInitializeNPagedLookasideList(
334             &(kmc->npll),
335             NULL,
336             NULL,
337             0,
338             size,
339             'pnmk',
340             0);
341  
342 errorout:
343
344     return kmc;
345 }
346
347 /*
348  * cfs_mem_cache_destroy
349  *   To destroy the unused SLAB cache
350  *
351  * Arguments:
352  *   kmc: the SLAB cache to be destroied.
353  *
354  * Return Value:
355  *   0: in success case.
356  *   1: in failure case.
357  *
358  * Notes: 
359  *   N/A
360  */
361
362 int cfs_mem_cache_destroy (cfs_mem_cache_t * kmc)
363 {
364     ASSERT(kmc != NULL);
365
366     ExDeleteNPagedLookasideList(&(kmc->npll));
367
368     cfs_free(kmc);
369
370     return 0;
371 }
372
373 /*
374  * cfs_mem_cache_alloc
375  *   To allocate an object (LookAside entry) from the SLAB
376  *
377  * Arguments:
378  *   kmc:   the SLAB cache to be allocated from.
379  *   flags: flags for allocation options
380  *
381  * Return Value:
382  *   object buffer address: in success case.
383  *   NULL: in failure case.
384  *
385  * Notes: 
386  *   N/A
387  */
388
389 void *cfs_mem_cache_alloc(cfs_mem_cache_t * kmc, int flags)
390 {
391     void *buf = NULL;
392
393     buf = ExAllocateFromNPagedLookasideList(&(kmc->npll));
394
395     return buf;
396 }
397
398 /*
399  * cfs_mem_cache_free
400  *   To free an object (LookAside entry) to the SLAB cache
401  *
402  * Arguments:
403  *   kmc: the SLAB cache to be freed to.
404  *   buf: the pointer to the object to be freed.
405  *
406  * Return Value:
407  *   N/A
408  *
409  * Notes: 
410  *   N/A
411  */
412
413 void cfs_mem_cache_free(cfs_mem_cache_t * kmc, void * buf)
414 {
415     ExFreeToNPagedLookasideList(&(kmc->npll), buf);
416 }
417
418 cfs_spinlock_t  shrinker_guard = {0};
419 CFS_LIST_HEAD(shrinker_hdr);
420 cfs_timer_t shrinker_timer = {0};
421
422 struct cfs_shrinker * cfs_set_shrinker(int seeks, shrink_callback cb)
423 {
424     struct cfs_shrinker * s = (struct cfs_shrinker *)
425         cfs_alloc(sizeof(struct cfs_shrinker), CFS_ALLOC_ZERO);
426     if (s) {
427         s->cb = cb;
428         s->seeks = seeks;
429         s->nr = 2;
430         cfs_spin_lock(&shrinker_guard);
431         cfs_list_add(&s->list, &shrinker_hdr); 
432         cfs_spin_unlock(&shrinker_guard);
433     }
434
435     return s;
436 }
437
438 void cfs_remove_shrinker(struct cfs_shrinker *s)
439 {
440     struct cfs_shrinker *tmp;
441     cfs_spin_lock(&shrinker_guard);
442 #if TRUE
443     cfs_list_for_each_entry_typed(tmp, &shrinker_hdr,
444                                   struct cfs_shrinker, list) {
445         if (tmp == s) {
446             cfs_list_del(&tmp->list);
447             break;
448         } 
449     }
450 #else
451     cfs_list_del(&s->list);
452 #endif
453     cfs_spin_unlock(&shrinker_guard);
454     cfs_free(s);
455 }
456
457 /* time ut test proc */
458 void shrinker_timer_proc(ulong_ptr_t arg)
459 {
460     struct cfs_shrinker *s;
461     cfs_spin_lock(&shrinker_guard);
462
463     cfs_list_for_each_entry_typed(s, &shrinker_hdr,
464                                   struct cfs_shrinker, list) {
465             s->cb(s->nr, __GFP_FS);
466     }
467     cfs_spin_unlock(&shrinker_guard);
468     cfs_timer_arm(&shrinker_timer, 300);
469 }
470
471 int start_shrinker_timer()
472 {
473     /* initialize shriner timer */
474     cfs_timer_init(&shrinker_timer, shrinker_timer_proc, NULL);
475
476     /* start the timer to trigger in 5 minutes */
477     cfs_timer_arm(&shrinker_timer, 300);
478
479     return 0;
480 }
481
482 void stop_shrinker_timer()
483 {
484     /* cancel the timer */
485     cfs_timer_disarm(&shrinker_timer);
486     cfs_timer_done(&shrinker_timer);
487 }