19 #define pr_fmt(fmt) "ashmem: " fmt
21 #include <linux/module.h>
24 #include <linux/falloc.h>
28 #include <linux/mman.h>
30 #include <linux/personality.h>
31 #include <linux/bitops.h>
36 #define ASHMEM_NAME_PREFIX "dev/ashmem/"
37 #define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1)
38 #define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN)
72 static unsigned long lru_count;
84 #define range_size(range) \
85 ((range)->pgend - (range)->pgstart + 1)
87 #define range_on_lru(range) \
88 ((range)->purged == ASHMEM_NOT_PURGED)
90 #define page_range_subsumes_range(range, start, end) \
91 (((range)->pgstart >= (start)) && ((range)->pgend <= (end)))
93 #define page_range_subsumed_by_range(range, start, end) \
94 (((range)->pgstart <= (start)) && ((range)->pgend >= (end)))
96 #define page_in_range(range, page) \
97 (((range)->pgstart <= (page)) && ((range)->pgend >= (page)))
99 #define page_range_in_range(range, start, end) \
100 (page_in_range(range, start) || page_in_range(range, end) || \
101 page_range_subsumes_range(range, start, end))
103 #define range_before_page(range, page) \
104 ((range)->pgend < (page))
106 #define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE)
137 range = kmem_cache_zalloc(ashmem_range_cachep,
GFP_KERNEL);
167 static inline void range_shrink(
struct ashmem_range *range,
168 size_t start,
size_t end)
188 asma = kmem_cache_zalloc(ashmem_area_cachep,
GFP_KERNEL);
200 static int ashmem_release(
struct inode *
ignored,
struct file *file)
218 size_t len, loff_t *
pos)
234 ret = asma->
file->f_op->read(asma->
file, buf, len, pos);
246 static loff_t ashmem_llseek(
struct file *file, loff_t
offset,
int origin)
253 if (asma->
size == 0) {
263 ret = asma->
file->f_op->llseek(asma->
file, offset, origin);
275 static inline vm_flags_t calc_vm_may_flags(
unsigned long prot)
282 static int ashmem_mmap(
struct file *file,
struct vm_area_struct *vma)
313 ret = PTR_ERR(vmfile);
318 get_file(asma->
file);
386 static struct shrinker ashmem_shrinker = {
387 .shrink = ashmem_shrink,
391 static int set_prot_mask(
struct ashmem_area *asma,
unsigned long prot)
414 static int set_name(
struct ashmem_area *asma,
void __user *name)
437 static int get_name(
struct ashmem_area *asma,
void __user *name)
504 if (range->
pgstart >= pgstart) {
505 range_shrink(range, pgend + 1, range->
pgend);
510 if (range->
pgend <= pgend) {
511 range_shrink(range, range->
pgstart, pgstart-1);
520 range_alloc(asma, range, range->
purged,
521 pgend + 1, range->
pgend);
522 range_shrink(range, range->
pgstart, pgstart - 1);
535 static int ashmem_unpin(
struct ashmem_area *asma,
size_t pgstart,
size_t pgend)
561 return range_alloc(asma, range, purged, pgstart, pgend);
570 static int ashmem_get_pin_status(
struct ashmem_area *asma,
size_t pgstart,
588 static int ashmem_pin_unpin(
struct ashmem_area *asma,
unsigned long cmd,
592 size_t pgstart, pgend;
624 ret = ashmem_unpin(asma, pgstart, pgend);
627 ret = ashmem_get_pin_status(asma, pgstart, pgend);
636 static long ashmem_ioctl(
struct file *file,
unsigned int cmd,
unsigned long arg)
643 ret = set_name(asma, (
void __user *) arg);
646 ret = get_name(asma, (
void __user *) arg);
659 ret = set_prot_mask(asma, arg);
667 ret = ashmem_pin_unpin(asma, cmd, (
void __user *) arg);
676 ret = ashmem_shrink(&ashmem_shrinker, &sc);
678 ashmem_shrink(&ashmem_shrinker, &sc);
689 .release = ashmem_release,
691 .llseek = ashmem_llseek,
693 .unlocked_ioctl = ashmem_ioctl,
694 .compat_ioctl = ashmem_ioctl,
700 .fops = &ashmem_fops,
703 static int __init ashmem_init(
void)
710 if (
unlikely(!ashmem_area_cachep)) {
711 pr_err(
"failed to create slab cache\n");
718 if (
unlikely(!ashmem_range_cachep)) {
719 pr_err(
"failed to create slab cache\n");
725 pr_err(
"failed to register misc device!\n");
736 static void __exit ashmem_exit(
void)
744 pr_err(
"failed to unregister misc device!\n");