struct shmem_inode_info *info;
        struct page *page;
        unsigned long batch = sc ? sc->nr_to_scan : 128;
-       int removed = 0, split = 0;
+       int split = 0;
 
        if (list_empty(&sbinfo->shrinklist))
                return SHRINK_STOP;
                /* inode is about to be evicted */
                if (!inode) {
                        list_del_init(&info->shrinklist);
-                       removed++;
                        goto next;
                }
 
                if (round_up(inode->i_size, PAGE_SIZE) ==
                                round_up(inode->i_size, HPAGE_PMD_SIZE)) {
                        list_move(&info->shrinklist, &to_remove);
-                       removed++;
                        goto next;
                }
 
                list_move(&info->shrinklist, &list);
 next:
+               sbinfo->shrinklist_len--;
                if (!--batch)
                        break;
        }
                inode = &info->vfs_inode;
 
                if (nr_to_split && split >= nr_to_split)
-                       goto leave;
+                       goto move_back;
 
                page = find_get_page(inode->i_mapping,
                                (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT);
                }
 
                /*
-                * Leave the inode on the list if we failed to lock
-                * the page at this time.
+                * Move the inode on the list back to shrinklist if we failed
+                * to lock the page at this time.
                 *
                 * Waiting for the lock may lead to deadlock in the
                 * reclaim path.
                 */
                if (!trylock_page(page)) {
                        put_page(page);
-                       goto leave;
+                       goto move_back;
                }
 
                ret = split_huge_page(page);
                unlock_page(page);
                put_page(page);
 
-               /* If split failed leave the inode on the list */
+               /* If split failed move the inode on the list back to shrinklist */
                if (ret)
-                       goto leave;
+                       goto move_back;
 
                split++;
 drop:
                list_del_init(&info->shrinklist);
-               removed++;
-leave:
+               goto put;
+move_back:
+               /*
+                * Make sure the inode is either on the global list or deleted
+                * from any local list before iput() since it could be deleted
+                * in another thread once we put the inode (then the local list
+                * is corrupted).
+                */
+               spin_lock(&sbinfo->shrinklist_lock);
+               list_move(&info->shrinklist, &sbinfo->shrinklist);
+               sbinfo->shrinklist_len++;
+               spin_unlock(&sbinfo->shrinklist_lock);
+put:
                iput(inode);
        }
 
-       spin_lock(&sbinfo->shrinklist_lock);
-       list_splice_tail(&list, &sbinfo->shrinklist);
-       sbinfo->shrinklist_len -= removed;
-       spin_unlock(&sbinfo->shrinklist_lock);
-
        return split;
 }