swapfile.c 5.4 KB

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