Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  fs/dcache: allow d_obtain_alias() to return unhashed dentries
  Check for immutable/append flag in fallocate path
  sysctl: the include of rcupdate.h is only needed in the kernel
  fat: fix d_revalidate oopsen on NFS exports
  jfs: fix d_revalidate oopsen on NFS exports
  ocfs2: fix d_revalidate oopsen on NFS exports
  gfs2: fix d_revalidate oopsen on NFS exports
  fuse: fix d_revalidate oopsen on NFS exports
  ceph: fix d_revalidate oopsen on NFS exports
  reiserfs xattr ->d_revalidate() shouldn't care about RCU
  /proc/self is never going to be invalidated...
This commit is contained in:
Linus Torvalds 2011-03-10 13:16:01 -08:00
commit 4afcc10a65
10 changed files with 39 additions and 41 deletions

View File

@ -993,7 +993,7 @@ static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct inode *dir;
if (nd->flags & LOOKUP_RCU)
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
dir = dentry->d_parent->d_inode;

View File

@ -1523,6 +1523,28 @@ struct dentry * d_alloc_root(struct inode * root_inode)
}
EXPORT_SYMBOL(d_alloc_root);
static struct dentry * __d_find_any_alias(struct inode *inode)
{
struct dentry *alias;
if (list_empty(&inode->i_dentry))
return NULL;
alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias);
__dget(alias);
return alias;
}
static struct dentry * d_find_any_alias(struct inode *inode)
{
struct dentry *de;
spin_lock(&inode->i_lock);
de = __d_find_any_alias(inode);
spin_unlock(&inode->i_lock);
return de;
}
/**
* d_obtain_alias - find or allocate a dentry for a given inode
* @inode: inode to allocate the dentry for
@ -1552,7 +1574,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
if (IS_ERR(inode))
return ERR_CAST(inode);
res = d_find_alias(inode);
res = d_find_any_alias(inode);
if (res)
goto out_iput;
@ -1565,7 +1587,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
spin_lock(&inode->i_lock);
res = __d_find_alias(inode, 0);
res = __d_find_any_alias(inode);
if (res) {
spin_unlock(&inode->i_lock);
dput(tmp);

View File

@ -43,7 +43,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
{
if (nd->flags & LOOKUP_RCU)
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
/* This is not negative dentry. Always valid. */
@ -54,7 +54,7 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
{
if (nd->flags & LOOKUP_RCU)
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
/*

View File

@ -158,7 +158,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
{
struct inode *inode;
if (nd->flags & LOOKUP_RCU)
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
inode = entry->d_inode;

View File

@ -44,7 +44,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
int error;
int had_lock = 0;
if (nd->flags & LOOKUP_RCU)
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
parent = dget_parent(dentry);

View File

@ -1600,7 +1600,7 @@ out:
static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
{
if (nd->flags & LOOKUP_RCU)
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
/*
* This is not negative dentry. Always valid.

View File

@ -56,7 +56,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
int ret = 0; /* if all else fails, just return false */
struct ocfs2_super *osb;
if (nd->flags & LOOKUP_RCU)
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
inode = dentry->d_inode;

View File

@ -233,6 +233,14 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (!(file->f_mode & FMODE_WRITE))
return -EBADF;
/* It's not possible punch hole on append only file */
if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode))
return -EPERM;
if (IS_IMMUTABLE(inode))
return -EPERM;
/*
* Revalidate the write permissions, in case security policy has
* changed since the files were opened.

View File

@ -2620,35 +2620,6 @@ static const struct pid_entry proc_base_stuff[] = {
&proc_self_inode_operations, NULL, {}),
};
/*
* Exceptional case: normally we are not allowed to unhash a busy
* directory. In this case, however, we can do it - no aliasing problems
* due to the way we treat inodes.
*/
static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode;
struct task_struct *task;
if (nd->flags & LOOKUP_RCU)
return -ECHILD;
inode = dentry->d_inode;
task = get_proc_task(inode);
if (task) {
put_task_struct(task);
return 1;
}
d_drop(dentry);
return 0;
}
static const struct dentry_operations proc_base_dentry_operations =
{
.d_revalidate = proc_base_revalidate,
.d_delete = pid_delete_dentry,
};
static struct dentry *proc_base_instantiate(struct inode *dir,
struct dentry *dentry, struct task_struct *task, const void *ptr)
{
@ -2685,7 +2656,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
if (p->fop)
inode->i_fop = p->fop;
ei->op = p->op;
d_set_d_op(dentry, &proc_base_dentry_operations);
d_add(dentry, inode);
error = NULL;
out:

View File

@ -978,8 +978,6 @@ int reiserfs_permission(struct inode *inode, int mask, unsigned int flags)
static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
{
if (nd->flags & LOOKUP_RCU)
return -ECHILD;
return -EPERM;
}