The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mm/fadvise.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * mm/fadvise.c
    3  *
    4  * Copyright (C) 2002, Linus Torvalds
    5  *
    6  * 11Jan2003    Andrew Morton
    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 SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
   28 {
   29         struct fd f = fdget(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 (!f.file)
   39                 return -EBADF;
   40 
   41         if (S_ISFIFO(f.file->f_path.dentry->d_inode->i_mode)) {
   42                 ret = -ESPIPE;
   43                 goto out;
   44         }
   45 
   46         mapping = f.file->f_mapping;
   47         if (!mapping || len < 0) {
   48                 ret = -EINVAL;
   49                 goto out;
   50         }
   51 
   52         if (mapping->a_ops->get_xip_mem) {
   53                 switch (advice) {
   54                 case POSIX_FADV_NORMAL:
   55                 case POSIX_FADV_RANDOM:
   56                 case POSIX_FADV_SEQUENTIAL:
   57                 case POSIX_FADV_WILLNEED:
   58                 case POSIX_FADV_NOREUSE:
   59                 case POSIX_FADV_DONTNEED:
   60                         /* no bad return value, but ignore advice */
   61                         break;
   62                 default:
   63                         ret = -EINVAL;
   64                 }
   65                 goto out;
   66         }
   67 
   68         /* Careful about overflows. Len == 0 means "as much as possible" */
   69         endbyte = offset + len;
   70         if (!len || endbyte < len)
   71                 endbyte = -1;
   72         else
   73                 endbyte--;              /* inclusive */
   74 
   75         bdi = mapping->backing_dev_info;
   76 
   77         switch (advice) {
   78         case POSIX_FADV_NORMAL:
   79                 f.file->f_ra.ra_pages = bdi->ra_pages;
   80                 spin_lock(&f.file->f_lock);
   81                 f.file->f_mode &= ~FMODE_RANDOM;
   82                 spin_unlock(&f.file->f_lock);
   83                 break;
   84         case POSIX_FADV_RANDOM:
   85                 spin_lock(&f.file->f_lock);
   86                 f.file->f_mode |= FMODE_RANDOM;
   87                 spin_unlock(&f.file->f_lock);
   88                 break;
   89         case POSIX_FADV_SEQUENTIAL:
   90                 f.file->f_ra.ra_pages = bdi->ra_pages * 2;
   91                 spin_lock(&f.file->f_lock);
   92                 f.file->f_mode &= ~FMODE_RANDOM;
   93                 spin_unlock(&f.file->f_lock);
   94                 break;
   95         case POSIX_FADV_WILLNEED:
   96                 /* First and last PARTIAL page! */
   97                 start_index = offset >> PAGE_CACHE_SHIFT;
   98                 end_index = endbyte >> PAGE_CACHE_SHIFT;
   99 
  100                 /* Careful about overflow on the "+1" */
  101                 nrpages = end_index - start_index + 1;
  102                 if (!nrpages)
  103                         nrpages = ~0UL;
  104 
  105                 /*
  106                  * Ignore return value because fadvise() shall return
  107                  * success even if filesystem can't retrieve a hint,
  108                  */
  109                 force_page_cache_readahead(mapping, f.file, start_index,
  110                                            nrpages);
  111                 break;
  112         case POSIX_FADV_NOREUSE:
  113                 break;
  114         case POSIX_FADV_DONTNEED:
  115                 if (!bdi_write_congested(mapping->backing_dev_info))
  116                         __filemap_fdatawrite_range(mapping, offset, endbyte,
  117                                                    WB_SYNC_NONE);
  118 
  119                 /* First and last FULL page! */
  120                 start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT;
  121                 end_index = (endbyte >> PAGE_CACHE_SHIFT);
  122 
  123                 if (end_index >= start_index)
  124                         invalidate_mapping_pages(mapping, start_index,
  125                                                 end_index);
  126                 break;
  127         default:
  128                 ret = -EINVAL;
  129         }
  130 out:
  131         fdput(f);
  132         return ret;
  133 }
  134 #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
  135 asmlinkage long SyS_fadvise64_64(long fd, loff_t offset, loff_t len, long advice)
  136 {
  137         return SYSC_fadvise64_64((int) fd, offset, len, (int) advice);
  138 }
  139 SYSCALL_ALIAS(sys_fadvise64_64, SyS_fadvise64_64);
  140 #endif
  141 
  142 #ifdef __ARCH_WANT_SYS_FADVISE64
  143 
  144 SYSCALL_DEFINE(fadvise64)(int fd, loff_t offset, size_t len, int advice)
  145 {
  146         return sys_fadvise64_64(fd, offset, len, advice);
  147 }
  148 #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
  149 asmlinkage long SyS_fadvise64(long fd, loff_t offset, long len, long advice)
  150 {
  151         return SYSC_fadvise64((int) fd, offset, (size_t)len, (int)advice);
  152 }
  153 SYSCALL_ALIAS(sys_fadvise64, SyS_fadvise64);
  154 #endif
  155 
  156 #endif

Cache object: 8ce957d41d6eb141ec5c564e471c74c1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.