Skip to content

Commit 0b001b2

Browse files
committed
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
2 parents 5dfcc87 + d525e8a commit 0b001b2

8 files changed

+62
-22
lines changed

fs/btrfs/btrfs_inode.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,11 @@ static inline u64 btrfs_ino(struct inode *inode)
176176
{
177177
u64 ino = BTRFS_I(inode)->location.objectid;
178178

179-
if (ino <= BTRFS_FIRST_FREE_OBJECTID)
179+
/*
180+
* !ino: btree_inode
181+
* type == BTRFS_ROOT_ITEM_KEY: subvol dir
182+
*/
183+
if (!ino || BTRFS_I(inode)->location.type == BTRFS_ROOT_ITEM_KEY)
180184
ino = inode->i_ino;
181185
return ino;
182186
}

fs/btrfs/file-item.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
183183
* read from the commit root and sidestep a nasty deadlock
184184
* between reading the free space cache and updating the csum tree.
185185
*/
186-
if (btrfs_is_free_space_inode(root, inode))
186+
if (btrfs_is_free_space_inode(root, inode)) {
187187
path->search_commit_root = 1;
188+
path->skip_locking = 1;
189+
}
188190

189191
disk_bytenr = (u64)bio->bi_sector << 9;
190192
if (dio)

fs/btrfs/file.c

+10-6
Original file line numberDiff line numberDiff line change
@@ -1075,12 +1075,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
10751075
start_pos = pos & ~((u64)root->sectorsize - 1);
10761076
last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT;
10771077

1078-
if (start_pos > inode->i_size) {
1079-
err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
1080-
if (err)
1081-
return err;
1082-
}
1083-
10841078
again:
10851079
for (i = 0; i < num_pages; i++) {
10861080
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,
13381332
struct inode *inode = fdentry(file)->d_inode;
13391333
struct btrfs_root *root = BTRFS_I(inode)->root;
13401334
loff_t *ppos = &iocb->ki_pos;
1335+
u64 start_pos;
13411336
ssize_t num_written = 0;
13421337
ssize_t err = 0;
13431338
size_t count, ocount;
@@ -1386,6 +1381,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
13861381
file_update_time(file);
13871382
BTRFS_I(inode)->sequence++;
13881383

1384+
start_pos = round_down(pos, root->sectorsize);
1385+
if (start_pos > i_size_read(inode)) {
1386+
err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
1387+
if (err) {
1388+
mutex_unlock(&inode->i_mutex);
1389+
goto out;
1390+
}
1391+
}
1392+
13891393
if (unlikely(file->f_flags & O_DIRECT)) {
13901394
num_written = __btrfs_direct_write(iocb, iov, nr_segs,
13911395
pos, ppos, count, ocount);

fs/btrfs/free-space-cache.c

+4
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,11 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
190190
struct btrfs_path *path,
191191
struct inode *inode)
192192
{
193+
struct btrfs_block_rsv *rsv;
193194
loff_t oldsize;
194195
int ret = 0;
195196

197+
rsv = trans->block_rsv;
196198
trans->block_rsv = root->orphan_block_rsv;
197199
ret = btrfs_block_rsv_check(trans, root,
198200
root->orphan_block_rsv,
@@ -210,6 +212,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
210212
*/
211213
ret = btrfs_truncate_inode_items(trans, root, inode,
212214
0, BTRFS_EXTENT_DATA_KEY);
215+
216+
trans->block_rsv = rsv;
213217
if (ret) {
214218
WARN_ON(1);
215219
return ret;

fs/btrfs/inode.c

+11-11
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
17861786
&ordered_extent->list);
17871787

17881788
ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
1789-
if (!ret) {
1789+
if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
17901790
ret = btrfs_update_inode(trans, root, inode);
17911791
BUG_ON(ret);
17921792
}
@@ -3510,15 +3510,19 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
35103510
err = btrfs_drop_extents(trans, inode, cur_offset,
35113511
cur_offset + hole_size,
35123512
&hint_byte, 1);
3513-
if (err)
3513+
if (err) {
3514+
btrfs_end_transaction(trans, root);
35143515
break;
3516+
}
35153517

35163518
err = btrfs_insert_file_extent(trans, root,
35173519
btrfs_ino(inode), cur_offset, 0,
35183520
0, hole_size, 0, hole_size,
35193521
0, 0, 0);
3520-
if (err)
3522+
if (err) {
3523+
btrfs_end_transaction(trans, root);
35213524
break;
3525+
}
35223526

35233527
btrfs_drop_extent_cache(inode, hole_start,
35243528
last_byte - 1, 0);
@@ -3952,7 +3956,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
39523956
struct btrfs_root *root, int *new)
39533957
{
39543958
struct inode *inode;
3955-
int bad_inode = 0;
39563959

39573960
inode = btrfs_iget_locked(s, location->objectid, root);
39583961
if (!inode)
@@ -3968,15 +3971,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
39683971
if (new)
39693972
*new = 1;
39703973
} else {
3971-
bad_inode = 1;
3974+
unlock_new_inode(inode);
3975+
iput(inode);
3976+
inode = ERR_PTR(-ESTALE);
39723977
}
39733978
}
39743979

3975-
if (bad_inode) {
3976-
iput(inode);
3977-
inode = ERR_PTR(-ESTALE);
3978-
}
3979-
39803980
return inode;
39813981
}
39823982

@@ -5823,7 +5823,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
58235823

58245824
add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
58255825
ret = btrfs_ordered_update_i_size(inode, 0, ordered);
5826-
if (!ret)
5826+
if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags))
58275827
btrfs_update_inode(trans, root, inode);
58285828
ret = 0;
58295829
out_unlock:

fs/btrfs/ioctl.c

+16-3
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
22202220
!IS_ALIGNED(destoff, bs))
22212221
goto out_unlock;
22222222

2223+
if (destoff > inode->i_size) {
2224+
ret = btrfs_cont_expand(inode, inode->i_size, destoff);
2225+
if (ret)
2226+
goto out_unlock;
2227+
}
2228+
22232229
/* do any pending delalloc/csum calc on src, one way or
22242230
another, and lock file content */
22252231
while (1) {
@@ -2325,14 +2331,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
23252331

23262332
if (type == BTRFS_FILE_EXTENT_REG ||
23272333
type == BTRFS_FILE_EXTENT_PREALLOC) {
2334+
/*
2335+
* a | --- range to clone ---| b
2336+
* | ------------- extent ------------- |
2337+
*/
2338+
2339+
/* substract range b */
2340+
if (key.offset + datal > off + len)
2341+
datal = off + len - key.offset;
2342+
2343+
/* substract range a */
23282344
if (off > key.offset) {
23292345
datao += off - key.offset;
23302346
datal -= off - key.offset;
23312347
}
23322348

2333-
if (key.offset + datal > off + len)
2334-
datal = off + len - key.offset;
2335-
23362349
ret = btrfs_drop_extents(trans, inode,
23372350
new_key.offset,
23382351
new_key.offset + datal,

fs/btrfs/transaction.c

+4
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
884884
struct btrfs_root *tree_root = fs_info->tree_root;
885885
struct btrfs_root *root = pending->root;
886886
struct btrfs_root *parent_root;
887+
struct btrfs_block_rsv *rsv;
887888
struct inode *parent_inode;
888889
struct dentry *parent;
889890
struct dentry *dentry;
@@ -895,6 +896,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
895896
u64 objectid;
896897
u64 root_flags;
897898

899+
rsv = trans->block_rsv;
900+
898901
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
899902
if (!new_root_item) {
900903
pending->error = -ENOMEM;
@@ -1002,6 +1005,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
10021005
btrfs_orphan_post_snapshot(trans, pending);
10031006
fail:
10041007
kfree(new_root_item);
1008+
trans->block_rsv = rsv;
10051009
btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);
10061010
return 0;
10071011
}

fs/btrfs/xattr.c

+9
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
116116
if (ret)
117117
goto out;
118118
btrfs_release_path(path);
119+
120+
/*
121+
* remove the attribute
122+
*/
123+
if (!value)
124+
goto out;
119125
}
120126

121127
again:
@@ -158,6 +164,9 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
158164
return ret;
159165
}
160166

167+
/*
168+
* @value: "" makes the attribute to empty, NULL removes it
169+
*/
161170
int __btrfs_setxattr(struct btrfs_trans_handle *trans,
162171
struct inode *inode, const char *name,
163172
const void *value, size_t size, int flags)

0 commit comments

Comments
 (0)