* [PATCH -V6 0/8] Generic name to handle and open by handle syscalls
@ 2010-04-27 16:13 Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 1/8] exportfs: Return the minimum required handle size Aneesh Kumar K.V
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb; +Cc: linux-fsdevel, sfrench
Hi,
The below set of patches implement open by handle support using exportfs
operations. This allows user space application to map a file name to file
handle and later open the file using handle. This should be usable
for userspace NFS [1] and 9P server [2]. XFS already support this with the ioctls
XFS_IOC_PATH_TO_HANDLE and XFS_IOC_OPEN_BY_HANDLE.
[1] http://nfs-ganesha.sourceforge.net/
[2] http://lists.gnu.org/archive/html/qemu-devel/2010-03/msg01087.html
TODO:
I guess we would need to optimize how we get the vfsmount for the filesystem
uuid specified. Searching the file system list and task name space may be a big
overhead for each open by handle call.
Changes from V5:
a) added sys_name_to_handle_at syscall which takes AT_SYMLINK_NOFOLLOW flag
instead of two syscalls sys_name_to_handle and sys_lname_to_handle.
b) addressed review comments from Niel Brown
c) rebased to b91ce4d14a21fc04d165be30319541e0f9204f15
d) Add compat_sys_open_by_handle
Chages from V4:
a) Changed the syscal arguments so that we don't need compat syscalls
as suggested by Christoph
c) Added two new syscall sys_lname_to_handle and sys_freadlink to work with
symlinks
d) Changed open_by_handle to work with all file types
e) Add ext3 support
Changes from V3:
a) Code cleanup suggested by Andreas
b) x86_64 syscall support
c) add compat syscall
Chages from V2:
a) Support system wide unique handle.
Changes from v1:
a) handle size is now specified in bytes
b) returns -EOVERFLOW if the handle size is small
c) dropped open_handle syscall and added open_by_handle_at syscall
open_by_handle_at takes mount_fd as the directory fd of the mount point
containing the file
e) handle will only be unique in a given file system. So for an NFS server
exporting multiple file system, NFS server will have to internally track the
mount point to which a file handle belongs to. We should be able to do it much
easily than expecting kernel to give a system wide unique file handle. System
wide unique file handle would need much larger changes to the exportfs or VFS
interface and I was not sure whether we really need to do that in the kernel or
in the user space
f) open_handle_at now only check for DAC_OVERRIDE capability
Example program: (x86_32). (x86_64 would need a different syscall number)
----------------
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
struct uuid {
unsigned char uuid[16];
};
struct file_handle {
int handle_size;
int handle_type;
struct uuid fsid;
unsigned char handle[0];
};
#define AT_FDCWD -100
#define AT_SYMLINK_NOFOLLOW 0x100
static int name_to_handle(const char *name, struct file_handle *fh)
{
return syscall(338, AT_FDCWD, name, fh, 0);
}
static int lname_to_handle(const char *name, struct file_handle *fh)
{
return syscall(338, AT_FDCWD, name, fh, AT_SYMLINK_NOFOLLOW);
}
static int open_by_handle(struct file_handle *fh, int flags)
{
return syscall(339, fh, flags);
}
static int freadlink(int fd, char *buf, size_t bufsiz)
{
return syscall(340, fd, buf, bufsiz);
}
#define BUFSZ 100
int main(int argc, char *argv[])
{
int ret;
int handle_sz;
struct stat bufstat;
int fd, dirfd;
char buf[BUFSZ];
struct file_handle *fh = NULL;;
again:
if (fh && fh->handle_size) {
handle_sz = fh->handle_size;
free(fh);
fh = malloc(sizeof(struct file_handle) + handle_sz);
fh->handle_size = handle_sz;
} else {
fh = malloc(sizeof(struct file_handle));
fh->handle_size = 0;
}
errno = 0;
ret = lname_to_handle(argv[1], fh);
if (ret && errno == EOVERFLOW) {
perror("Error:");
printf("Found the handle size needed to be %d\n", fh->handle_size);
printf("Trying again..\n");
goto again;
} else if (ret) {
perror("Error:");
exit(1);
}
fd = open_by_handle(fh, O_RDONLY);
if (fd <= 0 ) {
perror("Error:");
exit(1);
}
fstat(fd, &bufstat);
ret = S_ISLNK(bufstat.st_mode);
if (ret) {
memset(buf, 0 , BUFSZ);
freadlink(fd, buf, BUFSZ);
printf("%s is a symlink pointing to %s\n", argv[1], buf);
}
memset(buf, 0 , BUFSZ);
while (1) {
ret = read(fd, buf, BUFSZ -1);
if (ret <= 0)
break;
buf[ret] = '\0';
printf("%s", buf);
memset(buf, 0 , BUFSZ);
}
return 0;
}
-aneesh
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH -V6 1/8] exportfs: Return the minimum required handle size
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 2/8] vfs: Add name to file handle conversion support Aneesh Kumar K.V
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, 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 +++-
mm/shmem.c | 4 +++-
11 files changed, 56 insertions(+), 15 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 0ce143b..6f83bc7 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -738,8 +738,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 c22c211..d022236 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 dc2c65e..5fff1e2 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 7581602..37ce713 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1360,8 +1360,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/mm/shmem.c b/mm/shmem.c
index eef4ebe..bbeda1c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2125,8 +2125,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.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH -V6 2/8] vfs: Add name to file handle conversion support
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 1/8] exportfs: Return the minimum required handle size Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 3/8] vfs: Add open by file handle support Aneesh Kumar K.V
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, 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/open.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 15 +++++++++
2 files changed, 105 insertions(+), 0 deletions(-)
diff --git a/fs/open.c b/fs/open.c
index 74e5cd9..5d0f87b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -30,6 +30,8 @@
#include <linux/falloc.h>
#include <linux/fs_struct.h>
#include <linux/ima.h>
+#include <linux/exportfs.h>
+#include <linux/mnt_namespace.h>
#include "internal.h"
@@ -1206,3 +1208,91 @@ int nonseekable_open(struct inode *inode, struct file *filp)
}
EXPORT_SYMBOL(nonseekable_open);
+
+/* 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)
+{
+ int retval;
+ int handle_size;
+ struct super_block *sb;
+ struct uuid this_fs_id;
+ struct file_handle f_handle;
+ struct file_handle *handle = NULL;
+
+ sb = path->mnt->mnt_sb;
+ if (!sb->s_op->get_fsid) {
+ retval = -ENOTSUPP;
+ goto err_out;
+ }
+ 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;
+ }
+ handle_size = f_handle.handle_size;
+
+ /* 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 */
+ retval = sb->s_op->get_fsid(sb, &this_fs_id);
+ if (!retval) {
+ memcpy(handle->fsid.uuid,
+ this_fs_id.uuid,
+ sizeof(handle->fsid.uuid));
+ }
+ } 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;
+}
+
+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_NOFOLLOW) != 0)
+ goto err_out;
+
+ follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
+ ret = user_path_at(dfd, name, follow, &path);
+ if (ret)
+ goto err_out;
+ ret = do_sys_name_to_handle(&path, handle);
+ path_put(&path);
+err_out:
+ /* avoid REGPARM breakage on x86: */
+ asmlinkage_protect(4, ret, dfd, name, handle, flag);
+ return ret;
+}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 44f35ae..055734c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -948,6 +948,20 @@ struct file {
unsigned long f_mnt_write_state;
#endif
};
+
+struct uuid {
+ unsigned char uuid[16];
+};
+
+struct file_handle {
+ int handle_size;
+ int handle_type;
+ /* File system identifier */
+ struct uuid fsid;
+ /* 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);
@@ -1580,6 +1594,7 @@ struct super_operations {
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
#endif
int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+ int (*get_fsid)(struct super_block *, struct uuid *);
};
/*
--
1.7.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH -V6 3/8] vfs: Add open by file handle support
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 1/8] exportfs: Return the minimum required handle size Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 2/8] vfs: Add name to file handle conversion support Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 4/8] vfs: Add freadlink syscall Aneesh Kumar K.V
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, 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/filesystems.c | 33 +++++++++-
fs/namei.c | 24 -------
fs/namespace.c | 38 +++++++++++
fs/open.c | 142 +++++++++++++++++++++++++++++++++++++++++
fs/pnode.c | 2 +-
include/linux/fs.h | 1 +
include/linux/mnt_namespace.h | 2 +
include/linux/namei.h | 24 +++++++
8 files changed, 240 insertions(+), 26 deletions(-)
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 68ba492..a424691 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -281,5 +281,36 @@ struct file_system_type *get_fs_type(const char *name)
}
return fs;
}
-
EXPORT_SYMBOL(get_fs_type);
+
+struct super_block *fs_get_sb(struct uuid *fsid)
+{
+ int error;
+ struct uuid this_fsid;
+ struct file_system_type *fs_type;
+ struct super_block *sb, *found_sb = NULL;
+
+ read_lock(&file_systems_lock);
+ for (fs_type = file_systems; fs_type; fs_type = fs_type->next) {
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &fs_type->fs_supers, s_instances) {
+ if (!sb->s_op->get_fsid)
+ continue;
+ error = sb->s_op->get_fsid(sb, &this_fsid);
+ if (error)
+ continue;
+ if (!memcmp(fsid->uuid, this_fsid.uuid,
+ sizeof(this_fsid.uuid))) {
+ /* found the matching super_block */
+ atomic_inc(&sb->s_active);
+ found_sb = sb;
+ spin_unlock(&sb_lock);
+ goto out;
+ }
+ }
+ spin_unlock(&sb_lock);
+ }
+out:
+ read_unlock(&file_systems_lock);
+ return found_sb;
+}
diff --git a/fs/namei.c b/fs/namei.c
index a7dce91..a18711e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1521,30 +1521,6 @@ out_unlock:
return may_open(&nd->path, 0, open_flag & ~O_TRUNC);
}
-/*
- * Note that while the flag value (low two bits) for sys_open means:
- * 00 - read-only
- * 01 - write-only
- * 10 - read-write
- * 11 - special
- * it is changed into
- * 00 - no permissions needed
- * 01 - read-permission
- * 10 - write-permission
- * 11 - read-write
- * for the internal routines (ie open_namei()/follow_link() etc)
- * This is more logical, and also allows the 00 "no perm needed"
- * to be used for symlinks (where the permissions are checked
- * later).
- *
-*/
-static inline int open_to_namei_flags(int flag)
-{
- if ((flag+1) & O_ACCMODE)
- flag++;
- return flag;
-}
-
static int open_will_truncate(int flag, struct inode *inode)
{
/*
diff --git a/fs/namespace.c b/fs/namespace.c
index 8174c8a..6168526 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2364,3 +2364,41 @@ void put_mnt_ns(struct mnt_namespace *ns)
kfree(ns);
}
EXPORT_SYMBOL(put_mnt_ns);
+
+/*
+ * Get any vfsmount mapping the superblock in the
+ * task namespace
+ */
+struct vfsmount *fs_get_vfsmount(struct task_struct *task,
+ struct super_block *sb)
+{
+ struct nsproxy *nsp;
+ struct list_head *mount_list;
+ struct mnt_namespace *ns = NULL;
+ struct vfsmount *mnt, *sb_mnt = NULL;
+
+ rcu_read_lock();
+ nsp = task_nsproxy(task);
+ if (nsp) {
+ ns = nsp->mnt_ns;
+ if (ns)
+ get_mnt_ns(ns);
+ }
+ rcu_read_unlock();
+ if (!ns)
+ return NULL;
+ down_read(&namespace_sem);
+ list_for_each(mount_list, &ns->list) {
+ mnt = list_entry(mount_list, struct vfsmount, mnt_list);
+ if (mnt->mnt_sb == sb) {
+ /* found the matching super block */
+ sb_mnt = mnt;
+ mntget(sb_mnt);
+ break;
+ }
+ }
+ up_read(&namespace_sem);
+
+ put_mnt_ns(ns);
+ return sb_mnt;
+}
diff --git a/fs/open.c b/fs/open.c
index 5d0f87b..e0a0cb1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1296,3 +1296,145 @@ err_out:
asmlinkage_protect(4, ret, dfd, name, handle, flag);
return ret;
}
+
+static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
+{
+ return 1;
+}
+
+static struct dentry *handle_to_dentry(struct vfsmount *mnt,
+ struct file_handle *handle)
+{
+ int handle_size;
+ struct dentry *dentry;
+
+ /* change the handle size to multiple of sizeof(u32) */
+ handle_size = handle->handle_size >> 2;
+ dentry = exportfs_decode_fh(mnt, (struct fid *)handle->f_handle,
+ handle_size, handle->handle_type,
+ vfs_dentry_acceptable, NULL);
+ return dentry;
+}
+
+static long do_sys_open_by_handle(struct file_handle __user *ufh, int flags)
+{
+ int fd;
+ int retval = 0;
+ int d_flags = flags;
+ struct file *filp;
+ struct vfsmount *mnt;
+ struct inode *inode;
+ struct dentry *dentry;
+ 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 out_err;
+ }
+ if ((f_handle.handle_size > MAX_HANDLE_SZ) ||
+ (f_handle.handle_size <= 0)) {
+ retval = -EINVAL;
+ goto out_err;
+ }
+ if (!capable(CAP_DAC_OVERRIDE)) {
+ retval = -EPERM;
+ goto out_err;
+ }
+ sb = fs_get_sb(&f_handle.fsid);
+ if (!sb)
+ return -ESTALE;
+ /*
+ * Find the vfsmount for this superblock in the
+ * current namespace
+ */
+ mnt = fs_get_vfsmount(current, sb);
+ if (!mnt) {
+ retval = -ESTALE;
+ goto out_sb;
+ }
+
+ handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_size,
+ GFP_KERNEL);
+ if (!handle) {
+ retval = -ENOMEM;
+ goto out_mnt;
+ }
+ /* copy the full handle */
+ if (copy_from_user(handle, ufh,
+ sizeof(struct file_handle) +
+ f_handle.handle_size)) {
+ retval = -EFAULT;
+ goto out_mnt;
+ }
+ dentry = handle_to_dentry(mnt, handle);
+ if (IS_ERR(dentry)) {
+ retval = PTR_ERR(dentry);
+ goto out_mnt;
+ }
+ inode = dentry->d_inode;
+ flags = open_to_namei_flags(flags);
+ /* O_TRUNC implies we need access checks for write permissions */
+ if (flags & O_TRUNC)
+ flags |= MAY_WRITE;
+
+ if ((!(flags & O_APPEND) || (flags & O_TRUNC)) &&
+ (flags & FMODE_WRITE) && IS_APPEND(inode)) {
+ retval = -EPERM;
+ goto out_dentry;
+ }
+ if ((flags & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
+ retval = -EACCES;
+ goto out_dentry;
+ }
+ /* Can't write directories. */
+ if (S_ISDIR(inode->i_mode) && (flags & FMODE_WRITE)) {
+ retval = -EISDIR;
+ goto out_dentry;
+ }
+ fd = get_unused_fd_flags(d_flags);
+ if (fd < 0) {
+ retval = fd;
+ goto out_dentry;
+ }
+ filp = dentry_open(dget(dentry), mntget(mnt),
+ d_flags, current_cred());
+ if (IS_ERR(filp)) {
+ put_unused_fd(fd);
+ retval = PTR_ERR(filp);
+ goto out_dentry;
+ }
+ if (inode->i_mode & S_IFREG) {
+ filp->f_flags |= O_NOATIME;
+ filp->f_mode |= FMODE_NOCMTIME;
+ }
+ fsnotify_open(filp->f_path.dentry);
+ fd_install(fd, filp);
+ retval = fd;
+
+out_dentry:
+ dput(dentry);
+out_mnt:
+ kfree(handle);
+ mntput(mnt);
+out_sb:
+ deactivate_super(sb);
+out_err:
+ return retval;
+}
+
+SYSCALL_DEFINE2(open_by_handle, struct file_handle __user *, handle,
+ int, flags)
+{
+ long ret;
+
+ if (force_o_largefile())
+ flags |= O_LARGEFILE;
+
+ ret = do_sys_open_by_handle(handle, flags);
+
+ /* avoid REGPARM breakage on x86: */
+ asmlinkage_protect(2, ret, handle, flags);
+ return ret;
+}
diff --git a/fs/pnode.c b/fs/pnode.c
index 5cc564a..9f6d12d 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -6,9 +6,9 @@
* Author : Ram Pai (linuxram@us.ibm.com)
*
*/
+#include <linux/fs.h>
#include <linux/mnt_namespace.h>
#include <linux/mount.h>
-#include <linux/fs.h>
#include "internal.h"
#include "pnode.h"
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 055734c..da6d297 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2344,6 +2344,7 @@ extern struct super_block *get_super(struct block_device *);
extern struct super_block *get_active_super(struct block_device *bdev);
extern struct super_block *user_get_super(dev_t);
extern void drop_super(struct super_block *sb);
+extern struct super_block *fs_get_sb(struct uuid *fsid);
extern int dcache_dir_open(struct inode *, struct file *);
extern int dcache_dir_close(struct inode *, struct file *);
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 0b89efc..d363ecc 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -36,6 +36,8 @@ extern const struct seq_operations mounts_op;
extern const struct seq_operations mountinfo_op;
extern const struct seq_operations mountstats_op;
extern int mnt_had_events(struct proc_mounts *);
+extern struct vfsmount *fs_get_vfsmount(struct task_struct *task,
+ struct super_block *sb);
#endif
#endif
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 05b441d..a853aa0 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -4,6 +4,7 @@
#include <linux/dcache.h>
#include <linux/linkage.h>
#include <linux/path.h>
+#include <asm-generic/fcntl.h>
struct vfsmount;
@@ -96,4 +97,27 @@ static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
((char *) name)[min(len, maxlen)] = '\0';
}
+/*
+ * Note that while the flag value (low two bits) for sys_open means:
+ * 00 - read-only
+ * 01 - write-only
+ * 10 - read-write
+ * 11 - special
+ * it is changed into
+ * 00 - no permissions needed
+ * 01 - read-permission
+ * 10 - write-permission
+ * 11 - read-write
+ * for the internal routines (ie open_namei()/follow_link() etc)
+ * This is more logical, and also allows the 00 "no perm needed"
+ * to be used for symlinks (where the permissions are checked
+ * later).
+ *
+*/
+static inline int open_to_namei_flags(int flag)
+{
+ if ((flag+1) & O_ACCMODE)
+ flag++;
+ return flag;
+}
#endif /* _LINUX_NAMEI_H */
--
1.7.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH -V6 4/8] vfs: Add freadlink syscall
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (2 preceding siblings ...)
2010-04-27 16:13 ` [PATCH -V6 3/8] vfs: Add open by file handle support Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 5/8] ext4: Add get_fsid callback Aneesh Kumar K.V
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, Aneesh Kumar K.V
This enables to use open-by-handle and then get the link target
details of a symlink using the fd returned by handle
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/stat.c | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/fs/stat.c b/fs/stat.c
index c4ecd52..0fbab00 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -314,6 +314,33 @@ SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
}
+SYSCALL_DEFINE3(freadlink, int, fd, char __user *, buf,
+ int, bufsiz)
+{
+ int fput_needed;
+ struct file *file;
+ int error = -EBADF;
+ struct inode *inode;
+
+ file = fget_light(fd, &fput_needed);
+ if (!file)
+ return error;
+
+ inode = file->f_path.dentry->d_inode;
+ error = -EINVAL;
+ if (inode->i_op->readlink) {
+ error = security_inode_readlink(file->f_path.dentry);
+ if (!error) {
+ touch_atime(file->f_path.mnt, file->f_path.dentry);
+ error = inode->i_op->readlink(file->f_path.dentry,
+ buf, bufsiz);
+ }
+ }
+ fput_light(file, fput_needed);
+ return error;
+}
+
+
/* ---------- LFS-64 ----------- */
#ifdef __ARCH_WANT_STAT64
--
1.7.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH -V6 5/8] ext4: Add get_fsid callback
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (3 preceding siblings ...)
2010-04-27 16:13 ` [PATCH -V6 4/8] vfs: Add freadlink syscall Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 6/8] x86: Add new syscalls for x86_32 Aneesh Kumar K.V
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, 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/ext4/super.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e14d22c..fc7d464 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1049,6 +1049,19 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
return try_to_free_buffers(page);
}
+static int ext4_get_fsid(struct super_block *sb, struct uuid *fsid)
+{
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ struct ext4_super_block *es = sbi->s_es;
+
+ memcpy(fsid->uuid, es->s_uuid, sizeof(fsid->uuid));
+ /*
+ * We may want to make sure we return error if the s_uuid is not
+ * exactly unique
+ */
+ return 0;
+}
+
#ifdef CONFIG_QUOTA
#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
@@ -1109,6 +1122,7 @@ static const struct super_operations ext4_sops = {
.quota_write = ext4_quota_write,
#endif
.bdev_try_to_free_page = bdev_try_to_free_page,
+ .get_fsid = ext4_get_fsid,
};
static const struct super_operations ext4_nojournal_sops = {
@@ -1128,6 +1142,7 @@ static const struct super_operations ext4_nojournal_sops = {
.quota_write = ext4_quota_write,
#endif
.bdev_try_to_free_page = bdev_try_to_free_page,
+ .get_fsid = ext4_get_fsid,
};
static const struct export_operations ext4_export_ops = {
--
1.7.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH -V6 6/8] x86: Add new syscalls for x86_32
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (4 preceding siblings ...)
2010-04-27 16:13 ` [PATCH -V6 5/8] ext4: Add get_fsid callback Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 16:45 ` Aneesh Kumar K. V
2010-04-27 16:13 ` [PATCH -V6 7/8] x86: Add new syscalls for x86_64 Aneesh Kumar K.V
` (2 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, Aneesh Kumar K.V
This patch adds sys_name_to_handle, sys_lname_to_handle, sys_open_by_handle
and sys_freadlink 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 | 5 ++++-
arch/x86/kernel/syscall_table_32.S | 3 +++
2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index beb9b5f..a78505c 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -343,10 +343,13 @@
#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 339
+#define __NR_freadlink 340
#ifdef __KERNEL__
-#define NR_syscalls 338
+#define NR_syscalls 341
#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..64b8d5d 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -337,3 +337,6 @@ 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
+ .long sys_freadlink /* 340 */
--
1.7.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH -V6 7/8] x86: Add new syscalls for x86_64
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (5 preceding siblings ...)
2010-04-27 16:13 ` [PATCH -V6 6/8] x86: Add new syscalls for x86_32 Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 8/8] ext3: Add get_fsid callback Aneesh Kumar K.V
2010-04-27 21:13 ` [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Andreas Dilger
8 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, Aneesh Kumar K.V
Add sys_name_to_handle, sys_lname_to_handle, sys_open_by_handle syscall
and sys_freadlink for x86_64
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/x86/ia32/ia32entry.S | 3 +++
arch/x86/include/asm/unistd_64.h | 6 ++++++
fs/compat.c | 10 ++++++++++
fs/open.c | 2 +-
include/linux/fs.h | 1 +
5 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index e790bc1..2f4c979 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -842,4 +842,7 @@ 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
+ .quad sys_freadlink /* 340 */
ia32_syscall_end:
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index ff4307b..c32428d 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -663,6 +663,12 @@ __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, sys_name_to_handle)
+#define __NR_open_by_handle 301
+__SYSCALL(__NR_open_by_handle, sys_open_by_handle)
+#define __NR_freadlink 302
+__SYSCALL(__NR_freadlink, sys_freadlink)
#ifndef __NO_STUBS
#define __ARCH_WANT_OLD_READDIR
diff --git a/fs/compat.c b/fs/compat.c
index 4b6ed03..5c71c98 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -2310,3 +2310,13 @@ asmlinkage long compat_sys_timerfd_gettime(int ufd,
}
#endif /* CONFIG_TIMERFD */
+
+/*
+ * Exactly like fs/open.c:sys_open_by_handle(), except that it doesn't set the
+ * O_LARGEFILE flag.
+ */
+asmlinkage long
+compat_sys_open_by_handle(struct file_handle __user *handle, int flags)
+{
+ return do_sys_open_by_handle(handle, flags);
+}
diff --git a/fs/open.c b/fs/open.c
index e0a0cb1..9b114cd 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1316,7 +1316,7 @@ static struct dentry *handle_to_dentry(struct vfsmount *mnt,
return dentry;
}
-static long do_sys_open_by_handle(struct file_handle __user *ufh, int flags)
+long do_sys_open_by_handle(struct file_handle __user *ufh, int flags)
{
int fd;
int retval = 0;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index da6d297..d1c2051 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1933,6 +1933,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(struct file_handle __user *, int);
/* fs/ioctl.c */
--
1.7.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH -V6 8/8] ext3: Add get_fsid callback
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (6 preceding siblings ...)
2010-04-27 16:13 ` [PATCH -V6 7/8] x86: Add new syscalls for x86_64 Aneesh Kumar K.V
@ 2010-04-27 16:13 ` Aneesh Kumar K.V
2010-04-27 21:13 ` [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Andreas Dilger
8 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K.V @ 2010-04-27 16:13 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb
Cc: linux-fsdevel, sfrench, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/ext3/super.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 1bee604..63c322e 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -734,6 +734,15 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
return try_to_free_buffers(page);
}
+static int ext3_get_fsid(struct super_block *sb, struct uuid *fsid)
+{
+ struct ext3_sb_info *sbi = EXT3_SB(sb);
+ struct ext3_super_block *es = sbi->s_es;
+
+ memcpy(fsid->uuid, es->s_uuid, sizeof(fsid->uuid));
+ return 0;
+}
+
#ifdef CONFIG_QUOTA
#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
#define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
@@ -791,6 +800,7 @@ static const struct super_operations ext3_sops = {
.quota_write = ext3_quota_write,
#endif
.bdev_try_to_free_page = bdev_try_to_free_page,
+ .get_fsid = ext3_get_fsid,
};
static const struct export_operations ext3_export_ops = {
--
1.7.0.4.360.g11766c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH -V6 6/8] x86: Add new syscalls for x86_32
2010-04-27 16:13 ` [PATCH -V6 6/8] x86: Add new syscalls for x86_32 Aneesh Kumar K.V
@ 2010-04-27 16:45 ` Aneesh Kumar K. V
0 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K. V @ 2010-04-27 16:45 UTC (permalink / raw)
To: hch, viro, adilger, corbet, serue, neilb; +Cc: linux-fsdevel, sfrench
On Tue, 27 Apr 2010 21:43:48 +0530, "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:
> This patch adds sys_name_to_handle, sys_lname_to_handle, sys_open_by_handle
> and sys_freadlink syscalls to x86_32
That should be sys_name_to_handle_at, sys_open_by_handle and
sys_freadlink.
-aneesh
>
> 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 | 5 ++++-
> arch/x86/kernel/syscall_table_32.S | 3 +++
> 2 files changed, 7 insertions(+), 1 deletions(-)
>
> diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
> index beb9b5f..a78505c 100644
> --- a/arch/x86/include/asm/unistd_32.h
> +++ b/arch/x86/include/asm/unistd_32.h
> @@ -343,10 +343,13 @@
> #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 339
> +#define __NR_freadlink 340
>
> #ifdef __KERNEL__
>
> -#define NR_syscalls 338
> +#define NR_syscalls 341
>
> #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..64b8d5d 100644
> --- a/arch/x86/kernel/syscall_table_32.S
> +++ b/arch/x86/kernel/syscall_table_32.S
> @@ -337,3 +337,6 @@ 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
> + .long sys_freadlink /* 340 */
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH -V6 0/8] Generic name to handle and open by handle syscalls
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
` (7 preceding siblings ...)
2010-04-27 16:13 ` [PATCH -V6 8/8] ext3: Add get_fsid callback Aneesh Kumar K.V
@ 2010-04-27 21:13 ` Andreas Dilger
2010-04-28 5:09 ` Aneesh Kumar K. V
8 siblings, 1 reply; 12+ messages in thread
From: Andreas Dilger @ 2010-04-27 21:13 UTC (permalink / raw)
To: Aneesh Kumar K.V
Cc: hch, viro, adilger, corbet, serue, neilb, linux-fsdevel, sfrench
On 2010-04-27, at 10:13, Aneesh Kumar K.V wrote:
> Changes from V5:
> a) added sys_name_to_handle_at syscall which takes AT_SYMLINK_NOFOLLOW flag
> instead of two syscalls sys_name_to_handle and sys_lname_to_handle.
>
> #define AT_FDCWD -100
> #define AT_SYMLINK_NOFOLLOW 0x100
>
> static int name_to_handle(const char *name, struct file_handle *fh)
> {
> return syscall(338, AT_FDCWD, name, fh, 0);
> }
>
> static int lname_to_handle(const char *name, struct file_handle *fh)
> {
> return syscall(338, AT_FDCWD, name, fh, AT_SYMLINK_NOFOLLOW);
> }
>
> static int open_by_handle(struct file_handle *fh, int flags)
> {
> return syscall(339, fh, flags);
> }
>
> static int freadlink(int fd, char *buf, size_t bufsiz)
> {
> return syscall(340, fd, buf, bufsiz);
> }
Your example, while #defining the AT_* stuff, did not actually change to use the _at() interface.
> #define BUFSZ 100
> int main(int argc, char *argv[])
> {
> int ret;
> int handle_sz;
> struct stat bufstat;
> int fd, dirfd;
> char buf[BUFSZ];
> struct file_handle *fh = NULL;;
> again:
> if (fh && fh->handle_size) {
> handle_sz = fh->handle_size;
> free(fh);
> fh = malloc(sizeof(struct file_handle) + handle_sz);
> fh->handle_size = handle_sz;
> } else {
> fh = malloc(sizeof(struct file_handle));
> fh->handle_size = 0;
> }
> errno = 0;
> ret = lname_to_handle(argv[1], fh);
> if (ret && errno == EOVERFLOW) {
> perror("Error:");
> printf("Found the handle size needed to be %d\n", fh->handle_size);
> printf("Trying again..\n");
> goto again;
> } else if (ret) {
> perror("Error:");
> exit(1);
> }
> fd = open_by_handle(fh, O_RDONLY);
> if (fd <= 0 ) {
> perror("Error:");
> exit(1);
> }
> fstat(fd, &bufstat);
> ret = S_ISLNK(bufstat.st_mode);
> if (ret) {
> memset(buf, 0 , BUFSZ);
> freadlink(fd, buf, BUFSZ);
> printf("%s is a symlink pointing to %s\n", argv[1], buf);
> }
> memset(buf, 0 , BUFSZ);
> while (1) {
> ret = read(fd, buf, BUFSZ -1);
> if (ret <= 0)
> break;
> buf[ret] = '\0';
> printf("%s", buf);
> memset(buf, 0 , BUFSZ);
> }
> return 0;
> }
Cheers, Andreas
--
Andreas Dilger
Lustre Technical Lead
Oracle Corporation Canada Inc.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH -V6 0/8] Generic name to handle and open by handle syscalls
2010-04-27 21:13 ` [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Andreas Dilger
@ 2010-04-28 5:09 ` Aneesh Kumar K. V
0 siblings, 0 replies; 12+ messages in thread
From: Aneesh Kumar K. V @ 2010-04-28 5:09 UTC (permalink / raw)
To: Andreas Dilger
Cc: hch, viro, adilger, corbet, serue, neilb, linux-fsdevel, sfrench
On Tue, 27 Apr 2010 15:13:20 -0600, Andreas Dilger <andreas.dilger@oracle.com> wrote:
>
> On 2010-04-27, at 10:13, Aneesh Kumar K.V wrote:
> > Changes from V5:
> > a) added sys_name_to_handle_at syscall which takes AT_SYMLINK_NOFOLLOW flag
> > instead of two syscalls sys_name_to_handle and sys_lname_to_handle.
> >
> > #define AT_FDCWD -100
> > #define AT_SYMLINK_NOFOLLOW 0x100
> >
> > static int name_to_handle(const char *name, struct file_handle *fh)
> > {
> > return syscall(338, AT_FDCWD, name, fh, 0);
> > }
> >
> > static int lname_to_handle(const char *name, struct file_handle *fh)
> > {
> > return syscall(338, AT_FDCWD, name, fh, AT_SYMLINK_NOFOLLOW);
> > }
> >
> > static int open_by_handle(struct file_handle *fh, int flags)
> > {
> > return syscall(339, fh, flags);
> > }
> >
> > static int freadlink(int fd, char *buf, size_t bufsiz)
> > {
> > return syscall(340, fd, buf, bufsiz);
> > }
>
> Your example, while #defining the AT_* stuff, did not actually change to use the _at() interface.
>
I retained the name name_to_handle and lname_to_handle in the example
but used the same syscall number for both with right flags. So it
should be using syscall sys_name_to_handle_at
-aneesh
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2010-04-28 5:10 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-27 16:13 [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 1/8] exportfs: Return the minimum required handle size Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 2/8] vfs: Add name to file handle conversion support Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 3/8] vfs: Add open by file handle support Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 4/8] vfs: Add freadlink syscall Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 5/8] ext4: Add get_fsid callback Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 6/8] x86: Add new syscalls for x86_32 Aneesh Kumar K.V
2010-04-27 16:45 ` Aneesh Kumar K. V
2010-04-27 16:13 ` [PATCH -V6 7/8] x86: Add new syscalls for x86_64 Aneesh Kumar K.V
2010-04-27 16:13 ` [PATCH -V6 8/8] ext3: Add get_fsid callback Aneesh Kumar K.V
2010-04-27 21:13 ` [PATCH -V6 0/8] Generic name to handle and open by handle syscalls Andreas Dilger
2010-04-28 5:09 ` Aneesh Kumar K. V
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.