forked from Minki/linux
Merge branch 'for-linus' of git://github.com/chrismason/linux
* 'for-linus' of git://github.com/chrismason/linux: Btrfs: add dummy extent if dst offset excceeds file end in Btrfs: calc file extent num_bytes correctly in file clone btrfs: xattr: fix attribute removal Btrfs: fix wrong nbytes information of the inode Btrfs: fix the file extent gap when doing direct IO Btrfs: fix unclosed transaction handle in btrfs_cont_expand Btrfs: fix misuse of trans block rsv Btrfs: reset to appropriate block rsv after orphan operations Btrfs: skip locking if searching the commit root in csum lookup btrfs: fix warning in iput for bad-inode Btrfs: fix an oops when deleting snapshots
This commit is contained in:
commit
0b001b2eda
@ -176,7 +176,11 @@ static inline u64 btrfs_ino(struct inode *inode)
|
||||
{
|
||||
u64 ino = BTRFS_I(inode)->location.objectid;
|
||||
|
||||
if (ino <= BTRFS_FIRST_FREE_OBJECTID)
|
||||
/*
|
||||
* !ino: btree_inode
|
||||
* type == BTRFS_ROOT_ITEM_KEY: subvol dir
|
||||
*/
|
||||
if (!ino || BTRFS_I(inode)->location.type == BTRFS_ROOT_ITEM_KEY)
|
||||
ino = inode->i_ino;
|
||||
return ino;
|
||||
}
|
||||
|
@ -183,8 +183,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
|
||||
* read from the commit root and sidestep a nasty deadlock
|
||||
* between reading the free space cache and updating the csum tree.
|
||||
*/
|
||||
if (btrfs_is_free_space_inode(root, inode))
|
||||
if (btrfs_is_free_space_inode(root, inode)) {
|
||||
path->search_commit_root = 1;
|
||||
path->skip_locking = 1;
|
||||
}
|
||||
|
||||
disk_bytenr = (u64)bio->bi_sector << 9;
|
||||
if (dio)
|
||||
|
@ -1075,12 +1075,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
|
||||
start_pos = pos & ~((u64)root->sectorsize - 1);
|
||||
last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT;
|
||||
|
||||
if (start_pos > inode->i_size) {
|
||||
err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
again:
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
pages[i] = find_or_create_page(inode->i_mapping, index + i,
|
||||
@ -1338,6 +1332,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
|
||||
struct inode *inode = fdentry(file)->d_inode;
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
loff_t *ppos = &iocb->ki_pos;
|
||||
u64 start_pos;
|
||||
ssize_t num_written = 0;
|
||||
ssize_t err = 0;
|
||||
size_t count, ocount;
|
||||
@ -1386,6 +1381,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
|
||||
file_update_time(file);
|
||||
BTRFS_I(inode)->sequence++;
|
||||
|
||||
start_pos = round_down(pos, root->sectorsize);
|
||||
if (start_pos > i_size_read(inode)) {
|
||||
err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
|
||||
if (err) {
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(file->f_flags & O_DIRECT)) {
|
||||
num_written = __btrfs_direct_write(iocb, iov, nr_segs,
|
||||
pos, ppos, count, ocount);
|
||||
|
@ -190,9 +190,11 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
|
||||
struct btrfs_path *path,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct btrfs_block_rsv *rsv;
|
||||
loff_t oldsize;
|
||||
int ret = 0;
|
||||
|
||||
rsv = trans->block_rsv;
|
||||
trans->block_rsv = root->orphan_block_rsv;
|
||||
ret = btrfs_block_rsv_check(trans, root,
|
||||
root->orphan_block_rsv,
|
||||
@ -210,6 +212,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
|
||||
*/
|
||||
ret = btrfs_truncate_inode_items(trans, root, inode,
|
||||
0, BTRFS_EXTENT_DATA_KEY);
|
||||
|
||||
trans->block_rsv = rsv;
|
||||
if (ret) {
|
||||
WARN_ON(1);
|
||||
return ret;
|
||||
|
@ -1786,7 +1786,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
|
||||
&ordered_extent->list);
|
||||
|
||||
ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
|
||||
if (!ret) {
|
||||
if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
|
||||
ret = btrfs_update_inode(trans, root, inode);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
@ -3510,15 +3510,19 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
|
||||
err = btrfs_drop_extents(trans, inode, cur_offset,
|
||||
cur_offset + hole_size,
|
||||
&hint_byte, 1);
|
||||
if (err)
|
||||
if (err) {
|
||||
btrfs_end_transaction(trans, root);
|
||||
break;
|
||||
}
|
||||
|
||||
err = btrfs_insert_file_extent(trans, root,
|
||||
btrfs_ino(inode), cur_offset, 0,
|
||||
0, hole_size, 0, hole_size,
|
||||
0, 0, 0);
|
||||
if (err)
|
||||
if (err) {
|
||||
btrfs_end_transaction(trans, root);
|
||||
break;
|
||||
}
|
||||
|
||||
btrfs_drop_extent_cache(inode, hole_start,
|
||||
last_byte - 1, 0);
|
||||
@ -3952,7 +3956,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
||||
struct btrfs_root *root, int *new)
|
||||
{
|
||||
struct inode *inode;
|
||||
int bad_inode = 0;
|
||||
|
||||
inode = btrfs_iget_locked(s, location->objectid, root);
|
||||
if (!inode)
|
||||
@ -3968,15 +3971,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
||||
if (new)
|
||||
*new = 1;
|
||||
} else {
|
||||
bad_inode = 1;
|
||||
unlock_new_inode(inode);
|
||||
iput(inode);
|
||||
inode = ERR_PTR(-ESTALE);
|
||||
}
|
||||
}
|
||||
|
||||
if (bad_inode) {
|
||||
iput(inode);
|
||||
inode = ERR_PTR(-ESTALE);
|
||||
}
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
@ -5823,7 +5823,7 @@ again:
|
||||
|
||||
add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
|
||||
ret = btrfs_ordered_update_i_size(inode, 0, ordered);
|
||||
if (!ret)
|
||||
if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags))
|
||||
btrfs_update_inode(trans, root, inode);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
|
@ -2220,6 +2220,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
!IS_ALIGNED(destoff, bs))
|
||||
goto out_unlock;
|
||||
|
||||
if (destoff > inode->i_size) {
|
||||
ret = btrfs_cont_expand(inode, inode->i_size, destoff);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* do any pending delalloc/csum calc on src, one way or
|
||||
another, and lock file content */
|
||||
while (1) {
|
||||
@ -2325,14 +2331,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
|
||||
if (type == BTRFS_FILE_EXTENT_REG ||
|
||||
type == BTRFS_FILE_EXTENT_PREALLOC) {
|
||||
/*
|
||||
* a | --- range to clone ---| b
|
||||
* | ------------- extent ------------- |
|
||||
*/
|
||||
|
||||
/* substract range b */
|
||||
if (key.offset + datal > off + len)
|
||||
datal = off + len - key.offset;
|
||||
|
||||
/* substract range a */
|
||||
if (off > key.offset) {
|
||||
datao += off - key.offset;
|
||||
datal -= off - key.offset;
|
||||
}
|
||||
|
||||
if (key.offset + datal > off + len)
|
||||
datal = off + len - key.offset;
|
||||
|
||||
ret = btrfs_drop_extents(trans, inode,
|
||||
new_key.offset,
|
||||
new_key.offset + datal,
|
||||
|
@ -884,6 +884,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *tree_root = fs_info->tree_root;
|
||||
struct btrfs_root *root = pending->root;
|
||||
struct btrfs_root *parent_root;
|
||||
struct btrfs_block_rsv *rsv;
|
||||
struct inode *parent_inode;
|
||||
struct dentry *parent;
|
||||
struct dentry *dentry;
|
||||
@ -895,6 +896,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||
u64 objectid;
|
||||
u64 root_flags;
|
||||
|
||||
rsv = trans->block_rsv;
|
||||
|
||||
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
|
||||
if (!new_root_item) {
|
||||
pending->error = -ENOMEM;
|
||||
@ -1002,6 +1005,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||
btrfs_orphan_post_snapshot(trans, pending);
|
||||
fail:
|
||||
kfree(new_root_item);
|
||||
trans->block_rsv = rsv;
|
||||
btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -116,6 +116,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
|
||||
if (ret)
|
||||
goto out;
|
||||
btrfs_release_path(path);
|
||||
|
||||
/*
|
||||
* remove the attribute
|
||||
*/
|
||||
if (!value)
|
||||
goto out;
|
||||
}
|
||||
|
||||
again:
|
||||
@ -158,6 +164,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* @value: "" makes the attribute to empty, NULL removes it
|
||||
*/
|
||||
int __btrfs_setxattr(struct btrfs_trans_handle *trans,
|
||||
struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
|
Loading…
Reference in New Issue
Block a user