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 19 #include <asm/unistd.h> 20 21 /* 22 * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could 23 * deactivate the pages and clear PG_Referenced. 24 */ 25 asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) 26 { 27 struct file *file = fget(fd); 28 struct address_space *mapping; 29 struct backing_dev_info *bdi; 30 loff_t endbyte; 31 pgoff_t start_index; 32 pgoff_t end_index; 33 unsigned long nrpages; 34 int ret = 0; 35 36 if (!file) 37 return -EBADF; 38 39 mapping = file->f_mapping; 40 if (!mapping || len < 0) { 41 ret = -EINVAL; 42 goto out; 43 } 44 45 /* Careful about overflows. Len == 0 means "as much as possible" */ 46 endbyte = offset + len; 47 if (!len || endbyte < len) 48 endbyte = -1; 49 50 bdi = mapping->backing_dev_info; 51 52 switch (advice) { 53 case POSIX_FADV_NORMAL: 54 file->f_ra.ra_pages = bdi->ra_pages; 55 break; 56 case POSIX_FADV_RANDOM: 57 file->f_ra.ra_pages = 0; 58 break; 59 case POSIX_FADV_SEQUENTIAL: 60 file->f_ra.ra_pages = bdi->ra_pages * 2; 61 break; 62 case POSIX_FADV_WILLNEED: 63 case POSIX_FADV_NOREUSE: 64 if (!mapping->a_ops->readpage) { 65 ret = -EINVAL; 66 break; 67 } 68 69 /* First and last PARTIAL page! */ 70 start_index = offset >> PAGE_CACHE_SHIFT; 71 end_index = (endbyte-1) >> PAGE_CACHE_SHIFT; 72 73 /* Careful about overflow on the "+1" */ 74 nrpages = end_index - start_index + 1; 75 if (!nrpages) 76 nrpages = ~0UL; 77 78 ret = force_page_cache_readahead(mapping, file, 79 start_index, 80 max_sane_readahead(nrpages)); 81 if (ret > 0) 82 ret = 0; 83 break; 84 case POSIX_FADV_DONTNEED: 85 if (!bdi_write_congested(mapping->backing_dev_info)) 86 filemap_flush(mapping); 87 88 /* First and last FULL page! */ 89 start_index = (offset + (PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT; 90 end_index = (endbyte >> PAGE_CACHE_SHIFT); 91 92 if (end_index > start_index) 93 invalidate_mapping_pages(mapping, start_index, end_index-1); 94 break; 95 default: 96 ret = -EINVAL; 97 } 98 out: 99 fput(file); 100 return ret; 101 } 102 103 #ifdef __ARCH_WANT_SYS_FADVISE64 104 105 asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) 106 { 107 return sys_fadvise64_64(fd, offset, len, advice); 108 } 109 110 #endif 111
This page was automatically generated by LXR 0.3.1. • Linux is a registered trademark of Linus Torvalds