diff options
| -rw-r--r-- | fs/btrfs/btrfs_inode.h | 6 | ||||
| -rw-r--r-- | fs/btrfs/file-item.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 16 | ||||
| -rw-r--r-- | fs/btrfs/free-space-cache.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 19 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/xattr.c | 9 |
8 files changed, 62 insertions, 22 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 502b9e988679..d9f99a16edd6 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
| @@ -176,7 +176,11 @@ static inline u64 btrfs_ino(struct inode *inode) | |||
| 176 | { | 176 | { |
| 177 | u64 ino = BTRFS_I(inode)->location.objectid; | 177 | u64 ino = BTRFS_I(inode)->location.objectid; |
| 178 | 178 | ||
| 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) | ||
| 180 | ino = inode->i_ino; | 184 | ino = inode->i_ino; |
| 181 | return ino; | 185 | return ino; |
| 182 | } | 186 | } |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index b910694f61ed..a1cb7821becd 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
| @@ -183,8 +183,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
| 183 | * read from the commit root and sidestep a nasty deadlock | 183 | * read from the commit root and sidestep a nasty deadlock |
| 184 | * between reading the free space cache and updating the csum tree. | 184 | * between reading the free space cache and updating the csum tree. |
| 185 | */ | 185 | */ |
| 186 | if (btrfs_is_free_space_inode(root, inode)) | 186 | if (btrfs_is_free_space_inode(root, inode)) { |
| 187 | path->search_commit_root = 1; | 187 | path->search_commit_root = 1; |
| 188 | path->skip_locking = 1; | ||
| 189 | } | ||
| 188 | 190 | ||
| 189 | disk_bytenr = (u64)bio->bi_sector << 9; | 191 | disk_bytenr = (u64)bio->bi_sector << 9; |
| 190 | if (dio) | 192 | if (dio) |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e7872e485f13..3c3abff731a7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -1075,12 +1075,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | |||
| 1075 | start_pos = pos & ~((u64)root->sectorsize - 1); | 1075 | start_pos = pos & ~((u64)root->sectorsize - 1); |
| 1076 | last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; | 1076 | last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; |
| 1077 | 1077 | ||
| 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 | |||
| 1084 | again: | 1078 | again: |
| 1085 | for (i = 0; i < num_pages; i++) { | 1079 | for (i = 0; i < num_pages; i++) { |
| 1086 | pages[i] = find_or_create_page(inode->i_mapping, index + i, | 1080 | 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 | struct inode *inode = fdentry(file)->d_inode; | 1332 | struct inode *inode = fdentry(file)->d_inode; |
| 1339 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1333 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1340 | loff_t *ppos = &iocb->ki_pos; | 1334 | loff_t *ppos = &iocb->ki_pos; |
| 1335 | u64 start_pos; | ||
| 1341 | ssize_t num_written = 0; | 1336 | ssize_t num_written = 0; |
| 1342 | ssize_t err = 0; | 1337 | ssize_t err = 0; |
| 1343 | size_t count, ocount; | 1338 | size_t count, ocount; |
| @@ -1386,6 +1381,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1386 | file_update_time(file); | 1381 | file_update_time(file); |
| 1387 | BTRFS_I(inode)->sequence++; | 1382 | BTRFS_I(inode)->sequence++; |
| 1388 | 1383 | ||
| 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 | |||
| 1389 | if (unlikely(file->f_flags & O_DIRECT)) { | 1393 | if (unlikely(file->f_flags & O_DIRECT)) { |
| 1390 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, | 1394 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, |
| 1391 | pos, ppos, count, ocount); | 1395 | pos, ppos, count, ocount); |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 6a265b9f85f2..41ac927401d0 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
| @@ -190,9 +190,11 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, | |||
| 190 | struct btrfs_path *path, | 190 | struct btrfs_path *path, |
| 191 | struct inode *inode) | 191 | struct inode *inode) |
| 192 | { | 192 | { |
| 193 | struct btrfs_block_rsv *rsv; | ||
| 193 | loff_t oldsize; | 194 | loff_t oldsize; |
| 194 | int ret = 0; | 195 | int ret = 0; |
| 195 | 196 | ||
| 197 | rsv = trans->block_rsv; | ||
| 196 | trans->block_rsv = root->orphan_block_rsv; | 198 | trans->block_rsv = root->orphan_block_rsv; |
| 197 | ret = btrfs_block_rsv_check(trans, root, | 199 | ret = btrfs_block_rsv_check(trans, root, |
| 198 | root->orphan_block_rsv, | 200 | root->orphan_block_rsv, |
| @@ -210,6 +212,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, | |||
| 210 | */ | 212 | */ |
| 211 | ret = btrfs_truncate_inode_items(trans, root, inode, | 213 | ret = btrfs_truncate_inode_items(trans, root, inode, |
| 212 | 0, BTRFS_EXTENT_DATA_KEY); | 214 | 0, BTRFS_EXTENT_DATA_KEY); |
| 215 | |||
| 216 | trans->block_rsv = rsv; | ||
| 213 | if (ret) { | 217 | if (ret) { |
| 214 | WARN_ON(1); | 218 | WARN_ON(1); |
| 215 | return ret; | 219 | return ret; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0ccc7438ad34..4d14de6d121b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -1786,7 +1786,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
| 1786 | &ordered_extent->list); | 1786 | &ordered_extent->list); |
| 1787 | 1787 | ||
| 1788 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); | 1788 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); |
| 1789 | if (!ret) { | 1789 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { |
| 1790 | ret = btrfs_update_inode(trans, root, inode); | 1790 | ret = btrfs_update_inode(trans, root, inode); |
| 1791 | BUG_ON(ret); | 1791 | BUG_ON(ret); |
| 1792 | } | 1792 | } |
| @@ -3510,15 +3510,19 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) | |||
| 3510 | err = btrfs_drop_extents(trans, inode, cur_offset, | 3510 | err = btrfs_drop_extents(trans, inode, cur_offset, |
| 3511 | cur_offset + hole_size, | 3511 | cur_offset + hole_size, |
| 3512 | &hint_byte, 1); | 3512 | &hint_byte, 1); |
| 3513 | if (err) | 3513 | if (err) { |
| 3514 | btrfs_end_transaction(trans, root); | ||
| 3514 | break; | 3515 | break; |
| 3516 | } | ||
| 3515 | 3517 | ||
| 3516 | err = btrfs_insert_file_extent(trans, root, | 3518 | err = btrfs_insert_file_extent(trans, root, |
| 3517 | btrfs_ino(inode), cur_offset, 0, | 3519 | btrfs_ino(inode), cur_offset, 0, |
| 3518 | 0, hole_size, 0, hole_size, | 3520 | 0, hole_size, 0, hole_size, |
| 3519 | 0, 0, 0); | 3521 | 0, 0, 0); |
| 3520 | if (err) | 3522 | if (err) { |
| 3523 | btrfs_end_transaction(trans, root); | ||
| 3521 | break; | 3524 | break; |
| 3525 | } | ||
| 3522 | 3526 | ||
| 3523 | btrfs_drop_extent_cache(inode, hole_start, | 3527 | btrfs_drop_extent_cache(inode, hole_start, |
| 3524 | last_byte - 1, 0); | 3528 | last_byte - 1, 0); |
| @@ -3952,7 +3956,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, | |||
| 3952 | struct btrfs_root *root, int *new) | 3956 | struct btrfs_root *root, int *new) |
| 3953 | { | 3957 | { |
| 3954 | struct inode *inode; | 3958 | struct inode *inode; |
| 3955 | int bad_inode = 0; | ||
| 3956 | 3959 | ||
| 3957 | inode = btrfs_iget_locked(s, location->objectid, root); | 3960 | inode = btrfs_iget_locked(s, location->objectid, root); |
| 3958 | if (!inode) | 3961 | if (!inode) |
| @@ -3968,15 +3971,12 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, | |||
| 3968 | if (new) | 3971 | if (new) |
| 3969 | *new = 1; | 3972 | *new = 1; |
| 3970 | } else { | 3973 | } else { |
| 3971 | bad_inode = 1; | 3974 | unlock_new_inode(inode); |
| 3975 | iput(inode); | ||
| 3976 | inode = ERR_PTR(-ESTALE); | ||
| 3972 | } | 3977 | } |
| 3973 | } | 3978 | } |
| 3974 | 3979 | ||
| 3975 | if (bad_inode) { | ||
| 3976 | iput(inode); | ||
| 3977 | inode = ERR_PTR(-ESTALE); | ||
| 3978 | } | ||
| 3979 | |||
| 3980 | return inode; | 3980 | return inode; |
| 3981 | } | 3981 | } |
| 3982 | 3982 | ||
| @@ -5823,7 +5823,7 @@ again: | |||
| 5823 | 5823 | ||
| 5824 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); | 5824 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); |
| 5825 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); | 5825 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
| 5826 | if (!ret) | 5826 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) |
| 5827 | btrfs_update_inode(trans, root, inode); | 5827 | btrfs_update_inode(trans, root, inode); |
| 5828 | ret = 0; | 5828 | ret = 0; |
| 5829 | out_unlock: | 5829 | out_unlock: |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 970977aab224..3351b1b24574 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -2220,6 +2220,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 2220 | !IS_ALIGNED(destoff, bs)) | 2220 | !IS_ALIGNED(destoff, bs)) |
| 2221 | goto out_unlock; | 2221 | goto out_unlock; |
| 2222 | 2222 | ||
| 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 | |||
| 2223 | /* do any pending delalloc/csum calc on src, one way or | 2229 | /* do any pending delalloc/csum calc on src, one way or |
| 2224 | another, and lock file content */ | 2230 | another, and lock file content */ |
| 2225 | while (1) { | 2231 | while (1) { |
| @@ -2325,14 +2331,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 2325 | 2331 | ||
| 2326 | if (type == BTRFS_FILE_EXTENT_REG || | 2332 | if (type == BTRFS_FILE_EXTENT_REG || |
| 2327 | type == BTRFS_FILE_EXTENT_PREALLOC) { | 2333 | 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 */ | ||
| 2328 | if (off > key.offset) { | 2344 | if (off > key.offset) { |
| 2329 | datao += off - key.offset; | 2345 | datao += off - key.offset; |
| 2330 | datal -= off - key.offset; | 2346 | datal -= off - key.offset; |
| 2331 | } | 2347 | } |
| 2332 | 2348 | ||
| 2333 | if (key.offset + datal > off + len) | ||
| 2334 | datal = off + len - key.offset; | ||
| 2335 | |||
| 2336 | ret = btrfs_drop_extents(trans, inode, | 2349 | ret = btrfs_drop_extents(trans, inode, |
| 2337 | new_key.offset, | 2350 | new_key.offset, |
| 2338 | new_key.offset + datal, | 2351 | new_key.offset + datal, |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 7dc36fab4afc..e24b7964a155 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -884,6 +884,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 884 | struct btrfs_root *tree_root = fs_info->tree_root; | 884 | struct btrfs_root *tree_root = fs_info->tree_root; |
| 885 | struct btrfs_root *root = pending->root; | 885 | struct btrfs_root *root = pending->root; |
| 886 | struct btrfs_root *parent_root; | 886 | struct btrfs_root *parent_root; |
| 887 | struct btrfs_block_rsv *rsv; | ||
| 887 | struct inode *parent_inode; | 888 | struct inode *parent_inode; |
| 888 | struct dentry *parent; | 889 | struct dentry *parent; |
| 889 | struct dentry *dentry; | 890 | struct dentry *dentry; |
| @@ -895,6 +896,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 895 | u64 objectid; | 896 | u64 objectid; |
| 896 | u64 root_flags; | 897 | u64 root_flags; |
| 897 | 898 | ||
| 899 | rsv = trans->block_rsv; | ||
| 900 | |||
| 898 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 901 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
| 899 | if (!new_root_item) { | 902 | if (!new_root_item) { |
| 900 | pending->error = -ENOMEM; | 903 | pending->error = -ENOMEM; |
| @@ -1002,6 +1005,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 1002 | btrfs_orphan_post_snapshot(trans, pending); | 1005 | btrfs_orphan_post_snapshot(trans, pending); |
| 1003 | fail: | 1006 | fail: |
| 1004 | kfree(new_root_item); | 1007 | kfree(new_root_item); |
| 1008 | trans->block_rsv = rsv; | ||
| 1005 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); | 1009 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); |
| 1006 | return 0; | 1010 | return 0; |
| 1007 | } | 1011 | } |
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index d733b9cfea34..69565e5fc6a0 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
| @@ -116,6 +116,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans, | |||
| 116 | if (ret) | 116 | if (ret) |
| 117 | goto out; | 117 | goto out; |
| 118 | btrfs_release_path(path); | 118 | btrfs_release_path(path); |
| 119 | |||
| 120 | /* | ||
| 121 | * remove the attribute | ||
| 122 | */ | ||
| 123 | if (!value) | ||
| 124 | goto out; | ||
| 119 | } | 125 | } |
| 120 | 126 | ||
| 121 | again: | 127 | again: |
| @@ -158,6 +164,9 @@ out: | |||
| 158 | return ret; | 164 | return ret; |
| 159 | } | 165 | } |
| 160 | 166 | ||
| 167 | /* | ||
| 168 | * @value: "" makes the attribute to empty, NULL removes it | ||
| 169 | */ | ||
| 161 | int __btrfs_setxattr(struct btrfs_trans_handle *trans, | 170 | int __btrfs_setxattr(struct btrfs_trans_handle *trans, |
| 162 | struct inode *inode, const char *name, | 171 | struct inode *inode, const char *name, |
| 163 | const void *value, size_t size, int flags) | 172 | const void *value, size_t size, int flags) |
