RHEL4/mm/fadvise.c
<<
>>
Prefs
   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 */
  25asmlinkage 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        }
  98out:
  99        fput(file);
 100        return ret;
 101}
 102
 103#ifdef __ARCH_WANT_SYS_FADVISE64
 104
 105asmlinkage 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