[RFC PATCH 2/5] fs: Add xgetdents system call and xreaddir file operation

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

 



Also add linux_xdirent structure that will be the container for
dirent, stat and xattr info.

Signed-off-by: Abhi Das <adas@xxxxxxxxxx>
---
 arch/x86/syscalls/syscall_32.tbl |  1 +
 arch/x86/syscalls/syscall_64.tbl |  1 +
 fs/readdir.c                     | 42 ++++++++++++++++++++++++++++++++++++++++
 fs/stat.c                        |  4 +++-
 include/linux/fs.h               |  1 +
 include/linux/stat.h             |  2 ++
 include/uapi/linux/stat.h        | 33 +++++++++++++++++++++++++++++++
 7 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index 6d6ca37..35723e3 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -362,3 +362,4 @@
 353	i386	renameat2		sys_renameat2
 354	i386	xstat			sys_xstat
 355	i386	fxstat			sys_fxstat
+356	i386	xgetdents		sys_xgetdents
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index 1308ee3..566aab1 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -325,6 +325,7 @@
 316	common	renameat2		sys_renameat2
 317	common 	xstat			sys_xstat
 318	common 	fxstat			sys_fxstat
+319	common	xgetdents		sys_xgetdents
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/fs/readdir.c b/fs/readdir.c
index 33fd922..d676088 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -224,6 +224,48 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
 	return error;
 }
 
+SYSCALL_DEFINE5(xgetdents, unsigned int, fd, unsigned, flags, unsigned int, mask, 
+		void __user *, buf, unsigned int, count)
+{
+	struct fd f;
+	struct inode *inode;
+	int error = -ENOTDIR;
+
+	if (!count)
+		return -EINVAL;
+
+	if (!access_ok(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+
+	f = fdget(fd);
+	if (!f.file)
+		return -EBADF;
+
+	inode = f.file->f_path.dentry->d_inode;
+
+	error = -ENOTSUPP;
+	if (!f.file->f_op || !f.file->f_op->xreaddir)
+		goto out;
+
+	error = security_file_permission(f.file, MAY_READ);
+	if (error)
+		goto out;
+
+	error = mutex_lock_killable(&inode->i_mutex);
+	if (error)
+		goto out;
+
+	error = -ENOENT;
+	if (!IS_DEADDIR(inode)) {
+		error = f.file->f_op->xreaddir(f.file, flags, mask, buf, count);
+		file_accessed(f.file);
+	}
+	mutex_unlock(&inode->i_mutex);
+out:
+	fdput(f);
+	return error;
+}
+
 struct getdents_callback64 {
 	struct dir_context ctx;
 	struct linux_dirent64 __user * current_dir;
diff --git a/fs/stat.c b/fs/stat.c
index 1fd0b3e..db45f8b 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -651,7 +651,7 @@ static int xstat_get_params(unsigned int mask, struct xstat __user *buffer,
  * Otherwise we copy the extended stats to userspace and return the amount of
  * data written into the buffer (or -EFAULT).
  */
-static long xstat_set_result(struct kstat *stat, struct xstat __user *buffer)
+long xstat_set_result(struct kstat *stat, struct xstat __user *buffer)
 {
 	u32 mask = stat->result_mask, gran = stat->tv_granularity;
 
@@ -701,6 +701,8 @@ static long xstat_set_result(struct kstat *stat, struct xstat __user *buffer)
 	return 0;
 }
 
+EXPORT_SYMBOL(xstat_set_result);
+
 /*
  * System call to get extended stats by path
  */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b91f235..79c7d39 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1464,6 +1464,7 @@ struct file_operations {
 	ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
 	ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
 	int (*iterate) (struct file *, struct dir_context *);
+	size_t (*xreaddir) (struct file *, unsigned int, unsigned int, void __user *, size_t);
 	unsigned int (*poll) (struct file *, struct poll_table_struct *);
 	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
 	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 552e047..75be415 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -46,4 +46,6 @@ struct kstat {
 	unsigned char   volume_id[16];              /* volume identifier */
 };
 
+long xstat_set_result(struct kstat *stat, struct xstat __user *buffer);
+
 #endif
diff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h
index 2907352..d7ea6c5 100644
--- a/include/uapi/linux/stat.h
+++ b/include/uapi/linux/stat.h
@@ -90,6 +90,14 @@
 #define XSTAT_VOLUME_ID        0x00008000U     /* want/got st_volume_id */
 #define XSTAT_ALL_STATS        0x0000ffffU     /* all supported stats */
 
+/* xattr request flags */
+#define XSTAT_XATTR_USER       0x00010000U     /* user.* xattrs */
+#define XSTAT_XATTR_SYSTEM     0x00020000U     /* system.* xattrs */
+#define XSTAT_XATTR_SECURITY   0x00040000U     /* security.* xattrs */
+#define XSTAT_XATTR_POSIX_ACL  0x00080000U     /* posix acl xattrs */
+#define XSTAT_XATTR_ALL        0x00ff0000U     /* all xattrs */
+#define XSTAT_XATTR_VALUES     0x01000000U     /* retrieve values along with keys */
+
 /*
  * Extended stat structures
  */
@@ -152,4 +160,29 @@ struct xstat {
 #define XSTAT_INFO_SYSTEM              0x00001000U /* File is marked system (DOS+) */
 #define XSTAT_INFO_ARCHIVE             0x00002000U /* File is marked archive (DOS+) */
 
+struct xdirent_xattr {
+	size_t       xa_value_len;   /* length of value field */
+	char         xa_name_val[1]; /* name/value pair, name is NULL terminated and 
+				      * value is xa_value_len in length */
+};
+
+/*
+ * xb_blob: first contains NULL terminated name, followed by struct xdirent_xattr
+ * objects packed together.
+ */
+struct xdirent_blob {
+	unsigned int    xb_xattr_count;
+	char            xb_blob[1]; /* contains variable length data like
+				     * NULL-terminated name, xattrs etc */
+};
+
+struct linux_xdirent {
+	unsigned long        xd_ino;
+	char                 xd_type;
+	unsigned long        xd_off;
+	struct xstat         xd_stat;
+	unsigned long        xd_reclen;
+	struct xdirent_blob  xd_blob;
+};
+
 #endif /* _UAPI_LINUX_STAT_H */
-- 
1.8.1.4

--
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