diff options
Diffstat (limited to 'fs/btrfs')
-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 | 25 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 4 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 40 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 40 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 4 | ||||
-rw-r--r-- | fs/btrfs/xattr.c | 9 |
8 files changed, 98 insertions, 34 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..a381cd22f518 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); |
@@ -1813,6 +1817,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) | |||
1813 | goto out; | 1817 | goto out; |
1814 | case SEEK_DATA: | 1818 | case SEEK_DATA: |
1815 | case SEEK_HOLE: | 1819 | case SEEK_HOLE: |
1820 | if (offset >= i_size_read(inode)) { | ||
1821 | mutex_unlock(&inode->i_mutex); | ||
1822 | return -ENXIO; | ||
1823 | } | ||
1824 | |||
1816 | ret = find_desired_extent(inode, &offset, origin); | 1825 | ret = find_desired_extent(inode, &offset, origin); |
1817 | if (ret) { | 1826 | if (ret) { |
1818 | mutex_unlock(&inode->i_mutex); | 1827 | mutex_unlock(&inode->i_mutex); |
@@ -1821,11 +1830,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) | |||
1821 | } | 1830 | } |
1822 | 1831 | ||
1823 | if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { | 1832 | if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { |
1824 | ret = -EINVAL; | 1833 | offset = -EINVAL; |
1825 | goto out; | 1834 | goto out; |
1826 | } | 1835 | } |
1827 | if (offset > inode->i_sb->s_maxbytes) { | 1836 | if (offset > inode->i_sb->s_maxbytes) { |
1828 | ret = -EINVAL; | 1837 | offset = -EINVAL; |
1829 | goto out; | 1838 | goto out; |
1830 | } | 1839 | } |
1831 | 1840 | ||
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..b2d004ad66a0 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 | ||
@@ -4018,7 +4018,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
4018 | memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key)); | 4018 | memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key)); |
4019 | kfree(dentry->d_fsdata); | 4019 | kfree(dentry->d_fsdata); |
4020 | dentry->d_fsdata = NULL; | 4020 | dentry->d_fsdata = NULL; |
4021 | d_clear_need_lookup(dentry); | 4021 | /* This thing is hashed, drop it for now */ |
4022 | d_drop(dentry); | ||
4022 | } else { | 4023 | } else { |
4023 | ret = btrfs_inode_by_name(dir, dentry, &location); | 4024 | ret = btrfs_inode_by_name(dir, dentry, &location); |
4024 | } | 4025 | } |
@@ -4085,7 +4086,15 @@ static void btrfs_dentry_release(struct dentry *dentry) | |||
4085 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | 4086 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, |
4086 | struct nameidata *nd) | 4087 | struct nameidata *nd) |
4087 | { | 4088 | { |
4088 | return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry); | 4089 | struct dentry *ret; |
4090 | |||
4091 | ret = d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry); | ||
4092 | if (unlikely(d_need_lookup(dentry))) { | ||
4093 | spin_lock(&dentry->d_lock); | ||
4094 | dentry->d_flags &= ~DCACHE_NEED_LOOKUP; | ||
4095 | spin_unlock(&dentry->d_lock); | ||
4096 | } | ||
4097 | return ret; | ||
4089 | } | 4098 | } |
4090 | 4099 | ||
4091 | unsigned char btrfs_filetype_table[] = { | 4100 | unsigned char btrfs_filetype_table[] = { |
@@ -4125,7 +4134,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4125 | 4134 | ||
4126 | /* special case for "." */ | 4135 | /* special case for "." */ |
4127 | if (filp->f_pos == 0) { | 4136 | if (filp->f_pos == 0) { |
4128 | over = filldir(dirent, ".", 1, 1, btrfs_ino(inode), DT_DIR); | 4137 | over = filldir(dirent, ".", 1, |
4138 | filp->f_pos, btrfs_ino(inode), DT_DIR); | ||
4129 | if (over) | 4139 | if (over) |
4130 | return 0; | 4140 | return 0; |
4131 | filp->f_pos = 1; | 4141 | filp->f_pos = 1; |
@@ -4134,7 +4144,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4134 | if (filp->f_pos == 1) { | 4144 | if (filp->f_pos == 1) { |
4135 | u64 pino = parent_ino(filp->f_path.dentry); | 4145 | u64 pino = parent_ino(filp->f_path.dentry); |
4136 | over = filldir(dirent, "..", 2, | 4146 | over = filldir(dirent, "..", 2, |
4137 | 2, pino, DT_DIR); | 4147 | filp->f_pos, pino, DT_DIR); |
4138 | if (over) | 4148 | if (over) |
4139 | return 0; | 4149 | return 0; |
4140 | filp->f_pos = 2; | 4150 | filp->f_pos = 2; |
@@ -5823,7 +5833,7 @@ again: | |||
5823 | 5833 | ||
5824 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); | 5834 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); |
5825 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); | 5835 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
5826 | if (!ret) | 5836 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) |
5827 | btrfs_update_inode(trans, root, inode); | 5837 | btrfs_update_inode(trans, root, inode); |
5828 | ret = 0; | 5838 | ret = 0; |
5829 | out_unlock: | 5839 | out_unlock: |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 970977aab224..538f65a79ec5 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -2177,6 +2177,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2177 | if (!(src_file->f_mode & FMODE_READ)) | 2177 | if (!(src_file->f_mode & FMODE_READ)) |
2178 | goto out_fput; | 2178 | goto out_fput; |
2179 | 2179 | ||
2180 | /* don't make the dst file partly checksummed */ | ||
2181 | if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != | ||
2182 | (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) | ||
2183 | goto out_fput; | ||
2184 | |||
2180 | ret = -EISDIR; | 2185 | ret = -EISDIR; |
2181 | if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) | 2186 | if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) |
2182 | goto out_fput; | 2187 | goto out_fput; |
@@ -2220,6 +2225,16 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2220 | !IS_ALIGNED(destoff, bs)) | 2225 | !IS_ALIGNED(destoff, bs)) |
2221 | goto out_unlock; | 2226 | goto out_unlock; |
2222 | 2227 | ||
2228 | if (destoff > inode->i_size) { | ||
2229 | ret = btrfs_cont_expand(inode, inode->i_size, destoff); | ||
2230 | if (ret) | ||
2231 | goto out_unlock; | ||
2232 | } | ||
2233 | |||
2234 | /* truncate page cache pages from target inode range */ | ||
2235 | truncate_inode_pages_range(&inode->i_data, destoff, | ||
2236 | PAGE_CACHE_ALIGN(destoff + len) - 1); | ||
2237 | |||
2223 | /* do any pending delalloc/csum calc on src, one way or | 2238 | /* do any pending delalloc/csum calc on src, one way or |
2224 | another, and lock file content */ | 2239 | another, and lock file content */ |
2225 | while (1) { | 2240 | while (1) { |
@@ -2236,10 +2251,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2236 | btrfs_wait_ordered_range(src, off, len); | 2251 | btrfs_wait_ordered_range(src, off, len); |
2237 | } | 2252 | } |
2238 | 2253 | ||
2239 | /* truncate page cache pages from target inode range */ | ||
2240 | truncate_inode_pages_range(&inode->i_data, off, | ||
2241 | ALIGN(off + len, PAGE_CACHE_SIZE) - 1); | ||
2242 | |||
2243 | /* clone data */ | 2254 | /* clone data */ |
2244 | key.objectid = btrfs_ino(src); | 2255 | key.objectid = btrfs_ino(src); |
2245 | key.type = BTRFS_EXTENT_DATA_KEY; | 2256 | key.type = BTRFS_EXTENT_DATA_KEY; |
@@ -2317,7 +2328,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2317 | else | 2328 | else |
2318 | new_key.offset = destoff; | 2329 | new_key.offset = destoff; |
2319 | 2330 | ||
2320 | trans = btrfs_start_transaction(root, 1); | 2331 | /* |
2332 | * 1 - adjusting old extent (we may have to split it) | ||
2333 | * 1 - add new extent | ||
2334 | * 1 - inode update | ||
2335 | */ | ||
2336 | trans = btrfs_start_transaction(root, 3); | ||
2321 | if (IS_ERR(trans)) { | 2337 | if (IS_ERR(trans)) { |
2322 | ret = PTR_ERR(trans); | 2338 | ret = PTR_ERR(trans); |
2323 | goto out; | 2339 | goto out; |
@@ -2325,14 +2341,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2325 | 2341 | ||
2326 | if (type == BTRFS_FILE_EXTENT_REG || | 2342 | if (type == BTRFS_FILE_EXTENT_REG || |
2327 | type == BTRFS_FILE_EXTENT_PREALLOC) { | 2343 | type == BTRFS_FILE_EXTENT_PREALLOC) { |
2344 | /* | ||
2345 | * a | --- range to clone ---| b | ||
2346 | * | ------------- extent ------------- | | ||
2347 | */ | ||
2348 | |||
2349 | /* substract range b */ | ||
2350 | if (key.offset + datal > off + len) | ||
2351 | datal = off + len - key.offset; | ||
2352 | |||
2353 | /* substract range a */ | ||
2328 | if (off > key.offset) { | 2354 | if (off > key.offset) { |
2329 | datao += off - key.offset; | 2355 | datao += off - key.offset; |
2330 | datal -= off - key.offset; | 2356 | datal -= off - key.offset; |
2331 | } | 2357 | } |
2332 | 2358 | ||
2333 | if (key.offset + datal > off + len) | ||
2334 | datal = off + len - key.offset; | ||
2335 | |||
2336 | ret = btrfs_drop_extents(trans, inode, | 2359 | ret = btrfs_drop_extents(trans, inode, |
2337 | new_key.offset, | 2360 | new_key.offset, |
2338 | new_key.offset + datal, | 2361 | new_key.offset + datal, |
@@ -2429,7 +2452,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2429 | if (endoff > inode->i_size) | 2452 | if (endoff > inode->i_size) |
2430 | btrfs_i_size_write(inode, endoff); | 2453 | btrfs_i_size_write(inode, endoff); |
2431 | 2454 | ||
2432 | BTRFS_I(inode)->flags = BTRFS_I(src)->flags; | ||
2433 | ret = btrfs_update_inode(trans, root, inode); | 2455 | ret = btrfs_update_inode(trans, root, inode); |
2434 | BUG_ON(ret); | 2456 | BUG_ON(ret); |
2435 | btrfs_end_transaction(trans, root); | 2457 | btrfs_end_transaction(trans, root); |
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) |