Commit 0b001b2e authored by Linus Torvalds's avatar Linus Torvalds

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
parents 5dfcc87f d525e8ab
...@@ -176,7 +176,11 @@ static inline u64 btrfs_ino(struct inode *inode) ...@@ -176,7 +176,11 @@ static inline u64 btrfs_ino(struct inode *inode)
{ {
u64 ino = BTRFS_I(inode)->location.objectid; 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; ino = inode->i_ino;
return ino; return ino;
} }
......
...@@ -183,8 +183,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -183,8 +183,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
* read from the commit root and sidestep a nasty deadlock * read from the commit root and sidestep a nasty deadlock
* between reading the free space cache and updating the csum tree. * 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->search_commit_root = 1;
path->skip_locking = 1;
}
disk_bytenr = (u64)bio->bi_sector << 9; disk_bytenr = (u64)bio->bi_sector << 9;
if (dio) if (dio)
......
...@@ -1075,12 +1075,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, ...@@ -1075,12 +1075,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
start_pos = pos & ~((u64)root->sectorsize - 1); start_pos = pos & ~((u64)root->sectorsize - 1);
last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; 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: again:
for (i = 0; i < num_pages; i++) { for (i = 0; i < num_pages; i++) {
pages[i] = find_or_create_page(inode->i_mapping, index + 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, ...@@ -1338,6 +1332,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
struct inode *inode = fdentry(file)->d_inode; struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
loff_t *ppos = &iocb->ki_pos; loff_t *ppos = &iocb->ki_pos;
u64 start_pos;
ssize_t num_written = 0; ssize_t num_written = 0;
ssize_t err = 0; ssize_t err = 0;
size_t count, ocount; size_t count, ocount;
...@@ -1386,6 +1381,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, ...@@ -1386,6 +1381,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
file_update_time(file); file_update_time(file);
BTRFS_I(inode)->sequence++; 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)) { if (unlikely(file->f_flags & O_DIRECT)) {
num_written = __btrfs_direct_write(iocb, iov, nr_segs, num_written = __btrfs_direct_write(iocb, iov, nr_segs,
pos, ppos, count, ocount); pos, ppos, count, ocount);
......
...@@ -190,9 +190,11 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, ...@@ -190,9 +190,11 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
struct btrfs_path *path, struct btrfs_path *path,
struct inode *inode) struct inode *inode)
{ {
struct btrfs_block_rsv *rsv;
loff_t oldsize; loff_t oldsize;
int ret = 0; int ret = 0;
rsv = trans->block_rsv;
trans->block_rsv = root->orphan_block_rsv; trans->block_rsv = root->orphan_block_rsv;
ret = btrfs_block_rsv_check(trans, root, ret = btrfs_block_rsv_check(trans, root,
root->orphan_block_rsv, root->orphan_block_rsv,
...@@ -210,6 +212,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, ...@@ -210,6 +212,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
*/ */
ret = btrfs_truncate_inode_items(trans, root, inode, ret = btrfs_truncate_inode_items(trans, root, inode,
0, BTRFS_EXTENT_DATA_KEY); 0, BTRFS_EXTENT_DATA_KEY);
trans->block_rsv = rsv;
if (ret) { if (ret) {
WARN_ON(1); WARN_ON(1);
return ret; return ret;
......
...@@ -1786,7 +1786,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1786,7 +1786,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
&ordered_extent->list); &ordered_extent->list);
ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); 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); ret = btrfs_update_inode(trans, root, inode);
BUG_ON(ret); BUG_ON(ret);
} }
...@@ -3510,15 +3510,19 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) ...@@ -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, err = btrfs_drop_extents(trans, inode, cur_offset,
cur_offset + hole_size, cur_offset + hole_size,
&hint_byte, 1); &hint_byte, 1);
if (err) if (err) {
btrfs_end_transaction(trans, root);
break; break;
}
err = btrfs_insert_file_extent(trans, root, err = btrfs_insert_file_extent(trans, root,
btrfs_ino(inode), cur_offset, 0, btrfs_ino(inode), cur_offset, 0,
0, hole_size, 0, hole_size, 0, hole_size, 0, hole_size,
0, 0, 0); 0, 0, 0);
if (err) if (err) {
btrfs_end_transaction(trans, root);
break; break;
}
btrfs_drop_extent_cache(inode, hole_start, btrfs_drop_extent_cache(inode, hole_start,
last_byte - 1, 0); last_byte - 1, 0);
...@@ -3952,7 +3956,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, ...@@ -3952,7 +3956,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
struct btrfs_root *root, int *new) struct btrfs_root *root, int *new)
{ {
struct inode *inode; struct inode *inode;
int bad_inode = 0;
inode = btrfs_iget_locked(s, location->objectid, root); inode = btrfs_iget_locked(s, location->objectid, root);
if (!inode) if (!inode)
...@@ -3968,15 +3971,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, ...@@ -3968,15 +3971,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
if (new) if (new)
*new = 1; *new = 1;
} else { } 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; return inode;
} }
...@@ -5823,7 +5823,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) ...@@ -5823,7 +5823,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
ret = btrfs_ordered_update_i_size(inode, 0, ordered); 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); btrfs_update_inode(trans, root, inode);
ret = 0; ret = 0;
out_unlock: out_unlock:
......
...@@ -2220,6 +2220,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, ...@@ -2220,6 +2220,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
!IS_ALIGNED(destoff, bs)) !IS_ALIGNED(destoff, bs))
goto out_unlock; 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 /* do any pending delalloc/csum calc on src, one way or
another, and lock file content */ another, and lock file content */
while (1) { while (1) {
...@@ -2325,14 +2331,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, ...@@ -2325,14 +2331,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
if (type == BTRFS_FILE_EXTENT_REG || if (type == BTRFS_FILE_EXTENT_REG ||
type == BTRFS_FILE_EXTENT_PREALLOC) { 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) { if (off > key.offset) {
datao += off - key.offset; datao += off - key.offset;
datal -= off - key.offset; datal -= off - key.offset;
} }
if (key.offset + datal > off + len)
datal = off + len - key.offset;
ret = btrfs_drop_extents(trans, inode, ret = btrfs_drop_extents(trans, inode,
new_key.offset, new_key.offset,
new_key.offset + datal, new_key.offset + datal,
......
...@@ -884,6 +884,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ...@@ -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 *tree_root = fs_info->tree_root;
struct btrfs_root *root = pending->root; struct btrfs_root *root = pending->root;
struct btrfs_root *parent_root; struct btrfs_root *parent_root;
struct btrfs_block_rsv *rsv;
struct inode *parent_inode; struct inode *parent_inode;
struct dentry *parent; struct dentry *parent;
struct dentry *dentry; struct dentry *dentry;
...@@ -895,6 +896,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ...@@ -895,6 +896,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
u64 objectid; u64 objectid;
u64 root_flags; u64 root_flags;
rsv = trans->block_rsv;
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
if (!new_root_item) { if (!new_root_item) {
pending->error = -ENOMEM; pending->error = -ENOMEM;
...@@ -1002,6 +1005,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ...@@ -1002,6 +1005,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_orphan_post_snapshot(trans, pending); btrfs_orphan_post_snapshot(trans, pending);
fail: fail:
kfree(new_root_item); kfree(new_root_item);
trans->block_rsv = rsv;
btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);
return 0; return 0;
} }
......
...@@ -116,6 +116,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans, ...@@ -116,6 +116,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
if (ret) if (ret)
goto out; goto out;
btrfs_release_path(path); btrfs_release_path(path);
/*
* remove the attribute
*/
if (!value)
goto out;
} }
again: again:
...@@ -158,6 +164,9 @@ static int do_setxattr(struct btrfs_trans_handle *trans, ...@@ -158,6 +164,9 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
/*
* @value: "" makes the attribute to empty, NULL removes it
*/
int __btrfs_setxattr(struct btrfs_trans_handle *trans, int __btrfs_setxattr(struct btrfs_trans_handle *trans,
struct inode *inode, const char *name, struct inode *inode, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment