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
;
35 uint64_t first_ppage_reported
;
40 * Round the start up and the end down so that the physical
41 * extent aligns to a page boundary.
43 first_ppage
= ALIGN(iomap
->addr
, PAGE_SIZE
) >> PAGE_SHIFT
;
44 next_ppage
= ALIGN_DOWN(iomap
->addr
+ iomap
->length
, PAGE_SIZE
) >>
47 /* Skip too-short physical extents. */
48 if (first_ppage
>= next_ppage
)
50 nr_pages
= next_ppage
- first_ppage
;
53 * Calculate how much swap space we're adding; the first page contains
54 * the swap header and doesn't count. The mm still wants that first
55 * page fed to add_swap_extent, however.
57 first_ppage_reported
= first_ppage
;
58 if (iomap
->offset
== 0)
59 first_ppage_reported
++;
60 if (isi
->lowest_ppage
> first_ppage_reported
)
61 isi
->lowest_ppage
= first_ppage_reported
;
62 if (isi
->highest_ppage
< (next_ppage
- 1))
63 isi
->highest_ppage
= next_ppage
- 1;
65 /* Add extent, set up for the next call. */
66 error
= add_swap_extent(isi
->sis
, isi
->nr_pages
, nr_pages
, first_ppage
);
69 isi
->nr_extents
+= error
;
70 isi
->nr_pages
+= nr_pages
;
74 static int iomap_swapfile_fail(struct iomap_swapfile_info
*isi
, const char *str
)
76 char *buf
, *p
= ERR_PTR(-ENOMEM
);
78 buf
= kmalloc(PATH_MAX
, GFP_KERNEL
);
80 p
= file_path(isi
->file
, buf
, PATH_MAX
);
81 pr_err("swapon: file %s %s\n", IS_ERR(p
) ? "<unknown>" : p
, str
);
87 * Accumulate iomaps for this swap file. We have to accumulate iomaps because
88 * swap only cares about contiguous page-aligned physical extents and makes no
89 * distinction between written and unwritten extents.
91 static loff_t
iomap_swapfile_activate_actor(struct inode
*inode
, loff_t pos
,
92 loff_t count
, void *data
, struct iomap
*iomap
,
95 struct iomap_swapfile_info
*isi
= data
;
98 switch (iomap
->type
) {
100 case IOMAP_UNWRITTEN
:
101 /* Only real or unwritten extents. */
104 /* No inline data. */
105 return iomap_swapfile_fail(isi
, "is inline");
107 return iomap_swapfile_fail(isi
, "has unallocated extents");
110 /* No uncommitted metadata or shared blocks. */
111 if (iomap
->flags
& IOMAP_F_DIRTY
)
112 return iomap_swapfile_fail(isi
, "is not committed");
113 if (iomap
->flags
& IOMAP_F_SHARED
)
114 return iomap_swapfile_fail(isi
, "has shared extents");
116 /* Only one bdev per swap file. */
117 if (iomap
->bdev
!= isi
->sis
->bdev
)
118 return iomap_swapfile_fail(isi
, "outside the main device");
120 if (isi
->iomap
.length
== 0) {
121 /* No accumulated extent, so just store it. */
122 memcpy(&isi
->iomap
, iomap
, sizeof(isi
->iomap
));
123 } else if (isi
->iomap
.addr
+ isi
->iomap
.length
== iomap
->addr
) {
124 /* Append this to the accumulated extent. */
125 isi
->iomap
.length
+= iomap
->length
;
127 /* Otherwise, add the retained iomap and store this one. */
128 error
= iomap_swapfile_add_extent(isi
);
131 memcpy(&isi
->iomap
, iomap
, sizeof(isi
->iomap
));
137 * Iterate a swap file's iomaps to construct physical extents that can be
138 * passed to the swapfile subsystem.
140 int iomap_swapfile_activate(struct swap_info_struct
*sis
,
141 struct file
*swap_file
, sector_t
*pagespan
,
142 const struct iomap_ops
*ops
)
144 struct iomap_swapfile_info isi
= {
146 .lowest_ppage
= (sector_t
)-1ULL,
149 struct address_space
*mapping
= swap_file
->f_mapping
;
150 struct inode
*inode
= mapping
->host
;
152 loff_t len
= ALIGN_DOWN(i_size_read(inode
), PAGE_SIZE
);
156 * Persist all file mapping metadata so that we won't have any
157 * IOMAP_F_DIRTY iomaps.
159 ret
= vfs_fsync(swap_file
, 1);
164 ret
= iomap_apply(inode
, pos
, len
, IOMAP_REPORT
,
165 ops
, &isi
, iomap_swapfile_activate_actor
);
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
);