1 /* 2 * mm/fadvise.c 3 * 4 * Copyright (C) 2002, Linus Torvalds 5 * 6 * 11Jan2003 akpm@digeo.com 7 * Initial version. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/file.h> 12 #include <linux/fs.h> 13 #include <linux/mm.h> 14 #include <linux/pagemap.h> 15 #include <linux/backing-dev.h> 16 #include <linux/pagevec.h> 17 #include <linux/fadvise.h> 18 #include <linux/writeback.h> 19 #include <linux/syscalls.h> 20 21 #include <asm/unistd.h> 22 23 /* 24 * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could 25 * deactivate the pages and clear PG_Referenced. 26 */ 27 asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) 28 { 29 struct file *file = fget(fd); 30 struct address_space *mapping; 31 struct backing_dev_info *bdi; 32 loff_t endbyte; /* inclusive */ 33 pgoff_t start_index; 34 pgoff_t end_index; 35 unsigned long nrpages; 36 int ret = 0; 37 38 if (!file) 39 return -EBADF; 40 41 if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) { 42 ret = -ESPIPE; 43 goto out; 44 } 45 46 mapping = file->f_mapping; 47 if (!mapping || len < 0) { 48 ret = -EINVAL; 49 goto out; 50 } 51 52 if (mapping->a_ops->get_xip_page) 53 /* no bad return value, but ignore advice */ 54 goto out; 55 56 /* Careful about overflows. Len == 0 means "as much as possible" */ 57 endbyte = offset + len; 58 if (!len || endbyte < len) 59 endbyte = -1; 60 else 61 endbyte--; /* inclusive */ 62 63 bdi = mapping->backing_dev_info; 64 65 switch (advice) { 66 case POSIX_FADV_NORMAL: 67 file->f_ra.ra_pages = bdi->ra_pages; 68 break; 69 case POSIX_FADV_RANDOM: 70 file->f_ra.ra_pages = 0; 71 break; 72 case POSIX_FADV_SEQUENTIAL: 73 file->f_ra.ra_pages = bdi->ra_pages * 2; 74 break; 75 case POSIX_FADV_WILLNEED: 76 if (!mapping->a_ops->readpage) { 77 ret = -EINVAL; 78 break; 79 } 80 81 /* First and last PARTIAL page! */ 82 start_index = offset >> PAGE_CACHE_SHIFT; 83 end_index = endbyte >> PAGE_CACHE_SHIFT; 84 85 /* Careful about overflow on the "+1" */ 86 nrpages = end_index - start_index + 1; 87 if (!nrpages) 88 nrpages = ~0UL; 89 90 ret = force_page_cache_readahead(mapping, file, 91 start_index, 92 max_sane_readahead(nrpages)); 93 if (ret > 0) 94 ret = 0; 95 break; 96 case POSIX_FADV_NOREUSE: 97 break; 98 case POSIX_FADV_DONTNEED: 99 if (!bdi_write_congested(mapping->backing_dev_info)) 100 filemap_flush(mapping); 101 102 /* First and last FULL page! */ 103 start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT; 104 end_index = (endbyte >> PAGE_CACHE_SHIFT); 105 106 if (end_index >= start_index) 107 invalidate_mapping_pages(mapping, start_index, 108 end_index); 109 break; 110 default: 111 ret = -EINVAL; 112 } 113 out: 114 fput(file); 115 return ret; 116 } 117 118 #ifdef __ARCH_WANT_SYS_FADVISE64 119 120 asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) 121 { 122 return sys_fadvise64_64(fd, offset, len, advice); 123 } 124 125 #endif 126