diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-10 18:21:47 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-10 18:21:47 -0400 |
| commit | d92581fcad188d38a5c82c01ace43623bcafea48 (patch) | |
| tree | 792b2e31170b32a41f4f19cea7a2be5efc5eb251 /fs/btrfs/backref.c | |
| parent | b8ea0d06ff00906f6ff133851496b48439d5b04f (diff) | |
| parent | db62efbbf883c099d44b0fafe18f8ad8f0396892 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason:
"These are assorted fixes, mostly from Josef nailing down xfstests
runs. Zach also has a long standing fix for problems with readdir
wrapping f_pos (or ctx->pos)
These patches were spread out over different bases, so I rebased
things on top of rc4 and retested overnight"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
btrfs: don't loop on large offsets in readdir
Btrfs: check to see if root_list is empty before adding it to dead roots
Btrfs: release both paths before logging dir/changed extents
Btrfs: allow splitting of hole em's when dropping extent cache
Btrfs: make sure the backref walker catches all refs to our extent
Btrfs: fix backref walking when we hit a compressed extent
Btrfs: do not offset physical if we're compressed
Btrfs: fix extent buffer leak after backref walking
Btrfs: fix a bug of snapshot-aware defrag to make it work on partial extents
btrfs: fix file truncation if FALLOC_FL_KEEP_SIZE is specified
Diffstat (limited to 'fs/btrfs/backref.c')
| -rw-r--r-- | fs/btrfs/backref.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index eaf133384a8f..8bc5e8ccb091 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -36,16 +36,23 @@ static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb, | |||
| 36 | u64 extent_item_pos, | 36 | u64 extent_item_pos, |
| 37 | struct extent_inode_elem **eie) | 37 | struct extent_inode_elem **eie) |
| 38 | { | 38 | { |
| 39 | u64 data_offset; | 39 | u64 offset = 0; |
| 40 | u64 data_len; | ||
| 41 | struct extent_inode_elem *e; | 40 | struct extent_inode_elem *e; |
| 42 | 41 | ||
| 43 | data_offset = btrfs_file_extent_offset(eb, fi); | 42 | if (!btrfs_file_extent_compression(eb, fi) && |
| 44 | data_len = btrfs_file_extent_num_bytes(eb, fi); | 43 | !btrfs_file_extent_encryption(eb, fi) && |
| 44 | !btrfs_file_extent_other_encoding(eb, fi)) { | ||
| 45 | u64 data_offset; | ||
| 46 | u64 data_len; | ||
| 45 | 47 | ||
| 46 | if (extent_item_pos < data_offset || | 48 | data_offset = btrfs_file_extent_offset(eb, fi); |
| 47 | extent_item_pos >= data_offset + data_len) | 49 | data_len = btrfs_file_extent_num_bytes(eb, fi); |
| 48 | return 1; | 50 | |
| 51 | if (extent_item_pos < data_offset || | ||
| 52 | extent_item_pos >= data_offset + data_len) | ||
| 53 | return 1; | ||
| 54 | offset = extent_item_pos - data_offset; | ||
| 55 | } | ||
| 49 | 56 | ||
| 50 | e = kmalloc(sizeof(*e), GFP_NOFS); | 57 | e = kmalloc(sizeof(*e), GFP_NOFS); |
| 51 | if (!e) | 58 | if (!e) |
| @@ -53,7 +60,7 @@ static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb, | |||
| 53 | 60 | ||
| 54 | e->next = *eie; | 61 | e->next = *eie; |
| 55 | e->inum = key->objectid; | 62 | e->inum = key->objectid; |
| 56 | e->offset = key->offset + (extent_item_pos - data_offset); | 63 | e->offset = key->offset + offset; |
| 57 | *eie = e; | 64 | *eie = e; |
| 58 | 65 | ||
| 59 | return 0; | 66 | return 0; |
| @@ -189,7 +196,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
| 189 | struct extent_buffer *eb; | 196 | struct extent_buffer *eb; |
| 190 | struct btrfs_key key; | 197 | struct btrfs_key key; |
| 191 | struct btrfs_file_extent_item *fi; | 198 | struct btrfs_file_extent_item *fi; |
| 192 | struct extent_inode_elem *eie = NULL; | 199 | struct extent_inode_elem *eie = NULL, *old = NULL; |
| 193 | u64 disk_byte; | 200 | u64 disk_byte; |
| 194 | 201 | ||
| 195 | if (level != 0) { | 202 | if (level != 0) { |
| @@ -223,6 +230,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
| 223 | 230 | ||
| 224 | if (disk_byte == wanted_disk_byte) { | 231 | if (disk_byte == wanted_disk_byte) { |
| 225 | eie = NULL; | 232 | eie = NULL; |
| 233 | old = NULL; | ||
| 226 | if (extent_item_pos) { | 234 | if (extent_item_pos) { |
| 227 | ret = check_extent_in_eb(&key, eb, fi, | 235 | ret = check_extent_in_eb(&key, eb, fi, |
| 228 | *extent_item_pos, | 236 | *extent_item_pos, |
| @@ -230,18 +238,20 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
| 230 | if (ret < 0) | 238 | if (ret < 0) |
| 231 | break; | 239 | break; |
| 232 | } | 240 | } |
| 233 | if (!ret) { | 241 | if (ret > 0) |
| 234 | ret = ulist_add(parents, eb->start, | 242 | goto next; |
| 235 | (uintptr_t)eie, GFP_NOFS); | 243 | ret = ulist_add_merge(parents, eb->start, |
| 236 | if (ret < 0) | 244 | (uintptr_t)eie, |
| 237 | break; | 245 | (u64 *)&old, GFP_NOFS); |
| 238 | if (!extent_item_pos) { | 246 | if (ret < 0) |
| 239 | ret = btrfs_next_old_leaf(root, path, | 247 | break; |
| 240 | time_seq); | 248 | if (!ret && extent_item_pos) { |
| 241 | continue; | 249 | while (old->next) |
| 242 | } | 250 | old = old->next; |
| 251 | old->next = eie; | ||
| 243 | } | 252 | } |
| 244 | } | 253 | } |
| 254 | next: | ||
| 245 | ret = btrfs_next_old_item(root, path, time_seq); | 255 | ret = btrfs_next_old_item(root, path, time_seq); |
| 246 | } | 256 | } |
| 247 | 257 | ||
