Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "This has our collection of bug fixes. I missed the last rc because I thought our patches were making NFS crash during my xfs test runs. Turns out it was an NFS client bug fixed by someone else while I tried to bisect it. All of these fixes are small, but some are fairly high impact. The biggest are fixes for our mount -o remount handling, a deadlock due to GFP_KERNEL allocations in readdir, and a RAID10 error handling bug. This was tested against both 3.3 and Linus' master as of this morning." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (26 commits) Btrfs: reduce lock contention during extent insertion Btrfs: avoid deadlocks from GFP_KERNEL allocations during btrfs_real_readdir Btrfs: Fix space checking during fs resize Btrfs: fix block_rsv and space_info lock ordering Btrfs: Prevent root_list corruption Btrfs: fix repair code for RAID10 Btrfs: do not start delalloc inodes during sync Btrfs: fix that check_int_data mount option was ignored Btrfs: don't count CRC or header errors twice while scrubbing Btrfs: fix btrfs_ioctl_dev_info() crash on missing device btrfs: don't return EINTR Btrfs: double unlock bug in error handling Btrfs: always store the mirror we read the eb from fs/btrfs/volumes.c: add missing free_fs_devices btrfs: fix early abort in 'remount' Btrfs: fix max chunk size check in chunk allocator Btrfs: add missing read locks in backref.c Btrfs: don't call free_extent_buffer twice in iterate_irefs Btrfs: Make free_ipath() deal gracefully with NULL pointers Btrfs: avoid possible use-after-free in clear_extent_bit() ...
This commit is contained in:
@@ -1947,7 +1947,7 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
|
||||
* extent_io.c will try to find good copies for us.
|
||||
*/
|
||||
static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
|
||||
struct extent_state *state)
|
||||
struct extent_state *state, int mirror)
|
||||
{
|
||||
size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT);
|
||||
struct inode *inode = page->mapping->host;
|
||||
@@ -4069,7 +4069,7 @@ static struct inode *new_simple_dir(struct super_block *s,
|
||||
BTRFS_I(inode)->dummy_inode = 1;
|
||||
|
||||
inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID;
|
||||
inode->i_op = &simple_dir_inode_operations;
|
||||
inode->i_op = &btrfs_dir_ro_inode_operations;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
@@ -4140,14 +4140,18 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
|
||||
static int btrfs_dentry_delete(const struct dentry *dentry)
|
||||
{
|
||||
struct btrfs_root *root;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
|
||||
if (!dentry->d_inode && !IS_ROOT(dentry))
|
||||
dentry = dentry->d_parent;
|
||||
if (!inode && !IS_ROOT(dentry))
|
||||
inode = dentry->d_parent->d_inode;
|
||||
|
||||
if (dentry->d_inode) {
|
||||
root = BTRFS_I(dentry->d_inode)->root;
|
||||
if (inode) {
|
||||
root = BTRFS_I(inode)->root;
|
||||
if (btrfs_root_refs(&root->root_item) == 0)
|
||||
return 1;
|
||||
|
||||
if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4188,7 +4192,6 @@ 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;
|
||||
@@ -4279,7 +4282,6 @@ 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;
|
||||
@@ -4300,35 +4302,15 @@ 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
|
||||
* skip it.
|
||||
*
|
||||
* In contrast to old kernels, we insert the snapshot's
|
||||
* dir item and dir index after it has been created, so
|
||||
* we won't find a reference to our own snapshot. We
|
||||
* still keep the following code for backward
|
||||
* compatibility.
|
||||
*/
|
||||
if (location.type == BTRFS_ROOT_ITEM_KEY &&
|
||||
location.objectid == root->root_key.objectid) {
|
||||
|
Reference in New Issue
Block a user