|
@@ -415,6 +415,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
|
|
struct shrink_control *sc, unsigned long nr_to_split)
|
|
struct shrink_control *sc, unsigned long nr_to_split)
|
|
{
|
|
{
|
|
LIST_HEAD(list), *pos, *next;
|
|
LIST_HEAD(list), *pos, *next;
|
|
|
|
+ LIST_HEAD(to_remove);
|
|
struct inode *inode;
|
|
struct inode *inode;
|
|
struct shmem_inode_info *info;
|
|
struct shmem_inode_info *info;
|
|
struct page *page;
|
|
struct page *page;
|
|
@@ -441,9 +442,8 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
|
|
/* Check if there's anything to gain */
|
|
/* Check if there's anything to gain */
|
|
if (round_up(inode->i_size, PAGE_SIZE) ==
|
|
if (round_up(inode->i_size, PAGE_SIZE) ==
|
|
round_up(inode->i_size, HPAGE_PMD_SIZE)) {
|
|
round_up(inode->i_size, HPAGE_PMD_SIZE)) {
|
|
- list_del_init(&info->shrinklist);
|
|
|
|
|
|
+ list_move(&info->shrinklist, &to_remove);
|
|
removed++;
|
|
removed++;
|
|
- iput(inode);
|
|
|
|
goto next;
|
|
goto next;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -454,6 +454,13 @@ next:
|
|
}
|
|
}
|
|
spin_unlock(&sbinfo->shrinklist_lock);
|
|
spin_unlock(&sbinfo->shrinklist_lock);
|
|
|
|
|
|
|
|
+ list_for_each_safe(pos, next, &to_remove) {
|
|
|
|
+ info = list_entry(pos, struct shmem_inode_info, shrinklist);
|
|
|
|
+ inode = &info->vfs_inode;
|
|
|
|
+ list_del_init(&info->shrinklist);
|
|
|
|
+ iput(inode);
|
|
|
|
+ }
|
|
|
|
+
|
|
list_for_each_safe(pos, next, &list) {
|
|
list_for_each_safe(pos, next, &list) {
|
|
int ret;
|
|
int ret;
|
|
|
|
|