diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-09-12 14:47:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-09-12 14:47:49 -0400 |
commit | 0b001b2edaead6fd906b1f87967ae05f082189c4 (patch) | |
tree | 2df377b4b08946af496941e9d18a48e9a100af6b /fs | |
parent | 5dfcc87fd79dfb96ed155b524337dbd0da4f5993 (diff) | |
parent | d525e8ab022cb000e6e31a515ba8c3cf0d9c6130 (diff) |
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
Diffstat (limited to 'fs')
-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) |