On Fri 16-03-18 13:59:08, Kirill A. Shutemov wrote:
[..]
> @@ -498,31 +498,42 @@ static unsigned long shmem_unused_huge_shrink(struct 
> shmem_sb_info *sbinfo,
>                       continue;
>               }
>  
> -             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;
> +             }

Can somebody split the huge page after the PageTransHuge check and
before we lock it?

> +
>               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);
>       }
>  
> -- 
> 2.16.1

-- 
Michal Hocko
SUSE Labs

Reply via email to