Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  xfs: Fix build breakage in xfs_iops.c when CONFIG_FS_POSIX_ACL is not set
  VFS: Reorganise shrink_dcache_for_umount_subtree() after demise of dcache_lock
  VFS: Remove dentry->d_lock locking from shrink_dcache_for_umount_subtree()
  VFS: Remove detached-dentry counter from shrink_dcache_for_umount_subtree()
  switch posix_acl_chmod() to umode_t
  switch posix_acl_from_mode() to umode_t
  switch posix_acl_equiv_mode() to umode_t *
  switch posix_acl_create() to umode_t *
  block: initialise bd_super in bdget()
  vfs: avoid call to inode_lru_list_del() if possible
  vfs: avoid taking inode_hash_lock on pipes and sockets
  vfs: conditionally call inode_wb_list_del()
  VFS: Fix automount for negative autofs dentries
  Btrfs: load the key from the dir item in readdir into a fake dentry
  devtmpfs: missing initialialization in never-hit case
  hppfs: missing include
  • Loading branch information
Linus Torvalds committed Aug 1, 2011
2 parents 12ff47e + 206d440 commit 1b8e949
Show file tree
Hide file tree
Showing 31 changed files with 161 additions and 150 deletions.
2 changes: 1 addition & 1 deletion drivers/base/devtmpfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ static int create_path(const char *nodepath)
{
char *path;
char *s;
int err;
int err = 0;

/* parent directories do not exist, create them */
path = kstrdup(nodepath, GFP_KERNEL);
Expand Down
6 changes: 3 additions & 3 deletions fs/9p/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,11 @@ int v9fs_set_create_acl(struct dentry *dentry,
return 0;
}

int v9fs_acl_mode(struct inode *dir, mode_t *modep,
int v9fs_acl_mode(struct inode *dir, umode_t *modep,
struct posix_acl **dpacl, struct posix_acl **pacl)
{
int retval = 0;
mode_t mode = *modep;
umode_t mode = *modep;
struct posix_acl *acl = NULL;

if (!S_ISLNK(mode)) {
Expand Down Expand Up @@ -319,7 +319,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
case ACL_TYPE_ACCESS:
name = POSIX_ACL_XATTR_ACCESS;
if (acl) {
mode_t mode = inode->i_mode;
umode_t mode = inode->i_mode;
retval = posix_acl_equiv_mode(acl, &mode);
if (retval < 0)
goto err_out;
Expand Down
4 changes: 2 additions & 2 deletions fs/9p/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type);
extern int v9fs_acl_chmod(struct dentry *);
extern int v9fs_set_create_acl(struct dentry *,
struct posix_acl **, struct posix_acl **);
extern int v9fs_acl_mode(struct inode *dir, mode_t *modep,
extern int v9fs_acl_mode(struct inode *dir, umode_t *modep,
struct posix_acl **dpacl, struct posix_acl **pacl);
#else
#define v9fs_iop_get_acl NULL
Expand All @@ -38,7 +38,7 @@ static inline int v9fs_set_create_acl(struct dentry *dentry,
{
return 0;
}
static inline int v9fs_acl_mode(struct inode *dir, mode_t *modep,
static inline int v9fs_acl_mode(struct inode *dir, umode_t *modep,
struct posix_acl **dpacl,
struct posix_acl **pacl)
{
Expand Down
6 changes: 3 additions & 3 deletions fs/9p/vfs_inode_dotl.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
int err = 0;
gid_t gid;
int flags;
mode_t mode;
umode_t mode;
char *name = NULL;
struct file *filp;
struct p9_qid qid;
Expand Down Expand Up @@ -348,7 +348,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
struct p9_fid *fid = NULL, *dfid = NULL;
gid_t gid;
char *name;
mode_t mode;
umode_t mode;
struct inode *inode;
struct p9_qid qid;
struct dentry *dir_dentry;
Expand Down Expand Up @@ -751,7 +751,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
int err;
gid_t gid;
char *name;
mode_t mode;
umode_t mode;
struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL, *dfid = NULL;
struct inode *inode;
Expand Down
1 change: 1 addition & 0 deletions fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@ struct block_device *bdget(dev_t dev)

if (inode->i_state & I_NEW) {
bdev->bd_contains = NULL;
bdev->bd_super = NULL;
bdev->bd_inode = inode;
bdev->bd_block_size = (1 << inode->i_blkbits);
bdev->bd_part_count = 0;
Expand Down
10 changes: 2 additions & 8 deletions fs/btrfs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,
int ret, size = 0;
const char *name;
char *value = NULL;
mode_t mode;

if (acl) {
ret = posix_acl_valid(acl);
Expand All @@ -122,13 +121,11 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,

switch (type) {
case ACL_TYPE_ACCESS:
mode = inode->i_mode;
name = POSIX_ACL_XATTR_ACCESS;
if (acl) {
ret = posix_acl_equiv_mode(acl, &mode);
ret = posix_acl_equiv_mode(acl, &inode->i_mode);
if (ret < 0)
return ret;
inode->i_mode = mode;
}
ret = 0;
break;
Expand Down Expand Up @@ -222,19 +219,16 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans,
}

if (IS_POSIXACL(dir) && acl) {
mode_t mode = inode->i_mode;

if (S_ISDIR(inode->i_mode)) {
ret = btrfs_set_acl(trans, inode, acl,
ACL_TYPE_DEFAULT);
if (ret)
goto failed;
}
ret = posix_acl_create(&acl, GFP_NOFS, &mode);
ret = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
if (ret < 0)
return ret;

inode->i_mode = mode;
if (ret > 0) {
/* we need an acl */
ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
Expand Down
47 changes: 45 additions & 2 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3993,12 +3993,19 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
struct btrfs_root *sub_root = root;
struct btrfs_key location;
int index;
int ret;
int ret = 0;

if (dentry->d_name.len > BTRFS_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);

ret = btrfs_inode_by_name(dir, dentry, &location);
if (unlikely(d_need_lookup(dentry))) {
memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
kfree(dentry->d_fsdata);
dentry->d_fsdata = NULL;
d_clear_need_lookup(dentry);
} else {
ret = btrfs_inode_by_name(dir, dentry, &location);
}

if (ret < 0)
return ERR_PTR(ret);
Expand Down Expand Up @@ -4053,6 +4060,12 @@ static int btrfs_dentry_delete(const struct dentry *dentry)
return 0;
}

static void btrfs_dentry_release(struct dentry *dentry)
{
if (dentry->d_fsdata)
kfree(dentry->d_fsdata);
}

static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
Expand All @@ -4075,6 +4088,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
struct btrfs_path *path;
struct list_head ins_list;
struct list_head del_list;
struct qstr q;
int ret;
struct extent_buffer *leaf;
int slot;
Expand Down Expand Up @@ -4164,6 +4178,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,

while (di_cur < di_total) {
struct btrfs_key location;
struct dentry *tmp;

if (verify_dir_item(root, leaf, di))
break;
Expand All @@ -4184,6 +4199,33 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
btrfs_dir_item_key_to_cpu(leaf, di, &location);

q.name = name_ptr;
q.len = name_len;
q.hash = full_name_hash(q.name, q.len);
tmp = d_lookup(filp->f_dentry, &q);
if (!tmp) {
struct btrfs_key *newkey;

newkey = kzalloc(sizeof(struct btrfs_key),
GFP_NOFS);
if (!newkey)
goto no_dentry;
tmp = d_alloc(filp->f_dentry, &q);
if (!tmp) {
kfree(newkey);
dput(tmp);
goto no_dentry;
}
memcpy(newkey, &location,
sizeof(struct btrfs_key));
tmp->d_fsdata = newkey;
tmp->d_flags |= DCACHE_NEED_LOOKUP;
d_rehash(tmp);
dput(tmp);
} else {
dput(tmp);
}
no_dentry:
/* is this a reference to our own snapshot? If so
* skip it
*/
Expand Down Expand Up @@ -7430,4 +7472,5 @@ static const struct inode_operations btrfs_symlink_inode_operations = {

const struct dentry_operations btrfs_dentry_operations = {
.d_delete = btrfs_dentry_delete,
.d_release = btrfs_dentry_release,
};
69 changes: 27 additions & 42 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,27 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
return parent;
}

/*
* Unhash a dentry without inserting an RCU walk barrier or checking that
* dentry->d_lock is locked. The caller must take care of that, if
* appropriate.
*/
static void __d_shrink(struct dentry *dentry)
{
if (!d_unhashed(dentry)) {
struct hlist_bl_head *b;
if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
b = &dentry->d_sb->s_anon;
else
b = d_hash(dentry->d_parent, dentry->d_name.hash);

hlist_bl_lock(b);
__hlist_bl_del(&dentry->d_hash);
dentry->d_hash.pprev = NULL;
hlist_bl_unlock(b);
}
}

/**
* d_drop - drop a dentry
* @dentry: dentry to drop
Expand All @@ -319,17 +340,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
void __d_drop(struct dentry *dentry)
{
if (!d_unhashed(dentry)) {
struct hlist_bl_head *b;
if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
b = &dentry->d_sb->s_anon;
else
b = d_hash(dentry->d_parent, dentry->d_name.hash);

hlist_bl_lock(b);
__hlist_bl_del(&dentry->d_hash);
dentry->d_hash.pprev = NULL;
hlist_bl_unlock(b);

__d_shrink(dentry);
dentry_rcuwalk_barrier(dentry);
}
}
Expand Down Expand Up @@ -828,44 +839,24 @@ EXPORT_SYMBOL(shrink_dcache_sb);
static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
{
struct dentry *parent;
unsigned detached = 0;

BUG_ON(!IS_ROOT(dentry));

/* detach this root from the system */
spin_lock(&dentry->d_lock);
dentry_lru_del(dentry);
__d_drop(dentry);
spin_unlock(&dentry->d_lock);

for (;;) {
/* descend to the first leaf in the current subtree */
while (!list_empty(&dentry->d_subdirs)) {
struct dentry *loop;

/* this is a branch with children - detach all of them
* from the system in one go */
spin_lock(&dentry->d_lock);
list_for_each_entry(loop, &dentry->d_subdirs,
d_u.d_child) {
spin_lock_nested(&loop->d_lock,
DENTRY_D_LOCK_NESTED);
dentry_lru_del(loop);
__d_drop(loop);
spin_unlock(&loop->d_lock);
}
spin_unlock(&dentry->d_lock);

/* move to the first child */
while (!list_empty(&dentry->d_subdirs))
dentry = list_entry(dentry->d_subdirs.next,
struct dentry, d_u.d_child);
}

/* consume the dentries from this leaf up through its parents
* until we find one with children or run out altogether */
do {
struct inode *inode;

/* detach from the system */
dentry_lru_del(dentry);
__d_shrink(dentry);

if (dentry->d_count != 0) {
printk(KERN_ERR
"BUG: Dentry %p{i=%lx,n=%s}"
Expand All @@ -886,14 +877,10 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
list_del(&dentry->d_u.d_child);
} else {
parent = dentry->d_parent;
spin_lock(&parent->d_lock);
parent->d_count--;
list_del(&dentry->d_u.d_child);
spin_unlock(&parent->d_lock);
}

detached++;

inode = dentry->d_inode;
if (inode) {
dentry->d_inode = NULL;
Expand Down Expand Up @@ -938,9 +925,7 @@ void shrink_dcache_for_umount(struct super_block *sb)

dentry = sb->s_root;
sb->s_root = NULL;
spin_lock(&dentry->d_lock);
dentry->d_count--;
spin_unlock(&dentry->d_lock);
shrink_dcache_for_umount_subtree(dentry);

while (!hlist_bl_empty(&sb->s_anon)) {
Expand Down
8 changes: 2 additions & 6 deletions fs/ext2/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,10 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
case ACL_TYPE_ACCESS:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
mode_t mode = inode->i_mode;
error = posix_acl_equiv_mode(acl, &mode);
error = posix_acl_equiv_mode(acl, &inode->i_mode);
if (error < 0)
return error;
else {
inode->i_mode = mode;
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
if (error == 0)
Expand Down Expand Up @@ -253,16 +251,14 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
inode->i_mode &= ~current_umask();
}
if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
mode_t mode = inode->i_mode;
if (S_ISDIR(inode->i_mode)) {
error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
if (error)
goto cleanup;
}
error = posix_acl_create(&acl, GFP_KERNEL, &mode);
error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
if (error < 0)
return error;
inode->i_mode = mode;
if (error > 0) {
/* This is an extended ACL */
error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
Expand Down
Loading

0 comments on commit 1b8e949

Please sign in to comment.