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) {