vfs: add the fadvise() file operation
This is going to be used by overlayfs and possibly useful for other filesystems. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
78
mm/fadvise.c
78
mm/fadvise.c
@@ -27,9 +27,9 @@
|
||||
* deactivate the pages and clear PG_Referenced.
|
||||
*/
|
||||
|
||||
int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||
static int generic_fadvise(struct file *file, loff_t offset, loff_t len,
|
||||
int advice)
|
||||
{
|
||||
struct fd f = fdget(fd);
|
||||
struct inode *inode;
|
||||
struct address_space *mapping;
|
||||
struct backing_dev_info *bdi;
|
||||
@@ -37,22 +37,14 @@ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||
pgoff_t start_index;
|
||||
pgoff_t end_index;
|
||||
unsigned long nrpages;
|
||||
int ret = 0;
|
||||
|
||||
if (!f.file)
|
||||
return -EBADF;
|
||||
inode = file_inode(file);
|
||||
if (S_ISFIFO(inode->i_mode))
|
||||
return -ESPIPE;
|
||||
|
||||
inode = file_inode(f.file);
|
||||
if (S_ISFIFO(inode->i_mode)) {
|
||||
ret = -ESPIPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mapping = f.file->f_mapping;
|
||||
if (!mapping || len < 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
mapping = file->f_mapping;
|
||||
if (!mapping || len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
bdi = inode_to_bdi(mapping->host);
|
||||
|
||||
@@ -67,9 +59,9 @@ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||
/* no bad return value, but ignore advice */
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
goto out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -85,21 +77,21 @@ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||
|
||||
switch (advice) {
|
||||
case POSIX_FADV_NORMAL:
|
||||
f.file->f_ra.ra_pages = bdi->ra_pages;
|
||||
spin_lock(&f.file->f_lock);
|
||||
f.file->f_mode &= ~FMODE_RANDOM;
|
||||
spin_unlock(&f.file->f_lock);
|
||||
file->f_ra.ra_pages = bdi->ra_pages;
|
||||
spin_lock(&file->f_lock);
|
||||
file->f_mode &= ~FMODE_RANDOM;
|
||||
spin_unlock(&file->f_lock);
|
||||
break;
|
||||
case POSIX_FADV_RANDOM:
|
||||
spin_lock(&f.file->f_lock);
|
||||
f.file->f_mode |= FMODE_RANDOM;
|
||||
spin_unlock(&f.file->f_lock);
|
||||
spin_lock(&file->f_lock);
|
||||
file->f_mode |= FMODE_RANDOM;
|
||||
spin_unlock(&file->f_lock);
|
||||
break;
|
||||
case POSIX_FADV_SEQUENTIAL:
|
||||
f.file->f_ra.ra_pages = bdi->ra_pages * 2;
|
||||
spin_lock(&f.file->f_lock);
|
||||
f.file->f_mode &= ~FMODE_RANDOM;
|
||||
spin_unlock(&f.file->f_lock);
|
||||
file->f_ra.ra_pages = bdi->ra_pages * 2;
|
||||
spin_lock(&file->f_lock);
|
||||
file->f_mode &= ~FMODE_RANDOM;
|
||||
spin_unlock(&file->f_lock);
|
||||
break;
|
||||
case POSIX_FADV_WILLNEED:
|
||||
/* First and last PARTIAL page! */
|
||||
@@ -115,8 +107,7 @@ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||
* Ignore return value because fadvise() shall return
|
||||
* success even if filesystem can't retrieve a hint,
|
||||
*/
|
||||
force_page_cache_readahead(mapping, f.file, start_index,
|
||||
nrpages);
|
||||
force_page_cache_readahead(mapping, file, start_index, nrpages);
|
||||
break;
|
||||
case POSIX_FADV_NOREUSE:
|
||||
break;
|
||||
@@ -183,9 +174,30 @@ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
|
||||
{
|
||||
if (file->f_op->fadvise)
|
||||
return file->f_op->fadvise(file, offset, len, advice);
|
||||
|
||||
return generic_fadvise(file, offset, len, advice);
|
||||
}
|
||||
EXPORT_SYMBOL(vfs_fadvise);
|
||||
|
||||
int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||
{
|
||||
struct fd f = fdget(fd);
|
||||
int ret;
|
||||
|
||||
if (!f.file)
|
||||
return -EBADF;
|
||||
|
||||
ret = vfs_fadvise(f.file, offset, len, advice);
|
||||
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user