It is pointless to calculate the swap ratio when there is only
one swap device in the group. Moreover the existing code would
result in a spinlock recursion because of not taking this into
consideration. Interestingly, this check is already performed
in swap_ratio_slow by this piece of code
if (&(*si)->avail_list == plist_last(&swap_avail_head)) {
/* just to make skip work */
n = *si;
ret = -ENODEV;
goto skip;
}
But there is window where we drop the swap_avail_lock before
invoking swap_ratio() and take it back again in swap_ratio_slow.
In this period the si can get removed from swap_avail_head,
resulting in the failure of above logic. So recheck again.
Similarly, bail out from swap_ratio() if the sysctl is disabled,
and thus avoiding overhead of taking unnecessary locks.
Change-Id: I81a9dd61d24b7da55d5341c48a1f71d2b4b1978d
Signed-off-by: Vinayak Menon <vinmenon@codeaurora.org>
n = plist_next_entry(&(*si)->avail_list,
struct swap_info_struct,
avail_list);
+ if (n == *si) {
+ /* No other swap device */
+ ret = -ENODEV;
+ goto skip;
+ }
+
spin_unlock(&swap_avail_lock);
spin_lock(&n->lock);
spin_lock(&swap_avail_lock);
int swap_ratio(struct swap_info_struct **si)
{
+ if (!sysctl_swap_ratio_enable)
+ return -ENODEV;
+
if (is_swap_ratio_group((*si)->prio))
return swap_ratio_slow(si);
else