* [PATCH 01/11] exportfs: Return the minimum required handle size
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:17 ` Aneesh Kumar K. V
2010-06-03 16:08 ` [PATCH 02/11] vfs: Add name to file handle conversion support Aneesh Kumar K.V
` (9 subsequent siblings)
10 siblings, 1 reply; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
The exportfs encode handle function should return the minimum required
handle size. This helps user to find out the handle size by passing 0
handle size in the first step and then redoing to the call again with
the returned handle size value.
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/btrfs/export.c | 8 ++++++--
fs/exportfs/expfs.c | 9 +++++++--
fs/fat/inode.c | 4 +++-
fs/fuse/inode.c | 4 +++-
fs/gfs2/export.c | 8 ++++++--
fs/isofs/export.c | 8 ++++++--
fs/ocfs2/export.c | 8 +++++++-
fs/reiserfs/inode.c | 7 ++++++-
fs/udf/namei.c | 7 ++++++-
fs/xfs/linux-2.6/xfs_export.c | 4 +++-
include/linux/exportfs.h | 6 ++++--
mm/shmem.c | 4 +++-
12 files changed, 60 insertions(+), 17 deletions(-)
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index 951ef09..5f8ee5a 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -21,9 +21,13 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
int len = *max_len;
int type;
- if ((len < BTRFS_FID_SIZE_NON_CONNECTABLE) ||
- (connectable && len < BTRFS_FID_SIZE_CONNECTABLE))
+ if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
+ *max_len = BTRFS_FID_SIZE_CONNECTABLE;
return 255;
+ } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
+ *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
+ return 255;
+ }
len = BTRFS_FID_SIZE_NON_CONNECTABLE;
type = FILEID_BTRFS_WITHOUT_PARENT;
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index e9e1759..cfee0f0 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -319,9 +319,14 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
struct inode * inode = dentry->d_inode;
int len = *max_len;
int type = FILEID_INO32_GEN;
-
- if (len < 2 || (connectable && len < 4))
+
+ if (connectable && (len < 4)) {
+ *max_len = 4;
+ return 255;
+ } else if (len < 2) {
+ *max_len = 2;
return 255;
+ }
len = 2;
fid->i32.ino = inode->i_ino;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 7bf45ae..da2f8a1 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -761,8 +761,10 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
struct inode *inode = de->d_inode;
u32 ipos_h, ipos_m, ipos_l;
- if (len < 5)
+ if (len < 5) {
+ *lenp = 5;
return 255; /* no room */
+ }
ipos_h = MSDOS_I(inode)->i_pos >> 8;
ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index ec14d19..beaea69 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -638,8 +638,10 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
u64 nodeid;
u32 generation;
- if (*max_len < len)
+ if (*max_len < len) {
+ *max_len = len;
return 255;
+ }
nodeid = get_fuse_inode(inode)->nodeid;
generation = inode->i_generation;
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c
index dfe237a..bd0fd68 100644
--- a/fs/gfs2/export.c
+++ b/fs/gfs2/export.c
@@ -36,9 +36,13 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
struct super_block *sb = inode->i_sb;
struct gfs2_inode *ip = GFS2_I(inode);
- if (*len < GFS2_SMALL_FH_SIZE ||
- (connectable && *len < GFS2_LARGE_FH_SIZE))
+ if (connectable && (*len < GFS2_LARGE_FH_SIZE)) {
+ *len = GFS2_LARGE_FH_SIZE;
return 255;
+ } else if (*len < GFS2_SMALL_FH_SIZE) {
+ *len = GFS2_SMALL_FH_SIZE;
+ return 255;
+ }
fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index ed752cb..dd4687f 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -124,9 +124,13 @@ isofs_export_encode_fh(struct dentry *dentry,
* offset of the inode and the upper 16 bits of fh32[1] to
* hold the offset of the parent.
*/
-
- if (len < 3 || (connectable && len < 5))
+ if (connectable && (len < 5)) {
+ *max_len = 5;
+ return 255;
+ } else if (len < 3) {
+ *max_len = 3;
return 255;
+ }
len = 3;
fh32[0] = ei->i_iget5_block;
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 19ad145..250a347 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -201,8 +201,14 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
dentry->d_name.len, dentry->d_name.name,
fh, len, connectable);
- if (len < 3 || (connectable && len < 6)) {
+ if (connectable && (len < 6)) {
mlog(ML_ERROR, "fh buffer is too small for encoding\n");
+ *max_len = 6;
+ type = 255;
+ goto bail;
+ } else if (len < 3) {
+ mlog(ML_ERROR, "fh buffer is too small for encoding\n");
+ *max_len = 3;
type = 255;
goto bail;
}
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 0f22fda..8f1bf99 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1588,8 +1588,13 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
struct inode *inode = dentry->d_inode;
int maxlen = *lenp;
- if (maxlen < 3)
+ if (need_parent && (maxlen < 5)) {
+ *lenp = 5;
return 255;
+ } else if (maxlen < 3) {
+ *lenp = 3;
+ return 255;
+ }
data[0] = inode->i_ino;
data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index bf5fc67..20db42f 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1336,8 +1336,13 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp,
struct fid *fid = (struct fid *)fh;
int type = FILEID_UDF_WITHOUT_PARENT;
- if (len < 3 || (connectable && len < 5))
+ if (connectable && (len < 5)) {
+ *lenp = 5;
+ return 255;
+ } else if (len < 3) {
+ *lenp = 3;
return 255;
+ }
*lenp = 3;
fid->udf.block = location.logicalBlockNum;
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index 846b75a..82c0553 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -81,8 +81,10 @@ xfs_fs_encode_fh(
* seven combinations work. The real answer is "don't use v2".
*/
len = xfs_fileid_length(fileid_type);
- if (*max_len < len)
+ if (*max_len < len) {
+ *max_len = len
return 255;
+ }
*max_len = len;
switch (fileid_type) {
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index a9cd507..acd0b2d 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -108,8 +108,10 @@ struct fid {
* set, the encode_fh() should store sufficient information so that a good
* attempt can be made to find not only the file but also it's place in the
* filesystem. This typically means storing a reference to de->d_parent in
- * the filehandle fragment. encode_fh() should return the number of bytes
- * stored or a negative error code such as %-ENOSPC
+ * the filehandle fragment. encode_fh() should return the fileid_type on
+ * success and on error returns 255 (if the space needed to encode fh is
+ * greater than @max_len*4 bytes). On error @max_len contain the minimum
+ * size(in 4 byte unit) needed to encode the file handle.
*
* fh_to_dentry:
* @fh_to_dentry is given a &struct super_block (@sb) and a file handle
diff --git a/mm/shmem.c b/mm/shmem.c
index 7e5030a..ee5a04b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2116,8 +2116,10 @@ static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
{
struct inode *inode = dentry->d_inode;
- if (*len < 3)
+ if (*len < 3) {
+ *len = 3;
return 255;
+ }
if (hlist_unhashed(&inode->i_hash)) {
/* Unfortunately insert_inode_hash is not idempotent,
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 01/11] exportfs: Return the minimum required handle size
2010-06-03 16:08 ` [PATCH 01/11] exportfs: Return the minimum required handle size Aneesh Kumar K.V
@ 2010-06-03 16:17 ` Aneesh Kumar K. V
0 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K. V @ 2010-06-03 16:17 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel
I missed a -V13 in the patchset subject. So will resend again with the
current version string so that we get the right patchset when merging
upstream.
-aneesh
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 02/11] vfs: Add name to file handle conversion support
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 01/11] exportfs: Return the minimum required handle size Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 03/11] vfs: Add open by file handle support Aneesh Kumar K.V
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
This patch add a new superblock field unsigned char s_uuid[16]
to store UUID mapping for the file system. The s_uuid[16] is used to
identify the file system apart of file_handle
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/open.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 11 ++++
include/linux/syscalls.h | 3 +
3 files changed, 128 insertions(+), 0 deletions(-)
diff --git a/fs/open.c b/fs/open.c
index 5463266..71f4e04 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -29,6 +29,7 @@
#include <linux/falloc.h>
#include <linux/fs_struct.h>
#include <linux/ima.h>
+#include <linux/exportfs.h>
#include "internal.h"
@@ -1040,3 +1041,116 @@ int nonseekable_open(struct inode *inode, struct file *filp)
}
EXPORT_SYMBOL(nonseekable_open);
+
+#ifdef CONFIG_EXPORTFS
+/* limit the handle size to some value */
+#define MAX_HANDLE_SZ 4096
+static long do_sys_name_to_handle(struct path *path,
+ struct file_handle __user *ufh)
+{
+ long retval;
+ int handle_size;
+ struct super_block *sb;
+ struct file_handle f_handle;
+ struct file_handle *handle = NULL;
+
+ if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ if (f_handle.handle_size > MAX_HANDLE_SZ) {
+ retval = -EINVAL;
+ goto err_out;
+ }
+ handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_size,
+ GFP_KERNEL);
+ if (!handle) {
+ retval = -ENOMEM;
+ goto err_out;
+ }
+
+ /* convert handle size to multiple of sizeof(u32) */
+ handle_size = f_handle.handle_size >> 2;
+
+ /* we ask for a non connected handle */
+ retval = exportfs_encode_fh(path->dentry,
+ (struct fid *)handle->f_handle,
+ &handle_size, 0);
+ /* convert handle size to bytes */
+ handle_size *= sizeof(u32);
+ handle->handle_type = retval;
+ handle->handle_size = handle_size;
+ if (handle_size <= f_handle.handle_size) {
+ /* get the uuid */
+ sb = path->mnt->mnt_sb;
+ memcpy(handle->fs_uuid,
+ sb->s_uuid,
+ sizeof(handle->fs_uuid));
+ retval = 0;
+ } else {
+ /*
+ * set the handle_size to zero so we copy only
+ * non variable part of the file_handle
+ */
+ handle_size = 0;
+ retval = -EOVERFLOW;
+ }
+ if (copy_to_user(ufh, handle,
+ sizeof(struct file_handle) + handle_size))
+ retval = -EFAULT;
+
+ kfree(handle);
+err_out:
+ 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
+ * @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_DEFINE4(name_to_handle_at, int, dfd, const char __user *, name,
+ struct file_handle __user *, handle, int, flag)
+{
+
+ int follow;
+ long ret = -EINVAL;
+ struct path path;
+
+ if ((flag & ~AT_SYMLINK_FOLLOW) != 0)
+ goto err_out;
+
+ follow = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
+ ret = user_path_at(dfd, name, follow, &path);
+ if (ret)
+ goto err_out;
+ /*
+ * 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) {
+ ret = -EOPNOTSUPP;
+ goto out_path;
+ }
+ ret = do_sys_name_to_handle(&path, handle);
+
+out_path:
+ path_put(&path);
+err_out:
+ return ret;
+}
+#else
+SYSCALL_DEFINE4(name_to_handle_at, int, dfd, const char __user *, name,
+ struct file_handle __user *, handle, int, flag)
+{
+ return -ENOSYS;
+}
+#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3428393..ef7b00c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -949,6 +949,16 @@ struct file {
unsigned long f_mnt_write_state;
#endif
};
+
+struct file_handle {
+ int handle_size;
+ int handle_type;
+ /* File system UUID identifier */
+ u8 fs_uuid[16];
+ /* file identifier */
+ unsigned char f_handle[0];
+};
+
extern spinlock_t files_lock;
#define file_list_lock() spin_lock(&files_lock);
#define file_list_unlock() spin_unlock(&files_lock);
@@ -1357,6 +1367,7 @@ struct super_block {
wait_queue_head_t s_wait_unfrozen;
char s_id[32]; /* Informational name */
+ u8 s_uuid[16]; /* UUID */
void *s_fs_info; /* Filesystem private info */
fmode_t s_mode;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a1a86a5..45c869b 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -61,6 +61,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>
@@ -823,5 +824,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 flag);
#endif
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 03/11] vfs: Add open by file handle support
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 01/11] exportfs: Return the minimum required handle size Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 02/11] vfs: Add name to file handle conversion support Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 04/11] vfs: Allow handle based open on symlinks Aneesh Kumar K.V
` (7 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/exportfs/expfs.c | 2 +
fs/namei.c | 50 ++++++++++++
fs/open.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 3 +-
include/linux/syscalls.h | 2 +
5 files changed, 254 insertions(+), 1 deletions(-)
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index cfee0f0..05a1179 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -373,6 +373,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
/*
* Try to get any dentry for the given file handle from the filesystem.
*/
+ if (!nop || !nop->fh_to_dentry)
+ return ERR_PTR(-ESTALE);
result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
if (!result)
result = ERR_PTR(-ESTALE);
diff --git a/fs/namei.c b/fs/namei.c
index 868d0cb..c2d19c7 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1557,6 +1557,56 @@ static int open_will_truncate(int flag, struct inode *inode)
return (flag & O_TRUNC);
}
+struct file *finish_open_handle(struct path *path,
+ int open_flag, int acc_mode)
+{
+ int error;
+ struct file *filp;
+ int will_truncate;
+
+ will_truncate = open_will_truncate(open_flag, path->dentry->d_inode);
+ if (will_truncate) {
+ error = mnt_want_write(path->mnt);
+ if (error)
+ goto exit;
+ }
+ error = may_open(path, acc_mode, open_flag);
+ if (error) {
+ if (will_truncate)
+ mnt_drop_write(path->mnt);
+ goto exit;
+ }
+ filp = dentry_open(path->dentry, path->mnt, open_flag, current_cred());
+ if (!IS_ERR(filp)) {
+ error = ima_file_check(filp, acc_mode);
+ if (error) {
+ fput(filp);
+ filp = ERR_PTR(error);
+ }
+ }
+ if (!IS_ERR(filp)) {
+ if (will_truncate) {
+ error = handle_truncate(path);
+ if (error) {
+ fput(filp);
+ filp = ERR_PTR(error);
+ }
+ }
+ }
+ /*
+ * It is now safe to drop the mnt write
+ * because the filp has had a write taken
+ * on its behalf.
+ */
+ if (will_truncate)
+ mnt_drop_write(path->mnt);
+ return filp;
+
+exit:
+ path_put(path);
+ return ERR_PTR(error);
+}
+
static struct file *finish_open(struct nameidata *nd,
int open_flag, int acc_mode)
{
diff --git a/fs/open.c b/fs/open.c
index 71f4e04..9c3df5f 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1154,3 +1154,201 @@ SYSCALL_DEFINE4(name_to_handle_at, int, dfd, const char __user *, name,
return -ENOSYS;
}
#endif
+
+#ifdef CONFIG_EXPORTFS
+static struct vfsmount *get_vfsmount_from_fd(int fd)
+{
+ int fput_needed;
+ struct path *path;
+ struct file *filep;
+
+ if (fd == AT_FDCWD) {
+ struct fs_struct *fs = current->fs;
+ read_lock(&fs->lock);
+ path = &fs->pwd;
+ mntget(path->mnt);
+ read_unlock(&fs->lock);
+ } else {
+ filep = fget_light(fd, &fput_needed);
+ if (!filep)
+ return ERR_PTR(-EBADF);
+ path = &filep->f_path;
+ mntget(path->mnt);
+ fput_light(filep, fput_needed);
+ }
+ return path->mnt;
+}
+
+static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
+{
+ return 1;
+}
+
+static struct path *handle_to_path(int mountdirfd, struct file_handle *handle)
+{
+ int retval;
+ int handle_size;
+ struct path *path;
+
+ path = kmalloc(sizeof(struct path), GFP_KERNEL);
+ if (!path)
+ return ERR_PTR(-ENOMEM);
+
+ path->mnt = get_vfsmount_from_fd(mountdirfd);
+ if (IS_ERR(path->mnt)) {
+ retval = PTR_ERR(path->mnt);
+ goto out_err;
+ }
+ /* change the handle size to multiple of sizeof(u32) */
+ handle_size = handle->handle_size >> 2;
+ path->dentry = exportfs_decode_fh(path->mnt,
+ (struct fid *)handle->f_handle,
+ handle_size, handle->handle_type,
+ vfs_dentry_acceptable, NULL);
+ if (IS_ERR(path->dentry)) {
+ retval = PTR_ERR(path->dentry);
+ goto out_mnt;
+ }
+ return path;
+out_mnt:
+ mntput(path->mnt);
+out_err:
+ kfree(path);
+ return ERR_PTR(retval);
+}
+
+static long do_sys_open_by_handle(int mountdirfd,
+ struct file_handle __user *ufh, int open_flag)
+{
+ long retval = 0;
+ int fd, acc_mode;
+ struct file *filp;
+ struct path *path;
+ struct file_handle f_handle;
+ struct file_handle *handle = NULL;
+
+ /*
+ * With handle we don't look at the execute bit on the
+ * the directory. Ideally we whould like CAP_DAC_SEARCH.
+ * But we don't have that
+ */
+ if (!capable(CAP_DAC_READ_SEARCH)) {
+ retval = -EPERM;
+ goto out_err;
+ }
+ /* can't use O_CREATE with open_by_handle */
+ if (open_flag & O_CREAT) {
+ retval = -EINVAL;
+ goto out_err;
+ }
+ if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) {
+ retval = -EFAULT;
+ goto out_err;
+ }
+ if ((f_handle.handle_size > MAX_HANDLE_SZ) ||
+ (f_handle.handle_size <= 0)) {
+ retval = -EINVAL;
+ goto out_err;
+ }
+ handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_size,
+ GFP_KERNEL);
+ if (!handle) {
+ retval = -ENOMEM;
+ goto out_err;
+ }
+ /* copy the full handle */
+ if (copy_from_user(handle, ufh,
+ sizeof(struct file_handle) +
+ f_handle.handle_size)) {
+ retval = -EFAULT;
+ goto out_handle;
+ }
+ path = handle_to_path(mountdirfd, handle);
+ if (IS_ERR(path)) {
+ retval = PTR_ERR(path);
+ goto out_handle;
+ }
+ if ((open_flag & O_DIRECTORY) &&
+ !S_ISDIR(path->dentry->d_inode->i_mode)) {
+ retval = -ENOTDIR;
+ goto out_path;
+ }
+ /*
+ * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
+ * check for O_DSYNC if the need any syncing at all we enforce it's
+ * always set instead of having to deal with possibly weird behaviour
+ * for malicious applications setting only __O_SYNC.
+ */
+ if (open_flag & __O_SYNC)
+ open_flag |= O_DSYNC;
+
+ acc_mode = MAY_OPEN | ACC_MODE(open_flag);
+
+ /* O_TRUNC implies we need access checks for write permissions */
+ if (open_flag & O_TRUNC)
+ acc_mode |= MAY_WRITE;
+ /*
+ * Allow the LSM permission hook to distinguish append
+ * access from general write access.
+ */
+ if (open_flag & O_APPEND)
+ acc_mode |= MAY_APPEND;
+
+ fd = get_unused_fd_flags(open_flag);
+ if (fd < 0) {
+ retval = fd;
+ goto out_path;
+ }
+ filp = finish_open_handle(path, open_flag, acc_mode);
+ if (IS_ERR(filp)) {
+ put_unused_fd(fd);
+ retval = PTR_ERR(filp);
+ } else {
+ retval = fd;
+ fsnotify_open(filp->f_path.dentry);
+ fd_install(fd, filp);
+ }
+ kfree(path);
+ kfree(handle);
+ return retval;
+
+out_path:
+ path_put(path);
+ kfree(path);
+out_handle:
+ kfree(handle);
+out_err:
+ return retval;
+}
+
+/**
+ * sys_open_by_handle_at: Open the file handle
+ * @mountdirfd: directory file descriptor
+ * @handle: file handle to be opened
+ * @flag: open flags.
+ *
+ * @mountdirfd indicate the directory file descriptor
+ * of the mount point. file handle is decoded relative
+ * to the vfsmount pointed by the @mountdirfd. @flags
+ * value is same as the open(2) flags.
+ */
+SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
+ struct file_handle __user *, handle,
+ int, flags)
+{
+ long ret;
+
+ if (force_o_largefile())
+ flags |= O_LARGEFILE;
+
+ ret = do_sys_open_by_handle(mountdirfd, handle, flags);
+ return ret;
+}
+#else
+SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
+ struct file_handle __user *, handle,
+ int, flags)
+{
+ return -ENOSYS;
+}
+#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ef7b00c..aec3292 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2141,7 +2141,8 @@ extern int may_open(struct path *, int, int);
extern int kernel_read(struct file *, loff_t, char *, unsigned long);
extern struct file * open_exec(const char *);
-
+extern struct file *finish_open_handle(struct path *, int, int);
+
/* fs/dcache.c -- generic fs support functions */
extern int is_subdir(struct dentry *, struct dentry *);
extern int path_is_under(struct path *, struct path *);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 45c869b..1bcdafd 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -826,5 +826,7 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
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 flag);
+asmlinkage long sys_open_by_handle_at(int mountdirfd,
+ struct file_handle __user *handle, int flags);
#endif
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 04/11] vfs: Allow handle based open on symlinks
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (2 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 03/11] vfs: Add open by file handle support Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 05/11] vfs: Support null pathname in readlink Aneesh Kumar K.V
` (6 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
The patch update may_open to allow handle based open on symlinks.
The file handle based API use file descritor returned from open_by_handle_at
to do different file system operations. To find the link target name we
need to get a file descriptor on symlinks.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/namei.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index c2d19c7..417bf53 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1422,7 +1422,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
return error;
}
-int may_open(struct path *path, int acc_mode, int flag)
+static int __may_open(struct path *path, int acc_mode, int flag, int handle)
{
struct dentry *dentry = path->dentry;
struct inode *inode = dentry->d_inode;
@@ -1433,7 +1433,13 @@ int may_open(struct path *path, int acc_mode, int flag)
switch (inode->i_mode & S_IFMT) {
case S_IFLNK:
- return -ELOOP;
+ /*
+ * For file handle based open we should allow
+ * open of symlink.
+ */
+ if (!handle)
+ return -ELOOP;
+ break;
case S_IFDIR:
if (acc_mode & MAY_WRITE)
return -EISDIR;
@@ -1473,6 +1479,11 @@ int may_open(struct path *path, int acc_mode, int flag)
return break_lease(inode, flag);
}
+int may_open(struct path *path, int acc_mode, int flag)
+{
+ return __may_open(path, acc_mode, flag, 0);
+}
+
static int handle_truncate(struct path *path)
{
struct inode *inode = path->dentry->d_inode;
@@ -1570,7 +1581,7 @@ struct file *finish_open_handle(struct path *path,
if (error)
goto exit;
}
- error = may_open(path, acc_mode, open_flag);
+ error = __may_open(path, acc_mode, open_flag, 1);
if (error) {
if (will_truncate)
mnt_drop_write(path->mnt);
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 05/11] vfs: Support null pathname in readlink
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (3 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 04/11] vfs: Allow handle based open on symlinks Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 06/11] ext4: Copy fs UUID to superblock Aneesh Kumar K.V
` (5 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
From: NeilBrown <neilb@suse.de>
This enables to use readlink to get the link target name
from a file descriptor point to the link. This can be used
with open_by_handle syscall that returns a file descriptor for a link.
We can then use this file descriptor to get the target name.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/stat.c | 30 ++++++++++++++++++++++--------
1 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/fs/stat.c b/fs/stat.c
index c4ecd52..49b95a7 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -284,26 +284,40 @@ SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
char __user *, buf, int, bufsiz)
{
- struct path path;
- int error;
+ int error = 0;
+ struct path path, *pp;
+ struct file *file = NULL;
if (bufsiz <= 0)
return -EINVAL;
- error = user_path_at(dfd, pathname, 0, &path);
+ if (pathname == NULL && dfd != AT_FDCWD) {
+ file = fget(dfd);
+
+ if (file)
+ pp = &file->f_path;
+ else
+ error = -EBADF;
+ } else {
+ error = user_path_at(dfd, pathname, 0, &path);
+ pp = &path;
+ }
if (!error) {
- struct inode *inode = path.dentry->d_inode;
+ struct inode *inode = pp->dentry->d_inode;
error = -EINVAL;
if (inode->i_op->readlink) {
- error = security_inode_readlink(path.dentry);
+ error = security_inode_readlink(pp->dentry);
if (!error) {
- touch_atime(path.mnt, path.dentry);
- error = inode->i_op->readlink(path.dentry,
+ touch_atime(pp->mnt, pp->dentry);
+ error = inode->i_op->readlink(pp->dentry,
buf, bufsiz);
}
}
- path_put(&path);
+ if (file)
+ fput(file);
+ else
+ path_put(&path);
}
return error;
}
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 06/11] ext4: Copy fs UUID to superblock
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (4 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 05/11] vfs: Support null pathname in readlink Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 07/11] x86: Add new syscalls for x86_32 Aneesh Kumar K.V
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
This enables userspace application to find the file system
UUID using sys_name_to_handle_at syscall
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/ext4/super.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4e8983a..f2bd1bc 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2816,6 +2816,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->s_qcop = &ext4_qctl_operations;
sb->dq_op = &ext4_quota_operations;
#endif
+ memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
+
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
mutex_init(&sbi->s_orphan_lock);
mutex_init(&sbi->s_resize_lock);
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 07/11] x86: Add new syscalls for x86_32
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (5 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 06/11] ext4: Copy fs UUID to superblock Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 08/11] x86: Add new syscalls for x86_64 Aneesh Kumar K.V
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
This patch adds sys_name_to_handle_at and sys_open_by_handle_at
syscalls to x86_32
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/x86/include/asm/unistd_32.h | 4 +++-
arch/x86/kernel/syscall_table_32.S | 2 ++
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index beb9b5f..06890db 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -343,10 +343,12 @@
#define __NR_rt_tgsigqueueinfo 335
#define __NR_perf_event_open 336
#define __NR_recvmmsg 337
+#define __NR_name_to_handle_at 338
+#define __NR_open_by_handle_at 339
#ifdef __KERNEL__
-#define NR_syscalls 338
+#define NR_syscalls 340
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 8b37293..646717f 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -337,3 +337,5 @@ ENTRY(sys_call_table)
.long sys_rt_tgsigqueueinfo /* 335 */
.long sys_perf_event_open
.long sys_recvmmsg
+ .long sys_name_to_handle_at
+ .long sys_open_by_handle_at /* 339 */
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 08/11] x86: Add new syscalls for x86_64
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (6 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 07/11] x86: Add new syscalls for x86_32 Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 09/11] ext3: Copy fs UUID to superblock Aneesh Kumar K.V
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
Add sys_name_to_handle_at and sys_open_by_handle_at syscalls
for x86_64
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/x86/ia32/ia32entry.S | 2 ++
arch/x86/include/asm/unistd_64.h | 4 ++++
fs/compat.c | 11 +++++++++++
fs/open.c | 20 ++++++++++----------
include/linux/fs.h | 1 +
5 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index e790bc1..99f9623 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -842,4 +842,6 @@ ia32_sys_call_table:
.quad compat_sys_rt_tgsigqueueinfo /* 335 */
.quad sys_perf_event_open
.quad compat_sys_recvmmsg
+ .quad sys_name_to_handle_at
+ .quad compat_sys_open_by_handle_at /* 339 */
ia32_syscall_end:
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index ff4307b..6afd818 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -663,6 +663,10 @@ __SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
#define __NR_recvmmsg 299
__SYSCALL(__NR_recvmmsg, sys_recvmmsg)
+#define __NR_name_to_handle_at 300
+__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+#define __NR_open_by_handle_at 301
+__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
#ifndef __NO_STUBS
#define __ARCH_WANT_OLD_READDIR
diff --git a/fs/compat.c b/fs/compat.c
index f0b391c..f2f86e5 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -2332,3 +2332,14 @@ asmlinkage long compat_sys_timerfd_gettime(int ufd,
}
#endif /* CONFIG_TIMERFD */
+
+/*
+ * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
+ * doesn't set the O_LARGEFILE flag.
+ */
+asmlinkage long
+compat_sys_open_by_handle_at(int mountdirfd,
+ struct file_handle __user *handle, int flags)
+{
+ return do_sys_open_by_handle(mountdirfd, handle, flags);
+}
diff --git a/fs/open.c b/fs/open.c
index 9c3df5f..3cff394 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1217,8 +1217,8 @@ out_err:
return ERR_PTR(retval);
}
-static long do_sys_open_by_handle(int mountdirfd,
- struct file_handle __user *ufh, int open_flag)
+long do_sys_open_by_handle(int mountdirfd,
+ struct file_handle __user *ufh, int open_flag)
{
long retval = 0;
int fd, acc_mode;
@@ -1320,6 +1320,14 @@ out_handle:
out_err:
return retval;
}
+#else
+long do_sys_open_by_handle(int mountdirfd,
+ struct file_handle __user *ufh, int open_flag)
+{
+
+ return -ENOSYS;
+}
+#endif
/**
* sys_open_by_handle_at: Open the file handle
@@ -1344,11 +1352,3 @@ SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
ret = do_sys_open_by_handle(mountdirfd, handle, flags);
return ret;
}
-#else
-SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
- struct file_handle __user *, handle,
- int, flags)
-{
- return -ENOSYS;
-}
-#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index aec3292..0a629de 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1930,6 +1930,7 @@ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
const struct cred *);
extern int filp_close(struct file *, fl_owner_t id);
extern char * getname(const char __user *);
+extern long do_sys_open_by_handle(int, struct file_handle __user *, int);
/* fs/ioctl.c */
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 09/11] ext3: Copy fs UUID to superblock.
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (7 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 08/11] x86: Add new syscalls for x86_64 Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 10/11] vfs: Support null pathname in faccessat Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 11/11] vfs: Support null pathname in linkat Aneesh Kumar K.V
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
This enable user space application to get the file system UUID
using sys_name_to_handle_at syscall
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/ext3/super.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 6c953bb..1596795 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1931,6 +1931,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sb->s_qcop = &ext3_qctl_operations;
sb->dq_op = &ext3_quota_operations;
#endif
+ memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
mutex_init(&sbi->s_orphan_lock);
mutex_init(&sbi->s_resize_lock);
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 10/11] vfs: Support null pathname in faccessat
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (8 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 09/11] ext3: Copy fs UUID to superblock Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
2010-06-03 16:08 ` [PATCH 11/11] vfs: Support null pathname in linkat Aneesh Kumar K.V
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
This enables to use faccessat to get the access check details
from a file descriptor pointing to the file. This can be used
with open_by_handle syscall that returns a file descriptor.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/open.c | 27 ++++++++++++++++++++-------
1 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/fs/open.c b/fs/open.c
index 3cff394..8998f2e 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -288,7 +288,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
{
const struct cred *old_cred;
struct cred *override_cred;
- struct path path;
+ struct file *file = NULL;
+ struct path path, *pp;
struct inode *inode;
int res;
@@ -312,12 +313,21 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
}
old_cred = override_creds(override_cred);
-
- res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
+ if (filename == NULL && dfd != AT_FDCWD) {
+ file = fget(dfd);
+ if (file) {
+ pp = &file->f_path;
+ res = 0;
+ } else
+ res = -EBADF;
+ } else {
+ res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
+ pp = &path;
+ }
if (res)
goto out;
- inode = path.dentry->d_inode;
+ inode = pp->dentry->d_inode;
if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
/*
@@ -325,7 +335,7 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
* with the "noexec" flag.
*/
res = -EACCES;
- if (path.mnt->mnt_flags & MNT_NOEXEC)
+ if (pp->mnt->mnt_flags & MNT_NOEXEC)
goto out_path_release;
}
@@ -343,11 +353,14 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
* inherently racy and know that the fs may change
* state before we even see this result.
*/
- if (__mnt_is_readonly(path.mnt))
+ if (__mnt_is_readonly(pp->mnt))
res = -EROFS;
out_path_release:
- path_put(&path);
+ if (file)
+ fput(file);
+ else
+ path_put(&path);
out:
revert_creds(old_cred);
put_cred(override_cred);
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 11/11] vfs: Support null pathname in linkat
2010-06-03 16:08 [PATCH -V13 0/11] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (9 preceding siblings ...)
2010-06-03 16:08 ` [PATCH 10/11] vfs: Support null pathname in faccessat Aneesh Kumar K.V
@ 2010-06-03 16:08 ` Aneesh Kumar K.V
10 siblings, 0 replies; 13+ messages in thread
From: Aneesh Kumar K.V @ 2010-06-03 16:08 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb, hooanon05, bfields
Cc: linux-fsdevel, sfrench, philippe.deniel, linux-kernel,
Aneesh Kumar K.V
This enables to use linkat to create hardlinks from a
file descriptor pointing to the file. This can be used
with open_by_handle syscall that returns a file descriptor.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/namei.c | 31 +++++++++++++++++++++++--------
1 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index 417bf53..8b1cc23 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2533,16 +2533,27 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
{
struct dentry *new_dentry;
struct nameidata nd;
- struct path old_path;
+ struct path old_path, *old_pathp;
+ struct file *file = NULL;
int error;
char *to;
if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
return -EINVAL;
- error = user_path_at(olddfd, oldname,
- flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
- &old_path);
+ if (oldname == NULL && olddfd != AT_FDCWD) {
+ file = fget(olddfd);
+ if (file) {
+ old_pathp = &file->f_path;
+ error = 0;
+ } else
+ error = -EBADF;
+ } else {
+ error = user_path_at(olddfd, oldname,
+ flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
+ &old_path);
+ old_pathp = &old_path;
+ }
if (error)
return error;
@@ -2550,7 +2561,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
if (error)
goto out;
error = -EXDEV;
- if (old_path.mnt != nd.path.mnt)
+ if (old_pathp->mnt != nd.path.mnt)
goto out_release;
new_dentry = lookup_create(&nd, 0);
error = PTR_ERR(new_dentry);
@@ -2559,10 +2570,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
error = mnt_want_write(nd.path.mnt);
if (error)
goto out_dput;
- error = security_path_link(old_path.dentry, &nd.path, new_dentry);
+ error = security_path_link(old_pathp->dentry, &nd.path, new_dentry);
if (error)
goto out_drop_write;
- error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
+ error = vfs_link(old_pathp->dentry,
+ nd.path.dentry->d_inode, new_dentry);
out_drop_write:
mnt_drop_write(nd.path.mnt);
out_dput:
@@ -2573,7 +2585,10 @@ out_release:
path_put(&nd.path);
putname(to);
out:
- path_put(&old_path);
+ if (file)
+ fput(file);
+ else
+ path_put(&old_path);
return error;
}
--
1.7.1.236.g81fa0
^ permalink raw reply related [flat|nested] 13+ messages in thread