* [patch 0/5] VFS changes
@ 2007-09-21 12:23 Miklos Szeredi
2007-09-21 12:23 ` [patch 1/5] VFS: pass open file to ->setattr() Miklos Szeredi
` (4 more replies)
0 siblings, 5 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 12:23 UTC (permalink / raw)
To: akpm; +Cc: hch, linux-kernel, linux-fsdevel
Hi,
Here's a bunch a VFS interface changes that are needed to implement
some FUSE features.
The biggest part is patches 1-3, which pass the open file to the
filesystem for syscalls passed an file descriptor, such as fstat(),
fchmod(), etc... These patches touch a lot of filesystems, but
otherwise quite simple and actually source and binary backward
compatible.
Christoph, can you please take a quick look at the patches, if the
interface changes are OK?
Thanks,
Miklos
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [patch 1/5] VFS: pass open file to ->setattr()
2007-09-21 12:23 [patch 0/5] VFS changes Miklos Szeredi
@ 2007-09-21 12:23 ` Miklos Szeredi
2007-09-21 12:23 ` [patch 2/5] VFS: pass open file to ->getattr() Miklos Szeredi
` (3 subsequent siblings)
4 siblings, 0 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 12:23 UTC (permalink / raw)
To: akpm; +Cc: hch, linux-kernel, linux-fsdevel
[-- Attachment #1: vfs_setattr_file.patch --]
[-- Type: text/plain, Size: 3340 bytes --]
From: Miklos Szeredi <mszeredi@suse.cz>
Pass the open file into the filesystem's ->setattr() method for
fchmod, fchown and some of the utimes variants.
This is needed to be able to correctly implement open-unlink-fsetattr
semantics in some filesystem such as sshfs, without having to resort
to "silly-renaming".
The infrastructure is already there, so just need to fill in
attrs.ia_file and set ATTR_FILE in attrs.ia_valid.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
Index: linux/fs/open.c
===================================================================
--- linux.orig/fs/open.c 2007-09-21 13:44:57.000000000 +0200
+++ linux/fs/open.c 2007-09-21 13:45:04.000000000 +0200
@@ -581,7 +581,8 @@ asmlinkage long sys_fchmod(unsigned int
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
+ newattrs.ia_file = file;
err = notify_change(dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
@@ -631,7 +632,8 @@ asmlinkage long sys_chmod(const char __u
return sys_fchmodat(AT_FDCWD, filename, mode);
}
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+static int chown_common(struct dentry * dentry, uid_t user, gid_t group,
+ struct file *file)
{
struct inode * inode;
int error;
@@ -660,6 +662,10 @@ static int chown_common(struct dentry *
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |=
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+ if (file) {
+ newattrs.ia_file = file;
+ newattrs.ia_valid |= ATTR_FILE;
+ }
mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
@@ -675,7 +681,7 @@ asmlinkage long sys_chown(const char __u
error = user_path_walk(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, user, group);
+ error = chown_common(nd.dentry, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -695,7 +701,7 @@ asmlinkage long sys_fchownat(int dfd, co
error = __user_walk_fd(dfd, filename, follow, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, user, group);
+ error = chown_common(nd.dentry, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -709,7 +715,7 @@ asmlinkage long sys_lchown(const char __
error = user_path_walk_link(filename, &nd);
if (error)
goto out;
- error = chown_common(nd.dentry, user, group);
+ error = chown_common(nd.dentry, user, group, NULL);
path_release(&nd);
out:
return error;
@@ -728,7 +734,7 @@ asmlinkage long sys_fchown(unsigned int
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
- error = chown_common(dentry, user, group);
+ error = chown_common(dentry, user, group, file);
fput(file);
out:
return error;
Index: linux/fs/utimes.c
===================================================================
--- linux.orig/fs/utimes.c 2007-09-21 13:44:57.000000000 +0200
+++ linux/fs/utimes.c 2007-09-21 13:45:04.000000000 +0200
@@ -130,6 +130,10 @@ long do_utimes(int dfd, char __user *fil
}
}
}
+ if (f) {
+ newattrs.ia_file = f;
+ newattrs.ia_valid |= ATTR_FILE;
+ }
mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [patch 2/5] VFS: pass open file to ->getattr()
2007-09-21 12:23 [patch 0/5] VFS changes Miklos Szeredi
2007-09-21 12:23 ` [patch 1/5] VFS: pass open file to ->setattr() Miklos Szeredi
@ 2007-09-21 12:23 ` Miklos Szeredi
2007-09-21 18:37 ` Andreas Dilger
2007-09-21 12:23 ` [patch 3/5] VFS: pass open file to ->xattr() Miklos Szeredi
` (2 subsequent siblings)
4 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 12:23 UTC (permalink / raw)
To: akpm; +Cc: hch, linux-kernel, linux-fsdevel
[-- Attachment #1: vfs_getattr_file.patch --]
[-- Type: text/plain, Size: 24679 bytes --]
From: Miklos Szeredi <mszeredi@suse.cz>
Pass the open file into the filesystem's ->getattr() method for
fstat().
This is needed to be able to correctly implement open-unlink-fstat
semantics in some filesystem such as sshfs, without having to resort
to "silly-renaming".
Do this by adding a 'struct file *' parameter to i_op->getattr(). For
fstat() pass the open file pointer, in other cases pass NULL.
This is safe from a compatibility standpoint, out-of-tree old stuff
will continue to work, but will get a warning at compile time.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
Index: linux/fs/9p/vfs_inode.c
===================================================================
--- linux.orig/fs/9p/vfs_inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/9p/vfs_inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -706,7 +706,7 @@ done:
static int
v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
int err;
struct v9fs_session_info *v9ses;
@@ -717,7 +717,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, s
err = -EPERM;
v9ses = v9fs_inode2v9ses(dentry->d_inode);
if (v9ses->cache == CACHE_LOOSE)
- return simple_getattr(mnt, dentry, stat);
+ return simple_getattr(mnt, dentry, stat, file);
fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid))
Index: linux/fs/afs/inode.c
===================================================================
--- linux.orig/fs/afs/inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/afs/inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -295,7 +295,7 @@ error_unlock:
* read the attributes of an inode
*/
int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
struct inode *inode;
Index: linux/fs/afs/internal.h
===================================================================
--- linux.orig/fs/afs/internal.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/afs/internal.h 2007-09-21 14:08:40.000000000 +0200
@@ -548,7 +548,8 @@ extern struct inode *afs_iget(struct sup
struct afs_callback *);
extern void afs_zap_data(struct afs_vnode *);
extern int afs_validate(struct afs_vnode *, struct key *);
-extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
extern int afs_setattr(struct dentry *, struct iattr *);
extern void afs_clear_inode(struct inode *);
Index: linux/fs/bad_inode.c
===================================================================
--- linux.orig/fs/bad_inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/bad_inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -250,7 +250,7 @@ static int bad_inode_permission(struct i
}
static int bad_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
return -EIO;
}
Index: linux/fs/cifs/cifsfs.h
===================================================================
--- linux.orig/fs/cifs/cifsfs.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/cifs/cifsfs.h 2007-09-21 14:08:40.000000000 +0200
@@ -55,7 +55,8 @@ extern int cifs_rmdir(struct inode *, st
extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
struct dentry *);
extern int cifs_revalidate(struct dentry *);
-extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
extern int cifs_setattr(struct dentry *, struct iattr *);
extern const struct inode_operations cifs_file_inode_ops;
Index: linux/fs/cifs/inode.c
===================================================================
--- linux.orig/fs/cifs/inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/cifs/inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -1340,7 +1340,7 @@ int cifs_revalidate(struct dentry *diren
}
int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
int err = cifs_revalidate(dentry);
if (!err) {
Index: linux/fs/coda/inode.c
===================================================================
--- linux.orig/fs/coda/inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/coda/inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -220,7 +220,8 @@ static void coda_clear_inode(struct inod
coda_cache_clear_inode(inode);
}
-int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int coda_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
int err = coda_revalidate_inode(dentry);
if (!err)
Index: linux/fs/fat/file.c
===================================================================
--- linux.orig/fs/fat/file.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/fat/file.c 2007-09-21 14:08:40.000000000 +0200
@@ -303,7 +303,8 @@ void fat_truncate(struct inode *inode)
fat_flush_inodes(inode->i_sb, inode, NULL);
}
-int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
generic_fillattr(inode, stat);
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2007-09-21 14:08:26.000000000 +0200
+++ linux/fs/fuse/dir.c 2007-09-21 14:08:40.000000000 +0200
@@ -1056,7 +1056,7 @@ static int fuse_setattr(struct dentry *e
}
static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_inode *fi = get_fuse_inode(inode);
Index: linux/fs/gfs2/ops_inode.c
===================================================================
--- linux.orig/fs/gfs2/ops_inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/gfs2/ops_inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -1041,7 +1041,7 @@ out:
*/
static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct gfs2_inode *ip = GFS2_I(inode);
Index: linux/fs/libfs.c
===================================================================
--- linux.orig/fs/libfs.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/libfs.c 2007-09-21 14:08:40.000000000 +0200
@@ -12,7 +12,7 @@
#include <asm/uaccess.h>
int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
generic_fillattr(inode, stat);
Index: linux/fs/nfs/inode.c
===================================================================
--- linux.orig/fs/nfs/inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/nfs/inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -423,7 +423,8 @@ static void nfs_wake_up_inode(struct ino
wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING);
}
-int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
Index: linux/fs/ocfs2/file.c
===================================================================
--- linux.orig/fs/ocfs2/file.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/ocfs2/file.c 2007-09-21 14:08:40.000000000 +0200
@@ -1073,7 +1073,8 @@ bail:
int ocfs2_getattr(struct vfsmount *mnt,
struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = dentry->d_inode->i_sb;
Index: linux/fs/ocfs2/file.h
===================================================================
--- linux.orig/fs/ocfs2/file.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/ocfs2/file.h 2007-09-21 14:08:40.000000000 +0200
@@ -55,7 +55,7 @@ int ocfs2_lock_allocators(struct inode *
struct ocfs2_alloc_context **meta_ac);
int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat);
+ struct kstat *stat, struct file *file);
int ocfs2_permission(struct inode *inode, int mask,
struct nameidata *nd);
Index: linux/fs/proc/base.c
===================================================================
--- linux.orig/fs/proc/base.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/proc/base.c 2007-09-21 14:08:40.000000000 +0200
@@ -1109,7 +1109,8 @@ out_unlock:
return NULL;
}
-static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct task_struct *task;
@@ -2703,7 +2704,8 @@ out_no_task:
return retval;
}
-static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct task_struct *p = get_proc_task(inode);
Index: linux/fs/proc/generic.c
===================================================================
--- linux.orig/fs/proc/generic.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/proc/generic.c 2007-09-21 14:08:40.000000000 +0200
@@ -255,7 +255,7 @@ out:
}
static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct proc_dir_entry *de = PROC_I(inode)->pde;
Index: linux/fs/proc/root.c
===================================================================
--- linux.orig/fs/proc/root.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/proc/root.c 2007-09-21 14:08:40.000000000 +0200
@@ -141,8 +141,8 @@ void __init proc_root_init(void)
proc_sys_init();
}
-static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
-)
+static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
generic_fillattr(dentry->d_inode, stat);
stat->nlink = proc_root.nlink + nr_processes();
Index: linux/fs/smbfs/inode.c
===================================================================
--- linux.orig/fs/smbfs/inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/smbfs/inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -659,7 +659,8 @@ smb_statfs(struct dentry *dentry, struct
return result;
}
-int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int smb_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
int err = smb_revalidate_inode(dentry);
if (!err)
Index: linux/fs/smbfs/proto.h
===================================================================
--- linux.orig/fs/smbfs/proto.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/smbfs/proto.h 2007-09-21 14:08:40.000000000 +0200
@@ -60,7 +60,8 @@ extern void smb_get_inode_attr(struct in
extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
extern void smb_invalidate_inodes(struct smb_sb_info *server);
extern int smb_revalidate_inode(struct dentry *dentry);
-extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
+extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file);
extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
/* file.c */
extern const struct address_space_operations smb_file_aops;
Index: linux/fs/stat.c
===================================================================
--- linux.orig/fs/stat.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/stat.c 2007-09-21 14:08:40.000000000 +0200
@@ -37,7 +37,8 @@ void generic_fillattr(struct inode *inod
EXPORT_SYMBOL(generic_fillattr);
-int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int vfs_fgetattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
struct inode *inode = dentry->d_inode;
int retval;
@@ -47,12 +48,17 @@ int vfs_getattr(struct vfsmount *mnt, st
return retval;
if (inode->i_op->getattr)
- return inode->i_op->getattr(mnt, dentry, stat);
+ return inode->i_op->getattr(mnt, dentry, stat, file);
generic_fillattr(inode, stat);
return 0;
}
+int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+ return vfs_fgetattr(mnt, dentry, stat, NULL);
+}
+
EXPORT_SYMBOL(vfs_getattr);
int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
@@ -62,7 +68,7 @@ int vfs_stat_fd(int dfd, char __user *na
error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
if (!error) {
- error = vfs_getattr(nd.mnt, nd.dentry, stat);
+ error = vfs_fgetattr(nd.mnt, nd.dentry, stat, NULL);
path_release(&nd);
}
return error;
@@ -82,7 +88,7 @@ int vfs_lstat_fd(int dfd, char __user *n
error = __user_walk_fd(dfd, name, 0, &nd);
if (!error) {
- error = vfs_getattr(nd.mnt, nd.dentry, stat);
+ error = vfs_fgetattr(nd.mnt, nd.dentry, stat, NULL);
path_release(&nd);
}
return error;
@@ -101,7 +107,7 @@ int vfs_fstat(unsigned int fd, struct ks
int error = -EBADF;
if (f) {
- error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
+ error = vfs_fgetattr(f->f_path.mnt, f->f_path.dentry, stat, f);
fput(f);
}
return error;
Index: linux/fs/sysv/itree.c
===================================================================
--- linux.orig/fs/sysv/itree.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/sysv/itree.c 2007-09-21 14:08:40.000000000 +0200
@@ -440,7 +440,8 @@ static unsigned sysv_nblocks(struct supe
return blocks;
}
-int sysv_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int sysv_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
struct super_block *s = mnt->mnt_sb;
generic_fillattr(dentry->d_inode, stat);
Index: linux/fs/sysv/sysv.h
===================================================================
--- linux.orig/fs/sysv/sysv.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/sysv/sysv.h 2007-09-21 14:08:40.000000000 +0200
@@ -145,7 +145,8 @@ extern int sysv_write_inode(struct inode
extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *, int);
extern void sysv_set_inode(struct inode *, dev_t);
-extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
extern int sysv_init_icache(void);
extern void sysv_destroy_icache(void);
Index: linux/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- linux.orig/fs/xfs/linux-2.6/xfs_iops.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/xfs/linux-2.6/xfs_iops.c 2007-09-21 14:08:40.000000000 +0200
@@ -569,7 +569,8 @@ STATIC int
xfs_vn_getattr(
struct vfsmount *mnt,
struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
bhv_vattr_t vattr = { .va_mask = XFS_AT_STAT };
Index: linux/include/linux/coda_linux.h
===================================================================
--- linux.orig/include/linux/coda_linux.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/include/linux/coda_linux.h 2007-09-21 14:08:40.000000000 +0200
@@ -39,7 +39,8 @@ int coda_open(struct inode *i, struct fi
int coda_release(struct inode *i, struct file *f);
int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
int coda_revalidate_inode(struct dentry *);
-int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
int coda_setattr(struct dentry *, struct iattr *);
/* this file: heloers */
Index: linux/include/linux/fs.h
===================================================================
--- linux.orig/include/linux/fs.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/include/linux/fs.h 2007-09-21 14:08:40.000000000 +0200
@@ -1212,7 +1212,8 @@ struct inode_operations {
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *);
- int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+ int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *,
+ struct file *file);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -1931,7 +1932,8 @@ extern int dcache_dir_open(struct inode
extern int dcache_dir_close(struct inode *, struct file *);
extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
extern int dcache_readdir(struct file *, void *, filldir_t);
-extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
extern int simple_statfs(struct dentry *, struct kstatfs *);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
extern int simple_unlink(struct inode *, struct dentry *);
Index: linux/include/linux/msdos_fs.h
===================================================================
--- linux.orig/include/linux/msdos_fs.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/include/linux/msdos_fs.h 2007-09-21 14:08:40.000000000 +0200
@@ -404,7 +404,7 @@ extern const struct inode_operations fat
extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
extern void fat_truncate(struct inode *inode);
extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat);
+ struct kstat *stat, struct file *file);
/* fat/inode.c */
extern void fat_attach(struct inode *inode, loff_t i_pos);
Index: linux/include/linux/nfs_fs.h
===================================================================
--- linux.orig/include/linux/nfs_fs.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/include/linux/nfs_fs.h 2007-09-21 14:08:40.000000000 +0200
@@ -288,7 +288,8 @@ extern struct inode *nfs_fhget(struct su
struct nfs_fattr *);
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
-extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
extern int nfs_permission(struct inode *, int, struct nameidata *);
extern int nfs_open(struct inode *, struct file *);
extern int nfs_release(struct inode *, struct file *);
Index: linux/fs/reiser4/plugin/inode_ops.c
===================================================================
--- linux.orig/fs/reiser4/plugin/inode_ops.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/reiser4/plugin/inode_ops.c 2007-09-21 14:08:40.000000000 +0200
@@ -475,7 +475,8 @@ int reiser4_setattr_common(struct dentry
inode_operations
*/
int reiser4_getattr_common(struct vfsmount *mnt UNUSED_ARG,
- struct dentry *dentry, struct kstat *stat)
+ struct dentry *dentry, struct kstat *stat,
+ struct file *file UNUSED_ARG)
{
struct inode *obj;
Index: linux/fs/reiser4/plugin/object.h
===================================================================
--- linux.orig/fs/reiser4/plugin/object.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/reiser4/plugin/object.h 2007-09-21 14:08:40.000000000 +0200
@@ -29,7 +29,7 @@ int reiser4_permission_common(struct ino
struct nameidata *nameidata);
int reiser4_setattr_common(struct dentry *, struct iattr *);
int reiser4_getattr_common(struct vfsmount *mnt, struct dentry *,
- struct kstat *);
+ struct kstat *, struct file *);
/* common implementations of file operations */
loff_t reiser4_llseek_dir_common(struct file *, loff_t off, int origin);
Index: linux/fs/revoked_inode.c
===================================================================
--- linux.orig/fs/revoked_inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/revoked_inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -295,7 +295,7 @@ static int revoked_inode_permission(stru
}
static int revoked_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+ struct kstat *stat, struct file *file)
{
return -EBADF;
}
Index: linux/fs/minix/inode.c
===================================================================
--- linux.orig/fs/minix/inode.c 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/minix/inode.c 2007-09-21 14:08:40.000000000 +0200
@@ -573,7 +573,8 @@ int minix_sync_inode(struct inode * inod
return err;
}
-int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int minix_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat, struct file *file)
{
struct inode *dir = dentry->d_parent->d_inode;
struct super_block *sb = dir->i_sb;
Index: linux/fs/minix/minix.h
===================================================================
--- linux.orig/fs/minix/minix.h 2007-09-21 14:08:25.000000000 +0200
+++ linux/fs/minix/minix.h 2007-09-21 14:08:40.000000000 +0200
@@ -53,7 +53,8 @@ extern unsigned long minix_count_free_in
extern int minix_new_block(struct inode * inode);
extern void minix_free_block(struct inode *inode, unsigned long block);
extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
-extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
extern int __minix_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata);
Index: linux/Documentation/filesystems/Locking
===================================================================
--- linux.orig/Documentation/filesystems/Locking 2007-09-21 14:08:25.000000000 +0200
+++ linux/Documentation/filesystems/Locking 2007-09-21 14:08:40.000000000 +0200
@@ -46,7 +46,8 @@ ata *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *);
- int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
+ int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *,
+ struct file *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
Index: linux/Documentation/filesystems/vfs.txt
===================================================================
--- linux.orig/Documentation/filesystems/vfs.txt 2007-09-21 14:08:25.000000000 +0200
+++ linux/Documentation/filesystems/vfs.txt 2007-09-21 14:08:40.000000000 +0200
@@ -342,7 +342,8 @@ struct inode_operations {
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *);
- int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+ int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *,
+ struct file *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -428,7 +429,8 @@ otherwise noted.
is called by chmod(2) and related system calls.
getattr: called by the VFS to get attributes of a file. This method
- is called by stat(2) and related system calls.
+ is called by stat(2) and related system calls. The last parameter
+ is the open file pointer for fstat(2) and NULL in other cases.
setxattr: called by the VFS to set an extended attribute for a file.
Extended attribute is a name:value pair associated with an
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 12:23 [patch 0/5] VFS changes Miklos Szeredi
2007-09-21 12:23 ` [patch 1/5] VFS: pass open file to ->setattr() Miklos Szeredi
2007-09-21 12:23 ` [patch 2/5] VFS: pass open file to ->getattr() Miklos Szeredi
@ 2007-09-21 12:23 ` Miklos Szeredi
2007-09-21 12:43 ` Christoph Hellwig
2007-09-21 18:39 ` Andreas Dilger
2007-09-21 12:23 ` [patch 4/5] VFS: allow filesystems to implement atomic open+truncate Miklos Szeredi
2007-09-21 12:23 ` [patch 5/5] VFS: allow filesystem to override mknod capability checks Miklos Szeredi
4 siblings, 2 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 12:23 UTC (permalink / raw)
To: akpm; +Cc: hch, linux-kernel, linux-fsdevel
[-- Attachment #1: vfs_xattr_file.patch --]
[-- Type: text/plain, Size: 51435 bytes --]
From: Miklos Szeredi <mszeredi@suse.cz>
Pass the open file into the filesystem's *xattr() methods.
This is needed to be able to correctly implement open-unlink-f*xattr
semantics, without having to resort to "silly-renaming".
Do this by adding a 'struct file *' parameter to i_op->*xattr(). For
f... variants pass the open file pointer, in other cases pass NULL.
This is safe from a compatibility standpoint, out-of-tree old stuff
will continue to work, but will get a warning at compile time.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
Index: linux/fs/bad_inode.c
===================================================================
--- linux.orig/fs/bad_inode.c 2007-09-21 13:45:07.000000000 +0200
+++ linux/fs/bad_inode.c 2007-09-21 13:45:11.000000000 +0200
@@ -261,24 +261,25 @@ static int bad_inode_setattr(struct dent
}
static int bad_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags, struct file *file)
{
return -EIO;
}
static ssize_t bad_inode_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size)
+ void *buffer, size_t size, struct file *file)
{
return -EIO;
}
static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
- size_t buffer_size)
+ size_t buffer_size, struct file *file)
{
return -EIO;
}
-static int bad_inode_removexattr(struct dentry *dentry, const char *name)
+static int bad_inode_removexattr(struct dentry *dentry, const char *name,
+ struct file *file)
{
return -EIO;
}
Index: linux/fs/ext2/xattr.c
===================================================================
--- linux.orig/fs/ext2/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ext2/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -328,7 +328,8 @@ cleanup:
* dentry->d_inode->i_mutex: don't care
*/
ssize_t
-ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *file)
{
return ext2_xattr_list(dentry->d_inode, buffer, size);
}
Index: linux/fs/ext2/xattr.h
===================================================================
--- linux.orig/fs/ext2/xattr.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ext2/xattr.h 2007-09-21 13:45:11.000000000 +0200
@@ -61,7 +61,7 @@ extern struct xattr_handler ext2_xattr_a
extern struct xattr_handler ext2_xattr_acl_default_handler;
extern struct xattr_handler ext2_xattr_security_handler;
-extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t, struct file *);
extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
Index: linux/fs/ext3/xattr.c
===================================================================
--- linux.orig/fs/ext3/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ext3/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -143,7 +143,8 @@ ext3_xattr_handler(int name_index)
* dentry->d_inode->i_mutex: don't care
*/
ssize_t
-ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *file)
{
return ext3_xattr_list(dentry->d_inode, buffer, size);
}
Index: linux/fs/ext3/xattr.h
===================================================================
--- linux.orig/fs/ext3/xattr.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ext3/xattr.h 2007-09-21 13:45:11.000000000 +0200
@@ -64,7 +64,7 @@ extern struct xattr_handler ext3_xattr_a
extern struct xattr_handler ext3_xattr_acl_default_handler;
extern struct xattr_handler ext3_xattr_security_handler;
-extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t, struct file *);
extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
extern int ext3_xattr_list(struct inode *, char *, size_t);
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2007-09-21 13:45:07.000000000 +0200
+++ linux/fs/fuse/dir.c 2007-09-21 13:45:11.000000000 +0200
@@ -1118,7 +1118,8 @@ static int fuse_getattr(struct vfsmount
}
static int fuse_setxattr(struct dentry *entry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags,
+ struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1156,7 +1157,7 @@ static int fuse_setxattr(struct dentry *
}
static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
- void *value, size_t size)
+ void *value, size_t size, struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1205,7 +1206,8 @@ static ssize_t fuse_getxattr(struct dent
return ret;
}
-static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
+static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size,
+ struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1255,7 +1257,8 @@ static ssize_t fuse_listxattr(struct den
return ret;
}
-static int fuse_removexattr(struct dentry *entry, const char *name)
+static int fuse_removexattr(struct dentry *entry, const char *name,
+ struct file *file)
{
struct inode *inode = entry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
Index: linux/fs/nfs/nfs3acl.c
===================================================================
--- linux.orig/fs/nfs/nfs3acl.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/nfs/nfs3acl.c 2007-09-21 13:45:11.000000000 +0200
@@ -7,7 +7,8 @@
#define NFSDBG_FACILITY NFSDBG_PROC
-ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
struct posix_acl *acl;
@@ -47,7 +48,7 @@ ssize_t nfs3_listxattr(struct dentry *de
}
ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size)
+ void *buffer, size_t size, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct posix_acl *acl;
@@ -76,7 +77,7 @@ ssize_t nfs3_getxattr(struct dentry *den
}
int nfs3_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct posix_acl *acl;
@@ -98,7 +99,7 @@ int nfs3_setxattr(struct dentry *dentry,
return error;
}
-int nfs3_removexattr(struct dentry *dentry, const char *name)
+int nfs3_removexattr(struct dentry *dentry, const char *name, struct file *file)
{
struct inode *inode = dentry->d_inode;
int type;
Index: linux/fs/nfs/nfs4_fs.h
===================================================================
--- linux.orig/fs/nfs/nfs4_fs.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/nfs/nfs4_fs.h 2007-09-21 13:45:11.000000000 +0200
@@ -167,9 +167,11 @@ extern struct dentry_operations nfs4_den
extern const struct inode_operations nfs4_dir_inode_operations;
/* inode.c */
-extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
-extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t, int);
-extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
+extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t,
+ struct file *);
+extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t,
+ int, struct file *);
+extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t, struct file *);
/* nfs4proc.c */
Index: linux/fs/nfs/nfs4proc.c
===================================================================
--- linux.orig/fs/nfs/nfs4proc.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/nfs/nfs4proc.c 2007-09-21 13:45:11.000000000 +0200
@@ -3598,7 +3598,7 @@ out:
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
- size_t buflen, int flags)
+ size_t buflen, int flags, struct file *file)
{
struct inode *inode = dentry->d_inode;
@@ -3617,7 +3617,7 @@ int nfs4_setxattr(struct dentry *dentry,
* But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
* attributes in kernel-managed attribute namespaces. */
ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
- size_t buflen)
+ size_t buflen, struct file *file)
{
struct inode *inode = dentry->d_inode;
@@ -3627,7 +3627,8 @@ ssize_t nfs4_getxattr(struct dentry *den
return nfs4_proc_get_acl(inode, buf, buflen);
}
-ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
+ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen,
+ struct file *file)
{
size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
Index: linux/fs/revoked_inode.c
===================================================================
--- linux.orig/fs/revoked_inode.c 2007-09-21 13:45:07.000000000 +0200
+++ linux/fs/revoked_inode.c 2007-09-21 13:45:11.000000000 +0200
@@ -306,24 +306,27 @@ static int revoked_inode_setattr(struct
}
static int revoked_inode_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags,
+ struct file *file)
{
return -EBADF;
}
static ssize_t revoked_inode_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size)
+ void *buffer, size_t size,
+ struct file *file)
{
return -EBADF;
}
static ssize_t revoked_inode_listxattr(struct dentry *dentry, char *buffer,
- size_t buffer_size)
+ size_t buffer_size, struct file *file)
{
return -EBADF;
}
-static int revoked_inode_removexattr(struct dentry *dentry, const char *name)
+static int revoked_inode_removexattr(struct dentry *dentry, const char *name,
+ struct file *file)
{
return -EBADF;
}
Index: linux/fs/xattr.c
===================================================================
--- linux.orig/fs/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -67,9 +67,8 @@ xattr_permission(struct inode *inode, co
return permission(inode, mask, NULL);
}
-int
-vfs_setxattr(struct dentry *dentry, char *name, void *value,
- size_t size, int flags)
+static int vfs_fsetxattr(struct dentry *dentry, char *name, void *value,
+ size_t size, int flags, struct file *file)
{
struct inode *inode = dentry->d_inode;
int error;
@@ -84,7 +83,8 @@ vfs_setxattr(struct dentry *dentry, char
goto out;
error = -EOPNOTSUPP;
if (inode->i_op->setxattr) {
- error = inode->i_op->setxattr(dentry, name, value, size, flags);
+ error = inode->i_op->setxattr(dentry, name, value, size, flags,
+ file);
if (!error) {
fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value,
@@ -102,10 +102,16 @@ out:
mutex_unlock(&inode->i_mutex);
return error;
}
+
+int vfs_setxattr(struct dentry *dentry, char *name, void *value,
+ size_t size, int flags)
+{
+ return vfs_fsetxattr(dentry, name, value, size, flags, NULL);
+}
EXPORT_SYMBOL_GPL(vfs_setxattr);
-ssize_t
-vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+static ssize_t vfs_fgetxattr(struct dentry *dentry, char *name, void *value,
+ size_t size, struct file *file)
{
struct inode *inode = dentry->d_inode;
int error;
@@ -119,7 +125,7 @@ vfs_getxattr(struct dentry *dentry, char
return error;
if (inode->i_op->getxattr)
- error = inode->i_op->getxattr(dentry, name, value, size);
+ error = inode->i_op->getxattr(dentry, name, value, size, file);
else
error = -EOPNOTSUPP;
@@ -138,10 +144,17 @@ vfs_getxattr(struct dentry *dentry, char
return error;
}
+
+ssize_t vfs_getxattr(struct dentry *dentry, char *name, void *value,
+ size_t size)
+{
+ return vfs_fgetxattr(dentry, name, value, size, NULL);
+}
EXPORT_SYMBOL_GPL(vfs_getxattr);
-ssize_t
-vfs_listxattr(struct dentry *d, char *list, size_t size)
+
+static ssize_t vfs_flistxattr(struct dentry *d, char *list, size_t size,
+ struct file *file)
{
ssize_t error;
@@ -150,7 +163,7 @@ vfs_listxattr(struct dentry *d, char *li
return error;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
- error = d->d_inode->i_op->listxattr(d, list, size);
+ error = d->d_inode->i_op->listxattr(d, list, size, file);
} else {
error = security_inode_listsecurity(d->d_inode, list, size);
if (size && error > size)
@@ -158,10 +171,15 @@ vfs_listxattr(struct dentry *d, char *li
}
return error;
}
+
+ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size)
+{
+ return vfs_flistxattr(d, list, size, NULL);
+}
EXPORT_SYMBOL_GPL(vfs_listxattr);
-int
-vfs_removexattr(struct dentry *dentry, char *name)
+static int vfs_fremovexattr(struct dentry *dentry, char *name,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
int error;
@@ -178,13 +196,18 @@ vfs_removexattr(struct dentry *dentry, c
return error;
mutex_lock(&inode->i_mutex);
- error = inode->i_op->removexattr(dentry, name);
+ error = inode->i_op->removexattr(dentry, name, file);
mutex_unlock(&inode->i_mutex);
if (!error)
fsnotify_xattr(dentry);
return error;
}
+
+int vfs_removexattr(struct dentry *dentry, char *name)
+{
+ return vfs_fremovexattr(dentry, name, NULL);
+}
EXPORT_SYMBOL_GPL(vfs_removexattr);
@@ -193,7 +216,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
*/
static long
setxattr(struct dentry *d, char __user *name, void __user *value,
- size_t size, int flags)
+ size_t size, int flags, struct file *file)
{
int error;
void *kvalue = NULL;
@@ -220,7 +243,7 @@ setxattr(struct dentry *d, char __user *
}
}
- error = vfs_setxattr(d, kname, kvalue, size, flags);
+ error = vfs_fsetxattr(d, kname, kvalue, size, flags, file);
kfree(kvalue);
return error;
}
@@ -235,7 +258,7 @@ sys_setxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = setxattr(nd.dentry, name, value, size, flags);
+ error = setxattr(nd.dentry, name, value, size, flags, NULL);
path_release(&nd);
return error;
}
@@ -250,7 +273,7 @@ sys_lsetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = setxattr(nd.dentry, name, value, size, flags);
+ error = setxattr(nd.dentry, name, value, size, flags, NULL);
path_release(&nd);
return error;
}
@@ -268,7 +291,7 @@ sys_fsetxattr(int fd, char __user *name,
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = setxattr(dentry, name, value, size, flags);
+ error = setxattr(dentry, name, value, size, flags, f);
fput(f);
return error;
}
@@ -277,7 +300,8 @@ sys_fsetxattr(int fd, char __user *name,
* Extended attribute GET operations
*/
static ssize_t
-getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
+getxattr(struct dentry *d, char __user *name, void __user *value, size_t size,
+ struct file *file)
{
ssize_t error;
void *kvalue = NULL;
@@ -297,7 +321,7 @@ getxattr(struct dentry *d, char __user *
return -ENOMEM;
}
- error = vfs_getxattr(d, kname, kvalue, size);
+ error = vfs_fgetxattr(d, kname, kvalue, size, file);
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
@@ -320,7 +344,7 @@ sys_getxattr(char __user *path, char __u
error = user_path_walk(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, name, value, size);
+ error = getxattr(nd.dentry, name, value, size, NULL);
path_release(&nd);
return error;
}
@@ -335,7 +359,7 @@ sys_lgetxattr(char __user *path, char __
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = getxattr(nd.dentry, name, value, size);
+ error = getxattr(nd.dentry, name, value, size, NULL);
path_release(&nd);
return error;
}
@@ -350,7 +374,7 @@ sys_fgetxattr(int fd, char __user *name,
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = getxattr(f->f_path.dentry, name, value, size);
+ error = getxattr(f->f_path.dentry, name, value, size, f);
fput(f);
return error;
}
@@ -359,7 +383,7 @@ sys_fgetxattr(int fd, char __user *name,
* Extended attribute LIST operations
*/
static ssize_t
-listxattr(struct dentry *d, char __user *list, size_t size)
+listxattr(struct dentry *d, char __user *list, size_t size, struct file *file)
{
ssize_t error;
char *klist = NULL;
@@ -372,7 +396,7 @@ listxattr(struct dentry *d, char __user
return -ENOMEM;
}
- error = vfs_listxattr(d, klist, size);
+ error = vfs_flistxattr(d, klist, size, file);
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
@@ -394,7 +418,7 @@ sys_listxattr(char __user *path, char __
error = user_path_walk(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, list, size);
+ error = listxattr(nd.dentry, list, size, NULL);
path_release(&nd);
return error;
}
@@ -408,7 +432,7 @@ sys_llistxattr(char __user *path, char _
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = listxattr(nd.dentry, list, size);
+ error = listxattr(nd.dentry, list, size, NULL);
path_release(&nd);
return error;
}
@@ -423,7 +447,7 @@ sys_flistxattr(int fd, char __user *list
if (!f)
return error;
audit_inode(NULL, f->f_path.dentry);
- error = listxattr(f->f_path.dentry, list, size);
+ error = listxattr(f->f_path.dentry, list, size, f);
fput(f);
return error;
}
@@ -432,7 +456,7 @@ sys_flistxattr(int fd, char __user *list
* Extended attribute REMOVE operations
*/
static long
-removexattr(struct dentry *d, char __user *name)
+removexattr(struct dentry *d, char __user *name, struct file *file)
{
int error;
char kname[XATTR_NAME_MAX + 1];
@@ -443,7 +467,7 @@ removexattr(struct dentry *d, char __use
if (error < 0)
return error;
- return vfs_removexattr(d, kname);
+ return vfs_fremovexattr(d, kname, file);
}
asmlinkage long
@@ -455,7 +479,7 @@ sys_removexattr(char __user *path, char
error = user_path_walk(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, name);
+ error = removexattr(nd.dentry, name, NULL);
path_release(&nd);
return error;
}
@@ -469,7 +493,7 @@ sys_lremovexattr(char __user *path, char
error = user_path_walk_link(path, &nd);
if (error)
return error;
- error = removexattr(nd.dentry, name);
+ error = removexattr(nd.dentry, name, NULL);
path_release(&nd);
return error;
}
@@ -486,7 +510,7 @@ sys_fremovexattr(int fd, char __user *na
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = removexattr(dentry, name);
+ error = removexattr(dentry, name, f);
fput(f);
return error;
}
@@ -541,7 +565,8 @@ xattr_resolve_name(struct xattr_handler
* Find the handler for the prefix and dispatch its get() operation.
*/
ssize_t
-generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+generic_getxattr(struct dentry *dentry, const char *name, void *buffer,
+ size_t size, struct file *file)
{
struct xattr_handler *handler;
struct inode *inode = dentry->d_inode;
@@ -557,7 +582,8 @@ generic_getxattr(struct dentry *dentry,
* list.
*/
ssize_t
-generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
+generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
@@ -585,7 +611,8 @@ generic_listxattr(struct dentry *dentry,
* Find the handler for the prefix and dispatch its set() operation.
*/
int
-generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
+generic_setxattr(struct dentry *dentry, const char *name, const void *value,
+ size_t size, int flags, struct file *file)
{
struct xattr_handler *handler;
struct inode *inode = dentry->d_inode;
@@ -603,7 +630,7 @@ generic_setxattr(struct dentry *dentry,
* any associated extended attribute.
*/
int
-generic_removexattr(struct dentry *dentry, const char *name)
+generic_removexattr(struct dentry *dentry, const char *name, struct file *file)
{
struct xattr_handler *handler;
struct inode *inode = dentry->d_inode;
Index: linux/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- linux.orig/fs/xfs/linux-2.6/xfs_iops.c 2007-09-21 13:45:07.000000000 +0200
+++ linux/fs/xfs/linux-2.6/xfs_iops.c 2007-09-21 13:45:11.000000000 +0200
@@ -666,7 +666,8 @@ xfs_vn_setxattr(
const char *name,
const void *data,
size_t size,
- int flags)
+ int flags,
+ struct file *file)
{
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
char *attr = (char *)name;
@@ -696,7 +697,8 @@ xfs_vn_getxattr(
struct dentry *dentry,
const char *name,
void *data,
- size_t size)
+ size_t size,
+ struct file *file)
{
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
char *attr = (char *)name;
@@ -725,7 +727,8 @@ STATIC ssize_t
xfs_vn_listxattr(
struct dentry *dentry,
char *data,
- size_t size)
+ size_t size,
+ struct file *file)
{
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
int error, xflags = ATTR_KERNAMELS;
@@ -744,7 +747,8 @@ xfs_vn_listxattr(
STATIC int
xfs_vn_removexattr(
struct dentry *dentry,
- const char *name)
+ const char *name,
+ struct file *file)
{
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
char *attr = (char *)name;
Index: linux/include/linux/fs.h
===================================================================
--- linux.orig/include/linux/fs.h 2007-09-21 13:45:07.000000000 +0200
+++ linux/include/linux/fs.h 2007-09-21 13:45:11.000000000 +0200
@@ -1214,10 +1214,12 @@ struct inode_operations {
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *,
struct file *file);
- int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
- int (*removexattr) (struct dentry *, const char *);
+ int (*setxattr) (struct dentry *, const char *,const void *,size_t,int,
+ struct file *);
+ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,
+ struct file *);
+ ssize_t (*listxattr) (struct dentry *, char *, size_t, struct file *);
+ int (*removexattr) (struct dentry *, const char *, struct file *);
void (*truncate_range)(struct inode *, loff_t, loff_t);
long (*fallocate)(struct inode *inode, int mode, loff_t offset,
loff_t len);
Index: linux/include/linux/nfs_fs.h
===================================================================
--- linux.orig/include/linux/nfs_fs.h 2007-09-21 13:45:07.000000000 +0200
+++ linux/include/linux/nfs_fs.h 2007-09-21 13:45:11.000000000 +0200
@@ -343,11 +343,12 @@ static inline struct rpc_cred *nfs_file_
* linux/fs/nfs/xattr.c
*/
#ifdef CONFIG_NFS_V3_ACL
-extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
-extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t, struct file *);
+extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t,
+ struct file *);
extern int nfs3_setxattr(struct dentry *, const char *,
- const void *, size_t, int);
-extern int nfs3_removexattr (struct dentry *, const char *name);
+ const void *, size_t, int, struct file *);
+extern int nfs3_removexattr (struct dentry *, const char *name, struct file *);
#else
# define nfs3_listxattr NULL
# define nfs3_getxattr NULL
Index: linux/include/linux/xattr.h
===================================================================
--- linux.orig/include/linux/xattr.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/include/linux/xattr.h 2007-09-21 13:45:11.000000000 +0200
@@ -51,10 +51,14 @@ ssize_t vfs_listxattr(struct dentry *d,
int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
int vfs_removexattr(struct dentry *, char *);
-ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
-ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
-int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
-int generic_removexattr(struct dentry *dentry, const char *name);
+ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer,
+ size_t size, struct file *);
+ssize_t generic_listxattr(struct dentry *dentry, char *buffer,
+ size_t buffer_size, struct file *);
+int generic_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags, struct file *);
+int generic_removexattr(struct dentry *dentry, const char *name,
+ struct file *);
#endif /* __KERNEL__ */
Index: linux/fs/ext4/xattr.c
===================================================================
--- linux.orig/fs/ext4/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ext4/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -136,7 +136,8 @@ ext4_xattr_handler(int name_index)
* dentry->d_inode->i_mutex: don't care
*/
ssize_t
-ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ext4_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *file)
{
return ext4_xattr_list(dentry->d_inode, buffer, size);
}
Index: linux/fs/ext4/xattr.h
===================================================================
--- linux.orig/fs/ext4/xattr.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ext4/xattr.h 2007-09-21 13:45:11.000000000 +0200
@@ -71,7 +71,7 @@ extern struct xattr_handler ext4_xattr_a
extern struct xattr_handler ext4_xattr_acl_default_handler;
extern struct xattr_handler ext4_xattr_security_handler;
-extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
+extern ssize_t ext4_listxattr(struct dentry *, char *, size_t, struct file *);
extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);
extern int ext4_xattr_list(struct inode *, char *, size_t);
Index: linux/fs/gfs2/ops_inode.c
===================================================================
--- linux.orig/fs/gfs2/ops_inode.c 2007-09-21 13:45:07.000000000 +0200
+++ linux/fs/gfs2/ops_inode.c 2007-09-21 13:45:11.000000000 +0200
@@ -1064,7 +1064,8 @@ static int gfs2_getattr(struct vfsmount
}
static int gfs2_setxattr(struct dentry *dentry, const char *name,
- const void *data, size_t size, int flags)
+ const void *data, size_t size, int flags,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
struct gfs2_ea_request er;
@@ -1084,7 +1085,7 @@ static int gfs2_setxattr(struct dentry *
}
static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
- void *data, size_t size)
+ void *data, size_t size, struct file *file)
{
struct gfs2_ea_request er;
@@ -1099,7 +1100,8 @@ static ssize_t gfs2_getxattr(struct dent
return gfs2_ea_get(GFS2_I(dentry->d_inode), &er);
}
-static ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+static ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *file)
{
struct gfs2_ea_request er;
@@ -1110,7 +1112,8 @@ static ssize_t gfs2_listxattr(struct den
return gfs2_ea_list(GFS2_I(dentry->d_inode), &er);
}
-static int gfs2_removexattr(struct dentry *dentry, const char *name)
+static int gfs2_removexattr(struct dentry *dentry, const char *name,
+ struct file *file)
{
struct gfs2_ea_request er;
Index: linux/fs/hfs/attr.c
===================================================================
--- linux.orig/fs/hfs/attr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/hfs/attr.c 2007-09-21 13:45:11.000000000 +0200
@@ -14,7 +14,8 @@
#include "btree.h"
int hfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags,
+ struct file *unused_file)
{
struct inode *inode = dentry->d_inode;
struct hfs_find_data fd;
@@ -57,7 +58,7 @@ out:
}
ssize_t hfs_getxattr(struct dentry *dentry, const char *name,
- void *value, size_t size)
+ void *value, size_t size, struct file *unused_file)
{
struct inode *inode = dentry->d_inode;
struct hfs_find_data fd;
@@ -103,7 +104,8 @@ out:
#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
-ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *unused_file)
{
struct inode *inode = dentry->d_inode;
Index: linux/fs/hfs/hfs_fs.h
===================================================================
--- linux.orig/fs/hfs/hfs_fs.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/hfs/hfs_fs.h 2007-09-21 13:45:11.000000000 +0200
@@ -197,10 +197,12 @@ extern void hfs_delete_inode(struct inod
/* attr.c */
extern int hfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
+ const void *value, size_t size, int flags,
+ struct file *);
extern ssize_t hfs_getxattr(struct dentry *dentry, const char *name,
- void *value, size_t size);
-extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+ void *value, size_t size, struct file *);
+extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *);
/* mdb.c */
extern int hfs_mdb_get(struct super_block *);
Index: linux/fs/hfsplus/hfsplus_fs.h
===================================================================
--- linux.orig/fs/hfsplus/hfsplus_fs.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/hfsplus/hfsplus_fs.h 2007-09-21 13:45:11.000000000 +0200
@@ -335,10 +335,11 @@ void hfsplus_delete_inode(struct inode *
int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg);
int hfsplus_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
+ const void *value, size_t size, int flags, struct file *);
ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
- void *value, size_t size);
-ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
+ void *value, size_t size, struct file *);
+ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *);
/* options.c */
int hfsplus_parse_options(char *, struct hfsplus_sb_info *);
Index: linux/fs/hfsplus/ioctl.c
===================================================================
--- linux.orig/fs/hfsplus/ioctl.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/hfsplus/ioctl.c 2007-09-21 13:45:11.000000000 +0200
@@ -83,7 +83,8 @@ int hfsplus_ioctl(struct inode *inode, s
}
int hfsplus_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags,
+ struct file *unused_file)
{
struct inode *inode = dentry->d_inode;
struct hfs_find_data fd;
@@ -125,7 +126,7 @@ out:
}
ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
- void *value, size_t size)
+ void *value, size_t size, struct file *unused_file)
{
struct inode *inode = dentry->d_inode;
struct hfs_find_data fd;
@@ -170,7 +171,8 @@ out:
#define HFSPLUS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
-ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *unused_file)
{
struct inode *inode = dentry->d_inode;
Index: linux/fs/reiserfs/xattr.c
===================================================================
--- linux.orig/fs/reiserfs/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/reiserfs/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -896,7 +896,7 @@ int reiserfs_chown_xattrs(struct inode *
*/
ssize_t
reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
- size_t size)
+ size_t size, struct file *file)
{
struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
int err;
@@ -920,7 +920,7 @@ reiserfs_getxattr(struct dentry * dentry
*/
int
reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t size, int flags)
+ size_t size, int flags, struct file *file)
{
struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
int err;
@@ -950,7 +950,8 @@ reiserfs_setxattr(struct dentry *dentry,
*
* dentry->d_inode->i_mutex down
*/
-int reiserfs_removexattr(struct dentry *dentry, const char *name)
+int reiserfs_removexattr(struct dentry *dentry, const char *name,
+ struct file *file)
{
int err;
struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
@@ -1027,7 +1028,8 @@ reiserfs_listxattr_filler(void *buf, con
*
* Preliminary locking: we down dentry->d_inode->i_mutex
*/
-ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
+ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size,
+ struct file *unused_file)
{
struct file *fp;
struct dentry *dir;
Index: linux/fs/unionfs/union.h
===================================================================
--- linux.orig/fs/unionfs/union.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/unionfs/union.h 2007-09-21 13:45:11.000000000 +0200
@@ -349,12 +349,14 @@ static inline void unionfs_xattr_kfree(c
kfree(p);
}
extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
- void *value, size_t size);
-extern int unionfs_removexattr(struct dentry *dentry, const char *name);
+ void *value, size_t size, struct file *);
+extern int unionfs_removexattr(struct dentry *dentry, const char *name,
+ struct file *);
extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
- size_t size);
+ size_t size, struct file *);
extern int unionfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
+ const void *value, size_t size, int flags,
+ struct file *);
#endif /* CONFIG_UNION_FS_XATTR */
/* The root directory is unhashed, but isn't deleted. */
Index: linux/fs/unionfs/xattr.c
===================================================================
--- linux.orig/fs/unionfs/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/unionfs/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -40,7 +40,7 @@ void *unionfs_xattr_alloc(size_t size, s
* dentry->d_inode->i_mutex locked
*/
ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
- size_t size)
+ size_t size, struct file *file)
{
struct dentry *lower_dentry = NULL;
int err = -EOPNOTSUPP;
@@ -69,7 +69,8 @@ out:
* dentry->d_inode->i_mutex locked
*/
int unionfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+ const void *value, size_t size, int flags,
+ struct file *file)
{
struct dentry *lower_dentry = NULL;
int err = -EOPNOTSUPP;
@@ -98,7 +99,8 @@ out:
* BKL held by caller.
* dentry->d_inode->i_mutex locked
*/
-int unionfs_removexattr(struct dentry *dentry, const char *name)
+int unionfs_removexattr(struct dentry *dentry, const char *name,
+ struct file *file)
{
struct dentry *lower_dentry = NULL;
int err = -EOPNOTSUPP;
@@ -126,7 +128,8 @@ out:
* BKL held by caller.
* dentry->d_inode->i_mutex locked
*/
-ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
+ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size,
+ struct file *file)
{
struct dentry *lower_dentry = NULL;
int err = -EOPNOTSUPP;
Index: linux/include/linux/reiserfs_xattr.h
===================================================================
--- linux.orig/include/linux/reiserfs_xattr.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/include/linux/reiserfs_xattr.h 2007-09-21 13:45:11.000000000 +0200
@@ -47,11 +47,13 @@ struct reiserfs_xattr_handler {
#define is_reiserfs_priv_object(inode) IS_PRIVATE(inode)
#define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
ssize_t reiserfs_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size);
+ void *buffer, size_t size, struct file *);
int reiserfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
-ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-int reiserfs_removexattr(struct dentry *dentry, const char *name);
+ const void *value, size_t size, int flags, struct file *);
+ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *);
+int reiserfs_removexattr(struct dentry *dentry, const char *name,
+ struct file *);
int reiserfs_delete_xattrs(struct inode *inode);
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
Index: linux/fs/cifs/cifsfs.h
===================================================================
--- linux.orig/fs/cifs/cifsfs.h 2007-09-21 13:45:07.000000000 +0200
+++ linux/fs/cifs/cifsfs.h 2007-09-21 13:45:11.000000000 +0200
@@ -95,11 +95,12 @@ extern int cifs_readlink(struct dentry *
int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname);
-extern int cifs_removexattr(struct dentry *, const char *);
+extern int cifs_removexattr(struct dentry *, const char *, struct file *);
extern int cifs_setxattr(struct dentry *, const char *, const void *,
- size_t, int);
-extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
-extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
+ size_t, int, struct file *);
+extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t,
+ struct file *);
+extern ssize_t cifs_listxattr(struct dentry *, char *, size_t, struct file *);
extern int cifs_ioctl(struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.51"
Index: linux/fs/cifs/xattr.c
===================================================================
--- linux.orig/fs/cifs/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/cifs/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -40,7 +40,8 @@
-int cifs_removexattr(struct dentry *direntry, const char *ea_name)
+int cifs_removexattr(struct dentry *direntry, const char *ea_name,
+ struct file *file)
{
int rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
@@ -94,7 +95,8 @@ remove_ea_exit:
}
int cifs_setxattr(struct dentry *direntry, const char *ea_name,
- const void *ea_value, size_t value_size, int flags)
+ const void *ea_value, size_t value_size, int flags,
+ struct file *file)
{
int rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
@@ -200,7 +202,7 @@ set_ea_exit:
}
ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
- void *ea_value, size_t buf_size)
+ void *ea_value, size_t buf_size, struct file *file)
{
ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
@@ -318,7 +320,8 @@ get_ea_exit:
return rc;
}
-ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
+ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size,
+ struct file *file)
{
ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
Index: linux/fs/ecryptfs/crypto.c
===================================================================
--- linux.orig/fs/ecryptfs/crypto.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ecryptfs/crypto.c 2007-09-21 13:45:11.000000000 +0200
@@ -1445,7 +1445,7 @@ ecryptfs_write_metadata_to_xattr(struct
int rc;
rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt,
- size, 0);
+ size, 0, NULL);
return rc;
}
@@ -1640,7 +1640,7 @@ int ecryptfs_read_xattr_region(char *pag
int rc = 0;
size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME,
- page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
+ page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE, NULL);
if (size < 0) {
printk(KERN_DEBUG "Error attempting to read the [%s] "
"xattr from the lower file; return value = [%zd]\n",
Index: linux/fs/ecryptfs/ecryptfs_kernel.h
===================================================================
--- linux.orig/fs/ecryptfs/ecryptfs_kernel.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ecryptfs/ecryptfs_kernel.h 2007-09-21 13:45:11.000000000 +0200
@@ -587,10 +587,10 @@ int ecryptfs_open_lower_file(struct file
struct vfsmount *lower_mnt, int flags);
int ecryptfs_close_lower_file(struct file *lower_file);
ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
- size_t size);
+ size_t size, struct file *);
int
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t size, int flags);
+ size_t size, int flags, struct file *);
int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry);
int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
int ecryptfs_process_quit(uid_t uid, pid_t pid);
Index: linux/fs/ecryptfs/inode.c
===================================================================
--- linux.orig/fs/ecryptfs/inode.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ecryptfs/inode.c 2007-09-21 13:45:11.000000000 +0200
@@ -967,7 +967,7 @@ out:
int
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t size, int flags)
+ size_t size, int flags, struct file *file)
{
int rc = 0;
struct dentry *lower_dentry;
@@ -979,7 +979,7 @@ ecryptfs_setxattr(struct dentry *dentry,
}
mutex_lock(&lower_dentry->d_inode->i_mutex);
rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry, name, value,
- size, flags);
+ size, flags, NULL);
mutex_unlock(&lower_dentry->d_inode->i_mutex);
out:
return rc;
@@ -987,7 +987,7 @@ out:
ssize_t
ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
- size_t size)
+ size_t size, struct file *file)
{
int rc = 0;
struct dentry *lower_dentry;
@@ -999,14 +999,15 @@ ecryptfs_getxattr(struct dentry *dentry,
}
mutex_lock(&lower_dentry->d_inode->i_mutex);
rc = lower_dentry->d_inode->i_op->getxattr(lower_dentry, name, value,
- size);
+ size, NULL);
mutex_unlock(&lower_dentry->d_inode->i_mutex);
out:
return rc;
}
static ssize_t
-ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size)
+ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size,
+ struct file *file)
{
int rc = 0;
struct dentry *lower_dentry;
@@ -1017,13 +1018,15 @@ ecryptfs_listxattr(struct dentry *dentry
goto out;
}
mutex_lock(&lower_dentry->d_inode->i_mutex);
- rc = lower_dentry->d_inode->i_op->listxattr(lower_dentry, list, size);
+ rc = lower_dentry->d_inode->i_op->listxattr(lower_dentry, list, size,
+ NULL);
mutex_unlock(&lower_dentry->d_inode->i_mutex);
out:
return rc;
}
-static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
+static int ecryptfs_removexattr(struct dentry *dentry, const char *name,
+ struct file *file)
{
int rc = 0;
struct dentry *lower_dentry;
@@ -1034,7 +1037,7 @@ static int ecryptfs_removexattr(struct d
goto out;
}
mutex_lock(&lower_dentry->d_inode->i_mutex);
- rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name);
+ rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name, NULL);
mutex_unlock(&lower_dentry->d_inode->i_mutex);
out:
return rc;
Index: linux/fs/ecryptfs/mmap.c
===================================================================
--- linux.orig/fs/ecryptfs/mmap.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/ecryptfs/mmap.c 2007-09-21 13:45:11.000000000 +0200
@@ -532,7 +532,7 @@ static int ecryptfs_write_inode_size_to_
size = lower_dentry->d_inode->i_op->getxattr(lower_dentry,
ECRYPTFS_XATTR_NAME,
xattr_virt,
- PAGE_CACHE_SIZE);
+ PAGE_CACHE_SIZE, NULL);
if (!lower_i_mutex_held)
mutex_unlock(&lower_dentry->d_inode->i_mutex);
if (size < 0)
@@ -544,7 +544,7 @@ static int ecryptfs_write_inode_size_to_
mutex_lock(&lower_dentry->d_inode->i_mutex);
rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry,
ECRYPTFS_XATTR_NAME,
- xattr_virt, size, 0);
+ xattr_virt, size, 0, NULL);
if (!lower_i_mutex_held)
mutex_unlock(&lower_dentry->d_inode->i_mutex);
if (rc)
Index: linux/fs/jffs2/xattr.c
===================================================================
--- linux.orig/fs/jffs2/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/jffs2/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -947,7 +947,8 @@ static struct xattr_handler *xprefix_to_
return ret;
}
-ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
Index: linux/fs/jffs2/xattr.h
===================================================================
--- linux.orig/fs/jffs2/xattr.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/jffs2/xattr.h 2007-09-21 13:45:11.000000000 +0200
@@ -97,7 +97,7 @@ extern struct xattr_handler *jffs2_xattr
extern struct xattr_handler jffs2_user_xattr_handler;
extern struct xattr_handler jffs2_trusted_xattr_handler;
-extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
+extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t, struct file *);
#define jffs2_getxattr generic_getxattr
#define jffs2_setxattr generic_setxattr
#define jffs2_removexattr generic_removexattr
Index: linux/fs/jfs/jfs_xattr.h
===================================================================
--- linux.orig/fs/jfs/jfs_xattr.h 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/jfs/jfs_xattr.h 2007-09-21 13:45:11.000000000 +0200
@@ -55,11 +55,13 @@ struct jfs_ea_list {
extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *,
size_t, int);
extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
- int);
+ int, struct file *);
extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
-extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
-extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
-extern int jfs_removexattr(struct dentry *, const char *);
+extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t,
+ struct file *);
+extern ssize_t jfs_listxattr(struct dentry *, char *, size_t,
+ struct file *);
+extern int jfs_removexattr(struct dentry *, const char *, struct file *);
#ifdef CONFIG_JFS_SECURITY
extern int jfs_init_security(tid_t, struct inode *, struct inode *);
Index: linux/fs/jfs/xattr.c
===================================================================
--- linux.orig/fs/jfs/xattr.c 2007-09-21 13:44:54.000000000 +0200
+++ linux/fs/jfs/xattr.c 2007-09-21 13:45:11.000000000 +0200
@@ -920,7 +920,7 @@ int __jfs_setxattr(tid_t tid, struct ino
}
int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t value_len, int flags)
+ size_t value_len, int flags, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct jfs_inode_info *ji = JFS_IP(inode);
@@ -1012,7 +1012,7 @@ ssize_t __jfs_getxattr(struct inode *ino
}
ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
- size_t buf_size)
+ size_t buf_size, struct file *file)
{
int err;
@@ -1031,7 +1031,8 @@ static inline int can_list(struct jfs_ea
capable(CAP_SYS_ADMIN));
}
-ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
+ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size,
+ struct file *file)
{
struct inode *inode = dentry->d_inode;
char *buffer;
@@ -1084,7 +1085,7 @@ ssize_t jfs_listxattr(struct dentry * de
return size;
}
-int jfs_removexattr(struct dentry *dentry, const char *name)
+int jfs_removexattr(struct dentry *dentry, const char *name, struct file *file)
{
struct inode *inode = dentry->d_inode;
struct jfs_inode_info *ji = JFS_IP(inode);
Index: linux/Documentation/filesystems/Locking
===================================================================
--- linux.orig/Documentation/filesystems/Locking 2007-09-21 13:45:07.000000000 +0200
+++ linux/Documentation/filesystems/Locking 2007-09-21 13:45:11.000000000 +0200
@@ -48,10 +48,12 @@ ata *);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *,
struct file *);
- int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
- int (*removexattr) (struct dentry *, const char *);
+ int (*setxattr) (struct dentry *, const char *, const void *, size_t,
+ int, struct file *);
+ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,
+ struct file *);
+ ssize_t (*listxattr) (struct dentry *, char *, size_t, struct file *);
+ int (*removexattr) (struct dentry *, const char *, struct file *);
locking rules:
all may block, none have BKL
Index: linux/Documentation/filesystems/vfs.txt
===================================================================
--- linux.orig/Documentation/filesystems/vfs.txt 2007-09-21 13:45:07.000000000 +0200
+++ linux/Documentation/filesystems/vfs.txt 2007-09-21 13:45:11.000000000 +0200
@@ -344,10 +344,12 @@ struct inode_operations {
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *,
struct file *);
- int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
- int (*removexattr) (struct dentry *, const char *);
+ int (*setxattr) (struct dentry *, const char *, const void *, size_t,
+ int, struct file *);
+ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,
+ struct file *);
+ ssize_t (*listxattr) (struct dentry *, char *, size_t, struct file *);
+ int (*removexattr) (struct dentry *, const char *, struct file *);
void (*truncate_range)(struct inode *, loff_t, loff_t);
};
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [patch 4/5] VFS: allow filesystems to implement atomic open+truncate
2007-09-21 12:23 [patch 0/5] VFS changes Miklos Szeredi
` (2 preceding siblings ...)
2007-09-21 12:23 ` [patch 3/5] VFS: pass open file to ->xattr() Miklos Szeredi
@ 2007-09-21 12:23 ` Miklos Szeredi
2007-09-21 12:44 ` Christoph Hellwig
2007-09-21 18:47 ` Andreas Dilger
2007-09-21 12:23 ` [patch 5/5] VFS: allow filesystem to override mknod capability checks Miklos Szeredi
4 siblings, 2 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 12:23 UTC (permalink / raw)
To: akpm; +Cc: hch, linux-kernel, linux-fsdevel
[-- Attachment #1: vfs_atomic_open_truncate.patch --]
[-- Type: text/plain, Size: 2553 bytes --]
From: Miklos Szeredi <mszeredi@suse.cz>
Add a new attribute flag ATTR_OPEN, with the meaning: "truncation was
initiated by open() due to the O_TRUNC flag".
This way filesystems wanting to implement truncation within their
->open() method can ignore such truncate requests.
This is a quick & dirty hack, but it comes for free.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
Index: linux/fs/namei.c
===================================================================
--- linux.orig/fs/namei.c 2007-09-21 13:44:53.000000000 +0200
+++ linux/fs/namei.c 2007-09-21 13:45:14.000000000 +0200
@@ -1656,8 +1656,10 @@ int may_open(struct nameidata *nd, int a
error = locks_verify_locked(inode);
if (!error) {
DQUOT_INIT(inode);
-
- error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL);
+
+ error = do_truncate(dentry, 0,
+ ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
+ NULL);
}
put_write_access(inode);
if (error)
Index: linux/include/linux/fs.h
===================================================================
--- linux.orig/include/linux/fs.h 2007-09-21 13:45:11.000000000 +0200
+++ linux/include/linux/fs.h 2007-09-21 13:45:14.000000000 +0200
@@ -337,6 +337,7 @@ typedef void (dio_iodone_t)(struct kiocb
#define ATTR_KILL_SGID 4096
#define ATTR_FILE 8192
#define ATTR_KILL_PRIV 16384
+#define ATTR_OPEN 32768 /* Truncating from open(O_TRUNC) */
/*
* This is the Inode Attributes structure, used for notify_change(). It
@@ -1526,7 +1527,7 @@ static inline int break_lease(struct ino
/* fs/open.c */
-extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
+extern int do_truncate(struct dentry *, loff_t start, unsigned int attrs,
struct file *filp);
extern long do_sys_open(int fdf, const char __user *filename, int flags,
int mode);
Index: linux/fs/open.c
===================================================================
--- linux.orig/fs/open.c 2007-09-21 13:45:04.000000000 +0200
+++ linux/fs/open.c 2007-09-21 13:45:14.000000000 +0200
@@ -194,7 +194,7 @@ out:
return error;
}
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+int do_truncate(struct dentry *dentry, loff_t length, unsigned int attrs,
struct file *filp)
{
int err;
@@ -205,7 +205,7 @@ int do_truncate(struct dentry *dentry, l
return -EINVAL;
newattrs.ia_size = length;
- newattrs.ia_valid = ATTR_SIZE | time_attrs;
+ newattrs.ia_valid = ATTR_SIZE | attrs;
if (filp) {
newattrs.ia_file = filp;
newattrs.ia_valid |= ATTR_FILE;
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 12:23 [patch 0/5] VFS changes Miklos Szeredi
` (3 preceding siblings ...)
2007-09-21 12:23 ` [patch 4/5] VFS: allow filesystems to implement atomic open+truncate Miklos Szeredi
@ 2007-09-21 12:23 ` Miklos Szeredi
2007-09-21 12:45 ` Christoph Hellwig
4 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 12:23 UTC (permalink / raw)
To: akpm; +Cc: hch, linux-kernel, linux-fsdevel
[-- Attachment #1: vfs_mknod_nocheck.patch --]
[-- Type: text/plain, Size: 2055 bytes --]
From: Miklos Szeredi <mszeredi@suse.cz>
Add a new filesystem flag, that results in the VFS not checking if the
current process has enough privileges to do an mknod().
This is needed on filesystems, where an unprivileged user may be able
to create a device node, without causing security problems.
One such example is "mountlo" a loopback mount utility implemented
with fuse and UML, which runs as an unprivileged userspace process.
In this case the user does in fact have the right to create device
nodes within the filesystem image, as long as the user has write
access to the image. Since the filesystem is mounted with "nodev",
adding device nodes is not a security concern.
This feature is basically "fuse-only", so it does not make sense to
change the semantics of ->mknod().
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
Index: linux/fs/namei.c
===================================================================
--- linux.orig/fs/namei.c 2007-09-21 13:45:14.000000000 +0200
+++ linux/fs/namei.c 2007-09-21 13:45:16.000000000 +0200
@@ -1922,7 +1922,8 @@ int vfs_mknod(struct inode *dir, struct
if (error)
return error;
- if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
+ if (!(dir->i_sb->s_type->fs_flags & FS_MKNOD_CHECKS_PERM) &&
+ (S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
return -EPERM;
if (!dir->i_op || !dir->i_op->mknod)
Index: linux/include/linux/fs.h
===================================================================
--- linux.orig/include/linux/fs.h 2007-09-21 13:45:14.000000000 +0200
+++ linux/include/linux/fs.h 2007-09-21 13:45:16.000000000 +0200
@@ -97,6 +97,7 @@ extern int dir_notify_enable;
#define FS_BINARY_MOUNTDATA 2
#define FS_HAS_SUBTYPE 4
#define FS_SAFE 8 /* Safe to mount by unprivileged users */
+#define FS_MKNOD_CHECKS_PERM 16 /* FS checks if device creation is allowed */
#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move()
* during rename() internally.
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 12:23 ` [patch 3/5] VFS: pass open file to ->xattr() Miklos Szeredi
@ 2007-09-21 12:43 ` Christoph Hellwig
2007-09-21 13:00 ` Miklos Szeredi
2007-09-21 18:39 ` Andreas Dilger
1 sibling, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 12:43 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: akpm, hch, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 02:23:46PM +0200, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
>
> Pass the open file into the filesystem's *xattr() methods.
>
> This is needed to be able to correctly implement open-unlink-f*xattr
> semantics, without having to resort to "silly-renaming".
>
> Do this by adding a 'struct file *' parameter to i_op->*xattr(). For
> f... variants pass the open file pointer, in other cases pass NULL.
>
> This is safe from a compatibility standpoint, out-of-tree old stuff
> will continue to work, but will get a warning at compile time.
NACK, no more optional arguments, and passing file structs to xattr
stuff is silly. If your filesystem doesn't get open but unliked
right you will have to resort to silly renaming, I'm sorry.
Same argument applies to all pass file down patches in the series,
I won't comment on the separately.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 4/5] VFS: allow filesystems to implement atomic open+truncate
2007-09-21 12:23 ` [patch 4/5] VFS: allow filesystems to implement atomic open+truncate Miklos Szeredi
@ 2007-09-21 12:44 ` Christoph Hellwig
2007-09-21 13:01 ` Miklos Szeredi
2007-09-21 18:47 ` Andreas Dilger
1 sibling, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 12:44 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: akpm, hch, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 02:23:47PM +0200, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
>
> Add a new attribute flag ATTR_OPEN, with the meaning: "truncation was
> initiated by open() due to the O_TRUNC flag".
>
> This way filesystems wanting to implement truncation within their
> ->open() method can ignore such truncate requests.
>
> This is a quick & dirty hack, but it comes for free.
Fine with me as it doesn't cause any active harm, but expect this to
go away once the nfs intent mess is cleaned up and we'll get a real
method for this kind of thing.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 12:23 ` [patch 5/5] VFS: allow filesystem to override mknod capability checks Miklos Szeredi
@ 2007-09-21 12:45 ` Christoph Hellwig
2007-09-21 13:10 ` Miklos Szeredi
0 siblings, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 12:45 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: akpm, hch, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 02:23:48PM +0200, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
>
> Add a new filesystem flag, that results in the VFS not checking if the
> current process has enough privileges to do an mknod().
>
> This is needed on filesystems, where an unprivileged user may be able
> to create a device node, without causing security problems.
A user should never be able to create devices. And no, I don't want to
see a filesystem that implements it's own file operations for device nodes.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 12:43 ` Christoph Hellwig
@ 2007-09-21 13:00 ` Miklos Szeredi
2007-09-21 13:06 ` Christoph Hellwig
0 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 13:00 UTC (permalink / raw)
To: hch; +Cc: miklos, akpm, hch, linux-kernel, linux-fsdevel
> On Fri, Sep 21, 2007 at 02:23:46PM +0200, Miklos Szeredi wrote:
> > From: Miklos Szeredi <mszeredi@suse.cz>
> >
> > Pass the open file into the filesystem's *xattr() methods.
> >
> > This is needed to be able to correctly implement open-unlink-f*xattr
> > semantics, without having to resort to "silly-renaming".
> >
> > Do this by adding a 'struct file *' parameter to i_op->*xattr(). For
> > f... variants pass the open file pointer, in other cases pass NULL.
> >
> > This is safe from a compatibility standpoint, out-of-tree old stuff
> > will continue to work, but will get a warning at compile time.
>
> NACK, no more optional arguments, and passing file structs to xattr
> stuff is silly. If your filesystem doesn't get open but unliked
> right you will have to resort to silly renaming, I'm sorry.
>
> Same argument applies to all pass file down patches in the series,
> I won't comment on the separately.
I don't think it's silly. Read/write get passed the file descriptor,
and it makes a lot of sense, if the filesystem has stateful opens.
Similarly for any fs operation that gets a file descriptor, it makes
sense to pass the relevant open file down into the filesystem.
If you look carefully, the ftrunacate() already does this, becuse
without that it's impossible to implement correct semantics in the
filesystem in some cases.
For other operations it's not impossible, but it would mean more hacks
in the filesystem itself (such as sillyrenaming) that are entirely
unneeded if the file info is available.
I agree, that the xattr API is quite ugly already, but adding one more
argument won't make it all that much worse.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 4/5] VFS: allow filesystems to implement atomic open+truncate
2007-09-21 12:44 ` Christoph Hellwig
@ 2007-09-21 13:01 ` Miklos Szeredi
0 siblings, 0 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 13:01 UTC (permalink / raw)
To: hch; +Cc: miklos, akpm, hch, linux-kernel, linux-fsdevel
> > From: Miklos Szeredi <mszeredi@suse.cz>
> >
> > Add a new attribute flag ATTR_OPEN, with the meaning: "truncation was
> > initiated by open() due to the O_TRUNC flag".
> >
> > This way filesystems wanting to implement truncation within their
> > ->open() method can ignore such truncate requests.
> >
> > This is a quick & dirty hack, but it comes for free.
>
> Fine with me as it doesn't cause any active harm, but expect this to
> go away once the nfs intent mess is cleaned up and we'll get a real
> method for this kind of thing.
Sure.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 13:00 ` Miklos Szeredi
@ 2007-09-21 13:06 ` Christoph Hellwig
2007-09-21 13:16 ` Miklos Szeredi
0 siblings, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 13:06 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: hch, akpm, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 03:00:06PM +0200, Miklos Szeredi wrote:
> I don't think it's silly. Read/write get passed the file descriptor,
> and it makes a lot of sense, if the filesystem has stateful opens.
>
> Similarly for any fs operation that gets a file descriptor, it makes
> sense to pass the relevant open file down into the filesystem.
read/write fundamentally operate on file descriptors. None of these
operations does, rather their normal forms get a path name and special
forms operate on a file descriptor to avoid lookup races. Still the
underlying operation has nothing to do with the file descriptor at all.
> If you look carefully, the ftrunacate() already does this, becuse
> without that it's impossible to implement correct semantics in the
> filesystem in some cases.
ftruncate is a special case due to O_TRUNC. But I have plans to solve
this whole issue more elegant than the current hack.
> For other operations it's not impossible, but it would mean more hacks
> in the filesystem itself (such as sillyrenaming) that are entirely
> unneeded if the file info is available.
It's not a problem at all for filesystem that implement normal unix
semantics. If you want to shoer-horn strange semantics that barely
fit, you'll need some more hacks.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 12:45 ` Christoph Hellwig
@ 2007-09-21 13:10 ` Miklos Szeredi
2007-09-21 13:14 ` Christoph Hellwig
0 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 13:10 UTC (permalink / raw)
To: hch; +Cc: miklos, akpm, hch, linux-kernel, linux-fsdevel
> > From: Miklos Szeredi <mszeredi@suse.cz>
> >
> > Add a new filesystem flag, that results in the VFS not checking if the
> > current process has enough privileges to do an mknod().
> >
> > This is needed on filesystems, where an unprivileged user may be able
> > to create a device node, without causing security problems.
>
> A user should never be able to create devices.
A user can already create a device with fuse implicitly. This patch
would just allow that explicitly.
Take this example: I've loopback mounted an UML disk image using fuse
(no privileges required), and want to create some device nodes. I
can't yet boot the UML because the device node is missing from the
image. So what should I do. Currently I have to manipulate the
mounted image as root. But that's really shouldn't be needed.
> And no, I don't want to see a filesystem that implements it's own
> file operations for device nodes.
I don't want that either, and it has nothing to do with this patch.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 13:10 ` Miklos Szeredi
@ 2007-09-21 13:14 ` Christoph Hellwig
2007-09-21 13:18 ` Miklos Szeredi
0 siblings, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 13:14 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: hch, akpm, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 03:10:26PM +0200, Miklos Szeredi wrote:
> Take this example: I've loopback mounted an UML disk image using fuse
> (no privileges required), and want to create some device nodes. I
> can't yet boot the UML because the device node is missing from the
> image. So what should I do. Currently I have to manipulate the
> mounted image as root. But that's really shouldn't be needed.
That's something that shouldn't be solved in the filesystem, but rather
through exact semantics of unprivilegued mounts. Given that an
unprivilegued implies ignoring the device files we can easily allow
users to create them, because they're nothing special anymore.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 13:06 ` Christoph Hellwig
@ 2007-09-21 13:16 ` Miklos Szeredi
2007-09-21 14:32 ` Trond Myklebust
0 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 13:16 UTC (permalink / raw)
To: hch; +Cc: miklos, hch, akpm, linux-kernel, linux-fsdevel
> > I don't think it's silly. Read/write get passed the file descriptor,
> > and it makes a lot of sense, if the filesystem has stateful opens.
> >
> > Similarly for any fs operation that gets a file descriptor, it makes
> > sense to pass the relevant open file down into the filesystem.
>
> read/write fundamentally operate on file descriptors. None of these
> operations does, rather their normal forms get a path name and special
> forms operate on a file descriptor to avoid lookup races. Still the
> underlying operation has nothing to do with the file descriptor at all.
I don't see why read/write are special, "normal" filesystems don't
need the file descriptor in that case either.
And other in BSD's, OS X, the read/write fs ops don't get the open
file, and their fuse implementations have to hack around this.
The exact same thing is true for the other operations on file
descriptors, just in those cases Linux does the same as the other
OS's.
> > If you look carefully, the ftrunacate() already does this, becuse
> > without that it's impossible to implement correct semantics in the
> > filesystem in some cases.
>
> ftruncate is a special case due to O_TRUNC.
No, it's special, because it does not do permission checking, while
truncate() does.
> > For other operations it's not impossible, but it would mean more hacks
> > in the filesystem itself (such as sillyrenaming) that are entirely
> > unneeded if the file info is available.
>
> It's not a problem at all for filesystem that implement normal unix
> semantics. If you want to shoer-horn strange semantics that barely
> fit, you'll need some more hacks.
What about sshfs. Basically it uses the sftp protocol, which more or
less implements the UNIX API in a remote protocol.
So it has OPEN, READ, WRITE, CLOSE, STAT, FSTAT, etc. operation. Now
why is FSTAT different than READ or WRITE?
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 13:14 ` Christoph Hellwig
@ 2007-09-21 13:18 ` Miklos Szeredi
2007-09-21 14:33 ` Christoph Hellwig
0 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 13:18 UTC (permalink / raw)
To: hch; +Cc: miklos, hch, akpm, linux-kernel, linux-fsdevel
> > Take this example: I've loopback mounted an UML disk image using fuse
> > (no privileges required), and want to create some device nodes. I
> > can't yet boot the UML because the device node is missing from the
> > image. So what should I do. Currently I have to manipulate the
> > mounted image as root. But that's really shouldn't be needed.
>
> That's something that shouldn't be solved in the filesystem, but rather
> through exact semantics of unprivilegued mounts. Given that an
> unprivilegued implies ignoring the device files we can easily allow
> users to create them, because they're nothing special anymore.
Exacly. And we already have an API for that: mknod(2). It would be
quite stupid to introduce _another_ API to do the same. It would mean
that all the tools, like mknod(8) would not work with the new API.
Or am I misunderstanding your suggestion?
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 13:16 ` Miklos Szeredi
@ 2007-09-21 14:32 ` Trond Myklebust
2007-09-21 14:34 ` Christoph Hellwig
2007-09-21 14:43 ` Miklos Szeredi
0 siblings, 2 replies; 30+ messages in thread
From: Trond Myklebust @ 2007-09-21 14:32 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: hch, akpm, linux-kernel, linux-fsdevel
On Fri, 2007-09-21 at 15:16 +0200, Miklos Szeredi wrote:
> > ftruncate is a special case due to O_TRUNC.
>
> No, it's special, because it does not do permission checking, while
> truncate() does.
So why not just add file->f_op->ftruncate() and file->f_op->fstat()?
Most filesystems can trivially redirect these to do_truncate() and their
existing getattr() method. Those, like FUSE, that care can use the hook.
In fact, I think that NFSv4 could also benefit from an ftruncate():
currently we have to hunt around for an open file context for that
particular case.
Trond
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 13:18 ` Miklos Szeredi
@ 2007-09-21 14:33 ` Christoph Hellwig
2007-09-21 14:48 ` Miklos Szeredi
0 siblings, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 14:33 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: hch, akpm, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 03:18:33PM +0200, Miklos Szeredi wrote:
> > That's something that shouldn't be solved in the filesystem, but rather
> > through exact semantics of unprivilegued mounts. Given that an
> > unprivilegued implies ignoring the device files we can easily allow
> > users to create them, because they're nothing special anymore.
>
> Exacly. And we already have an API for that: mknod(2). It would be
> quite stupid to introduce _another_ API to do the same. It would mean
> that all the tools, like mknod(8) would not work with the new API.
>
> Or am I misunderstanding your suggestion?
Yes :)
My suggestions is:
- mknod for unprivilegued user is allowed in the following case
(1) mount point is mounted with MNT_NODEV
(2) mount point is owner by the user doing mknod
- and maybe
(3) we have a special mount option to allow it if we don't want
to allow it for normal unprivilegued mounts for some reason
which implies we need to get in unprivilegued mounts first, but we'll
have to do that anyway.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 14:32 ` Trond Myklebust
@ 2007-09-21 14:34 ` Christoph Hellwig
2007-09-21 14:59 ` Miklos Szeredi
2007-09-21 14:43 ` Miklos Szeredi
1 sibling, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 14:34 UTC (permalink / raw)
To: Trond Myklebust; +Cc: Miklos Szeredi, hch, akpm, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 10:32:31AM -0400, Trond Myklebust wrote:
> On Fri, 2007-09-21 at 15:16 +0200, Miklos Szeredi wrote:
>
> > > ftruncate is a special case due to O_TRUNC.
> >
> > No, it's special, because it does not do permission checking, while
> > truncate() does.
>
> So why not just add file->f_op->ftruncate() and file->f_op->fstat()?
> Most filesystems can trivially redirect these to do_truncate() and their
> existing getattr() method. Those, like FUSE, that care can use the hook.
> In fact, I think that NFSv4 could also benefit from an ftruncate():
> currently we have to hunt around for an open file context for that
> particular case.
Havin the file for fruncate is fine and I'm planning to do something
along those lines. Having it for (f)stat is dumb because the operation
is in no way related to the open file descriptor.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 14:32 ` Trond Myklebust
2007-09-21 14:34 ` Christoph Hellwig
@ 2007-09-21 14:43 ` Miklos Szeredi
1 sibling, 0 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 14:43 UTC (permalink / raw)
To: trond.myklebust; +Cc: hch, akpm, linux-kernel, linux-fsdevel
> > > ftruncate is a special case due to O_TRUNC.
> >
> > No, it's special, because it does not do permission checking, while
> > truncate() does.
>
> So why not just add file->f_op->ftruncate() and file->f_op->fstat()?
Sure, we could add those.
I'm not sure it's worth adding new file operations, instead of just
adding a parameter to ->getattr(), and ->*xattr(), but if that's more
acceptable. it's fine for me.
> Most filesystems can trivially redirect these to do_truncate() and their
> existing getattr() method. Those, like FUSE, that care can use the hook.
> In fact, I think that NFSv4 could also benefit from an ftruncate():
> currently we have to hunt around for an open file context for that
> particular case.
For ftruncate you can already access the open file from iattr->ia_file.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 14:33 ` Christoph Hellwig
@ 2007-09-21 14:48 ` Miklos Szeredi
2007-09-21 14:53 ` Christoph Hellwig
0 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 14:48 UTC (permalink / raw)
To: hch; +Cc: miklos, hch, akpm, linux-kernel, linux-fsdevel
> On Fri, Sep 21, 2007 at 03:18:33PM +0200, Miklos Szeredi wrote:
> > > That's something that shouldn't be solved in the filesystem, but rather
> > > through exact semantics of unprivilegued mounts. Given that an
> > > unprivilegued implies ignoring the device files we can easily allow
> > > users to create them, because they're nothing special anymore.
> >
> > Exacly. And we already have an API for that: mknod(2). It would be
> > quite stupid to introduce _another_ API to do the same. It would mean
> > that all the tools, like mknod(8) would not work with the new API.
> >
> > Or am I misunderstanding your suggestion?
>
> Yes :)
>
> My suggestions is:
>
> - mknod for unprivilegued user is allowed in the following case
>
> (1) mount point is mounted with MNT_NODEV
> (2) mount point is owner by the user doing mknod
Ah, OK. Well, that's what fuse would do with the above change. So
you are basically saying, the change is OK, but we want proper
unprivileged mounts first.
> - and maybe
>
> (3) we have a special mount option to allow it if we don't want
> to allow it for normal unprivilegued mounts for some reason
I'm sure we don't want it by default.
For example if user bind mounts / onto /home/user/myroot (with 'nodev'
of couse), we still don't want mknod to work on that mount, for
obvious reasons.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 14:48 ` Miklos Szeredi
@ 2007-09-21 14:53 ` Christoph Hellwig
2007-09-21 15:11 ` Miklos Szeredi
0 siblings, 1 reply; 30+ messages in thread
From: Christoph Hellwig @ 2007-09-21 14:53 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: hch, akpm, linux-kernel, linux-fsdevel
On Fri, Sep 21, 2007 at 04:48:58PM +0200, Miklos Szeredi wrote:
> Ah, OK. Well, that's what fuse would do with the above change. So
> you are basically saying, the change is OK, but we want proper
> unprivileged mounts first.
Yes, that and that it should be a mount flag, not a file_system_type
flag.
> I'm sure we don't want it by default.
>
> For example if user bind mounts / onto /home/user/myroot (with 'nodev'
> of couse), we still don't want mknod to work on that mount, for
> obvious reasons.
True, we'll have to deny it if there is any non-privilegued mount of
the backing device possible. At this point it's getting rather nasty
and I wonder whether it's really worth it..
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 14:34 ` Christoph Hellwig
@ 2007-09-21 14:59 ` Miklos Szeredi
2007-09-21 18:44 ` Andreas Dilger
0 siblings, 1 reply; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 14:59 UTC (permalink / raw)
To: hch; +Cc: trond.myklebust, miklos, hch, akpm, linux-kernel, linux-fsdevel
> On Fri, Sep 21, 2007 at 10:32:31AM -0400, Trond Myklebust wrote:
> > On Fri, 2007-09-21 at 15:16 +0200, Miklos Szeredi wrote:
> >
> > > > ftruncate is a special case due to O_TRUNC.
> > >
> > > No, it's special, because it does not do permission checking, while
> > > truncate() does.
> >
> > So why not just add file->f_op->ftruncate() and file->f_op->fstat()?
> > Most filesystems can trivially redirect these to do_truncate() and their
> > existing getattr() method. Those, like FUSE, that care can use the hook.
> > In fact, I think that NFSv4 could also benefit from an ftruncate():
> > currently we have to hunt around for an open file context for that
> > particular case.
>
> Havin the file for fruncate is fine and I'm planning to do something
> along those lines. Having it for (f)stat is dumb because the operation
> is in no way related to the open file descriptor.
What I'm saying is that read and write are _no_more_ related to the
file than fstat. Read/write operate on inode data, fstat operates on
inode metadata.
OK, read/write have a position state in the open file, but that is
something the filesystem should _never_ touch anyway, so it's
irrelevant to the discussion.
The fact is, if the filesystem uses a stateful open API, which defines
an fstat() operation, it can be useful to use that instead of the
plain stat(). But that is only possible if the VFS supplies the open
file, otherwise there will be just "hunting around" for suitable open
files, or "sillyrenaming". None of which is desirable.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 5/5] VFS: allow filesystem to override mknod capability checks
2007-09-21 14:53 ` Christoph Hellwig
@ 2007-09-21 15:11 ` Miklos Szeredi
0 siblings, 0 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 15:11 UTC (permalink / raw)
To: hch; +Cc: miklos, hch, akpm, linux-kernel, linux-fsdevel
> On Fri, Sep 21, 2007 at 04:48:58PM +0200, Miklos Szeredi wrote:
> > Ah, OK. Well, that's what fuse would do with the above change. So
> > you are basically saying, the change is OK, but we want proper
> > unprivileged mounts first.
>
> Yes, that and that it should be a mount flag, not a file_system_type
> flag.
>
> > I'm sure we don't want it by default.
> >
> > For example if user bind mounts / onto /home/user/myroot (with 'nodev'
> > of couse), we still don't want mknod to work on that mount, for
> > obvious reasons.
>
> True, we'll have to deny it if there is any non-privilegued mount of
> the backing device possible. At this point it's getting rather nasty
> and I wonder whether it's really worth it..
I think the assumption, that we want this as a generic service is
false.
We want this as a special service for a few filesystems, such as the
unprivileged userspace loopback mounting I was talking about.
So my thinking is: if an unprivileged filesystem explicitly asks for
this, then it should be allowed. It could be a per-superblock flag
instead of a per fs-type flag, if that sounds better.
My fuse implementation would have been exactly the same: the ->mknod()
implementation would check a per filesystem flag, and if it's not set,
check the permissions as normal mknod() would. Here's the relevant
patch snippet:
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2007-09-21 13:45:23.000000000 +0200
+++ linux/fs/fuse/dir.c 2007-09-21 13:45:25.000000000 +0200
@@ -486,7 +486,13 @@ static int fuse_mknod(struct inode *dir,
{
struct fuse_mknod_in inarg;
struct fuse_conn *fc = get_fuse_conn(dir);
- struct fuse_req *req = fuse_get_req(fc);
+ struct fuse_req *req;
+
+ if (!fc->mknod_nocheck &&
+ ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)))
+ return -EPERM;
+
+ req = fuse_get_req(fc);
if (IS_ERR(req))
return PTR_ERR(req);
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 2/5] VFS: pass open file to ->getattr()
2007-09-21 12:23 ` [patch 2/5] VFS: pass open file to ->getattr() Miklos Szeredi
@ 2007-09-21 18:37 ` Andreas Dilger
2007-09-21 21:07 ` Miklos Szeredi
0 siblings, 1 reply; 30+ messages in thread
From: Andreas Dilger @ 2007-09-21 18:37 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: akpm, hch, linux-kernel, linux-fsdevel
On Sep 21, 2007 14:23 +0200, Miklos Szeredi wrote:
> @@ -1212,7 +1212,8 @@ struct inode_operations {
> - int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
> + int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *,
> + struct file *file);
It's not much of an inode operation anymore if you need to pass a file
to it... Since the attributes are really part of the inode and not
the file, this seems like a bit of a hack.
Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 12:23 ` [patch 3/5] VFS: pass open file to ->xattr() Miklos Szeredi
2007-09-21 12:43 ` Christoph Hellwig
@ 2007-09-21 18:39 ` Andreas Dilger
1 sibling, 0 replies; 30+ messages in thread
From: Andreas Dilger @ 2007-09-21 18:39 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: akpm, hch, linux-kernel, linux-fsdevel
On Sep 21, 2007 14:23 +0200, Miklos Szeredi wrote:
> @@ -1214,10 +1214,12 @@ struct inode_operations {
> + int (*setxattr) (struct dentry *, const char *,const void *,size_t,int,
> + struct file *);
> + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,
> + struct file *);
> + ssize_t (*listxattr) (struct dentry *, char *, size_t, struct file *);
> + int (*removexattr) (struct dentry *, const char *, struct file *);
Likewise - these are no longer inode operations if you need a file.
Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 14:59 ` Miklos Szeredi
@ 2007-09-21 18:44 ` Andreas Dilger
2007-09-21 21:15 ` Miklos Szeredi
0 siblings, 1 reply; 30+ messages in thread
From: Andreas Dilger @ 2007-09-21 18:44 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: hch, trond.myklebust, akpm, linux-kernel, linux-fsdevel
On Sep 21, 2007 16:59 +0200, Miklos Szeredi wrote:
> What I'm saying is that read and write are _no_more_ related to the
> file than fstat. Read/write operate on inode data, fstat operates on
> inode metadata.
The read and write operations are DEFINITELY related to the file descriptor
because of f_pos. Each process opening the same file can have a different
f_pos so read/write will work in different locations of the file.
In contrast getattr and getxattr operate on the single inode and you don't
get e.g. a different i_size or i_uid or i_gid depending on who opened a
file, nor is the xattr different.
Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 4/5] VFS: allow filesystems to implement atomic open+truncate
2007-09-21 12:23 ` [patch 4/5] VFS: allow filesystems to implement atomic open+truncate Miklos Szeredi
2007-09-21 12:44 ` Christoph Hellwig
@ 2007-09-21 18:47 ` Andreas Dilger
1 sibling, 0 replies; 30+ messages in thread
From: Andreas Dilger @ 2007-09-21 18:47 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: akpm, hch, linux-kernel, linux-fsdevel
On Sep 21, 2007 14:23 +0200, Miklos Szeredi wrote:
> Add a new attribute flag ATTR_OPEN, with the meaning: "truncation was
> initiated by open() due to the O_TRUNC flag".
>
> This way filesystems wanting to implement truncation within their
> ->open() method can ignore such truncate requests.
This is actually something we've needed to do in Lustre for a while also.
We called it ATTR_FROM_OPEN, but I don't really mind ATTR_OPEN either -
the less patching we need to do the better.
Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 2/5] VFS: pass open file to ->getattr()
2007-09-21 18:37 ` Andreas Dilger
@ 2007-09-21 21:07 ` Miklos Szeredi
0 siblings, 0 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 21:07 UTC (permalink / raw)
To: adilger; +Cc: miklos, akpm, hch, linux-kernel, linux-fsdevel
> On Sep 21, 2007 14:23 +0200, Miklos Szeredi wrote:
> > @@ -1212,7 +1212,8 @@ struct inode_operations {
> > - int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
> > + int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *,
> > + struct file *file);
>
> It's not much of an inode operation anymore if you need to pass a file
> to it... Since the attributes are really part of the inode and not
> the file, this seems like a bit of a hack.
Well, the data is part of the inode and not the file as well. So why
are read/write special?
OK, I realize now, that with special files (device, fifo) the I/O is
actually on the open file and _not_ on the inode. So the above is
only true for regular files.
And so it really would make sense to make a separate fgetattr() file
operation, so we only get it for regular files and not for special
files. Because for the specail file case it really doesn't make sense
to pass the file pointer to the filesystem, since the filesystem knows
nothing about the open file.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [patch 3/5] VFS: pass open file to ->xattr()
2007-09-21 18:44 ` Andreas Dilger
@ 2007-09-21 21:15 ` Miklos Szeredi
0 siblings, 0 replies; 30+ messages in thread
From: Miklos Szeredi @ 2007-09-21 21:15 UTC (permalink / raw)
To: adilger; +Cc: miklos, hch, trond.myklebust, akpm, linux-kernel, linux-fsdevel
> > What I'm saying is that read and write are _no_more_ related to the
> > file than fstat. Read/write operate on inode data, fstat operates on
> > inode metadata.
>
> The read and write operations are DEFINITELY related to the file descriptor
> because of f_pos. Each process opening the same file can have a different
> f_pos so read/write will work in different locations of the file.
Ah yes, but f_pos is handled entirely within the VFS. The filesystem
has nothing to do with f_pos, and the read/write methods are passed
the offset explicitly.
So with that the read/write calls (for regular files at least) really
are not that different from fstat.
> In contrast getattr and getxattr operate on the single inode and you don't
> get e.g. a different i_size or i_uid or i_gid depending on who opened a
> file, nor is the xattr different.
You won't get different data either (again for regular files). Yet
passing file operations down to the filesystem implementation makes
sense even for regular files, even if for most filesystems we could
get away with a totally stateless read/write model (as some other OS's
apparently do).
What I'm arguing, is that if we pass the open file for read/write to
the filesystem for regular files, it makes _equally_ as much sense to
pass the open file for getattr/setattr/xattr operations.
Miklos
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2007-09-21 21:16 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-21 12:23 [patch 0/5] VFS changes Miklos Szeredi
2007-09-21 12:23 ` [patch 1/5] VFS: pass open file to ->setattr() Miklos Szeredi
2007-09-21 12:23 ` [patch 2/5] VFS: pass open file to ->getattr() Miklos Szeredi
2007-09-21 18:37 ` Andreas Dilger
2007-09-21 21:07 ` Miklos Szeredi
2007-09-21 12:23 ` [patch 3/5] VFS: pass open file to ->xattr() Miklos Szeredi
2007-09-21 12:43 ` Christoph Hellwig
2007-09-21 13:00 ` Miklos Szeredi
2007-09-21 13:06 ` Christoph Hellwig
2007-09-21 13:16 ` Miklos Szeredi
2007-09-21 14:32 ` Trond Myklebust
2007-09-21 14:34 ` Christoph Hellwig
2007-09-21 14:59 ` Miklos Szeredi
2007-09-21 18:44 ` Andreas Dilger
2007-09-21 21:15 ` Miklos Szeredi
2007-09-21 14:43 ` Miklos Szeredi
2007-09-21 18:39 ` Andreas Dilger
2007-09-21 12:23 ` [patch 4/5] VFS: allow filesystems to implement atomic open+truncate Miklos Szeredi
2007-09-21 12:44 ` Christoph Hellwig
2007-09-21 13:01 ` Miklos Szeredi
2007-09-21 18:47 ` Andreas Dilger
2007-09-21 12:23 ` [patch 5/5] VFS: allow filesystem to override mknod capability checks Miklos Szeredi
2007-09-21 12:45 ` Christoph Hellwig
2007-09-21 13:10 ` Miklos Szeredi
2007-09-21 13:14 ` Christoph Hellwig
2007-09-21 13:18 ` Miklos Szeredi
2007-09-21 14:33 ` Christoph Hellwig
2007-09-21 14:48 ` Miklos Szeredi
2007-09-21 14:53 ` Christoph Hellwig
2007-09-21 15:11 ` Miklos Szeredi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).