5 |
* |
* |
6 |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
7 |
* |
* |
8 |
* Version: 1.6.6-pre 2008/12/01 |
* Version: 1.6.6-pre 2008/12/24 |
9 |
* |
* |
10 |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
11 |
* See README.ccs for ChangeLog. |
* See README.ccs for ChangeLog. |
24 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) |
25 |
#include <linux/namei.h> |
#include <linux/namei.h> |
26 |
#include <linux/mount.h> |
#include <linux/mount.h> |
27 |
static const int lookup_flags = LOOKUP_FOLLOW; |
static const int ccs_lookup_flags = LOOKUP_FOLLOW; |
28 |
#else |
#else |
29 |
static const int lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE; |
static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE; |
30 |
#endif |
#endif |
31 |
#include <linux/realpath.h> |
#include <linux/realpath.h> |
32 |
#include <linux/proc_fs.h> |
#include <linux/proc_fs.h> |
33 |
#include <linux/ccs_common.h> |
#include <linux/ccs_common.h> |
34 |
|
|
35 |
/** |
/** |
36 |
* get_absolute_path - Get the path of a dentry but ignores chroot'ed root. |
* ccs_get_absolute_path - Get the path of a dentry but ignores chroot'ed root. |
37 |
* |
* |
38 |
* @dentry: Pointer to "struct dentry". |
* @dentry: Pointer to "struct dentry". |
39 |
* @vfsmnt: Pointer to "struct vfsmount". |
* @vfsmnt: Pointer to "struct vfsmount". |
50 |
* \ooo style octal string. |
* \ooo style octal string. |
51 |
* Character \ is converted to \\ string. |
* Character \ is converted to \\ string. |
52 |
*/ |
*/ |
53 |
static int get_absolute_path(struct dentry *dentry, struct vfsmount *vfsmnt, |
static int ccs_get_absolute_path(struct dentry *dentry, struct vfsmount *vfsmnt, |
54 |
char *buffer, int buflen) |
char *buffer, int buflen) |
55 |
{ |
{ |
56 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
57 |
char *start = buffer; |
char *start = buffer; |
245 |
d_mnt = mntget(mnt); |
d_mnt = mntget(mnt); |
246 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
247 |
ccs_realpath_lock(); |
ccs_realpath_lock(); |
248 |
error = get_absolute_path(d_dentry, d_mnt, newname, newname_len); |
error = ccs_get_absolute_path(d_dentry, d_mnt, newname, newname_len); |
249 |
ccs_realpath_unlock(); |
ccs_realpath_unlock(); |
250 |
/***** CRITICAL SECTION END *****/ |
/***** CRITICAL SECTION END *****/ |
251 |
dput(d_dentry); |
dput(d_dentry); |
289 |
char *ccs_realpath(const char *pathname) |
char *ccs_realpath(const char *pathname) |
290 |
{ |
{ |
291 |
struct nameidata nd; |
struct nameidata nd; |
292 |
if (pathname && path_lookup(pathname, lookup_flags, &nd) == 0) { |
if (pathname && path_lookup(pathname, ccs_lookup_flags, &nd) == 0) { |
293 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) |
294 |
char *buf = ccs_realpath_from_dentry(nd.path.dentry, |
char *buf = ccs_realpath_from_dentry(nd.path.dentry, |
295 |
nd.path.mnt); |
nd.path.mnt); |
313 |
char *ccs_realpath_nofollow(const char *pathname) |
char *ccs_realpath_nofollow(const char *pathname) |
314 |
{ |
{ |
315 |
struct nameidata nd; |
struct nameidata nd; |
316 |
if (pathname && path_lookup(pathname, lookup_flags ^ LOOKUP_FOLLOW, |
if (pathname && path_lookup(pathname, ccs_lookup_flags ^ LOOKUP_FOLLOW, |
317 |
&nd) == 0) { |
&nd) == 0) { |
318 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) |
319 |
char *buf = ccs_realpath_from_dentry(nd.path.dentry, |
char *buf = ccs_realpath_from_dentry(nd.path.dentry, |
329 |
} |
} |
330 |
|
|
331 |
/** |
/** |
332 |
* round_up - Round up an integer so that the returned pointers are appropriately aligned. |
* ccs_round_up - Round up an integer so that the returned pointers are appropriately aligned. |
333 |
* |
* |
334 |
* @size: Size in bytes. |
* @size: Size in bytes. |
335 |
* |
* |
338 |
* FIXME: Are there more requirements that is needed for assigning value |
* FIXME: Are there more requirements that is needed for assigning value |
339 |
* atomically? |
* atomically? |
340 |
*/ |
*/ |
341 |
static inline unsigned int round_up(const unsigned int size) |
static inline unsigned int ccs_round_up(const unsigned int size) |
342 |
{ |
{ |
343 |
if (sizeof(void *) >= sizeof(long)) |
if (sizeof(void *) >= sizeof(long)) |
344 |
return ((size + sizeof(void *) - 1) |
return ((size + sizeof(void *) - 1) |
348 |
/ sizeof(long)) * sizeof(long); |
/ sizeof(long)) * sizeof(long); |
349 |
} |
} |
350 |
|
|
351 |
static unsigned int allocated_memory_for_elements; |
static unsigned int ccs_allocated_memory_for_elements; |
352 |
static unsigned int quota_for_elements; |
static unsigned int ccs_quota_for_elements; |
353 |
|
|
354 |
/** |
/** |
355 |
* ccs_alloc_element - Allocate permanent memory for structures. |
* ccs_alloc_element - Allocate permanent memory for structures. |
363 |
void *ccs_alloc_element(const unsigned int size) |
void *ccs_alloc_element(const unsigned int size) |
364 |
{ |
{ |
365 |
static DEFINE_MUTEX(lock); |
static DEFINE_MUTEX(lock); |
366 |
static char *buf; |
static char *ccs_buf; |
367 |
static unsigned int buf_used_len = PAGE_SIZE; |
static unsigned int ccs_buf_used_len = PAGE_SIZE; |
368 |
char *ptr = NULL; |
char *ptr = NULL; |
369 |
const unsigned int word_aligned_size = round_up(size); |
const unsigned int word_aligned_size = ccs_round_up(size); |
370 |
if (word_aligned_size > PAGE_SIZE) |
if (word_aligned_size > PAGE_SIZE) |
371 |
return NULL; |
return NULL; |
372 |
mutex_lock(&lock); |
mutex_lock(&lock); |
373 |
if (buf_used_len + word_aligned_size > PAGE_SIZE) { |
if (ccs_buf_used_len + word_aligned_size > PAGE_SIZE) { |
374 |
if (!quota_for_elements || allocated_memory_for_elements |
if (!ccs_quota_for_elements || ccs_allocated_memory_for_elements |
375 |
+ PAGE_SIZE <= quota_for_elements) |
+ PAGE_SIZE <= ccs_quota_for_elements) |
376 |
ptr = kzalloc(PAGE_SIZE, GFP_KERNEL); |
ptr = kzalloc(PAGE_SIZE, GFP_KERNEL); |
377 |
if (!ptr) { |
if (!ptr) { |
378 |
printk(KERN_WARNING "ERROR: Out of memory " |
printk(KERN_WARNING "ERROR: Out of memory " |
379 |
"for ccs_alloc_element().\n"); |
"for ccs_alloc_element().\n"); |
380 |
if (!sbin_init_started) |
if (!ccs_sbin_init_started) |
381 |
panic("MAC Initialization failed.\n"); |
panic("MAC Initialization failed.\n"); |
382 |
} else { |
} else { |
383 |
buf = ptr; |
ccs_buf = ptr; |
384 |
allocated_memory_for_elements += PAGE_SIZE; |
ccs_allocated_memory_for_elements += PAGE_SIZE; |
385 |
buf_used_len = word_aligned_size; |
ccs_buf_used_len = word_aligned_size; |
|
ptr = buf; |
|
386 |
} |
} |
387 |
} else if (word_aligned_size) { |
} else if (word_aligned_size) { |
388 |
int i; |
int i; |
389 |
ptr = buf + buf_used_len; |
ptr = ccs_buf + ccs_buf_used_len; |
390 |
buf_used_len += word_aligned_size; |
ccs_buf_used_len += word_aligned_size; |
391 |
for (i = 0; i < word_aligned_size; i++) { |
for (i = 0; i < word_aligned_size; i++) { |
392 |
if (!ptr[i]) |
if (!ptr[i]) |
393 |
continue; |
continue; |
400 |
return ptr; |
return ptr; |
401 |
} |
} |
402 |
|
|
403 |
static unsigned int allocated_memory_for_savename; |
static unsigned int ccs_allocated_memory_for_savename; |
404 |
static unsigned int quota_for_savename; |
static unsigned int ccs_quota_for_savename; |
405 |
|
|
406 |
#define MAX_HASH 256 |
#define MAX_HASH 256 |
407 |
|
|
408 |
/* Structure for string data. */ |
/* Structure for string data. */ |
409 |
struct name_entry { |
struct ccs_name_entry { |
410 |
struct list1_head list; |
struct list1_head list; |
411 |
struct path_info entry; |
struct ccs_path_info entry; |
412 |
}; |
}; |
413 |
|
|
414 |
/* Structure for available memory region. */ |
/* Structure for available memory region. */ |
415 |
struct free_memory_block_list { |
struct ccs_free_memory_block_list { |
416 |
struct list_head list; |
struct list_head list; |
417 |
char *ptr; /* Pointer to a free area. */ |
char *ptr; /* Pointer to a free area. */ |
418 |
int len; /* Length of the area. */ |
int len; /* Length of the area. */ |
419 |
}; |
}; |
420 |
|
|
421 |
/* The list for "struct name_entry". */ |
/* The list for "struct ccs_name_entry". */ |
422 |
static struct list1_head name_list[MAX_HASH]; |
static struct list1_head ccs_name_list[MAX_HASH]; |
423 |
|
|
424 |
/** |
/** |
425 |
* ccs_save_name - Allocate permanent memory for string data. |
* ccs_save_name - Allocate permanent memory for string data. |
426 |
* |
* |
427 |
* @name: The string to store into the permernent memory. |
* @name: The string to store into the permernent memory. |
428 |
* |
* |
429 |
* Returns pointer to "struct path_info" on success, NULL otherwise. |
* Returns pointer to "struct ccs_path_info" on success, NULL otherwise. |
430 |
* |
* |
431 |
* The RAM is shared, so NEVER try to modify or kfree() the returned name. |
* The RAM is shared, so NEVER try to modify or kfree() the returned name. |
432 |
*/ |
*/ |
433 |
const struct path_info *ccs_save_name(const char *name) |
const struct ccs_path_info *ccs_save_name(const char *name) |
434 |
{ |
{ |
435 |
static LIST_HEAD(fmb_list); |
static LIST_HEAD(ccs_fmb_list); |
436 |
static DEFINE_MUTEX(lock); |
static DEFINE_MUTEX(lock); |
437 |
struct name_entry *ptr; |
struct ccs_name_entry *ptr; |
438 |
unsigned int hash; |
unsigned int hash; |
439 |
struct free_memory_block_list *fmb; |
struct ccs_free_memory_block_list *fmb; |
440 |
int len; |
int len; |
441 |
char *cp; |
char *cp; |
442 |
if (!name) |
if (!name) |
449 |
} |
} |
450 |
hash = full_name_hash((const unsigned char *) name, len - 1); |
hash = full_name_hash((const unsigned char *) name, len - 1); |
451 |
mutex_lock(&lock); |
mutex_lock(&lock); |
452 |
list1_for_each_entry(ptr, &name_list[hash % MAX_HASH], list) { |
list1_for_each_entry(ptr, &ccs_name_list[hash % MAX_HASH], list) { |
453 |
if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name)) |
if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name)) |
454 |
goto out; |
goto out; |
455 |
} |
} |
456 |
list_for_each_entry(fmb, &fmb_list, list) { |
list_for_each_entry(fmb, &ccs_fmb_list, list) { |
457 |
if (len <= fmb->len) |
if (len <= fmb->len) |
458 |
goto ready; |
goto ready; |
459 |
} |
} |
460 |
if (!quota_for_savename || allocated_memory_for_savename + PAGE_SIZE |
if (!ccs_quota_for_savename || |
461 |
<= quota_for_savename) |
ccs_allocated_memory_for_savename + PAGE_SIZE |
462 |
|
<= ccs_quota_for_savename) |
463 |
cp = kzalloc(PAGE_SIZE, GFP_KERNEL); |
cp = kzalloc(PAGE_SIZE, GFP_KERNEL); |
464 |
else |
else |
465 |
cp = NULL; |
cp = NULL; |
469 |
kfree(fmb); |
kfree(fmb); |
470 |
printk(KERN_WARNING "ERROR: Out of memory " |
printk(KERN_WARNING "ERROR: Out of memory " |
471 |
"for ccs_save_name().\n"); |
"for ccs_save_name().\n"); |
472 |
if (!sbin_init_started) |
if (!ccs_sbin_init_started) |
473 |
panic("MAC Initialization failed.\n"); |
panic("MAC Initialization failed.\n"); |
474 |
ptr = NULL; |
ptr = NULL; |
475 |
goto out; |
goto out; |
476 |
} |
} |
477 |
allocated_memory_for_savename += PAGE_SIZE; |
ccs_allocated_memory_for_savename += PAGE_SIZE; |
478 |
list_add(&fmb->list, &fmb_list); |
list_add(&fmb->list, &ccs_fmb_list); |
479 |
fmb->ptr = cp; |
fmb->ptr = cp; |
480 |
fmb->len = PAGE_SIZE; |
fmb->len = PAGE_SIZE; |
481 |
ready: |
ready: |
487 |
ccs_fill_path_info(&ptr->entry); |
ccs_fill_path_info(&ptr->entry); |
488 |
fmb->ptr += len; |
fmb->ptr += len; |
489 |
fmb->len -= len; |
fmb->len -= len; |
490 |
list1_add_tail_mb(&ptr->list, &name_list[hash % MAX_HASH]); |
list1_add_tail_mb(&ptr->list, &ccs_name_list[hash % MAX_HASH]); |
491 |
if (fmb->len == 0) { |
if (fmb->len == 0) { |
492 |
list_del(&fmb->list); |
list_del(&fmb->list); |
493 |
kfree(fmb); |
kfree(fmb); |
498 |
} |
} |
499 |
|
|
500 |
/* Structure for temporarily allocated memory. */ |
/* Structure for temporarily allocated memory. */ |
501 |
struct cache_entry { |
struct ccs_cache_entry { |
502 |
struct list_head list; |
struct list_head list; |
503 |
void *ptr; |
void *ptr; |
504 |
int size; |
int size; |
521 |
if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE) |
if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE) |
522 |
panic("Bad size."); |
panic("Bad size."); |
523 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) |
524 |
ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry), |
ccs_cachep = kmem_cache_create("ccs_cache", |
525 |
|
sizeof(struct ccs_cache_entry), |
526 |
0, 0, NULL); |
0, 0, NULL); |
527 |
#else |
#else |
528 |
ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry), |
ccs_cachep = kmem_cache_create("ccs_cache", |
529 |
|
sizeof(struct ccs_cache_entry), |
530 |
0, 0, NULL, NULL); |
0, 0, NULL, NULL); |
531 |
#endif |
#endif |
532 |
if (!ccs_cachep) |
if (!ccs_cachep) |
533 |
panic("Can't create cache.\n"); |
panic("Can't create cache.\n"); |
534 |
for (i = 0; i < MAX_HASH; i++) |
for (i = 0; i < MAX_HASH; i++) |
535 |
INIT_LIST1_HEAD(&name_list[i]); |
INIT_LIST1_HEAD(&ccs_name_list[i]); |
536 |
INIT_LIST1_HEAD(&KERNEL_DOMAIN.acl_info_list); |
INIT_LIST1_HEAD(&KERNEL_DOMAIN.acl_info_list); |
537 |
KERNEL_DOMAIN.domainname = ccs_save_name(ROOT_NAME); |
KERNEL_DOMAIN.domainname = ccs_save_name(ROOT_NAME); |
538 |
list1_add_tail_mb(&KERNEL_DOMAIN.list, &domain_list); |
list1_add_tail_mb(&KERNEL_DOMAIN.list, &ccs_domain_list); |
539 |
if (ccs_find_domain(ROOT_NAME) != &KERNEL_DOMAIN) |
if (ccs_find_domain(ROOT_NAME) != &KERNEL_DOMAIN) |
540 |
panic("Can't register KERNEL_DOMAIN"); |
panic("Can't register KERNEL_DOMAIN"); |
541 |
return 0; |
return 0; |
547 |
core_initcall(ccs_realpath_init); |
core_initcall(ccs_realpath_init); |
548 |
#endif |
#endif |
549 |
|
|
550 |
/* The list for "struct cache_entry". */ |
/* The list for "struct ccs_cache_entry". */ |
551 |
static LIST_HEAD(audit_cache_list); |
static LIST_HEAD(ccs_audit_cache_list); |
552 |
static LIST_HEAD(acl_cache_list); |
static LIST_HEAD(ccs_acl_cache_list); |
553 |
static DEFINE_SPINLOCK(cache_list_lock); |
static DEFINE_SPINLOCK(ccs_cache_list_lock); |
554 |
|
|
555 |
static unsigned int dynamic_memory_size; |
static unsigned int ccs_dynamic_memory_size; |
556 |
static unsigned int quota_for_dynamic; |
static unsigned int ccs_quota_for_dynamic; |
557 |
|
|
558 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) |
559 |
/** |
/** |
560 |
* round2 - Rounded up to power-of-two value. |
* ccs_round2 - Rounded up to power-of-two value. |
561 |
* |
* |
562 |
* @size: Size in bytes. |
* @size: Size in bytes. |
563 |
* |
* |
564 |
* Returns power-of-two of @size. |
* Returns power-of-two of @size. |
565 |
*/ |
*/ |
566 |
static int round2(size_t size) |
static int ccs_round2(size_t size) |
567 |
{ |
{ |
568 |
#if PAGE_SIZE == 4096 |
#if PAGE_SIZE == 4096 |
569 |
size_t bsize = 32; |
size_t bsize = 32; |
585 |
*/ |
*/ |
586 |
void *ccs_alloc(const size_t size, const _Bool check_quota) |
void *ccs_alloc(const size_t size, const _Bool check_quota) |
587 |
{ |
{ |
588 |
struct cache_entry *new_entry; |
struct ccs_cache_entry *new_entry; |
589 |
void *ret = kzalloc(size, GFP_KERNEL); |
void *ret = kzalloc(size, GFP_KERNEL); |
590 |
if (!ret) |
if (!ret) |
591 |
goto out; |
goto out; |
600 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) |
601 |
new_entry->size = ksize(ret); |
new_entry->size = ksize(ret); |
602 |
#else |
#else |
603 |
new_entry->size = round2(size); |
new_entry->size = ccs_round2(size); |
604 |
#endif |
#endif |
605 |
if (check_quota) { |
if (check_quota) { |
606 |
bool quota_exceeded = false; |
bool quota_exceeded = false; |
607 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
608 |
spin_lock(&cache_list_lock); |
spin_lock(&ccs_cache_list_lock); |
609 |
if (!quota_for_dynamic || dynamic_memory_size + new_entry->size |
if (!ccs_quota_for_dynamic || |
610 |
<= quota_for_dynamic) { |
ccs_dynamic_memory_size + new_entry->size |
611 |
list_add_tail(&new_entry->list, &audit_cache_list); |
<= ccs_quota_for_dynamic) { |
612 |
dynamic_memory_size += new_entry->size; |
list_add_tail(&new_entry->list, &ccs_audit_cache_list); |
613 |
|
ccs_dynamic_memory_size += new_entry->size; |
614 |
} else { |
} else { |
615 |
quota_exceeded = true; |
quota_exceeded = true; |
616 |
} |
} |
617 |
spin_unlock(&cache_list_lock); |
spin_unlock(&ccs_cache_list_lock); |
618 |
/***** CRITICAL SECTION END *****/ |
/***** CRITICAL SECTION END *****/ |
619 |
if (quota_exceeded) { |
if (quota_exceeded) { |
620 |
kfree(ret); |
kfree(ret); |
623 |
} |
} |
624 |
} else { |
} else { |
625 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
626 |
spin_lock(&cache_list_lock); |
spin_lock(&ccs_cache_list_lock); |
627 |
list_add(&new_entry->list, &acl_cache_list); |
list_add(&new_entry->list, &ccs_acl_cache_list); |
628 |
dynamic_memory_size += new_entry->size; |
ccs_dynamic_memory_size += new_entry->size; |
629 |
spin_unlock(&cache_list_lock); |
spin_unlock(&ccs_cache_list_lock); |
630 |
/***** CRITICAL SECTION END *****/ |
/***** CRITICAL SECTION END *****/ |
631 |
} |
} |
632 |
out: |
out: |
643 |
void ccs_free(const void *p) |
void ccs_free(const void *p) |
644 |
{ |
{ |
645 |
struct list_head *v; |
struct list_head *v; |
646 |
struct cache_entry *entry = NULL; |
struct ccs_cache_entry *entry = NULL; |
647 |
if (!p) |
if (!p) |
648 |
return; |
return; |
649 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
650 |
spin_lock(&cache_list_lock); |
spin_lock(&ccs_cache_list_lock); |
651 |
list_for_each(v, &acl_cache_list) { |
list_for_each(v, &ccs_acl_cache_list) { |
652 |
entry = list_entry(v, struct cache_entry, list); |
entry = list_entry(v, struct ccs_cache_entry, list); |
653 |
if (entry->ptr == p) |
if (entry->ptr == p) |
654 |
break; |
break; |
655 |
entry = NULL; |
entry = NULL; |
656 |
} |
} |
657 |
if (!entry) { |
if (!entry) { |
658 |
list_for_each(v, &audit_cache_list) { |
list_for_each(v, &ccs_audit_cache_list) { |
659 |
entry = list_entry(v, struct cache_entry, list); |
entry = list_entry(v, struct ccs_cache_entry, list); |
660 |
if (entry->ptr == p) |
if (entry->ptr == p) |
661 |
break; |
break; |
662 |
entry = NULL; |
entry = NULL; |
664 |
} |
} |
665 |
if (entry) { |
if (entry) { |
666 |
list_del(&entry->list); |
list_del(&entry->list); |
667 |
dynamic_memory_size -= entry->size; |
ccs_dynamic_memory_size -= entry->size; |
668 |
} |
} |
669 |
spin_unlock(&cache_list_lock); |
spin_unlock(&ccs_cache_list_lock); |
670 |
/***** CRITICAL SECTION END *****/ |
/***** CRITICAL SECTION END *****/ |
671 |
if (entry) { |
if (entry) { |
672 |
kfree(p); |
kfree(p); |
686 |
int ccs_read_memory_counter(struct ccs_io_buffer *head) |
int ccs_read_memory_counter(struct ccs_io_buffer *head) |
687 |
{ |
{ |
688 |
if (!head->read_eof) { |
if (!head->read_eof) { |
689 |
const unsigned int shared = allocated_memory_for_savename; |
const unsigned int shared = ccs_allocated_memory_for_savename; |
690 |
const unsigned int private = allocated_memory_for_elements; |
const unsigned int private = ccs_allocated_memory_for_elements; |
691 |
const unsigned int dynamic = dynamic_memory_size; |
const unsigned int dynamic = ccs_dynamic_memory_size; |
692 |
char buffer[64]; |
char buffer[64]; |
693 |
memset(buffer, 0, sizeof(buffer)); |
memset(buffer, 0, sizeof(buffer)); |
694 |
if (quota_for_savename) |
if (ccs_quota_for_savename) |
695 |
snprintf(buffer, sizeof(buffer) - 1, |
snprintf(buffer, sizeof(buffer) - 1, |
696 |
" (Quota: %10u)", quota_for_savename); |
" (Quota: %10u)", ccs_quota_for_savename); |
697 |
else |
else |
698 |
buffer[0] = '\0'; |
buffer[0] = '\0'; |
699 |
ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer); |
ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer); |
700 |
if (quota_for_elements) |
if (ccs_quota_for_elements) |
701 |
snprintf(buffer, sizeof(buffer) - 1, |
snprintf(buffer, sizeof(buffer) - 1, |
702 |
" (Quota: %10u)", quota_for_elements); |
" (Quota: %10u)", ccs_quota_for_elements); |
703 |
else |
else |
704 |
buffer[0] = '\0'; |
buffer[0] = '\0'; |
705 |
ccs_io_printf(head, "Private: %10u%s\n", private, buffer); |
ccs_io_printf(head, "Private: %10u%s\n", private, buffer); |
706 |
if (quota_for_dynamic) |
if (ccs_quota_for_dynamic) |
707 |
snprintf(buffer, sizeof(buffer) - 1, |
snprintf(buffer, sizeof(buffer) - 1, |
708 |
" (Quota: %10u)", quota_for_dynamic); |
" (Quota: %10u)", ccs_quota_for_dynamic); |
709 |
else |
else |
710 |
buffer[0] = '\0'; |
buffer[0] = '\0'; |
711 |
ccs_io_printf(head, "Dynamic: %10u%s\n", dynamic, buffer); |
ccs_io_printf(head, "Dynamic: %10u%s\n", dynamic, buffer); |
728 |
char *data = head->write_buf; |
char *data = head->write_buf; |
729 |
unsigned int size; |
unsigned int size; |
730 |
if (sscanf(data, "Shared: %u", &size) == 1) |
if (sscanf(data, "Shared: %u", &size) == 1) |
731 |
quota_for_savename = size; |
ccs_quota_for_savename = size; |
732 |
else if (sscanf(data, "Private: %u", &size) == 1) |
else if (sscanf(data, "Private: %u", &size) == 1) |
733 |
quota_for_elements = size; |
ccs_quota_for_elements = size; |
734 |
else if (sscanf(data, "Dynamic: %u", &size) == 1) |
else if (sscanf(data, "Dynamic: %u", &size) == 1) |
735 |
quota_for_dynamic = size; |
ccs_quota_for_dynamic = size; |
736 |
return 0; |
return 0; |
737 |
} |
} |