aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-01-29 08:13:26 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-15 02:21:37 -0400
commit990d6c2d7aee921e3bce22b2d6a750fd552262be (patch)
treeaf273c4bfbfd0342d39d05d5a017382eb32a7538
parentf52e0c11305aa09ed56cad97ffc8f0cdc3d78b5d (diff)
vfs: Add name to file handle conversion support
The syscall also return mount id which can be used to lookup file system specific information such as uuid in /proc/<pid>/mountinfo Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/Makefile2
-rw-r--r--fs/fhandle.c107
-rw-r--r--include/linux/exportfs.h3
-rw-r--r--include/linux/fs.h7
-rw-r--r--include/linux/syscalls.h5
-rw-r--r--init/Kconfig12
-rw-r--r--kernel/sys_ni.c3
8 files changed, 139 insertions, 2 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 3db9caa57edc..7cb53aafac1e 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -47,7 +47,7 @@ config FS_POSIX_ACL
47 def_bool n 47 def_bool n
48 48
49config EXPORTFS 49config EXPORTFS
50 tristate 50 bool
51 51
52config FILE_LOCKING 52config FILE_LOCKING
53 bool "Enable POSIX file locking API" if EXPERT 53 bool "Enable POSIX file locking API" if EXPERT
diff --git a/fs/Makefile b/fs/Makefile
index a7f7cef0c0c8..ba01202844c5 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -48,6 +48,8 @@ obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o
48obj-$(CONFIG_NFS_COMMON) += nfs_common/ 48obj-$(CONFIG_NFS_COMMON) += nfs_common/
49obj-$(CONFIG_GENERIC_ACL) += generic_acl.o 49obj-$(CONFIG_GENERIC_ACL) += generic_acl.o
50 50
51obj-$(CONFIG_FHANDLE) += fhandle.o
52
51obj-y += quota/ 53obj-y += quota/
52 54
53obj-$(CONFIG_PROC_FS) += proc/ 55obj-$(CONFIG_PROC_FS) += proc/
diff --git a/fs/fhandle.c b/fs/fhandle.c
new file mode 100644
index 000000000000..9f79e743a840
--- /dev/null
+++ b/fs/fhandle.c
@@ -0,0 +1,107 @@
1#include <linux/syscalls.h>
2#include <linux/slab.h>
3#include <linux/fs.h>
4#include <linux/file.h>
5#include <linux/mount.h>
6#include <linux/namei.h>
7#include <linux/exportfs.h>
8#include <asm/uaccess.h>
9#include "internal.h"
10
11static long do_sys_name_to_handle(struct path *path,
12 struct file_handle __user *ufh,
13 int __user *mnt_id)
14{
15 long retval;
16 struct file_handle f_handle;
17 int handle_dwords, handle_bytes;
18 struct file_handle *handle = NULL;
19
20 /*
21 * We need t make sure wether the file system
22 * support decoding of the file handle
23 */
24 if (!path->mnt->mnt_sb->s_export_op ||
25 !path->mnt->mnt_sb->s_export_op->fh_to_dentry)
26 return -EOPNOTSUPP;
27
28 if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
29 return -EFAULT;
30
31 if (f_handle.handle_bytes > MAX_HANDLE_SZ)
32 return -EINVAL;
33
34 handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
35 GFP_KERNEL);
36 if (!handle)
37 return -ENOMEM;
38
39 /* convert handle size to multiple of sizeof(u32) */
40 handle_dwords = f_handle.handle_bytes >> 2;
41
42 /* we ask for a non connected handle */
43 retval = exportfs_encode_fh(path->dentry,
44 (struct fid *)handle->f_handle,
45 &handle_dwords, 0);
46 handle->handle_type = retval;
47 /* convert handle size to bytes */
48 handle_bytes = handle_dwords * sizeof(u32);
49 handle->handle_bytes = handle_bytes;
50 if ((handle->handle_bytes > f_handle.handle_bytes) ||
51 (retval == 255) || (retval == -ENOSPC)) {
52 /* As per old exportfs_encode_fh documentation
53 * we could return ENOSPC to indicate overflow
54 * But file system returned 255 always. So handle
55 * both the values
56 */
57 /*
58 * set the handle size to zero so we copy only
59 * non variable part of the file_handle
60 */
61 handle_bytes = 0;
62 retval = -EOVERFLOW;
63 } else
64 retval = 0;
65 /* copy the mount id */
66 if (copy_to_user(mnt_id, &path->mnt->mnt_id, sizeof(*mnt_id)) ||
67 copy_to_user(ufh, handle,
68 sizeof(struct file_handle) + handle_bytes))
69 retval = -EFAULT;
70 kfree(handle);
71 return retval;
72}
73
74/**
75 * sys_name_to_handle_at: convert name to handle
76 * @dfd: directory relative to which name is interpreted if not absolute
77 * @name: name that should be converted to handle.
78 * @handle: resulting file handle
79 * @mnt_id: mount id of the file system containing the file
80 * @flag: flag value to indicate whether to follow symlink or not
81 *
82 * @handle->handle_size indicate the space available to store the
83 * variable part of the file handle in bytes. If there is not
84 * enough space, the field is updated to return the minimum
85 * value required.
86 */
87SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
88 struct file_handle __user *, handle, int __user *, mnt_id,
89 int, flag)
90{
91 struct path path;
92 int lookup_flags;
93 int err;
94
95 if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
96 return -EINVAL;
97
98 lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
99 if (flag & AT_EMPTY_PATH)
100 lookup_flags |= LOOKUP_EMPTY;
101 err = user_path_at(dfd, name, lookup_flags, &path);
102 if (!err) {
103 err = do_sys_name_to_handle(&path, handle, mnt_id);
104 path_put(&path);
105 }
106 return err;
107}
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 65afdfd31b7b..33a42f24b275 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -8,6 +8,9 @@ struct inode;
8struct super_block; 8struct super_block;
9struct vfsmount; 9struct vfsmount;
10 10
11/* limit the handle size to NFSv4 handle size now */
12#define MAX_HANDLE_SZ 128
13
11/* 14/*
12 * The fileid_type identifies how the file within the filesystem is encoded. 15 * The fileid_type identifies how the file within the filesystem is encoded.
13 * In theory this is freely set and parsed by the filesystem, but we try to 16 * In theory this is freely set and parsed by the filesystem, but we try to
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b7178b05cf3a..3f64630c0e10 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -978,6 +978,13 @@ struct file {
978#endif 978#endif
979}; 979};
980 980
981struct file_handle {
982 __u32 handle_bytes;
983 int handle_type;
984 /* file identifier */
985 unsigned char f_handle[0];
986};
987
981#define get_file(x) atomic_long_inc(&(x)->f_count) 988#define get_file(x) atomic_long_inc(&(x)->f_count)
982#define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1) 989#define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1)
983#define file_count(x) atomic_long_read(&(x)->f_count) 990#define file_count(x) atomic_long_read(&(x)->f_count)
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 98664db1be47..970112613fb4 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -62,6 +62,7 @@ struct robust_list_head;
62struct getcpu_cache; 62struct getcpu_cache;
63struct old_linux_dirent; 63struct old_linux_dirent;
64struct perf_event_attr; 64struct perf_event_attr;
65struct file_handle;
65 66
66#include <linux/types.h> 67#include <linux/types.h>
67#include <linux/aio_abi.h> 68#include <linux/aio_abi.h>
@@ -832,5 +833,7 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
832 unsigned long prot, unsigned long flags, 833 unsigned long prot, unsigned long flags,
833 unsigned long fd, unsigned long pgoff); 834 unsigned long fd, unsigned long pgoff);
834asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); 835asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
835 836asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
837 struct file_handle __user *handle,
838 int __user *mnt_id, int flag);
836#endif 839#endif
diff --git a/init/Kconfig b/init/Kconfig
index be788c0957d4..e72fa17fe559 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -287,6 +287,18 @@ config BSD_PROCESS_ACCT_V3
287 for processing it. A preliminary version of these tools is available 287 for processing it. A preliminary version of these tools is available
288 at <http://www.gnu.org/software/acct/>. 288 at <http://www.gnu.org/software/acct/>.
289 289
290config FHANDLE
291 bool "open by fhandle syscalls"
292 select EXPORTFS
293 help
294 If you say Y here, a user level program will be able to map
295 file names to handle and then later use the handle for
296 different file system operations. This is useful in implementing
297 userspace file servers, which now track files using handles instead
298 of names. The handle would remain the same even if file names
299 get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2)
300 syscalls.
301
290config TASKSTATS 302config TASKSTATS
291 bool "Export task/process statistics through netlink (EXPERIMENTAL)" 303 bool "Export task/process statistics through netlink (EXPERIMENTAL)"
292 depends on NET 304 depends on NET
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index c782fe9924c7..4e013439ac28 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -186,3 +186,6 @@ cond_syscall(sys_perf_event_open);
186/* fanotify! */ 186/* fanotify! */
187cond_syscall(sys_fanotify_init); 187cond_syscall(sys_fanotify_init);
188cond_syscall(sys_fanotify_mark); 188cond_syscall(sys_fanotify_mark);
189
190/* open by handle */
191cond_syscall(sys_name_to_handle_at);