On Tue, Jan 08, 2013 at 09:30:54AM +0100, David Sterba wrote:
> On Tue, Jan 08, 2013 at 10:46:38AM +0800, Liu Bo wrote:
> > Hmm, not always here, lockend = inode->i_size - 1, so lockend % 2 == 1 may
> > not
> > be true.
>
> Yeah, that's the case that must be handled,
>
> > But this check can worked in those places where we've rounded the range up
> > to
> > PAGE_SIZE :)
>
> context:
> 2233 u64 lockend = i_size_read(inode);
> ...
> 2236 u64 len = i_size_read(inode);
> ...
> 2240 lockend = max_t(u64, root->sectorsize, lockend);
> ^^^^
>
> lockend will be always at least root->sectorsize == PAGE_SIZE, so the simple
> % 2 == 1 test should work generally. Am I missing something? Do we really lock
> sub-PAGE_SIZE ranges?
Of course this only works for files smaller than PAGE_SIZE, a larger
file is locked up to it's i_size. In that case the value of lockend that
arrives at eg. __set_extent_bit can be of any value.
We can access the inode->i_size via extent_io_tree::mapping->host, so
it's possible to do the exact check.
with this simple check:
void check_range(const char *caller, struct inode *inode, u64 start, u64 end)
{
u64 isize = i_size_read(inode);
if (end >= PAGE_SIZE && (end % 2) == 0 && end != isize - 1) {
printk_ratelimited(KERN_DEBUG
"D: %s isize = %llu odd range [%llu,%llu)\n",
caller,
(unsigned long long)isize,
(unsigned long long)start,
(unsigned long long)end);
}
}
called as:
check_range(__func__, tree->mapping->host, start, end);
from clear_extent_bit, wait_extent_bit, __set_extent_bit,
convert_extent_bit and your "lockend--" fix I can't reproduce the
off-by-one error.
$ cat seektest.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/fcntl.h>
#ifndef SEEK_DATA
#define SEEK_DATA 3
#endif
static char buf[16*1024];
void do_test(const char *fname, loff_t data_start, loff_t len) {
int fd;
loff_t lret;
fd = open(fname, O_RDWR|O_CREAT, 0644);
if (fd == -1) {
perror("open()");
exit(1);
}
printf("[0,%llu] hole\n", data_start - 1);
llseek(fd, data_start, SEEK_SET);
write(fd, buf, len);
printf("[%llu,%llu] data\n", data_start, len - 1);
fsync(fd);
llseek(fd, 0, SEEK_SET);
lret = llseek(fd, 0, SEEK_DATA);
printf("seek to data returned: %llu\n",
(unsigned long long)lret);
close(fd);
}
int main() {
do_test("seektest-small-even", 3072, 512);
do_test("seektest-small-odd", 3072, 511);
do_test("seektest-big-even", 8192, 512);
do_test("seektest-big-odd", 8192, 511);
do_test("seektest-big-aligned", 8192, 4096);
do_test("seektest-big-aligned-1", 8192, 4095);
do_test("seektest-big-aligned+1", 8192, 4097);
return 0;
}
---
However, I'm running xfstests with this debugging patch and I cant'
explain such messages:
[20177.655732] D: __set_extent_bit isize = 0 odd range
[352256,8740681790172090368)
[20177.664485] D: clear_extent_bit isize = 0 odd range
[352256,8740681790172090368)
[20182.399257] D: __set_extent_bit isize = 944560 odd range
[229376,7504638559450173440)
[20182.408465] D: clear_extent_bit isize = 944560 odd range
[229376,7504638559450173440)
[20183.543186] D: __set_extent_bit isize = 396355 odd range
[692224,2301956497953013760)
[20183.552170] D: clear_extent_bit isize = 396355 odd range
[692224,2301956497953013760)
[20187.018092] D: __set_extent_bit isize = 0 odd range
[401408,306555945915797504)
[20187.026532] D: clear_extent_bit isize = 0 odd range
[401408,306555945915797504)
[20189.941615] D: __set_extent_bit isize = 1936258 odd range
[2457600,6817576374066888704)
[20189.950751] D: clear_extent_bit isize = 1936258 odd range
[2457600,6817576374066888704)
[20190.642796] D: __set_extent_bit isize = 0 odd range
[274432,8022548162794254336)
[20190.651380] D: clear_extent_bit isize = 0 odd range
[274432,8022548162794254336)
[20191.244458] D: __set_extent_bit isize = 845491 odd range
[1671168,5821247760915324928)
[20191.253508] D: clear_extent_bit isize = 845491 odd range
[1671168,5821247760915324928)
[20191.948060] D: __set_extent_bit isize = 0 odd range
[774144,7384799041917984768)
[20191.956581] D: clear_extent_bit isize = 0 odd range
[774144,7384799041917984768)
so I'm not sending it as a separate patch yet until the check covers all cases.
david
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html