|
@@ -493,36 +493,45 @@ next:
|
|
|
info = list_entry(pos, struct shmem_inode_info, shrinklist);
|
|
|
inode = &info->vfs_inode;
|
|
|
|
|
|
- if (nr_to_split && split >= nr_to_split) {
|
|
|
- iput(inode);
|
|
|
- continue;
|
|
|
- }
|
|
|
+ if (nr_to_split && split >= nr_to_split)
|
|
|
+ goto leave;
|
|
|
|
|
|
- page = find_lock_page(inode->i_mapping,
|
|
|
+ page = find_get_page(inode->i_mapping,
|
|
|
(inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT);
|
|
|
if (!page)
|
|
|
goto drop;
|
|
|
|
|
|
+ /* No huge page at the end of the file: nothing to split */
|
|
|
if (!PageTransHuge(page)) {
|
|
|
- unlock_page(page);
|
|
|
put_page(page);
|
|
|
goto drop;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Leave the inode on the list 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;
|
|
|
+ }
|
|
|
+
|
|
|
ret = split_huge_page(page);
|
|
|
unlock_page(page);
|
|
|
put_page(page);
|
|
|
|
|
|
- if (ret) {
|
|
|
- /* split failed: leave it on the list */
|
|
|
- iput(inode);
|
|
|
- continue;
|
|
|
- }
|
|
|
+ /* If split failed leave the inode on the list */
|
|
|
+ if (ret)
|
|
|
+ goto leave;
|
|
|
|
|
|
split++;
|
|
|
drop:
|
|
|
list_del_init(&info->shrinklist);
|
|
|
removed++;
|
|
|
+leave:
|
|
|
iput(inode);
|
|
|
}
|
|
|
|