linux-cifs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
@ 2019-08-15  6:30 ronnie sahlberg
  2019-08-15 15:15 ` Tom Talpey
  2019-08-15 15:48 ` David Disseldorp
  0 siblings, 2 replies; 11+ messages in thread
From: ronnie sahlberg @ 2019-08-15  6:30 UTC (permalink / raw)
  To: linux-cifs

I am seeing issues with how FSCTL_QUERY_ALLOCATED_RANGES behaves under windows,
in particular that it is inconsistent so we can't run certain xfstests
against windows servers.


The behavior can be triggered using the following command from xfstests :
  ./src/seek_sanity_test -s 19 -e 19 /mnt/file
(where /mnt is an smb share mounted from a windows 2016 server.)

In cifs.ko we use this FSCTL to implement both SEEK_HOLE/SEEK_DATA as well as
fiemap(). But since the behavior of this FSCTL is not deteministic it often
cause the tests to fail.


This is a test tool for SEEK_DATA and SEEK_HOLE. As part of this it performs
a check to try to discover if the filesystem supports sparse files or not.
For non-sparse files SEEK_DATA is basically a no-op and SEEK_HOLE just returns
the file size.
Later during the test, the result of whether the file is "sparse" or not
will affect what the expected results are. If this check gets the
sparse-supported wrong the test cases later will fail.


How the check works:
====================
The actual check for whether the file supports being sparse or not is the
following snippet :
        ftruncate(fd, 0);
        bufsz = alloc_size * 2;
        filsz = bufsz * 2;

        buf = do_malloc(bufsz);
        if (!buf)
                goto out;
        memset(buf, 'a', bufsz);

        /* File with 2 allocated blocks.... */
        ret = do_pwrite(fd, buf, bufsz, 0);
        if (ret)
                goto out;

        /* followed by a hole... */
        ret = do_truncate(fd, filsz);
        if (ret)
                goto out;

        /* Is SEEK_DATA and SEEK_HOLE supported in the kernel? */
        pos = lseek(fd, 0, SEEK_HOLE);
        if (pos == -1) {
                fprintf(stderr, "Kernel does not support llseek(2) extension "
                        "SEEK_HOLE. Aborting.\n");
                ret = -1;
                goto out;
        }

        if (pos == filsz) {
                default_behavior = 1;
                fprintf(stderr, "File system supports the default behavior.\n")\
;
        }

I.e.
1, ftruncate to 0
2, write 2M to the start of the file
3, ftruncate the file to be 4Mb
4, SEEK_HOLE and check if it returns 4Mb or no.
If it returns 4Mb then we switch back to default_behavior and we allow
the semantics as if the file is not sparse.
I.e. allow SEEK_DATA to behave as if the file is either sparse or not-sparse.

Also note that if it looks like the sparse-file is not supported then
it prints ""File system supports the default behavior." which may help when
running the test tool.

Strace for this check (when the check failed.)
=============================================
18:22:14.949612 ftruncate(3, 0)         = 0 <0.011513>
18:22:14.963725 mmap(NULL, 2101248, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe8d9f14000 <0.0
00192>
18:22:14.970334 pwrite64(3,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...,
2097152, 0) = 2097152 <0.002127>
18:22:14.972620 ftruncate(3, 4194304)   = 0 <0.582491>
18:22:15.557308 lseek(3, 0, SEEK_HOLE)  = 4194304 <0.012791>
18:22:15.572457 write(2, "File system supports the default
behavior.\n", 43) = 43 <0.000318>


Example of when the check goes "Wrong". Capture seek_good.cap
=============================================================
The relevant packets here are
1820, set end of file == 0
(1822/1823 update timestamps)
2930, write 2Mb to offset 0
3008, set the file sparse
3010, set end of file to 4M
3019, query-allocated-ranges

In 3019/3020 the server responds that the full 0-4M range is allocated.
This is wrong since file should only be allocated in the first 2Mb at
this stage.
And this makes the test tool think that we don't support sparse files,
and sets default_behavior to 1.

A different run when the check is successful (seek_bad.cap)
============================================================
In the seek_bad capture you can see the same sequence in packets
1869, set end of file == 0
2990, write the first 2M of the file
3067, set file sparse
3069, set end of file to 4M
3078, query-allocated-ranges
But this time, query-allocated-ranges report that only 0-2M is mapped,
which is the correct range,
and thus the test tool assumes that we can handle holes properly.

The captures are ~5MByte each unfiltered so too big for the list.
Email me directly and I will send them to you.


So the question here is what is the actual semantics for sparse files
and query-allocated-ranges on windows?


regards
ronnie sahlberg

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-15  6:30 FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016 ronnie sahlberg
@ 2019-08-15 15:15 ` Tom Talpey
  2019-08-16  2:17   ` ronnie sahlberg
  2019-08-15 15:48 ` David Disseldorp
  1 sibling, 1 reply; 11+ messages in thread
From: Tom Talpey @ 2019-08-15 15:15 UTC (permalink / raw)
  To: ronnie sahlberg, linux-cifs

> -----Original Message-----
> From: linux-cifs-owner@vger.kernel.org <linux-cifs-owner@vger.kernel.org> On
> Behalf Of ronnie sahlberg
> Sent: Wednesday, August 14, 2019 11:31 PM
> To: linux-cifs <linux-cifs@vger.kernel.org>
> Subject: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
> 
> I am seeing issues with how FSCTL_QUERY_ALLOCATED_RANGES behaves
> under windows,
> in particular that it is inconsistent so we can't run certain xfstests
> against windows servers.
> 
> 
> The behavior can be triggered using the following command from xfstests :
>   ./src/seek_sanity_test -s 19 -e 19 /mnt/file
> (where /mnt is an smb share mounted from a windows 2016 server.)
> 
> In cifs.ko we use this FSCTL to implement both SEEK_HOLE/SEEK_DATA as well
> as
> fiemap(). But since the behavior of this FSCTL is not deteministic it often
> cause the tests to fail.
> 
> 
> This is a test tool for SEEK_DATA and SEEK_HOLE. As part of this it performs
> a check to try to discover if the filesystem supports sparse files or not.
> For non-sparse files SEEK_DATA is basically a no-op and SEEK_HOLE just returns
> the file size.
> Later during the test, the result of whether the file is "sparse" or not
> will affect what the expected results are. If this check gets the
> sparse-supported wrong the test cases later will fail.
> 
> 
> How the check works:
> ====================
> The actual check for whether the file supports being sparse or not is the
> following snippet :
>         ftruncate(fd, 0);
>         bufsz = alloc_size * 2;
>         filsz = bufsz * 2;
> 
>         buf = do_malloc(bufsz);
>         if (!buf)
>                 goto out;
>         memset(buf, 'a', bufsz);
> 
>         /* File with 2 allocated blocks.... */
>         ret = do_pwrite(fd, buf, bufsz, 0);
>         if (ret)
>                 goto out;
> 
>         /* followed by a hole... */
>         ret = do_truncate(fd, filsz);
>         if (ret)
>                 goto out;
> 
>         /* Is SEEK_DATA and SEEK_HOLE supported in the kernel? */
>         pos = lseek(fd, 0, SEEK_HOLE);
>         if (pos == -1) {
>                 fprintf(stderr, "Kernel does not support llseek(2) extension "
>                         "SEEK_HOLE. Aborting.\n");
>                 ret = -1;
>                 goto out;
>         }
> 
>         if (pos == filsz) {
>                 default_behavior = 1;
>                 fprintf(stderr, "File system supports the default behavior.\n")\
> ;
>         }
> 
> I.e.
> 1, ftruncate to 0
> 2, write 2M to the start of the file
> 3, ftruncate the file to be 4Mb
> 4, SEEK_HOLE and check if it returns 4Mb or no.
> If it returns 4Mb then we switch back to default_behavior and we allow
> the semantics as if the file is not sparse.
> I.e. allow SEEK_DATA to behave as if the file is either sparse or not-sparse.
> 
> Also note that if it looks like the sparse-file is not supported then
> it prints ""File system supports the default behavior." which may help when
> running the test tool.
> 
> Strace for this check (when the check failed.)
> =============================================
> 18:22:14.949612 ftruncate(3, 0)         = 0 <0.011513>
> 18:22:14.963725 mmap(NULL, 2101248, PROT_READ|PROT_WRITE,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe8d9f14000 <0.0
> 00192>
> 18:22:14.970334 pwrite64(3,
> "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> aaaaaaaaaaaaaaaaaa
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...,
> 2097152, 0) = 2097152 <0.002127>
> 18:22:14.972620 ftruncate(3, 4194304)   = 0 <0.582491>
> 18:22:15.557308 lseek(3, 0, SEEK_HOLE)  = 4194304 <0.012791>
> 18:22:15.572457 write(2, "File system supports the default
> behavior.\n", 43) = 43 <0.000318>
> 
> 
> Example of when the check goes "Wrong". Capture seek_good.cap
> =============================================================
> The relevant packets here are
> 1820, set end of file == 0
> (1822/1823 update timestamps)
> 2930, write 2Mb to offset 0
> 3008, set the file sparse
> 3010, set end of file to 4M
> 3019, query-allocated-ranges
> 
> In 3019/3020 the server responds that the full 0-4M range is allocated.
> This is wrong since file should only be allocated in the first 2Mb at
> this stage.
> And this makes the test tool think that we don't support sparse files,
> and sets default_behavior to 1.
> 
> A different run when the check is successful (seek_bad.cap)
> ============================================================
> In the seek_bad capture you can see the same sequence in packets
> 1869, set end of file == 0
> 2990, write the first 2M of the file
> 3067, set file sparse
> 3069, set end of file to 4M
> 3078, query-allocated-ranges
> But this time, query-allocated-ranges report that only 0-2M is mapped,
> which is the correct range,
> and thus the test tool assumes that we can handle holes properly.
> 
> The captures are ~5MByte each unfiltered so too big for the list.
> Email me directly and I will send them to you.
> 
> 
> So the question here is what is the actual semantics for sparse files
> and query-allocated-ranges on windows?

I'll try to get you an answer, but in the meantime just a question...
Does the behavior change if the file is opened with FILE_FLAG_WRITE_THROUGH?

Tom.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-15  6:30 FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016 ronnie sahlberg
  2019-08-15 15:15 ` Tom Talpey
@ 2019-08-15 15:48 ` David Disseldorp
  2019-08-16  2:07   ` ronnie sahlberg
  1 sibling, 1 reply; 11+ messages in thread
From: David Disseldorp @ 2019-08-15 15:48 UTC (permalink / raw)
  To: ronnie sahlberg; +Cc: linux-cifs

Hi Ronnie,

Is the file flagged sparse (FSCTL_SET_SPARSE()) prior to the QAR
request? When implementing the Samba server-side I tried to match
Windows/spec behaviour with:

702         if (!fsp->is_sparse) {
703                 struct file_alloced_range_buf qar_buf;
704 
705                 /* file is non-sparse, claim file_off->max_off is allocated */
706                 qar_buf.file_off = qar_req.buf.file_off;
707                 /* + 1 to convert maximum offset back to length */
708                 qar_buf.len = max_off - qar_req.buf.file_off + 1;
709 
710                 status = fsctl_qar_buf_push(mem_ctx, &qar_buf, &qar_array_blob);
711         } else {
712                 status = fsctl_qar_seek_fill(mem_ctx, fsp, qar_req.buf.file_off,
713                                              max_off, &qar_array_blob);
714         }

...in which case you should see similar test results against Samba. This
also excersized via the ioctl_sparse_qar* smbtorture tests.

Cheers, David

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-15 15:48 ` David Disseldorp
@ 2019-08-16  2:07   ` ronnie sahlberg
  2019-08-16  4:36     ` ronnie sahlberg
  2019-08-16  9:07     ` David Disseldorp
  0 siblings, 2 replies; 11+ messages in thread
From: ronnie sahlberg @ 2019-08-16  2:07 UTC (permalink / raw)
  To: David Disseldorp; +Cc: linux-cifs

On Fri, Aug 16, 2019 at 1:48 AM David Disseldorp <ddiss@suse.de> wrote:
>
> Hi Ronnie,
>
> Is the file flagged sparse (FSCTL_SET_SPARSE()) prior to the QAR
> request?

Yes. The file is written to, the first 2MB.
Then FSCTL_SET_SPARSE is called to make it sparse.
Then there is a SET-INFO SET_END_OF_FILE to expand the file to 4Mb.
there are a few other commands
Then there is a GET-INFO / FILE_ALL_INFO and the sparse flag is still set
then a QUERY_ALLOCATED_RANGES which returns a single region from 0 to 4Mb.

The whole behavior is really odd.

I am happy to mail you the wireshark traces for this. Can I do that?
Just so you can look at them and confirm I am not crazy :-)
I cant send them to the list because they are 5Mb each and it is rude
to send such big attachments to a mailinglist.



> When implementing the Samba server-side I tried to match
> Windows/spec behaviour with:
>
> 702         if (!fsp->is_sparse) {
> 703                 struct file_alloced_range_buf qar_buf;
> 704
> 705                 /* file is non-sparse, claim file_off->max_off is allocated */
> 706                 qar_buf.file_off = qar_req.buf.file_off;
> 707                 /* + 1 to convert maximum offset back to length */
> 708                 qar_buf.len = max_off - qar_req.buf.file_off + 1;
> 709
> 710                 status = fsctl_qar_buf_push(mem_ctx, &qar_buf, &qar_array_blob);
> 711         } else {
> 712                 status = fsctl_qar_seek_fill(mem_ctx, fsp, qar_req.buf.file_off,
> 713                                              max_off, &qar_array_blob);
> 714         }
>
> ...in which case you should see similar test results against Samba. This
> also excersized via the ioctl_sparse_qar* smbtorture tests.
>
> Cheers, David

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-15 15:15 ` Tom Talpey
@ 2019-08-16  2:17   ` ronnie sahlberg
  0 siblings, 0 replies; 11+ messages in thread
From: ronnie sahlberg @ 2019-08-16  2:17 UTC (permalink / raw)
  To: Tom Talpey; +Cc: linux-cifs

On Fri, Aug 16, 2019 at 1:15 AM Tom Talpey <ttalpey@microsoft.com> wrote:
>
> > -----Original Message-----
> > From: linux-cifs-owner@vger.kernel.org <linux-cifs-owner@vger.kernel.org> On
> > Behalf Of ronnie sahlberg
> > Sent: Wednesday, August 14, 2019 11:31 PM
> > To: linux-cifs <linux-cifs@vger.kernel.org>
> > Subject: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
> >
> > I am seeing issues with how FSCTL_QUERY_ALLOCATED_RANGES behaves
> > under windows,
> > in particular that it is inconsistent so we can't run certain xfstests
> > against windows servers.
> >
> >
> > The behavior can be triggered using the following command from xfstests :
> >   ./src/seek_sanity_test -s 19 -e 19 /mnt/file
> > (where /mnt is an smb share mounted from a windows 2016 server.)
> >
> > In cifs.ko we use this FSCTL to implement both SEEK_HOLE/SEEK_DATA as well
> > as
> > fiemap(). But since the behavior of this FSCTL is not deteministic it often
> > cause the tests to fail.
> >
> >
> > This is a test tool for SEEK_DATA and SEEK_HOLE. As part of this it performs
> > a check to try to discover if the filesystem supports sparse files or not.
> > For non-sparse files SEEK_DATA is basically a no-op and SEEK_HOLE just returns
> > the file size.
> > Later during the test, the result of whether the file is "sparse" or not
> > will affect what the expected results are. If this check gets the
> > sparse-supported wrong the test cases later will fail.
> >
> >
> > How the check works:
> > ====================
> > The actual check for whether the file supports being sparse or not is the
> > following snippet :
> >         ftruncate(fd, 0);
> >         bufsz = alloc_size * 2;
> >         filsz = bufsz * 2;
> >
> >         buf = do_malloc(bufsz);
> >         if (!buf)
> >                 goto out;
> >         memset(buf, 'a', bufsz);
> >
> >         /* File with 2 allocated blocks.... */
> >         ret = do_pwrite(fd, buf, bufsz, 0);
> >         if (ret)
> >                 goto out;
> >
> >         /* followed by a hole... */
> >         ret = do_truncate(fd, filsz);
> >         if (ret)
> >                 goto out;
> >
> >         /* Is SEEK_DATA and SEEK_HOLE supported in the kernel? */
> >         pos = lseek(fd, 0, SEEK_HOLE);
> >         if (pos == -1) {
> >                 fprintf(stderr, "Kernel does not support llseek(2) extension "
> >                         "SEEK_HOLE. Aborting.\n");
> >                 ret = -1;
> >                 goto out;
> >         }
> >
> >         if (pos == filsz) {
> >                 default_behavior = 1;
> >                 fprintf(stderr, "File system supports the default behavior.\n")\
> > ;
> >         }
> >
> > I.e.
> > 1, ftruncate to 0
> > 2, write 2M to the start of the file
> > 3, ftruncate the file to be 4Mb
> > 4, SEEK_HOLE and check if it returns 4Mb or no.
> > If it returns 4Mb then we switch back to default_behavior and we allow
> > the semantics as if the file is not sparse.
> > I.e. allow SEEK_DATA to behave as if the file is either sparse or not-sparse.
> >
> > Also note that if it looks like the sparse-file is not supported then
> > it prints ""File system supports the default behavior." which may help when
> > running the test tool.
> >
> > Strace for this check (when the check failed.)
> > =============================================
> > 18:22:14.949612 ftruncate(3, 0)         = 0 <0.011513>
> > 18:22:14.963725 mmap(NULL, 2101248, PROT_READ|PROT_WRITE,
> > MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe8d9f14000 <0.0
> > 00192>
> > 18:22:14.970334 pwrite64(3,
> > "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> > aaaaaaaaaaaaaaaaaa
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...,
> > 2097152, 0) = 2097152 <0.002127>
> > 18:22:14.972620 ftruncate(3, 4194304)   = 0 <0.582491>
> > 18:22:15.557308 lseek(3, 0, SEEK_HOLE)  = 4194304 <0.012791>
> > 18:22:15.572457 write(2, "File system supports the default
> > behavior.\n", 43) = 43 <0.000318>
> >
> >
> > Example of when the check goes "Wrong". Capture seek_good.cap
> > =============================================================
> > The relevant packets here are
> > 1820, set end of file == 0
> > (1822/1823 update timestamps)
> > 2930, write 2Mb to offset 0
> > 3008, set the file sparse
> > 3010, set end of file to 4M
> > 3019, query-allocated-ranges
> >
> > In 3019/3020 the server responds that the full 0-4M range is allocated.
> > This is wrong since file should only be allocated in the first 2Mb at
> > this stage.
> > And this makes the test tool think that we don't support sparse files,
> > and sets default_behavior to 1.
> >
> > A different run when the check is successful (seek_bad.cap)
> > ============================================================
> > In the seek_bad capture you can see the same sequence in packets
> > 1869, set end of file == 0
> > 2990, write the first 2M of the file
> > 3067, set file sparse
> > 3069, set end of file to 4M
> > 3078, query-allocated-ranges
> > But this time, query-allocated-ranges report that only 0-2M is mapped,
> > which is the correct range,
> > and thus the test tool assumes that we can handle holes properly.
> >
> > The captures are ~5MByte each unfiltered so too big for the list.
> > Email me directly and I will send them to you.
> >
> >
> > So the question here is what is the actual semantics for sparse files
> > and query-allocated-ranges on windows?
>
> I'll try to get you an answer, but in the meantime just a question...
> Does the behavior change if the file is opened with FILE_FLAG_WRITE_THROUGH?

I will try that shortly.
There is a SMB2_FLUSH call on the handle immediately before the call
to QUERY-ALLOCATED_RANGES.
Would that have the same effect as the writethrough flag?

I am happy to email the wireshark traces to you to look at exactly
what goes on on the wire.
I have two example traces, taken a minute apart.
One instance QAR reports a range of 0-2M, the other the reported range is 0-4M


>
> Tom.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-16  2:07   ` ronnie sahlberg
@ 2019-08-16  4:36     ` ronnie sahlberg
  2019-08-19 16:31       ` David Disseldorp
  2019-08-16  9:07     ` David Disseldorp
  1 sibling, 1 reply; 11+ messages in thread
From: ronnie sahlberg @ 2019-08-16  4:36 UTC (permalink / raw)
  To: David Disseldorp; +Cc: linux-cifs

So to recap. Win2016 server in our buildbot.

We write to the file and populate the first 2Mb
we set the file to sparse using FSCTL SET-SPARSE
we use SET-INFO and file-end-of-file-info and set the new end of file to 4Mb
we use set-info and file-all-info and update the timestamps
we use get-info/file-all-info and the sparse flag is still set. **
we flush the file (we always destage all dirty pages and flush before
calling qar)
we call qar and sometimes it returns that 0-2Mb is allocated.
sometimes it returns that 0-4Mb is allocated.

In both cases, in ** the sparse flag is still set.

Just looking further down in the trace.  A few packets later after the
QAR  we re-open the file.
In the SMB2-CREATE response   the Sparse flag is still set.


At this point I just consider "sparse flag is just advisory, a hint.
if you expand a sparse file using set-end-of-file the behaviour is
undefined. it can either allocate the new region  or it can just leave
it unallocated."


On Fri, Aug 16, 2019 at 12:07 PM ronnie sahlberg
<ronniesahlberg@gmail.com> wrote:
>
> On Fri, Aug 16, 2019 at 1:48 AM David Disseldorp <ddiss@suse.de> wrote:
> >
> > Hi Ronnie,
> >
> > Is the file flagged sparse (FSCTL_SET_SPARSE()) prior to the QAR
> > request?
>
> Yes. The file is written to, the first 2MB.
> Then FSCTL_SET_SPARSE is called to make it sparse.
> Then there is a SET-INFO SET_END_OF_FILE to expand the file to 4Mb.
> there are a few other commands
> Then there is a GET-INFO / FILE_ALL_INFO and the sparse flag is still set
> then a QUERY_ALLOCATED_RANGES which returns a single region from 0 to 4Mb.
>
> The whole behavior is really odd.
>
> I am happy to mail you the wireshark traces for this. Can I do that?
> Just so you can look at them and confirm I am not crazy :-)
> I cant send them to the list because they are 5Mb each and it is rude
> to send such big attachments to a mailinglist.
>
>
>
> > When implementing the Samba server-side I tried to match
> > Windows/spec behaviour with:
> >
> > 702         if (!fsp->is_sparse) {
> > 703                 struct file_alloced_range_buf qar_buf;
> > 704
> > 705                 /* file is non-sparse, claim file_off->max_off is allocated */
> > 706                 qar_buf.file_off = qar_req.buf.file_off;
> > 707                 /* + 1 to convert maximum offset back to length */
> > 708                 qar_buf.len = max_off - qar_req.buf.file_off + 1;
> > 709
> > 710                 status = fsctl_qar_buf_push(mem_ctx, &qar_buf, &qar_array_blob);
> > 711         } else {
> > 712                 status = fsctl_qar_seek_fill(mem_ctx, fsp, qar_req.buf.file_off,
> > 713                                              max_off, &qar_array_blob);
> > 714         }
> >
> > ...in which case you should see similar test results against Samba. This
> > also excersized via the ioctl_sparse_qar* smbtorture tests.
> >
> > Cheers, David

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-16  2:07   ` ronnie sahlberg
  2019-08-16  4:36     ` ronnie sahlberg
@ 2019-08-16  9:07     ` David Disseldorp
  1 sibling, 0 replies; 11+ messages in thread
From: David Disseldorp @ 2019-08-16  9:07 UTC (permalink / raw)
  To: ronnie sahlberg; +Cc: linux-cifs

On Fri, 16 Aug 2019 12:07:28 +1000, ronnie sahlberg wrote:

> I am happy to mail you the wireshark traces for this. Can I do that?
> Just so you can look at them and confirm I am not crazy :-)
> I cant send them to the list because they are 5Mb each and it is rude
> to send such big attachments to a mailinglist.

Sure, go for it. btw, you could also put them up at
https://www.samba.org/~sahlberg/

Cheers, David

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-16  4:36     ` ronnie sahlberg
@ 2019-08-19 16:31       ` David Disseldorp
  2019-08-19 22:03         ` David Disseldorp
  0 siblings, 1 reply; 11+ messages in thread
From: David Disseldorp @ 2019-08-19 16:31 UTC (permalink / raw)
  To: ronnie sahlberg; +Cc: linux-cifs

Hi Ronnie,

Nothing stands out in the captures to me, but I'd be curious whether you
see any differences in behaviour if you set write-through on open or
explicitly FLUSH after the SET-SPARSE call.

Cheers, David

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-19 16:31       ` David Disseldorp
@ 2019-08-19 22:03         ` David Disseldorp
  2019-08-20 17:47           ` Tom Talpey
  0 siblings, 1 reply; 11+ messages in thread
From: David Disseldorp @ 2019-08-19 22:03 UTC (permalink / raw)
  To: ronnie sahlberg; +Cc: linux-cifs

On Mon, 19 Aug 2019 18:31:51 +0200, David Disseldorp wrote:

> Nothing stands out in the captures to me, but I'd be curious whether you
> see any differences in behaviour if you set write-through on open or
> explicitly FLUSH after the SET-SPARSE call.

Hmm actually it looks like there's already a FLUSH shortly after the
mtime update following the SetInfo(EOF). One thing that does look a
little weird is the AllocationSize field before that FLUSH - in
seek_bad.cap.gz it's 2M, whereas it's ~6M in seek_good.cap.gz.

This'd be a good case to use Aurélien's smbcmp utility :)

Cheers, David

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-19 22:03         ` David Disseldorp
@ 2019-08-20 17:47           ` Tom Talpey
  2019-08-22 22:46             ` ronnie sahlberg
  0 siblings, 1 reply; 11+ messages in thread
From: Tom Talpey @ 2019-08-20 17:47 UTC (permalink / raw)
  To: David Disseldorp, ronnie sahlberg; +Cc: linux-cifs

> -----Original Message-----
> From: linux-cifs-owner@vger.kernel.org <linux-cifs-owner@vger.kernel.org> On
> Behalf Of David Disseldorp
> Sent: Monday, August 19, 2019 6:04 PM
> To: ronnie sahlberg <ronniesahlberg@gmail.com>
> Cc: linux-cifs <linux-cifs@vger.kernel.org>
> Subject: Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
> 
> On Mon, 19 Aug 2019 18:31:51 +0200, David Disseldorp wrote:
> 
> > Nothing stands out in the captures to me, but I'd be curious whether you
> > see any differences in behaviour if you set write-through on open or
> > explicitly FLUSH after the SET-SPARSE call.
> 
> Hmm actually it looks like there's already a FLUSH shortly after the
> mtime update following the SetInfo(EOF). One thing that does look a
> little weird is the AllocationSize field before that FLUSH - in
> seek_bad.cap.gz it's 2M, whereas it's ~6M in seek_good.cap.gz.

Another oddity is that the FSCTL_SET_SPARSE comes *after* the 2MB
write. It seems entirely possible that filesystem may have decided to
allocate additional blocks during the write, in expectation of more
writes. Since the EOF pointer is still 2MB, I believe the filesystem may
be well within its rights there. In any event there may be a timing thing
going on, because it's doing immediately:

write 2MB
fsctl SET_SPARSE
setinfo EOF=4MB
compound open+mtime+close (why a new handle for setting mtime btw?)
getinfo
flush
fsctl QUERY_ALLOCATED_RANGES


The NTFS developers were kind of skeptical of the approach of looking
at the block allocation counts to detect holes. The first example they
mentioned was a small file, like 400 bytes, for which the entire content
would fall into the MFT record. Such a file would show zero blocks
allocated, regardless of sparseness.

Tom.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
  2019-08-20 17:47           ` Tom Talpey
@ 2019-08-22 22:46             ` ronnie sahlberg
  0 siblings, 0 replies; 11+ messages in thread
From: ronnie sahlberg @ 2019-08-22 22:46 UTC (permalink / raw)
  To: Tom Talpey; +Cc: David Disseldorp, linux-cifs

On Wed, Aug 21, 2019 at 3:47 AM Tom Talpey <ttalpey@microsoft.com> wrote:
>
> > -----Original Message-----
> > From: linux-cifs-owner@vger.kernel.org <linux-cifs-owner@vger.kernel.org> On
> > Behalf Of David Disseldorp
> > Sent: Monday, August 19, 2019 6:04 PM
> > To: ronnie sahlberg <ronniesahlberg@gmail.com>
> > Cc: linux-cifs <linux-cifs@vger.kernel.org>
> > Subject: Re: FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016
> >
> > On Mon, 19 Aug 2019 18:31:51 +0200, David Disseldorp wrote:
> >
> > > Nothing stands out in the captures to me, but I'd be curious whether you
> > > see any differences in behaviour if you set write-through on open or
> > > explicitly FLUSH after the SET-SPARSE call.
> >
> > Hmm actually it looks like there's already a FLUSH shortly after the
> > mtime update following the SetInfo(EOF). One thing that does look a
> > little weird is the AllocationSize field before that FLUSH - in
> > seek_bad.cap.gz it's 2M, whereas it's ~6M in seek_good.cap.gz.
>
> Another oddity is that the FSCTL_SET_SPARSE comes *after* the 2MB
> write. It seems entirely possible that filesystem may have decided to
> allocate additional blocks during the write, in expectation of more
> writes. Since the EOF pointer is still 2MB, I believe the filesystem may
> be well within its rights there. In any event there may be a timing thing
> going on, because it's doing immediately:
>
> write 2MB
> fsctl SET_SPARSE
> setinfo EOF=4MB
> compound open+mtime+close (why a new handle for setting mtime btw?)

It is because internally in the kernel API setting this timestamps is
a path based call.
We could search for and see if there is a writeable open handle and
use that IF there is such handle but it would be more code and
complexity.

It was just easier to make it into a compound. It should be cheap
enough and have no ill effects.

> getinfo
> flush
> fsctl QUERY_ALLOCATED_RANGES
>
>
> The NTFS developers were kind of skeptical of the approach of looking
> at the block allocation counts to detect holes. The first example they
> mentioned was a small file, like 400 bytes, for which the entire content
> would fall into the MFT record. Such a file would show zero blocks
> allocated, regardless of sparseness.

Ok, fair enough.
So if the filesystem has heuristics that can cause it to allocate
extra blocks like that (not unreasonable)
then it just means that these xfstests make assumptions about the
filesystem that are just not guaranteed to be true
when used with cifs.

That is fair enough. It just means there is no bug. It is just that
the test tool is not compatible with ntfs.
I can live with that. I do run it against btrfs and there I get the
result to allow me to run this part of the test in
the regression testsuite. That is good enough for me.

Thanks
Ronnie Sahlberg

>
> Tom.
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-08-22 22:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-15  6:30 FSCTL_QUERY_ALLOCATED_RANGES issue with Windows2016 ronnie sahlberg
2019-08-15 15:15 ` Tom Talpey
2019-08-16  2:17   ` ronnie sahlberg
2019-08-15 15:48 ` David Disseldorp
2019-08-16  2:07   ` ronnie sahlberg
2019-08-16  4:36     ` ronnie sahlberg
2019-08-19 16:31       ` David Disseldorp
2019-08-19 22:03         ` David Disseldorp
2019-08-20 17:47           ` Tom Talpey
2019-08-22 22:46             ` ronnie sahlberg
2019-08-16  9:07     ` David Disseldorp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).