mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
ANDROID: ashmem: Add support for disabling unpinning feature
The final version of ashmem will not support unpinning buffers. Therefore, to be able to have the ashmem driver behave as close as possible to its final configuration for testing, add a device node that can be used to disable unpinning. This node will make it so that the ashmem shrinker stops running, and that all unpinning requests are ignored. Bug: 111903542 Change-Id: I99ae9b1a4e56ee8a5224d647a6f2f9eeeb86ef02 Signed-off-by: Isaac J. Manjarres <isaacmanjarres@google.com>
This commit is contained in:
@@ -104,6 +104,9 @@ static struct kmem_cache *ashmem_range_cachep __read_mostly;
|
||||
*/
|
||||
static struct lock_class_key backing_shmem_inode_class;
|
||||
|
||||
/* Enable unpinning feature by default to retain compatibility with existing behavior. */
|
||||
static bool unpinning_enable = true;
|
||||
|
||||
static inline unsigned long range_size(struct ashmem_range *range)
|
||||
{
|
||||
return range->pgend - range->pgstart + 1;
|
||||
@@ -479,6 +482,9 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
|
||||
{
|
||||
unsigned long freed = 0;
|
||||
|
||||
if (!unpinning_enable)
|
||||
return 0;
|
||||
|
||||
/* We might recurse into filesystem code, so bail out if necessary */
|
||||
if (!(sc->gfp_mask & __GFP_FS))
|
||||
return SHRINK_STOP;
|
||||
@@ -524,7 +530,7 @@ ashmem_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
|
||||
* objects on the list. This means the scan function needs to return the
|
||||
* number of pages freed, not the number of objects scanned.
|
||||
*/
|
||||
return lru_count;
|
||||
return unpinning_enable ? lru_count : SHRINK_EMPTY;
|
||||
}
|
||||
|
||||
static struct shrinker ashmem_shrinker = {
|
||||
@@ -802,7 +808,7 @@ static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
|
||||
ret = ashmem_pin(asma, pgstart, pgend, &range);
|
||||
break;
|
||||
case ASHMEM_UNPIN:
|
||||
ret = ashmem_unpin(asma, pgstart, pgend, &range);
|
||||
ret = unpinning_enable ? ashmem_unpin(asma, pgstart, pgend, &range) : 0;
|
||||
break;
|
||||
case ASHMEM_GET_PIN_STATUS:
|
||||
ret = ashmem_get_pin_status(asma, pgstart, pgend);
|
||||
@@ -921,6 +927,40 @@ static void ashmem_show_fdinfo(struct seq_file *m, struct file *file)
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int unpinning_enable_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = &unpinning_enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t attr_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
bool *attrp = file->private_data;
|
||||
char val_str[2];
|
||||
|
||||
val_str[0] = *attrp ? '1' : '0';
|
||||
val_str[1] = '\n';
|
||||
return simple_read_from_buffer(buf, count, ppos, val_str, sizeof(val_str));
|
||||
}
|
||||
|
||||
static ssize_t attr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
bool *attrp = file->private_data;
|
||||
bool enable;
|
||||
ssize_t ret = count;
|
||||
|
||||
if (!kstrtobool_from_user(buf, count, &enable)) {
|
||||
mutex_lock(&ashmem_mutex);
|
||||
*attrp = enable;
|
||||
mutex_unlock(&ashmem_mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations ashmem_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ashmem_open,
|
||||
@@ -946,15 +986,30 @@ int is_ashmem_file(struct file *file)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(is_ashmem_file);
|
||||
|
||||
static struct miscdevice ashmem_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "ashmem",
|
||||
.fops = &ashmem_fops,
|
||||
static const struct file_operations unpinning_enable_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = unpinning_enable_open,
|
||||
.read = attr_read,
|
||||
.write = attr_write,
|
||||
};
|
||||
|
||||
static struct miscdevice ashmem_miscs[] = {
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "ashmem",
|
||||
.fops = &ashmem_fops,
|
||||
},
|
||||
{
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "ashmem_unpinning_enable",
|
||||
.fops = &unpinning_enable_fops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ashmem_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
int i;
|
||||
|
||||
ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
|
||||
sizeof(struct ashmem_area),
|
||||
@@ -972,10 +1027,12 @@ static int __init ashmem_init(void)
|
||||
goto out_free1;
|
||||
}
|
||||
|
||||
ret = misc_register(&ashmem_misc);
|
||||
if (ret) {
|
||||
pr_err("failed to register misc device!\n");
|
||||
goto out_free2;
|
||||
for (i = 0; i < ARRAY_SIZE(ashmem_miscs); i++) {
|
||||
ret = misc_register(&ashmem_miscs[i]);
|
||||
if (ret) {
|
||||
pr_err("failed to register %s misc device!\n", ashmem_miscs[i].name);
|
||||
goto out_demisc;
|
||||
}
|
||||
}
|
||||
|
||||
ret = register_shrinker(&ashmem_shrinker, "android-ashmem");
|
||||
@@ -989,8 +1046,8 @@ static int __init ashmem_init(void)
|
||||
return 0;
|
||||
|
||||
out_demisc:
|
||||
misc_deregister(&ashmem_misc);
|
||||
out_free2:
|
||||
while (--i >= 0)
|
||||
misc_deregister(&ashmem_miscs[i]);
|
||||
kmem_cache_destroy(ashmem_range_cachep);
|
||||
out_free1:
|
||||
kmem_cache_destroy(ashmem_area_cachep);
|
||||
|
||||
Reference in New Issue
Block a user