OSDN Git Service

Merge "drm/msm/sde: add post_disable stage for phys encoder"
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / mm / swap_ratio.c
1 /*
2  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 and
6  * only version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/mm_types.h>
15 #include <linux/swapfile.h>
16 #include <linux/swap.h>
17
18 #define SWAP_RATIO_GROUP_START (SWAP_FLAG_PRIO_MASK - 9) /* 32758 */
19 #define SWAP_RATIO_GROUP_END (SWAP_FLAG_PRIO_MASK) /* 32767 */
20 #define SWAP_FAST_WRITES (SWAPFILE_CLUSTER * (SWAP_CLUSTER_MAX / 8))
21 #define SWAP_SLOW_WRITES SWAPFILE_CLUSTER
22
23 /*
24  * The fast/slow swap write ratio.
25  * 100 indicates that all writes should
26  * go to fast swap device.
27  */
28 int sysctl_swap_ratio = 100;
29
30 /* Enable the swap ratio feature */
31 int sysctl_swap_ratio_enable;
32
33 static bool is_same_group(struct swap_info_struct *a,
34                 struct swap_info_struct *b)
35 {
36         if (!sysctl_swap_ratio_enable)
37                 return false;
38
39         if (!is_swap_ratio_group(a->prio))
40                 return false;
41
42         if (a->prio == b->prio)
43                 return true;
44
45         return false;
46 }
47
48 /* Caller must hold swap_avail_lock */
49 static int calculate_write_pending(struct swap_info_struct *si,
50                         struct swap_info_struct *n)
51 {
52         int ratio = sysctl_swap_ratio;
53
54         if ((ratio < 0) || (ratio > 100))
55                 return -EINVAL;
56
57         if (WARN_ON(!(si->flags & SWP_FAST)))
58                 return -ENODEV;
59
60         if ((n->flags & SWP_FAST) || !is_same_group(si, n))
61                 return -ENODEV;
62
63         si->max_writes = ratio ? SWAP_FAST_WRITES : 0;
64         n->max_writes  = ratio ? (SWAP_FAST_WRITES * 100) /
65                         ratio - SWAP_FAST_WRITES : SWAP_SLOW_WRITES;
66
67         si->write_pending = si->max_writes;
68         n->write_pending = n->max_writes;
69
70         trace_printk("%u, %u\n", si->max_writes, n->max_writes);
71
72         return 0;
73 }
74
75 static int swap_ratio_slow(struct swap_info_struct **si)
76 {
77         struct swap_info_struct *n = NULL;
78         int ret = 0;
79
80         spin_lock(&(*si)->lock);
81         spin_lock(&swap_avail_lock);
82         if (&(*si)->avail_list == plist_last(&swap_avail_head)) {
83                 /* just to make skip work */
84                 n = *si;
85                 ret = -ENODEV;
86                 goto skip;
87         }
88         n = plist_next_entry(&(*si)->avail_list,
89                         struct swap_info_struct,
90                         avail_list);
91         if (n == *si) {
92                 /* No other swap device */
93                 ret = -ENODEV;
94                 goto skip;
95         }
96
97         spin_unlock(&swap_avail_lock);
98         spin_lock(&n->lock);
99         spin_lock(&swap_avail_lock);
100
101         if ((*si)->flags & SWP_FAST) {
102                 if ((*si)->write_pending) {
103                         (*si)->write_pending--;
104                         goto exit;
105                 } else {
106                         if ((n->flags & SWP_FAST) || !is_same_group(*si, n)) {
107                                 /* Should never happen */
108                                 ret = -ENODEV;
109                         } else if (n->write_pending) {
110                                 /*
111                                  * Requeue fast device, since there are pending
112                                  * writes for slow device.
113                                  */
114                                 plist_requeue(&(*si)->avail_list,
115                                         &swap_avail_head);
116                                 n->write_pending--;
117                                 spin_unlock(&(*si)->lock);
118                                 *si = n;
119                                 goto skip;
120                         } else {
121                                 if (0 > calculate_write_pending(*si, n)) {
122                                         ret = -ENODEV;
123                                         goto exit;
124                                 }
125                                 /* Restart from fast device */
126                                 (*si)->write_pending--;
127                         }
128                 }
129         } else {
130                 if (!(n->flags & SWP_FAST) || !is_same_group(*si, n)) {
131                         /* Should never happen */
132                         ret = -ENODEV;
133                 } else if (n->write_pending) {
134                         /*
135                          * Pending writes for fast device.
136                          * We reach here when slow device is swapped on first,
137                          * before fast device.
138                          */
139                         /* requeue slow device to the end */
140                         plist_requeue(&(*si)->avail_list, &swap_avail_head);
141                         n->write_pending--;
142                         spin_unlock(&(*si)->lock);
143                         *si = n;
144                         goto skip;
145                 } else {
146                         if ((*si)->write_pending) {
147                                 (*si)->write_pending--;
148                         } else {
149                                 if (0 > calculate_write_pending(n, *si)) {
150                                         ret = -ENODEV;
151                                         goto exit;
152                                 }
153                                 n->write_pending--;
154                                 plist_requeue(&(*si)->avail_list,
155                                         &swap_avail_head);
156                                 spin_unlock(&(*si)->lock);
157                                 *si = n;
158                                 goto skip;
159                         }
160                 }
161         }
162 exit:
163         spin_unlock(&(*si)->lock);
164 skip:
165         spin_unlock(&swap_avail_lock);
166         /* n and si would have got interchanged */
167         spin_unlock(&n->lock);
168         return ret;
169 }
170
171 bool is_swap_ratio_group(int prio)
172 {
173         return ((prio >= SWAP_RATIO_GROUP_START) &&
174                 (prio <= SWAP_RATIO_GROUP_END)) ? true : false;
175 }
176
177 void setup_swap_ratio(struct swap_info_struct *p, int prio)
178 {
179         /* Used only if sysctl_swap_ratio_enable is set */
180         if (is_swap_ratio_group(prio)) {
181                 if (p->flags & SWP_FAST)
182                         p->write_pending = SWAP_FAST_WRITES;
183                 else
184                         p->write_pending = SWAP_SLOW_WRITES;
185                 p->max_writes =  p->write_pending;
186         }
187 }
188
189 int swap_ratio(struct swap_info_struct **si)
190 {
191         if (!sysctl_swap_ratio_enable)
192                 return -ENODEV;
193
194         if (is_swap_ratio_group((*si)->prio))
195                 return swap_ratio_slow(si);
196         else
197                 return -ENODEV;
198 }