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: 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
This commit is contained in:
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
@@ -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);
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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,
|
||||
};
|
||||
|
Reference in New Issue
Block a user