オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Annotation of /trunk/1.7.x/ccs-patch/security/ccsecurity/realpath.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1379 - (hide annotations) (download) (as text)
Thu Jul 10 06:52:35 2008 UTC (15 years, 10 months ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/realpath.c
File MIME type: text/x-csrc
File size: 17168 byte(s)


1 kumaneko 111 /*
2     * fs/realpath.c
3     *
4     * Get the canonicalized absolute pathnames. The basis for SAKURA and TOMOYO.
5     *
6 kumaneko 856 * Copyright (C) 2005-2008 NTT DATA CORPORATION
7 kumaneko 111 *
8 kumaneko 1379 * Version: 1.6.3-pre 2008/07/10
9 kumaneko 111 *
10     * This file is applicable to both 2.4.30 and 2.6.11 and later.
11     * See README.ccs for ChangeLog.
12     *
13     */
14     #include <linux/string.h>
15     #include <linux/mm.h>
16     #include <linux/utime.h>
17     #include <linux/file.h>
18     #include <linux/smp_lock.h>
19     #include <linux/module.h>
20     #include <linux/slab.h>
21     #include <asm/uaccess.h>
22     #include <asm/atomic.h>
23     #include <linux/version.h>
24 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
25 kumaneko 111 #include <linux/namei.h>
26     #include <linux/mount.h>
27     static const int lookup_flags = LOOKUP_FOLLOW;
28     #else
29     static const int lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
30     #endif
31     #include <linux/realpath.h>
32     #include <linux/proc_fs.h>
33     #include <linux/ccs_common.h>
34    
35 kumaneko 1052 /**
36     * get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
37 kumaneko 111 *
38 kumaneko 1052 * @dentry: Pointer to "struct dentry".
39     * @vfsmnt: Pointer to "struct vfsmount".
40     * @buffer: Pointer to buffer to return value in.
41     * @buflen: Sizeof @buffer.
42     *
43     * Returns 0 on success, -ENOMEM otherwise.
44     *
45 kumaneko 1064 * Caller holds the dcache_lock and vfsmount_lock.
46 kumaneko 111 * Based on __d_path() in fs/dcache.c
47     *
48     * If dentry is a directory, trailing '/' is appended.
49 kumaneko 1052 * Characters out of 0x20 < c < 0x7F range are converted to
50     * \ooo style octal string.
51 kumaneko 111 * Character \ is converted to \\ string.
52     */
53 kumaneko 1052 static int get_absolute_path(struct dentry *dentry, struct vfsmount *vfsmnt,
54     char *buffer, int buflen)
55 kumaneko 111 {
56 kumaneko 1052 /***** CRITICAL SECTION START *****/
57 kumaneko 111 char *start = buffer;
58     char *end = buffer + buflen;
59 kumaneko 621 bool is_dir = (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode));
60 kumaneko 111
61 kumaneko 1052 if (buflen < 256)
62     goto out;
63 kumaneko 111
64     *--end = '\0';
65     buflen--;
66    
67     for (;;) {
68     struct dentry *parent;
69    
70     if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
71     /* Global root? */
72 kumaneko 1052 if (vfsmnt->mnt_parent == vfsmnt)
73 kumaneko 111 break;
74     dentry = vfsmnt->mnt_mountpoint;
75     vfsmnt = vfsmnt->mnt_parent;
76     continue;
77     }
78     if (is_dir) {
79 kumaneko 1052 is_dir = false;
80     *--end = '/';
81     buflen--;
82 kumaneko 111 }
83     parent = dentry->d_parent;
84     {
85     const char *sp = dentry->d_name.name;
86     const char *cp = sp + dentry->d_name.len - 1;
87     unsigned char c;
88    
89 kumaneko 1052 /*
90     * Exception: Use /proc/self/ rather than
91     * /proc/\$/ for current process.
92     */
93     if (IS_ROOT(parent) && *sp > '0' && *sp <= '9' &&
94     parent->d_sb &&
95     parent->d_sb->s_magic == PROC_SUPER_MAGIC) {
96 kumaneko 111 char *ep;
97 kumaneko 1052 const pid_t pid
98     = (pid_t) simple_strtoul(sp, &ep, 10);
99     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
100     if (!*ep && pid == current->tgid) {
101     sp = "self";
102     cp = sp + 3;
103     }
104 kumaneko 111 #else
105 kumaneko 1052 if (!*ep && pid == current->pid) {
106     sp = "self";
107     cp = sp + 3;
108     }
109 kumaneko 111 #endif
110     }
111    
112     while (sp <= cp) {
113 kumaneko 1052 c = *(unsigned char *) cp;
114 kumaneko 111 if (c == '\\') {
115     buflen -= 2;
116 kumaneko 1052 if (buflen < 0)
117     goto out;
118 kumaneko 111 *--end = '\\';
119     *--end = '\\';
120     } else if (c > ' ' && c < 127) {
121 kumaneko 1052 if (--buflen < 0)
122     goto out;
123 kumaneko 111 *--end = (char) c;
124     } else {
125     buflen -= 4;
126 kumaneko 1052 if (buflen < 0)
127     goto out;
128 kumaneko 111 *--end = (c & 7) + '0';
129     *--end = ((c >> 3) & 7) + '0';
130     *--end = (c >> 6) + '0';
131     *--end = '\\';
132     }
133     cp--;
134     }
135 kumaneko 1052 if (--buflen < 0)
136     goto out;
137 kumaneko 111 *--end = '/';
138     }
139     dentry = parent;
140     }
141 kumaneko 1052 if (*end == '/') {
142     buflen++;
143     end++;
144     }
145 kumaneko 111 {
146     const char *sp = dentry->d_name.name;
147     const char *cp = sp + dentry->d_name.len - 1;
148     unsigned char c;
149     while (sp <= cp) {
150 kumaneko 1052 c = *(unsigned char *) cp;
151 kumaneko 111 if (c == '\\') {
152     buflen -= 2;
153 kumaneko 1052 if (buflen < 0)
154     goto out;
155 kumaneko 111 *--end = '\\';
156     *--end = '\\';
157     } else if (c > ' ' && c < 127) {
158 kumaneko 1052 if (--buflen < 0)
159     goto out;
160 kumaneko 111 *--end = (char) c;
161     } else {
162     buflen -= 4;
163 kumaneko 1052 if (buflen < 0)
164     goto out;
165 kumaneko 111 *--end = (c & 7) + '0';
166     *--end = ((c >> 3) & 7) + '0';
167     *--end = (c >> 6) + '0';
168     *--end = '\\';
169     }
170     cp--;
171     }
172     }
173     /* Move the pathname to the top of the buffer. */
174     memmove(start, end, strlen(end) + 1);
175     return 0;
176     out:
177     return -ENOMEM;
178 kumaneko 1052 /***** CRITICAL SECTION END *****/
179 kumaneko 111 }
180    
181 kumaneko 1052 /**
182 kumaneko 1054 * ccs_realpath_from_dentry2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
183 kumaneko 1052 *
184     * @dentry: Pointer to "struct dentry".
185     * @mnt: Pointer to "struct vfsmount".
186     * @newname: Pointer to buffer to return value in.
187 kumaneko 1064 * @newname_len: Size of @newname.
188 kumaneko 1052 *
189     * Returns 0 on success, negative value otherwise.
190     */
191     int ccs_realpath_from_dentry2(struct dentry *dentry, struct vfsmount *mnt,
192     char *newname, int newname_len)
193 kumaneko 111 {
194 kumaneko 1379 int error = -EINVAL;
195 kumaneko 111 struct dentry *d_dentry;
196     struct vfsmount *d_mnt;
197 kumaneko 1379 if (!dentry || !newname || newname_len <= 2048)
198     goto out;
199 kumaneko 1259 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
200     if (dentry->d_op && dentry->d_op->d_dname) {
201     /* For "socket:[\$]" and "pipe:[\$]". */
202     static const int offset = 1536;
203     char *dp = newname;
204     char *sp = dentry->d_op->d_dname(dentry, newname + offset,
205     newname_len - offset);
206     if (IS_ERR(sp)) {
207     error = PTR_ERR(sp);
208     goto out;
209     }
210     error = -ENOMEM;
211     newname += offset;
212     while (1) {
213     const unsigned char c = *(unsigned char *) sp++;
214     if (c == '\\') {
215     if (dp + 2 >= newname)
216     break;
217     *dp++ = '\\';
218     *dp++ = '\\';
219     } else if (c > ' ' && c < 127) {
220     if (dp + 1 >= newname)
221     break;
222     *dp++ = (char) c;
223     } else if (c) {
224     if (dp + 4 >= newname)
225     break;
226     *dp++ = '\\';
227     *dp++ = (c >> 6) + '0';
228     *dp++ = ((c >> 3) & 7) + '0';
229     *dp++ = (c & 7) + '0';
230     } else {
231     *dp = '\0';
232     return 0;
233     }
234     }
235     goto out;
236     }
237     #endif
238 kumaneko 1379 if (!mnt)
239     goto out;
240 kumaneko 111 d_dentry = dget(dentry);
241     d_mnt = mntget(mnt);
242     /***** CRITICAL SECTION START *****/
243     spin_lock(&dcache_lock);
244 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
245     spin_lock(&vfsmount_lock);
246     #endif
247     error = get_absolute_path(d_dentry, d_mnt, newname, newname_len);
248     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
249     spin_unlock(&vfsmount_lock);
250     #endif
251 kumaneko 111 spin_unlock(&dcache_lock);
252     /***** CRITICAL SECTION END *****/
253     dput(d_dentry);
254     mntput(d_mnt);
255 kumaneko 1259 out:
256 kumaneko 1056 if (error)
257 kumaneko 1379 printk(KERN_WARNING "ccs_realpath: Pathname too long. (%d)\n",
258     error);
259 kumaneko 111 return error;
260     }
261    
262 kumaneko 1052 /**
263 kumaneko 1054 * ccs_realpath_from_dentry - Returns realpath(3) of the given pathname but ignores chroot'ed root.
264 kumaneko 1052 *
265     * @dentry: Pointer to "struct dentry".
266     * @mnt: Pointer to "struct vfsmount".
267     *
268     * Returns the realpath of the given @dentry and @mnt on success,
269     * NULL otherwise.
270     *
271     * These functions use ccs_alloc(), so caller must ccs_free()
272     * if these functions didn't return NULL.
273     */
274     char *ccs_realpath_from_dentry(struct dentry *dentry, struct vfsmount *mnt)
275 kumaneko 111 {
276 kumaneko 1031 char *buf = ccs_alloc(sizeof(struct ccs_page_buffer));
277 kumaneko 1052 if (buf && ccs_realpath_from_dentry2(dentry, mnt, buf,
278     CCS_MAX_PATHNAME_LEN - 1) == 0)
279     return buf;
280 kumaneko 111 ccs_free(buf);
281     return NULL;
282     }
283    
284 kumaneko 1052 /**
285     * ccs_realpath - Get realpath of a pathname.
286     *
287     * @pathname: The pathname to solve.
288     *
289     * Returns the realpath of @pathname on success, NULL otherwise.
290     */
291     char *ccs_realpath(const char *pathname)
292 kumaneko 111 {
293     struct nameidata nd;
294     if (pathname && path_lookup(pathname, lookup_flags, &nd) == 0) {
295 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
296     char *buf = ccs_realpath_from_dentry(nd.path.dentry,
297     nd.path.mnt);
298 kumaneko 990 path_put(&nd.path);
299     #else
300 kumaneko 1052 char *buf = ccs_realpath_from_dentry(nd.dentry, nd.mnt);
301 kumaneko 111 path_release(&nd);
302 kumaneko 990 #endif
303 kumaneko 111 return buf;
304     }
305     return NULL;
306     }
307    
308 kumaneko 1052 /**
309     * ccs_realpath_nofollow - Get realpath of a pathname.
310     *
311     * @pathname: The pathname to solve.
312     *
313     * Returns the realpath of @pathname on success, NULL otherwise.
314     */
315     char *ccs_realpath_nofollow(const char *pathname)
316 kumaneko 111 {
317     struct nameidata nd;
318 kumaneko 1052 if (pathname && path_lookup(pathname, lookup_flags ^ LOOKUP_FOLLOW,
319     &nd) == 0) {
320     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
321     char *buf = ccs_realpath_from_dentry(nd.path.dentry,
322     nd.path.mnt);
323 kumaneko 990 path_put(&nd.path);
324     #else
325 kumaneko 1052 char *buf = ccs_realpath_from_dentry(nd.dentry, nd.mnt);
326 kumaneko 111 path_release(&nd);
327 kumaneko 990 #endif
328 kumaneko 111 return buf;
329     }
330     return NULL;
331     }
332    
333 kumaneko 1052 /**
334 kumaneko 1054 * round_up - Round up an integer so that the returned pointers are appropriately aligned.
335 kumaneko 1052 *
336     * @size: Size in bytes.
337     *
338     * Returns rounded value of @size.
339     *
340     * FIXME: Are there more requirements that is needed for assigning value
341     * atomically?
342 kumaneko 111 */
343 kumaneko 1052 static inline unsigned int round_up(const unsigned int size)
344     {
345     if (sizeof(void *) >= sizeof(long))
346     return ((size + sizeof(void *) - 1)
347     / sizeof(void *)) * sizeof(void *);
348     else
349     return ((size + sizeof(long) - 1)
350     / sizeof(long)) * sizeof(long);
351 kumaneko 111 }
352    
353 kumaneko 1052 static unsigned int allocated_memory_for_elements;
354 kumaneko 1180 static unsigned int quota_for_elements;
355 kumaneko 111
356 kumaneko 1052 /**
357     * ccs_alloc_element - Allocate permanent memory for structures.
358     *
359     * @size: Size in bytes.
360     *
361     * Returns pointer to allocated memory on success, NULL otherwise.
362     *
363     * The RAM is chunked, so NEVER try to kfree() the returned pointer.
364     */
365     void *ccs_alloc_element(const unsigned int size)
366 kumaneko 111 {
367 kumaneko 652 static DEFINE_MUTEX(lock);
368 kumaneko 1052 static char *buf;
369 kumaneko 111 static unsigned int buf_used_len = PAGE_SIZE;
370     char *ptr = NULL;
371 kumaneko 1052 const unsigned int word_aligned_size = round_up(size);
372     if (word_aligned_size > PAGE_SIZE)
373     return NULL;
374 kumaneko 652 mutex_lock(&lock);
375 kumaneko 111 if (buf_used_len + word_aligned_size > PAGE_SIZE) {
376 kumaneko 1180 if (!quota_for_elements || allocated_memory_for_elements
377     + PAGE_SIZE <= quota_for_elements)
378     ptr = kzalloc(PAGE_SIZE, GFP_KERNEL);
379 kumaneko 1052 if (!ptr) {
380     printk(KERN_WARNING "ERROR: Out of memory "
381     "for ccs_alloc_element().\n");
382     if (!sbin_init_started)
383     panic("MAC Initialization failed.\n");
384 kumaneko 111 } else {
385     buf = ptr;
386     allocated_memory_for_elements += PAGE_SIZE;
387     buf_used_len = word_aligned_size;
388     ptr = buf;
389     }
390     } else if (word_aligned_size) {
391     int i;
392     ptr = buf + buf_used_len;
393     buf_used_len += word_aligned_size;
394     for (i = 0; i < word_aligned_size; i++) {
395 kumaneko 1052 if (!ptr[i])
396     continue;
397     printk(KERN_ERR "WARNING: Reserved memory was tainted! "
398     "The system might go wrong.\n");
399     ptr[i] = '\0';
400 kumaneko 111 }
401     }
402 kumaneko 652 mutex_unlock(&lock);
403 kumaneko 111 return ptr;
404     }
405    
406 kumaneko 1052 static unsigned int allocated_memory_for_savename;
407 kumaneko 1180 static unsigned int quota_for_savename;
408 kumaneko 111
409     #define MAX_HASH 256
410    
411 kumaneko 1052 /* Structure for string data. */
412 kumaneko 214 struct name_entry {
413 kumaneko 731 struct list1_head list;
414 kumaneko 111 struct path_info entry;
415 kumaneko 214 };
416 kumaneko 111
417 kumaneko 1052 /* Structure for available memory region. */
418 kumaneko 214 struct free_memory_block_list {
419 kumaneko 731 struct list_head list;
420 kumaneko 1052 char *ptr; /* Pointer to a free area. */
421     int len; /* Length of the area. */
422 kumaneko 214 };
423 kumaneko 111
424 kumaneko 1052 /* The list for "struct name_entry". */
425     static struct list1_head name_list[MAX_HASH];
426 kumaneko 731
427 kumaneko 1052 /**
428     * ccs_save_name - Allocate permanent memory for string data.
429     *
430     * @name: The string to store into the permernent memory.
431     *
432     * Returns pointer to "struct path_info" on success, NULL otherwise.
433     *
434     * The RAM is shared, so NEVER try to modify or kfree() the returned name.
435     */
436     const struct path_info *ccs_save_name(const char *name)
437 kumaneko 111 {
438 kumaneko 731 static LIST_HEAD(fmb_list);
439 kumaneko 652 static DEFINE_MUTEX(lock);
440 kumaneko 731 struct name_entry *ptr;
441 kumaneko 111 unsigned int hash;
442 kumaneko 731 struct free_memory_block_list *fmb;
443 kumaneko 111 int len;
444 kumaneko 731 char *cp;
445 kumaneko 1052 if (!name)
446     return NULL;
447 kumaneko 111 len = strlen(name) + 1;
448     if (len > CCS_MAX_PATHNAME_LEN) {
449 kumaneko 1052 printk(KERN_WARNING "ERROR: Name too long "
450     "for ccs_save_name().\n");
451 kumaneko 111 return NULL;
452     }
453     hash = full_name_hash((const unsigned char *) name, len - 1);
454 kumaneko 652 mutex_lock(&lock);
455 kumaneko 731 list1_for_each_entry(ptr, &name_list[hash % MAX_HASH], list) {
456 kumaneko 1052 if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
457     goto out;
458 kumaneko 111 }
459 kumaneko 731 list_for_each_entry(fmb, &fmb_list, list) {
460 kumaneko 1052 if (len <= fmb->len)
461     goto ready;
462 kumaneko 111 }
463 kumaneko 1180 if (!quota_for_savename || allocated_memory_for_savename + PAGE_SIZE
464     <= quota_for_savename)
465     cp = kzalloc(PAGE_SIZE, GFP_KERNEL);
466     else
467     cp = NULL;
468 kumaneko 1016 fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
469 kumaneko 731 if (!cp || !fmb) {
470     kfree(cp);
471     kfree(fmb);
472 kumaneko 1052 printk(KERN_WARNING "ERROR: Out of memory "
473     "for ccs_save_name().\n");
474     if (!sbin_init_started)
475     panic("MAC Initialization failed.\n");
476 kumaneko 731 ptr = NULL;
477     goto out;
478     }
479     allocated_memory_for_savename += PAGE_SIZE;
480     list_add(&fmb->list, &fmb_list);
481     fmb->ptr = cp;
482     fmb->len = PAGE_SIZE;
483     ready:
484 kumaneko 1052 ptr = ccs_alloc_element(sizeof(*ptr));
485     if (!ptr)
486     goto out;
487 kumaneko 111 ptr->entry.name = fmb->ptr;
488     memmove(fmb->ptr, name, len);
489 kumaneko 1052 ccs_fill_path_info(&ptr->entry);
490 kumaneko 111 fmb->ptr += len;
491     fmb->len -= len;
492 kumaneko 731 list1_add_tail_mb(&ptr->list, &name_list[hash % MAX_HASH]);
493 kumaneko 111 if (fmb->len == 0) {
494 kumaneko 731 list_del(&fmb->list);
495     kfree(fmb);
496 kumaneko 111 }
497     out:
498 kumaneko 652 mutex_unlock(&lock);
499 kumaneko 111 return ptr ? &ptr->entry : NULL;
500     }
501    
502 kumaneko 1052 /* Structure for temporarily allocated memory. */
503 kumaneko 214 struct cache_entry {
504 kumaneko 111 struct list_head list;
505     void *ptr;
506     int size;
507 kumaneko 214 };
508 kumaneko 111
509 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
510     static struct kmem_cache *ccs_cachep;
511 kumaneko 111 #else
512 kumaneko 1052 static kmem_cache_t *ccs_cachep;
513 kumaneko 111 #endif
514    
515 kumaneko 1052 /**
516     * ccs_realpath_init - Initialize realpath related code.
517     *
518     * Returns 0.
519     */
520     static int __init ccs_realpath_init(void)
521 kumaneko 111 {
522 kumaneko 731 int i;
523 kumaneko 1052 if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
524     panic("Bad size.");
525     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
526     ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry),
527     0, 0, NULL);
528 kumaneko 316 #else
529 kumaneko 1052 ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry),
530     0, 0, NULL, NULL);
531 kumaneko 316 #endif
532 kumaneko 1052 if (!ccs_cachep)
533     panic("Can't create cache.\n");
534     for (i = 0; i < MAX_HASH; i++)
535 kumaneko 731 INIT_LIST1_HEAD(&name_list[i]);
536 kumaneko 722 INIT_LIST1_HEAD(&KERNEL_DOMAIN.acl_info_list);
537 kumaneko 1052 KERNEL_DOMAIN.domainname = ccs_save_name(ROOT_NAME);
538 kumaneko 722 list1_add_tail_mb(&KERNEL_DOMAIN.list, &domain_list);
539 kumaneko 1052 if (ccs_find_domain(ROOT_NAME) != &KERNEL_DOMAIN)
540     panic("Can't register KERNEL_DOMAIN");
541     return 0;
542 kumaneko 111 }
543    
544 kumaneko 1084 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
545 kumaneko 1052 __initcall(ccs_realpath_init);
546 kumaneko 1084 #else
547 kumaneko 1106 core_initcall(ccs_realpath_init);
548 kumaneko 1084 #endif
549 kumaneko 1052
550     /* The list for "struct cache_entry". */
551 kumaneko 111 static LIST_HEAD(cache_list);
552    
553 kumaneko 1052 static DEFINE_SPINLOCK(cache_list_lock);
554    
555     static unsigned int dynamic_memory_size;
556    
557     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
558     /**
559     * round2 - Rounded up to power-of-two value.
560     *
561     * @size: Size in bytes.
562     *
563     * Returns power-of-two of @size.
564     */
565 kumaneko 581 static int round2(size_t size)
566     {
567     #if PAGE_SIZE == 4096
568     size_t bsize = 32;
569     #else
570     size_t bsize = 64;
571     #endif
572 kumaneko 1064 while (size > bsize)
573     bsize <<= 1;
574 kumaneko 581 return bsize;
575     }
576     #endif
577    
578 kumaneko 1052 /**
579     * ccs_alloc - Allocate memory for temporal purpose.
580     *
581     * @size: Size in bytes.
582     *
583     * Returns pointer to allocated memory on success, NULL otherwise.
584     */
585 kumaneko 214 void *ccs_alloc(const size_t size)
586 kumaneko 111 {
587 kumaneko 1031 struct cache_entry *new_entry;
588 kumaneko 1055 void *ret = kzalloc(size, GFP_KERNEL);
589 kumaneko 1052 if (!ret)
590     goto out;
591 kumaneko 1031 new_entry = kmem_cache_alloc(ccs_cachep, GFP_KERNEL);
592     if (!new_entry) {
593 kumaneko 1064 kfree(ret);
594     ret = NULL;
595 kumaneko 1031 goto out;
596     }
597     INIT_LIST_HEAD(&new_entry->list);
598     new_entry->ptr = ret;
599 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
600 kumaneko 1031 new_entry->size = ksize(ret);
601     #else
602     new_entry->size = round2(size);
603     #endif
604 kumaneko 1052 /***** CRITICAL SECTION START *****/
605 kumaneko 1031 spin_lock(&cache_list_lock);
606     list_add_tail(&new_entry->list, &cache_list);
607     dynamic_memory_size += new_entry->size;
608     spin_unlock(&cache_list_lock);
609 kumaneko 1052 /***** CRITICAL SECTION END *****/
610 kumaneko 1031 out:
611 kumaneko 214 return ret;
612 kumaneko 111 }
613    
614 kumaneko 1052 /**
615     * ccs_free - Release memory allocated by ccs_alloc().
616     *
617     * @p: Pointer returned by ccs_alloc(). May be NULL.
618     *
619     * Returns nothing.
620     */
621 kumaneko 111 void ccs_free(const void *p)
622     {
623     struct list_head *v;
624 kumaneko 214 struct cache_entry *entry = NULL;
625 kumaneko 1052 if (!p)
626     return;
627     /***** CRITICAL SECTION START *****/
628 kumaneko 111 spin_lock(&cache_list_lock);
629     list_for_each(v, &cache_list) {
630 kumaneko 214 entry = list_entry(v, struct cache_entry, list);
631 kumaneko 111 if (entry->ptr != p) {
632 kumaneko 1064 entry = NULL;
633     continue;
634 kumaneko 111 }
635     list_del(&entry->list);
636     dynamic_memory_size -= entry->size;
637     break;
638     }
639     spin_unlock(&cache_list_lock);
640 kumaneko 1052 /***** CRITICAL SECTION END *****/
641 kumaneko 111 if (entry) {
642     kfree(p);
643     kmem_cache_free(ccs_cachep, entry);
644     } else {
645 kumaneko 1052 printk(KERN_WARNING "BUG: ccs_free() with invalid pointer.\n");
646 kumaneko 111 }
647     }
648 kumaneko 1180
649     /**
650     * ccs_read_memory_counter - Check for memory usage.
651     *
652     * @head: Pointer to "struct ccs_io_buffer".
653     *
654     * Returns memory usage.
655     */
656     int ccs_read_memory_counter(struct ccs_io_buffer *head)
657     {
658     if (!head->read_eof) {
659     const unsigned int shared = allocated_memory_for_savename;
660     const unsigned int private = allocated_memory_for_elements;
661     const unsigned int dynamic = dynamic_memory_size;
662     char buffer[64];
663     memset(buffer, 0, sizeof(buffer));
664     if (quota_for_savename)
665     snprintf(buffer, sizeof(buffer) - 1,
666     " (Quota: %10u)", quota_for_savename);
667     else
668     buffer[0] = '\0';
669     ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer);
670     if (quota_for_elements)
671     snprintf(buffer, sizeof(buffer) - 1,
672     " (Quota: %10u)", quota_for_elements);
673     else
674     buffer[0] = '\0';
675     ccs_io_printf(head, "Private: %10u%s\n", private, buffer);
676     ccs_io_printf(head, "Dynamic: %10u\n", dynamic);
677     ccs_io_printf(head, "Total: %10u\n",
678     shared + private + dynamic);
679     head->read_eof = true;
680     }
681     return 0;
682     }
683    
684     /**
685     * ccs_write_memory_quota - Set memory quota.
686     *
687     * @head: Pointer to "struct ccs_io_buffer".
688     *
689     * Returns 0.
690     */
691     int ccs_write_memory_quota(struct ccs_io_buffer *head)
692     {
693     char *data = head->write_buf;
694     unsigned int size;
695     if (sscanf(data, "Shared: %u", &size) == 1)
696     quota_for_savename = size;
697     else if (sscanf(data, "Private: %u", &size) == 1)
698     quota_for_elements = size;
699     return 0;
700     }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26