mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-23 23:21:46 +00:00
Merge branch 'for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "This is an assorted set I've been queuing up: Jeff Mahoney tracked down a tricky one where we ended up starting IO on the wrong mapping for special files in btrfs_evict_inode. A few people reported this one on the list. Filipe found (and provided a test for) a difficult bug in reading compressed extents, and Josef fixed up some quota record keeping with snapshot deletion. Chandan killed off an accounting bug during DIO that lead to WARN_ONs as we freed inodes" * 'for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: keep dropped roots in cache until transaction commit Btrfs: Direct I/O: Fix space accounting btrfs: skip waiting on ordered range for special files Btrfs: fix read corruption of compressed and shared extents Btrfs: remove unnecessary locking of cleaner_mutex to avoid deadlock Btrfs: don't initialize a space info as full to prevent ENOSPC
This commit is contained in:
commit
03e8f64486
8 changed files with 118 additions and 42 deletions
|
@ -5084,7 +5084,8 @@ void btrfs_evict_inode(struct inode *inode)
|
|||
goto no_delete;
|
||||
}
|
||||
/* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */
|
||||
btrfs_wait_ordered_range(inode, 0, (u64)-1);
|
||||
if (!special_file(inode->i_mode))
|
||||
btrfs_wait_ordered_range(inode, 0, (u64)-1);
|
||||
|
||||
btrfs_free_io_failure_record(inode, 0, (u64)-1);
|
||||
|
||||
|
@ -7408,6 +7409,10 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
|
|||
return em;
|
||||
}
|
||||
|
||||
struct btrfs_dio_data {
|
||||
u64 outstanding_extents;
|
||||
u64 reserve;
|
||||
};
|
||||
|
||||
static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
|
||||
struct buffer_head *bh_result, int create)
|
||||
|
@ -7415,10 +7420,10 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
|
|||
struct extent_map *em;
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
struct extent_state *cached_state = NULL;
|
||||
struct btrfs_dio_data *dio_data = NULL;
|
||||
u64 start = iblock << inode->i_blkbits;
|
||||
u64 lockstart, lockend;
|
||||
u64 len = bh_result->b_size;
|
||||
u64 *outstanding_extents = NULL;
|
||||
int unlock_bits = EXTENT_LOCKED;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -7436,7 +7441,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
|
|||
* that anything that needs to check if there's a transction doesn't get
|
||||
* confused.
|
||||
*/
|
||||
outstanding_extents = current->journal_info;
|
||||
dio_data = current->journal_info;
|
||||
current->journal_info = NULL;
|
||||
}
|
||||
|
||||
|
@ -7568,17 +7573,18 @@ unlock:
|
|||
* within our reservation, otherwise we need to adjust our inode
|
||||
* counter appropriately.
|
||||
*/
|
||||
if (*outstanding_extents) {
|
||||
(*outstanding_extents)--;
|
||||
if (dio_data->outstanding_extents) {
|
||||
(dio_data->outstanding_extents)--;
|
||||
} else {
|
||||
spin_lock(&BTRFS_I(inode)->lock);
|
||||
BTRFS_I(inode)->outstanding_extents++;
|
||||
spin_unlock(&BTRFS_I(inode)->lock);
|
||||
}
|
||||
|
||||
current->journal_info = outstanding_extents;
|
||||
btrfs_free_reserved_data_space(inode, len);
|
||||
set_bit(BTRFS_INODE_DIO_READY, &BTRFS_I(inode)->runtime_flags);
|
||||
WARN_ON(dio_data->reserve < len);
|
||||
dio_data->reserve -= len;
|
||||
current->journal_info = dio_data;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7601,8 +7607,8 @@ unlock:
|
|||
unlock_err:
|
||||
clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
|
||||
unlock_bits, 1, 0, &cached_state, GFP_NOFS);
|
||||
if (outstanding_extents)
|
||||
current->journal_info = outstanding_extents;
|
||||
if (dio_data)
|
||||
current->journal_info = dio_data;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -8329,7 +8335,8 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
|
|||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
u64 outstanding_extents = 0;
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
struct btrfs_dio_data dio_data = { 0 };
|
||||
size_t count = 0;
|
||||
int flags = 0;
|
||||
bool wakeup = true;
|
||||
|
@ -8367,7 +8374,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
|
|||
ret = btrfs_delalloc_reserve_space(inode, count);
|
||||
if (ret)
|
||||
goto out;
|
||||
outstanding_extents = div64_u64(count +
|
||||
dio_data.outstanding_extents = div64_u64(count +
|
||||
BTRFS_MAX_EXTENT_SIZE - 1,
|
||||
BTRFS_MAX_EXTENT_SIZE);
|
||||
|
||||
|
@ -8376,7 +8383,8 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
|
|||
* do the accounting properly if we go over the number we
|
||||
* originally calculated. Abuse current->journal_info for this.
|
||||
*/
|
||||
current->journal_info = &outstanding_extents;
|
||||
dio_data.reserve = round_up(count, root->sectorsize);
|
||||
current->journal_info = &dio_data;
|
||||
} else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
|
||||
&BTRFS_I(inode)->runtime_flags)) {
|
||||
inode_dio_end(inode);
|
||||
|
@ -8391,16 +8399,9 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
|
|||
if (iov_iter_rw(iter) == WRITE) {
|
||||
current->journal_info = NULL;
|
||||
if (ret < 0 && ret != -EIOCBQUEUED) {
|
||||
/*
|
||||
* If the error comes from submitting stage,
|
||||
* btrfs_get_blocsk_direct() has free'd data space,
|
||||
* and metadata space will be handled by
|
||||
* finish_ordered_fn, don't do that again to make
|
||||
* sure bytes_may_use is correct.
|
||||
*/
|
||||
if (!test_and_clear_bit(BTRFS_INODE_DIO_READY,
|
||||
&BTRFS_I(inode)->runtime_flags))
|
||||
btrfs_delalloc_release_space(inode, count);
|
||||
if (dio_data.reserve)
|
||||
btrfs_delalloc_release_space(inode,
|
||||
dio_data.reserve);
|
||||
} else if (ret >= 0 && (size_t)ret < count)
|
||||
btrfs_delalloc_release_space(inode,
|
||||
count - (size_t)ret);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue