fadvise.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * mm/fadvise.c
  3. *
  4. * Copyright (C) 2002, Linus Torvalds
  5. *
  6. * 11Jan2003 Andrew Morton
  7. * Initial version.
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/file.h>
  11. #include <linux/fs.h>
  12. #include <linux/mm.h>
  13. #include <linux/pagemap.h>
  14. #include <linux/backing-dev.h>
  15. #include <linux/pagevec.h>
  16. #include <linux/fadvise.h>
  17. #include <linux/writeback.h>
  18. #include <linux/syscalls.h>
  19. #include <linux/swap.h>
  20. #include <asm/unistd.h>
  21. /*
  22. * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could
  23. * deactivate the pages and clear PG_Referenced.
  24. */
  25. SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
  26. {
  27. struct fd f = fdget(fd);
  28. struct inode *inode;
  29. struct address_space *mapping;
  30. struct backing_dev_info *bdi;
  31. loff_t endbyte; /* inclusive */
  32. pgoff_t start_index;
  33. pgoff_t end_index;
  34. unsigned long nrpages;
  35. int ret = 0;
  36. if (!f.file)
  37. return -EBADF;
  38. inode = file_inode(f.file);
  39. if (S_ISFIFO(inode->i_mode)) {
  40. ret = -ESPIPE;
  41. goto out;
  42. }
  43. mapping = f.file->f_mapping;
  44. if (!mapping || len < 0) {
  45. ret = -EINVAL;
  46. goto out;
  47. }
  48. if (IS_DAX(inode)) {
  49. switch (advice) {
  50. case POSIX_FADV_NORMAL:
  51. case POSIX_FADV_RANDOM:
  52. case POSIX_FADV_SEQUENTIAL:
  53. case POSIX_FADV_WILLNEED:
  54. case POSIX_FADV_NOREUSE:
  55. case POSIX_FADV_DONTNEED:
  56. /* no bad return value, but ignore advice */
  57. break;
  58. default:
  59. ret = -EINVAL;
  60. }
  61. goto out;
  62. }
  63. /*
  64. * Careful about overflows. Len == 0 means "as much as possible". Use
  65. * unsigned math because signed overflows are undefined and UBSan
  66. * complains.
  67. */
  68. endbyte = (u64)offset + (u64)len;
  69. if (!len || endbyte < len)
  70. endbyte = -1;
  71. else
  72. endbyte--; /* inclusive */
  73. bdi = inode_to_bdi(mapping->host);
  74. switch (advice) {
  75. case POSIX_FADV_NORMAL:
  76. f.file->f_ra.ra_pages = bdi->ra_pages;
  77. spin_lock(&f.file->f_lock);
  78. f.file->f_mode &= ~FMODE_RANDOM;
  79. spin_unlock(&f.file->f_lock);
  80. break;
  81. case POSIX_FADV_RANDOM:
  82. spin_lock(&f.file->f_lock);
  83. f.file->f_mode |= FMODE_RANDOM;
  84. spin_unlock(&f.file->f_lock);
  85. break;
  86. case POSIX_FADV_SEQUENTIAL:
  87. f.file->f_ra.ra_pages = bdi->ra_pages * 2;
  88. spin_lock(&f.file->f_lock);
  89. f.file->f_mode &= ~FMODE_RANDOM;
  90. spin_unlock(&f.file->f_lock);
  91. break;
  92. case POSIX_FADV_WILLNEED:
  93. /* First and last PARTIAL page! */
  94. start_index = offset >> PAGE_CACHE_SHIFT;
  95. end_index = endbyte >> PAGE_CACHE_SHIFT;
  96. /* Careful about overflow on the "+1" */
  97. nrpages = end_index - start_index + 1;
  98. if (!nrpages)
  99. nrpages = ~0UL;
  100. /*
  101. * Ignore return value because fadvise() shall return
  102. * success even if filesystem can't retrieve a hint,
  103. */
  104. force_page_cache_readahead(mapping, f.file, start_index,
  105. nrpages);
  106. break;
  107. case POSIX_FADV_NOREUSE:
  108. break;
  109. case POSIX_FADV_DONTNEED:
  110. if (!inode_write_congested(mapping->host))
  111. __filemap_fdatawrite_range(mapping, offset, endbyte,
  112. WB_SYNC_NONE);
  113. /*
  114. * First and last FULL page! Partial pages are deliberately
  115. * preserved on the expectation that it is better to preserve
  116. * needed memory than to discard unneeded memory.
  117. */
  118. start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT;
  119. end_index = (endbyte >> PAGE_CACHE_SHIFT);
  120. if (end_index >= start_index) {
  121. unsigned long count = invalidate_mapping_pages(mapping,
  122. start_index, end_index);
  123. /*
  124. * If fewer pages were invalidated than expected then
  125. * it is possible that some of the pages were on
  126. * a per-cpu pagevec for a remote CPU. Drain all
  127. * pagevecs and try again.
  128. */
  129. if (count < (end_index - start_index + 1)) {
  130. lru_add_drain_all();
  131. invalidate_mapping_pages(mapping, start_index,
  132. end_index);
  133. }
  134. }
  135. break;
  136. default:
  137. ret = -EINVAL;
  138. }
  139. out:
  140. fdput(f);
  141. return ret;
  142. }
  143. #ifdef __ARCH_WANT_SYS_FADVISE64
  144. SYSCALL_DEFINE4(fadvise64, int, fd, loff_t, offset, size_t, len, int, advice)
  145. {
  146. return sys_fadvise64_64(fd, offset, len, advice);
  147. }
  148. #endif