struct file *file = fget(fd);
struct address_space *mapping;
struct backing_dev_info *bdi;
+ loff_t endbyte;
pgoff_t start_index;
pgoff_t end_index;
+ unsigned long nrpages;
int ret = 0;
if (!file)
goto out;
}
- if (len == 0) /* 0 == "all data following offset" */
- len = -1;
+ /* Careful about overflows. Len == 0 means "as much as possible" */
+ endbyte = offset + len;
+ if (!len || endbyte < len)
+ endbyte = -1;
bdi = mapping->backing_dev_info;
ret = -EINVAL;
break;
}
+
+ /* First and last PARTIAL page! */
+ start_index = offset >> PAGE_CACHE_SHIFT;
+ end_index = (endbyte-1) >> PAGE_CACHE_SHIFT;
+
+ /* Careful about overflow on the "+1" */
+ nrpages = end_index - start_index + 1;
+ if (!nrpages)
+ nrpages = ~0UL;
+
ret = force_page_cache_readahead(mapping, file,
- offset >> PAGE_CACHE_SHIFT,
- max_sane_readahead(len >> PAGE_CACHE_SHIFT));
+ start_index,
+ max_sane_readahead(nrpages));
if (ret > 0)
ret = 0;
break;
case POSIX_FADV_DONTNEED:
if (!bdi_write_congested(mapping->backing_dev_info))
filemap_flush(mapping);
- start_index = (offset + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
- end_index = ((offset + len) >> PAGE_CACHE_SHIFT) - 1;
- invalidate_mapping_pages(mapping, start_index, end_index);
+
+ /* First and last FULL page! */
+ start_index = (offset + (PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT;
+ end_index = (endbyte >> PAGE_CACHE_SHIFT);
+
+ if (end_index > start_index)
+ invalidate_mapping_pages(mapping, start_index, end_index-1);
break;
default:
ret = -EINVAL;