forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									f52e0c1130
								
							
						
					
					
						commit
						990d6c2d7a
					
				
					 8 changed files with 139 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -47,7 +47,7 @@ config FS_POSIX_ACL
 | 
			
		|||
	def_bool n
 | 
			
		||||
 | 
			
		||||
config EXPORTFS
 | 
			
		||||
	tristate
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config FILE_LOCKING
 | 
			
		||||
	bool "Enable POSIX file locking API" if EXPERT
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,8 @@ obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o xattr_acl.o
 | 
			
		|||
obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
 | 
			
		||||
obj-$(CONFIG_GENERIC_ACL)	+= generic_acl.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_FHANDLE)		+= fhandle.o
 | 
			
		||||
 | 
			
		||||
obj-y				+= quota/
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_PROC_FS)		+= proc/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										107
									
								
								fs/fhandle.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								fs/fhandle.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,107 @@
 | 
			
		|||
#include <linux/syscalls.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/fs.h>
 | 
			
		||||
#include <linux/file.h>
 | 
			
		||||
#include <linux/mount.h>
 | 
			
		||||
#include <linux/namei.h>
 | 
			
		||||
#include <linux/exportfs.h>
 | 
			
		||||
#include <asm/uaccess.h>
 | 
			
		||||
#include "internal.h"
 | 
			
		||||
 | 
			
		||||
static long do_sys_name_to_handle(struct path *path,
 | 
			
		||||
				  struct file_handle __user *ufh,
 | 
			
		||||
				  int __user *mnt_id)
 | 
			
		||||
{
 | 
			
		||||
	long retval;
 | 
			
		||||
	struct file_handle f_handle;
 | 
			
		||||
	int handle_dwords, handle_bytes;
 | 
			
		||||
	struct file_handle *handle = NULL;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * We need t make sure wether the file system
 | 
			
		||||
	 * support decoding of the file handle
 | 
			
		||||
	 */
 | 
			
		||||
	if (!path->mnt->mnt_sb->s_export_op ||
 | 
			
		||||
	    !path->mnt->mnt_sb->s_export_op->fh_to_dentry)
 | 
			
		||||
		return -EOPNOTSUPP;
 | 
			
		||||
 | 
			
		||||
	if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	if (f_handle.handle_bytes > MAX_HANDLE_SZ)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
 | 
			
		||||
			 GFP_KERNEL);
 | 
			
		||||
	if (!handle)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	/* convert handle size to  multiple of sizeof(u32) */
 | 
			
		||||
	handle_dwords = f_handle.handle_bytes >> 2;
 | 
			
		||||
 | 
			
		||||
	/* we ask for a non connected handle */
 | 
			
		||||
	retval = exportfs_encode_fh(path->dentry,
 | 
			
		||||
				    (struct fid *)handle->f_handle,
 | 
			
		||||
				    &handle_dwords,  0);
 | 
			
		||||
	handle->handle_type = retval;
 | 
			
		||||
	/* convert handle size to bytes */
 | 
			
		||||
	handle_bytes = handle_dwords * sizeof(u32);
 | 
			
		||||
	handle->handle_bytes = handle_bytes;
 | 
			
		||||
	if ((handle->handle_bytes > f_handle.handle_bytes) ||
 | 
			
		||||
	    (retval == 255) || (retval == -ENOSPC)) {
 | 
			
		||||
		/* As per old exportfs_encode_fh documentation
 | 
			
		||||
		 * we could return ENOSPC to indicate overflow
 | 
			
		||||
		 * But file system returned 255 always. So handle
 | 
			
		||||
		 * both the values
 | 
			
		||||
		 */
 | 
			
		||||
		/*
 | 
			
		||||
		 * set the handle size to zero so we copy only
 | 
			
		||||
		 * non variable part of the file_handle
 | 
			
		||||
		 */
 | 
			
		||||
		handle_bytes = 0;
 | 
			
		||||
		retval = -EOVERFLOW;
 | 
			
		||||
	} else
 | 
			
		||||
		retval = 0;
 | 
			
		||||
	/* copy the mount id */
 | 
			
		||||
	if (copy_to_user(mnt_id, &path->mnt->mnt_id, sizeof(*mnt_id)) ||
 | 
			
		||||
	    copy_to_user(ufh, handle,
 | 
			
		||||
			 sizeof(struct file_handle) + handle_bytes))
 | 
			
		||||
		retval = -EFAULT;
 | 
			
		||||
	kfree(handle);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sys_name_to_handle_at: convert name to handle
 | 
			
		||||
 * @dfd: directory relative to which name is interpreted if not absolute
 | 
			
		||||
 * @name: name that should be converted to handle.
 | 
			
		||||
 * @handle: resulting file handle
 | 
			
		||||
 * @mnt_id: mount id of the file system containing the file
 | 
			
		||||
 * @flag: flag value to indicate whether to follow symlink or not
 | 
			
		||||
 *
 | 
			
		||||
 * @handle->handle_size indicate the space available to store the
 | 
			
		||||
 * variable part of the file handle in bytes. If there is not
 | 
			
		||||
 * enough space, the field is updated to return the minimum
 | 
			
		||||
 * value required.
 | 
			
		||||
 */
 | 
			
		||||
SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
 | 
			
		||||
		struct file_handle __user *, handle, int __user *, mnt_id,
 | 
			
		||||
		int, flag)
 | 
			
		||||
{
 | 
			
		||||
	struct path path;
 | 
			
		||||
	int lookup_flags;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
 | 
			
		||||
	if (flag & AT_EMPTY_PATH)
 | 
			
		||||
		lookup_flags |= LOOKUP_EMPTY;
 | 
			
		||||
	err = user_path_at(dfd, name, lookup_flags, &path);
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		err = do_sys_name_to_handle(&path, handle, mnt_id);
 | 
			
		||||
		path_put(&path);
 | 
			
		||||
	}
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,9 @@ struct inode;
 | 
			
		|||
struct super_block;
 | 
			
		||||
struct vfsmount;
 | 
			
		||||
 | 
			
		||||
/* limit the handle size to NFSv4 handle size now */
 | 
			
		||||
#define MAX_HANDLE_SZ 128
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The fileid_type identifies how the file within the filesystem is encoded.
 | 
			
		||||
 * In theory this is freely set and parsed by the filesystem, but we try to
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -978,6 +978,13 @@ struct file {
 | 
			
		|||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct file_handle {
 | 
			
		||||
	__u32 handle_bytes;
 | 
			
		||||
	int handle_type;
 | 
			
		||||
	/* file identifier */
 | 
			
		||||
	unsigned char f_handle[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define get_file(x)	atomic_long_inc(&(x)->f_count)
 | 
			
		||||
#define fput_atomic(x)	atomic_long_add_unless(&(x)->f_count, -1, 1)
 | 
			
		||||
#define file_count(x)	atomic_long_read(&(x)->f_count)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,7 @@ struct robust_list_head;
 | 
			
		|||
struct getcpu_cache;
 | 
			
		||||
struct old_linux_dirent;
 | 
			
		||||
struct perf_event_attr;
 | 
			
		||||
struct file_handle;
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/aio_abi.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -832,5 +833,7 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
 | 
			
		|||
			unsigned long prot, unsigned long flags,
 | 
			
		||||
			unsigned long fd, unsigned long pgoff);
 | 
			
		||||
asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
 | 
			
		||||
 | 
			
		||||
asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
 | 
			
		||||
				      struct file_handle __user *handle,
 | 
			
		||||
				      int __user *mnt_id, int flag);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								init/Kconfig
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								init/Kconfig
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -287,6 +287,18 @@ config BSD_PROCESS_ACCT_V3
 | 
			
		|||
	  for processing it. A preliminary version of these tools is available
 | 
			
		||||
	  at <http://www.gnu.org/software/acct/>.
 | 
			
		||||
 | 
			
		||||
config FHANDLE
 | 
			
		||||
	bool "open by fhandle syscalls"
 | 
			
		||||
	select EXPORTFS
 | 
			
		||||
	help
 | 
			
		||||
	  If you say Y here, a user level program will be able to map
 | 
			
		||||
	  file names to handle and then later use the handle for
 | 
			
		||||
	  different file system operations. This is useful in implementing
 | 
			
		||||
	  userspace file servers, which now track files using handles instead
 | 
			
		||||
	  of names. The handle would remain the same even if file names
 | 
			
		||||
	  get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2)
 | 
			
		||||
	  syscalls.
 | 
			
		||||
 | 
			
		||||
config TASKSTATS
 | 
			
		||||
	bool "Export task/process statistics through netlink (EXPERIMENTAL)"
 | 
			
		||||
	depends on NET
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -186,3 +186,6 @@ cond_syscall(sys_perf_event_open);
 | 
			
		|||
/* fanotify! */
 | 
			
		||||
cond_syscall(sys_fanotify_init);
 | 
			
		||||
cond_syscall(sys_fanotify_mark);
 | 
			
		||||
 | 
			
		||||
/* open by handle */
 | 
			
		||||
cond_syscall(sys_name_to_handle_at);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue