On Wed, Mar 20, 2019 at 02:37:17PM +0800, Qu Wenruo wrote:
> @@ -5726,18 +5734,29 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, 
> struct dentry *dentry)
>       struct btrfs_root *root = BTRFS_I(dir)->root;
>       struct btrfs_root *sub_root = root;
>       struct btrfs_key location;
> +     u8 di_type = 0;
>       int index;
>       int ret = 0;
>  
>       if (dentry->d_name.len > BTRFS_NAME_LEN)
>               return ERR_PTR(-ENAMETOOLONG);
>  
> -     ret = btrfs_inode_by_name(dir, dentry, &location);
> +     ret = btrfs_inode_by_name(dir, dentry, &location, &di_type);
>       if (ret < 0)
>               return ERR_PTR(ret);
>  
>       if (location.type == BTRFS_INODE_ITEM_KEY) {
>               inode = btrfs_iget(dir->i_sb, &location, root, NULL);
> +
> +             /* Do extra check against inode mode with di_type */
> +             if (btrfs_inode_type(inode) != di_type) {
> +                     btrfs_crit(fs_info,
> +"inode mode mismatch with dir: inode mode=0%o btrfs type=%u dir type=%u",
> +                               inode->i_mode, btrfs_inode_type(inode),
> +                               di_type);
> +                     iput(inode);

The iput here seems suspicious.

> +                     return ERR_PTR(-EUCLEAN);
> +             }
>               return inode;
>       }

5792         index = srcu_read_lock(&fs_info->subvol_srcu);
5793         ret = fixup_tree_root_location(fs_info, dir, dentry,
5794                                        &location, &sub_root);
5795         if (ret < 0) {
5796                 if (ret != -ENOENT)
5797                         inode = ERR_PTR(ret);
5798                 else
5799                         inode = new_simple_dir(dir->i_sb, &location, 
sub_root);
5800         } else {
5801                 inode = btrfs_iget(dir->i_sb, &location, sub_root, NULL);
5802         }

The iget happens after this block so either there's another one in the caller
to pair, or the above iput is wrong.

Reply via email to