swapfile.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <darrick.wong@oracle.com>
  5. */
  6. #include <linux/module.h>
  7. #include <linux/compiler.h>
  8. #include <linux/fs.h>
  9. #include <linux/iomap.h>
  10. #include <linux/swap.h>
  11. /* Swapfile activation */
  12. struct iomap_swapfile_info {
  13. struct iomap iomap; /* accumulated iomap */
  14. struct swap_info_struct *sis;
  15. uint64_t lowest_ppage; /* lowest physical addr seen (pages) */
  16. uint64_t highest_ppage; /* highest physical addr seen (pages) */
  17. unsigned long nr_pages; /* number of pages collected */
  18. int nr_extents; /* extent count */
  19. };
  20. /*
  21. * Collect physical extents for this swap file. Physical extents reported to
  22. * the swap code must be trimmed to align to a page boundary. The logical
  23. * offset within the file is irrelevant since the swapfile code maps logical
  24. * page numbers of the swap device to the physical page-aligned extents.
  25. */
  26. static int iomap_swapfile_add_extent(struct iomap_swapfile_info *isi)
  27. {
  28. struct iomap *iomap = &isi->iomap;
  29. unsigned long nr_pages;
  30. unsigned long max_pages;
  31. uint64_t first_ppage;
  32. uint64_t first_ppage_reported;
  33. uint64_t next_ppage;
  34. int error;
  35. if (unlikely(isi->nr_pages >= isi->sis->max))
  36. return 0;
  37. max_pages = isi->sis->max - isi->nr_pages;
  38. /*
  39. * Round the start up and the end down so that the physical
  40. * extent aligns to a page boundary.
  41. */
  42. first_ppage = ALIGN(iomap->addr, PAGE_SIZE) >> PAGE_SHIFT;
  43. next_ppage = ALIGN_DOWN(iomap->addr + iomap->length, PAGE_SIZE) >>
  44. PAGE_SHIFT;
  45. /* Skip too-short physical extents. */
  46. if (first_ppage >= next_ppage)
  47. return 0;
  48. nr_pages = next_ppage - first_ppage;
  49. nr_pages = min(nr_pages, max_pages);
  50. /*
  51. * Calculate how much swap space we're adding; the first page contains
  52. * the swap header and doesn't count. The mm still wants that first
  53. * page fed to add_swap_extent, however.
  54. */
  55. first_ppage_reported = first_ppage;
  56. if (iomap->offset == 0)
  57. first_ppage_reported++;
  58. if (isi->lowest_ppage > first_ppage_reported)
  59. isi->lowest_ppage = first_ppage_reported;
  60. if (isi->highest_ppage < (next_ppage - 1))
  61. isi->highest_ppage = next_ppage - 1;
  62. /* Add extent, set up for the next call. */
  63. error = add_swap_extent(isi->sis, isi->nr_pages, nr_pages, first_ppage);
  64. if (error < 0)
  65. return error;
  66. isi->nr_extents += error;
  67. isi->nr_pages += nr_pages;
  68. return 0;
  69. }
  70. /*
  71. * Accumulate iomaps for this swap file. We have to accumulate iomaps because
  72. * swap only cares about contiguous page-aligned physical extents and makes no
  73. * distinction between written and unwritten extents.
  74. */
  75. static loff_t iomap_swapfile_activate_actor(struct inode *inode, loff_t pos,
  76. loff_t count, void *data, struct iomap *iomap,
  77. struct iomap *srcmap)
  78. {
  79. struct iomap_swapfile_info *isi = data;
  80. int error;
  81. switch (iomap->type) {
  82. case IOMAP_MAPPED:
  83. case IOMAP_UNWRITTEN:
  84. /* Only real or unwritten extents. */
  85. break;
  86. case IOMAP_INLINE:
  87. /* No inline data. */
  88. pr_err("swapon: file is inline\n");
  89. return -EINVAL;
  90. default:
  91. pr_err("swapon: file has unallocated extents\n");
  92. return -EINVAL;
  93. }
  94. /* No uncommitted metadata or shared blocks. */
  95. if (iomap->flags & IOMAP_F_DIRTY) {
  96. pr_err("swapon: file is not committed\n");
  97. return -EINVAL;
  98. }
  99. if (iomap->flags & IOMAP_F_SHARED) {
  100. pr_err("swapon: file has shared extents\n");
  101. return -EINVAL;
  102. }
  103. /* Only one bdev per swap file. */
  104. if (iomap->bdev != isi->sis->bdev) {
  105. pr_err("swapon: file is on multiple devices\n");
  106. return -EINVAL;
  107. }
  108. if (isi->iomap.length == 0) {
  109. /* No accumulated extent, so just store it. */
  110. memcpy(&isi->iomap, iomap, sizeof(isi->iomap));
  111. } else if (isi->iomap.addr + isi->iomap.length == iomap->addr) {
  112. /* Append this to the accumulated extent. */
  113. isi->iomap.length += iomap->length;
  114. } else {
  115. /* Otherwise, add the retained iomap and store this one. */
  116. error = iomap_swapfile_add_extent(isi);
  117. if (error)
  118. return error;
  119. memcpy(&isi->iomap, iomap, sizeof(isi->iomap));
  120. }
  121. return count;
  122. }
  123. /*
  124. * Iterate a swap file's iomaps to construct physical extents that can be
  125. * passed to the swapfile subsystem.
  126. */
  127. int iomap_swapfile_activate(struct swap_info_struct *sis,
  128. struct file *swap_file, sector_t *pagespan,
  129. const struct iomap_ops *ops)
  130. {
  131. struct iomap_swapfile_info isi = {
  132. .sis = sis,
  133. .lowest_ppage = (sector_t)-1ULL,
  134. };
  135. struct address_space *mapping = swap_file->f_mapping;
  136. struct inode *inode = mapping->host;
  137. loff_t pos = 0;
  138. loff_t len = ALIGN_DOWN(i_size_read(inode), PAGE_SIZE);
  139. loff_t ret;
  140. /*
  141. * Persist all file mapping metadata so that we won't have any
  142. * IOMAP_F_DIRTY iomaps.
  143. */
  144. ret = vfs_fsync(swap_file, 1);
  145. if (ret)
  146. return ret;
  147. while (len > 0) {
  148. ret = iomap_apply(inode, pos, len, IOMAP_REPORT,
  149. ops, &isi, iomap_swapfile_activate_actor);
  150. if (ret <= 0)
  151. return ret;
  152. pos += ret;
  153. len -= ret;
  154. }
  155. if (isi.iomap.length) {
  156. ret = iomap_swapfile_add_extent(&isi);
  157. if (ret)
  158. return ret;
  159. }
  160. /*
  161. * If this swapfile doesn't contain even a single page-aligned
  162. * contiguous range of blocks, reject this useless swapfile to
  163. * prevent confusion later on.
  164. */
  165. if (isi.nr_pages == 0) {
  166. pr_warn("swapon: Cannot find a single usable page in file.\n");
  167. return -EINVAL;
  168. }
  169. *pagespan = 1 + isi.highest_ppage - isi.lowest_ppage;
  170. sis->max = isi.nr_pages;
  171. sis->pages = isi.nr_pages - 1;
  172. sis->highest_bit = isi.nr_pages - 1;
  173. return isi.nr_extents;
  174. }
  175. EXPORT_SYMBOL_GPL(iomap_swapfile_activate);