[PATCH 2/3] fs: add fadvise file_operation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



sys_fadvise result in direct f_mode modification, which may be not
suitable for some unusual filesytems where file mode invariant is more
complex. In order to support such filesystems we have to delegate fadvise
logic to filesystem layer.

Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx>
---
 include/linux/fadvise.h |    3 ++
 include/linux/fs.h      |    1 +
 mm/fadvise.c            |   56 +++++++++++++++++++++++++++++++---------------
 3 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/include/linux/fadvise.h b/include/linux/fadvise.h
index e8e7471..8389378 100644
--- a/include/linux/fadvise.h
+++ b/include/linux/fadvise.h
@@ -18,4 +18,7 @@
 #define POSIX_FADV_NOREUSE	5 /* Data will be accessed once.  */
 #endif
 
+#ifdef __KERNEL__
+extern int generic_fadvise(struct file *file, loff_t off, loff_t len, int adv);
+#endif
 #endif	/* FADVISE_H_INCLUDED */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b176d11..63785d3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1522,6 +1522,7 @@ struct file_operations {
 	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
 	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
 	int (*setlease)(struct file *, long, struct file_lock **);
+	int (*fadvise)(struct file* file, loff_t offset, loff_t len, int advice);
 };
 
 struct inode_operations {
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 8d723c9..e13ee29 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -7,6 +7,7 @@
  *		Initial version.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/file.h>
 #include <linux/fs.h>
@@ -24,10 +25,9 @@
  * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could
  * deactivate the pages and clear PG_Referenced.
  */
-SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
+int generic_fadvise(struct file* file, loff_t offset, loff_t len, int advice)
 {
-	struct file *file = fget(fd);
-	struct address_space *mapping;
+	struct address_space *mapping = file->f_mapping;
 	struct backing_dev_info *bdi;
 	loff_t endbyte;			/* inclusive */
 	pgoff_t start_index;
@@ -35,20 +35,6 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
 	unsigned long nrpages;
 	int ret = 0;
 
-	if (!file)
-		return -EBADF;
-
-	if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) {
-		ret = -ESPIPE;
-		goto out;
-	}
-
-	mapping = file->f_mapping;
-	if (!mapping || len < 0) {
-		ret = -EINVAL;
-		goto out;
-	}
-
 	if (mapping->a_ops->get_xip_mem) {
 		switch (advice) {
 		case POSIX_FADV_NORMAL:
@@ -106,7 +92,7 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
 		nrpages = end_index - start_index + 1;
 		if (!nrpages)
 			nrpages = ~0UL;
-		
+
 		ret = force_page_cache_readahead(mapping, file,
 				start_index,
 				nrpages);
@@ -131,9 +117,43 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
 		ret = -EINVAL;
 	}
 out:
+	return ret;
+}
+EXPORT_SYMBOL(generic_fadvise);
+
+
+int do_fadvise(int fd, loff_t offset, loff_t len, int advice)
+
+{
+	struct file *file = fget(fd);
+	int (*fadvise)(struct file *,loff_t, loff_t, int) = generic_fadvise;
+	int ret = 0;
+	if (!file)
+		return -EBADF;
+
+	if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) {
+		ret = -ESPIPE;
+		goto out;
+	}
+
+	if (!file->f_mapping || len < 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+	if (file->f_op && file->f_op->fadvise)
+		fadvise = file->f_op->fadvise;
+
+	ret = fadvise(file, offset, len, advice);
+out:
 	fput(file);
 	return ret;
 }
+
+SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
+{
+	return do_fadvise(fd, offset, len, advice);
+}
+
 #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
 asmlinkage long SyS_fadvise64_64(long fd, loff_t offset, loff_t len, long advice)
 {
-- 
1.7.2.3

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux