From: Maxim P. <mpa...@pa...> - 2014-02-14 14:43:00
|
Miklos, On 02/13/2014 08:45 PM, Maxim Patlasov wrote: > On 02/13/2014 06:28 PM, Miklos Szeredi wrote: >> On Thu, Feb 13, 2014 at 2:59 PM, Maxim Patlasov <mpa...@pa...> wrote: >>> On 02/13/2014 04:35 PM, Miklos Szeredi wrote: >>>> On Thu, Feb 13, 2014 at 12:44 PM, Maxim Patlasov >>>> <mpa...@pa...> wrote: >>>> >>>> I intentionally took out writeback_enable from both userspace and >>>> kernel because I think it doesn't add any value. >>> Hm... I can still see: >>> >>> >>>> if (arg->flags & FUSE_WRITEBACK_CACHE && >>>> fc->flags & FUSE_ALLOW_WBCACHE) >>>> fc->writeback_cache = 1; >>> in fs/fuse/inode.c from writeback_cache branch. Where did you take it out in >>> kernel? >> Then you are looking at a different branch :) >> >> The one I'm looking at (and is on git.kernel.org) has head at b2ec2778df9d > Sorry, my fault. I used a slightly outdated version of the branch :( > > After updating to b2ec2778df9d an issue showed up: > > # dd if=/dev/zero of=/fuse/foo bs=4k count=1 > 1+0 records in > 1+0 records out > 4096 bytes (4.1 kB) copied, 0.00013326 s, 30.7 MB/s > # dd if=/dev/zero of=/fuse/foo bs=2k count=1 > dd: writing `/fuse/foo': Bad file descriptor > 1+0 records in > 0+0 records out > 0 bytes (0 B) copied, 0.000249716 s, 0.0 kB/s > > I'll investigate, fix it, re-run tests and let you know about results. The problem was in fusexmp_fh.c: if writeback_cache is enabled, we cannot pass O_WRONLY transparently to the host fs because a WRITE may require a READ (if write size < page size). I'm attaching a fix to the end of this email. After the fix, I re-ran tests and again all passed OK. The figures are essentially the same as I posted three days ago. The only difference is in small block sizes: Table 1. The file "foo" is placed on ext4: Host-fs wbc=0 wbc=1 ... bs=2k 111 46 52 (was 62) bs=1k 102 30 38 (was 44) Table 2. The file "foo" is placed on ramfs: Host-fs wbc=0 wbc=1 ... bs=2k 1600 83 100 (was 141) bs=1k 1100 44 61 (was 76) That ~20% degradation (as compared with my previous post that was based on outdated 1ff505ce) came from an optimization you thrown away: > page_len = fuse_page_length(page); > if (!page_len) { > fuse_wait_on_page_writeback(page->mapping->host, page->index); > zero_user(page, 0, PAGE_CACHE_SIZE); > return 0; > } - it's redundant to ask client fs for READ if it's beyond EOF (we trust inode->i_size anyway). Thanks, Maxim diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c index ba6789b..ed4b248 100755 --- a/example/fusexmp_fh.c +++ b/example/fusexmp_fh.c @@ -312,11 +312,20 @@ static int xmp_utimens(const char *path, const struct timespec ts[2]) } #endif +static int flags_for_wbc(int flags) +{ + if ((flags & 0x3) == O_WRONLY) + return (flags & ~0x3) | O_RDWR; + + return flags; + +} + static int xmp_create(const char *path, mode_t mode, struct fuse_file_info *fi) { int fd; - fd = open(path, fi->flags, mode); + fd = open(path, flags_for_wbc(fi->flags), mode); if (fd == -1) return -errno; @@ -328,7 +337,7 @@ static int xmp_open(const char *path, struct fuse_file_info *fi) { int fd; - fd = open(path, fi->flags); + fd = open(path, flags_for_wbc(fi->flags)); if (fd == -1) return -errno; |