aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/swap.h
diff options
context:
space:
mode:
authorRafael Aquini <aquini@redhat.com>2013-07-03 18:02:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:07:32 -0400
commitdcf6b7ddd7df8965727746f89c59229b23180e5a (patch)
tree5786f2748cfd0f6870ad092e41e524709dcd817e /include/linux/swap.h
parent917d9290af749fac9c4d90bacf18699c9d8ba28d (diff)
swap: discard while swapping only if SWAP_FLAG_DISCARD_PAGES
Considering the use cases where the swap device supports discard: a) and can do it quickly; b) but it's slow to do in small granularities (or concurrent with other I/O); c) but the implementation is so horrendous that you don't even want to send one down; And assuming that the sysadmin considers it useful to send the discards down at all, we would (probably) want the following solutions: i. do the fine-grained discards for freed swap pages, if device is capable of doing so optimally; ii. do single-time (batched) swap area discards, either at swapon or via something like fstrim (not implemented yet); iii. allow doing both single-time and fine-grained discards; or iv. turn it off completely (default behavior) As implemented today, one can only enable/disable discards for swap, but one cannot select, for instance, solution (ii) on a swap device like (b) even though the single-time discard is regarded to be interesting, or necessary to the workload because it would imply (1), and the device is not capable of performing it optimally. This patch addresses the scenario depicted above by introducing a way to ensure the (probably) wanted solutions (i, ii, iii and iv) can be flexibly flagged through swapon(8) to allow a sysadmin to select the best suitable swap discard policy accordingly to system constraints. This patch introduces SWAP_FLAG_DISCARD_PAGES and SWAP_FLAG_DISCARD_ONCE new flags to allow more flexibe swap discard policies being flagged through swapon(8). The default behavior is to keep both single-time, or batched, area discards (SWAP_FLAG_DISCARD_ONCE) and fine-grained discards for page-clusters (SWAP_FLAG_DISCARD_PAGES) enabled, in order to keep consistentcy with older kernel behavior, as well as maintain compatibility with older swapon(8). However, through the new introduced flags the best suitable discard policy can be selected accordingly to any given swap device constraint. [akpm@linux-foundation.org: tweak comments] Signed-off-by: Rafael Aquini <aquini@redhat.com> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Hugh Dickins <hughd@google.com> Cc: Shaohua Li <shli@kernel.org> Cc: Karel Zak <kzak@redhat.com> Cc: Jeff Moyer <jmoyer@redhat.com> Cc: Rik van Riel <riel@redhat.com> Cc: Larry Woodman <lwoodman@redhat.com> Cc: Mel Gorman <mel@csn.ul.ie> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/swap.h')
-rw-r--r--include/linux/swap.h13
1 files changed, 9 insertions, 4 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 85d74373002c..d95cde5e257d 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -20,10 +20,13 @@ struct bio;
20#define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */ 20#define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */
21#define SWAP_FLAG_PRIO_MASK 0x7fff 21#define SWAP_FLAG_PRIO_MASK 0x7fff
22#define SWAP_FLAG_PRIO_SHIFT 0 22#define SWAP_FLAG_PRIO_SHIFT 0
23#define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */ 23#define SWAP_FLAG_DISCARD 0x10000 /* enable discard for swap */
24#define SWAP_FLAG_DISCARD_ONCE 0x20000 /* discard swap area at swapon-time */
25#define SWAP_FLAG_DISCARD_PAGES 0x40000 /* discard page-clusters after use */
24 26
25#define SWAP_FLAGS_VALID (SWAP_FLAG_PRIO_MASK | SWAP_FLAG_PREFER | \ 27#define SWAP_FLAGS_VALID (SWAP_FLAG_PRIO_MASK | SWAP_FLAG_PREFER | \
26 SWAP_FLAG_DISCARD) 28 SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE | \
29 SWAP_FLAG_DISCARD_PAGES)
27 30
28static inline int current_is_kswapd(void) 31static inline int current_is_kswapd(void)
29{ 32{
@@ -147,14 +150,16 @@ struct swap_extent {
147enum { 150enum {
148 SWP_USED = (1 << 0), /* is slot in swap_info[] used? */ 151 SWP_USED = (1 << 0), /* is slot in swap_info[] used? */
149 SWP_WRITEOK = (1 << 1), /* ok to write to this swap? */ 152 SWP_WRITEOK = (1 << 1), /* ok to write to this swap? */
150 SWP_DISCARDABLE = (1 << 2), /* swapon+blkdev support discard */ 153 SWP_DISCARDABLE = (1 << 2), /* blkdev support discard */
151 SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */ 154 SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */
152 SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ 155 SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */
153 SWP_CONTINUED = (1 << 5), /* swap_map has count continuation */ 156 SWP_CONTINUED = (1 << 5), /* swap_map has count continuation */
154 SWP_BLKDEV = (1 << 6), /* its a block device */ 157 SWP_BLKDEV = (1 << 6), /* its a block device */
155 SWP_FILE = (1 << 7), /* set after swap_activate success */ 158 SWP_FILE = (1 << 7), /* set after swap_activate success */
159 SWP_AREA_DISCARD = (1 << 8), /* single-time swap area discards */
160 SWP_PAGE_DISCARD = (1 << 9), /* freed swap page-cluster discards */
156 /* add others here before... */ 161 /* add others here before... */
157 SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */ 162 SWP_SCANNING = (1 << 10), /* refcount in scan_swap_map */
158}; 163};
159 164
160#define SWAP_CLUSTER_MAX 32UL 165#define SWAP_CLUSTER_MAX 32UL