Hello,
When truncating a inline extent, btrfs_drop_extents doesn't properly
handle the case "key.offset > inline_limit". This bug can only
happen
when max line size is larger than 8K.
Attachment is the test case.
Regards
YZ
---
diff -r 96b323332c3b file.c
--- a/file.c Tue Jan 29 16:06:37 2008 -0500
+++ b/file.c Thu Jan 31 00:39:29 2008 +0800
@@ -591,8 +591,7 @@ next_slot:
}
}
bookend = 1;
- if (found_inline && start <= key.offset &&
- inline_limit < extent_end)
+ if (found_inline && start <= key.offset)
keep = 1;
}
/* truncate existing extent */
@@ -672,11 +671,10 @@ next_slot:
if (!bookend)
continue;
}
- if (bookend && found_inline && start <= key.offset
&&
- inline_limit < extent_end && key.offset <= inline_limit) {
+ if (bookend && found_inline && start <= key.offset) {
u32 new_size;
new_size = btrfs_file_extent_calc_inline_size(
- extent_end - inline_limit);
+ extent_end - end);
btrfs_truncate_item(trans, root, path, new_size, 0);
}
/* create bookend, splitting the extent in two */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.c
Type: text/x-csrc
Size: 680 bytes
Desc: not available
Url :
http://oss.oracle.com/pipermail/btrfs-devel/attachments/20080131/ae09680b/test.bin
Hello,
The test case in previous mail doesn't work due to changes recently
pushed out. Here is the new test case.
Regards
YZ
---
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd;
int ret;
char buf[8192];
fd = open(argv[1], O_RDWR | O_CREAT | O_EXCL, 0644);
if (fd < 0) {
perror("open");
exit(1);
}
/* create inline extent */
ret = pwrite(fd, buf, 1024 * 6 - 1, 4096);
if (ret < 0) {
perror("write");
exit(1);
}
/* disable packing of data */
ret = pwrite(fd, buf, 4096, 32768);
if (ret < 0) {
perror("write");
exit(1);
}
/* drop file extents in range 0 ~ 8192 */
ret = pwrite(fd, buf, 8192, 0);
if (ret < 0) {
perror("write");
exit(1);
}
close(fd);
return 0;
}
Hello,
It's possible "key.type == BTRFS_INODE_REF_KEY" and
"key.offset >= end".
Regards
YZ
---
diff -r ae9d13944c09 file.c
--- a/file.c Mon Feb 04 10:10:43 2008 -0500
+++ b/file.c Wed Feb 06 00:12:56 2008 +0800
@@ -510,10 +510,12 @@ next_slot:
ret = 0;
btrfs_item_key_to_cpu(leaf, &key, slot);
- if (key.offset >= end || key.objectid != inode->i_ino) {
- goto out;
- }
- if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY) {
+ if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY &&
+ key.offset >= end) {
+ goto out;
+ }
+ if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
+ key.objectid != inode->i_ino) {
goto out;
}
if (recow) {