1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
6 #include <linux/module.h>
7 #include <linux/compiler.h>
9 #include <linux/iomap.h>
10 #include <linux/swap.h>
12 /* Swapfile activation */
14 struct iomap_swapfile_info
{
15 struct iomap iomap
; /* accumulated iomap */
16 struct swap_info_struct
*sis
;
17 uint64_t lowest_ppage
; /* lowest physical addr seen (pages) */
18 uint64_t highest_ppage
; /* highest physical addr seen (pages) */
19 unsigned long nr_pages
; /* number of pages collected */
20 int nr_extents
; /* extent count */
25 * Collect physical extents for this swap file. Physical extents reported to
26 * the swap code must be trimmed to align to a page boundary. The logical
27 * offset within the file is irrelevant since the swapfile code maps logical
28 * page numbers of the swap device to the physical page-aligned extents.
30 static int iomap_swapfile_add_extent(struct iomap_swapfile_info
*isi
)
32 struct iomap
*iomap
= &isi
->iomap
;
33 unsigned long nr_pages
;
34 unsigned long max_pages
;
36 uint64_t first_ppage_reported
;
40 if (unlikely(isi
->nr_pages
>= isi
->sis
->max
))
42 max_pages
= isi
->sis
->max
- isi
->nr_pages
;
45 * Round the start up and the end down so that the physical
46 * extent aligns to a page boundary.
48 first_ppage
= ALIGN(iomap
->addr
, PAGE_SIZE
) >> PAGE_SHIFT
;
49 next_ppage
= ALIGN_DOWN(iomap
->addr
+ iomap
->length
, PAGE_SIZE
) >>
52 /* Skip too-short physical extents. */
53 if (first_ppage
>= next_ppage
)
55 nr_pages
= next_ppage
- first_ppage
;
56 nr_pages
= min(nr_pages
, max_pages
);
59 * Calculate how much swap space we're adding; the first page contains
60 * the swap header and doesn't count. The mm still wants that first
61 * page fed to add_swap_extent, however.
63 first_ppage_reported
= first_ppage
;
64 if (iomap
->offset
== 0)
65 first_ppage_reported
++;
66 if (isi
->lowest_ppage
> first_ppage_reported
)
67 isi
->lowest_ppage
= first_ppage_reported
;
68 if (isi
->highest_ppage
< (next_ppage
- 1))
69 isi
->highest_ppage
= next_ppage
- 1;
71 /* Add extent, set up for the next call. */
72 error
= add_swap_extent(isi
->sis
, isi
->nr_pages
, nr_pages
, first_ppage
);
75 isi
->nr_extents
+= error
;
76 isi
->nr_pages
+= nr_pages
;
80 static int iomap_swapfile_fail(struct iomap_swapfile_info
*isi
, const char *str
)
82 char *buf
, *p
= ERR_PTR(-ENOMEM
);
84 buf
= kmalloc(PATH_MAX
, GFP_KERNEL
);
86 p
= file_path(isi
->file
, buf
, PATH_MAX
);
87 pr_err("swapon: file %s %s\n", IS_ERR(p
) ? "<unknown>" : p
, str
);
93 * Accumulate iomaps for this swap file. We have to accumulate iomaps because
94 * swap only cares about contiguous page-aligned physical extents and makes no
95 * distinction between written and unwritten extents.
97 static loff_t
iomap_swapfile_iter(const struct iomap_iter
*iter
,
98 struct iomap
*iomap
, struct iomap_swapfile_info
*isi
)
100 switch (iomap
->type
) {
102 case IOMAP_UNWRITTEN
:
103 /* Only real or unwritten extents. */
106 /* No inline data. */
107 return iomap_swapfile_fail(isi
, "is inline");
109 return iomap_swapfile_fail(isi
, "has unallocated extents");
112 /* No uncommitted metadata or shared blocks. */
113 if (iomap
->flags
& IOMAP_F_DIRTY
)
114 return iomap_swapfile_fail(isi
, "is not committed");
115 if (iomap
->flags
& IOMAP_F_SHARED
)
116 return iomap_swapfile_fail(isi
, "has shared extents");
118 /* Only one bdev per swap file. */
119 if (iomap
->bdev
!= isi
->sis
->bdev
)
120 return iomap_swapfile_fail(isi
, "outside the main device");
122 if (isi
->iomap
.length
== 0) {
123 /* No accumulated extent, so just store it. */
124 memcpy(&isi
->iomap
, iomap
, sizeof(isi
->iomap
));
125 } else if (isi
->iomap
.addr
+ isi
->iomap
.length
== iomap
->addr
) {
126 /* Append this to the accumulated extent. */
127 isi
->iomap
.length
+= iomap
->length
;
129 /* Otherwise, add the retained iomap and store this one. */
130 int error
= iomap_swapfile_add_extent(isi
);
133 memcpy(&isi
->iomap
, iomap
, sizeof(isi
->iomap
));
135 return iomap_length(iter
);
139 * Iterate a swap file's iomaps to construct physical extents that can be
140 * passed to the swapfile subsystem.
142 int iomap_swapfile_activate(struct swap_info_struct
*sis
,
143 struct file
*swap_file
, sector_t
*pagespan
,
144 const struct iomap_ops
*ops
)
146 struct inode
*inode
= swap_file
->f_mapping
->host
;
147 struct iomap_iter iter
= {
150 .len
= ALIGN_DOWN(i_size_read(inode
), PAGE_SIZE
),
151 .flags
= IOMAP_REPORT
,
153 struct iomap_swapfile_info isi
= {
155 .lowest_ppage
= (sector_t
)-1ULL,
161 * Persist all file mapping metadata so that we won't have any
162 * IOMAP_F_DIRTY iomaps.
164 ret
= vfs_fsync(swap_file
, 1);
168 while ((ret
= iomap_iter(&iter
, ops
)) > 0)
169 iter
.processed
= iomap_swapfile_iter(&iter
, &iter
.iomap
, &isi
);
173 if (isi
.iomap
.length
) {
174 ret
= iomap_swapfile_add_extent(&isi
);
180 * If this swapfile doesn't contain even a single page-aligned
181 * contiguous range of blocks, reject this useless swapfile to
182 * prevent confusion later on.
184 if (isi
.nr_pages
== 0) {
185 pr_warn("swapon: Cannot find a single usable page in file.\n");
189 *pagespan
= 1 + isi
.highest_ppage
- isi
.lowest_ppage
;
190 sis
->max
= isi
.nr_pages
;
191 sis
->pages
= isi
.nr_pages
- 1;
192 sis
->highest_bit
= isi
.nr_pages
- 1;
193 return isi
.nr_extents
;
195 EXPORT_SYMBOL_GPL(iomap_swapfile_activate
);