Discussion:
setting allocation size in cifs/smb3
Steve French
2014-07-18 06:15:07 UTC
Permalink
I created a patch to cifs.ko to add fallocate FALLOC_FL_KEEP_SIZE
support and did some tests against a Samba server (Samba 4.1.6 on ext4
on Ubuntu) and also a Windows 8.1 server (NTFS file system) and ran
into an obvious problem. How to tell if the allocation size is
changed? Neither stat on the Samba server local file system nor the
Windows 8.1 properties show the size on disk changing.

I am sending SMB3 SetInfo level 0x13 (set allocation size) and getting
success back from the Windows server and from Samba server.

If I set the length past the end of file I get no error, but the
properties of the file in Windows Explorer still show the same (e.g.
zero) as the file size. If I try setting it to a size smaller than
the size of the file, the file shrinks (by the way this is an awkward
behavior to work around since on Linux fallocate can't shrink the file
- so if you have any ideas short of revalidating the file size before
deciding whether to send the fallocate request to Windows ...).

Any ideas why Samba shows success but doesn't actually call ext4 to
update the allocation size?

Also any ideas how to implement the normal fallocate behavior (mode =
0, grow the file if length past end of file, but don't shrink file
length if you set it shorter than end of file) which is basically the
opposite of how the level 0x19 works. I think mode=1 (keep size) is
going to be ok - if I can figure out why Samba ignores it and how to
make sure it is working to Windows.
--
Thanks,

Steve
Jeremy Allison
2014-07-18 17:09:52 UTC
Permalink
Post by Steve French
I created a patch to cifs.ko to add fallocate FALLOC_FL_KEEP_SIZE
support and did some tests against a Samba server (Samba 4.1.6 on ext4
on Ubuntu) and also a Windows 8.1 server (NTFS file system) and ran
into an obvious problem. How to tell if the allocation size is
changed? Neither stat on the Samba server local file system nor the
Windows 8.1 properties show the size on disk changing.
I am sending SMB3 SetInfo level 0x13 (set allocation size) and getting
success back from the Windows server and from Samba server.
If I set the length past the end of file I get no error, but the
properties of the file in Windows Explorer still show the same (e.g.
zero) as the file size. If I try setting it to a size smaller than
the size of the file, the file shrinks (by the way this is an awkward
behavior to work around since on Linux fallocate can't shrink the file
- so if you have any ideas short of revalidating the file size before
deciding whether to send the fallocate request to Windows ...).
Any ideas why Samba shows success but doesn't actually call ext4 to
update the allocation size?
smbd does use VFS_FALLOCATE_KEEP_SIZE, which maps
into fallocate FALLOC_FL_KEEP_SIZE if the underlying
storage supports it.

You need to set "strict allocate = true" on the
share in order to get this behavior though.

If you're setting allocation size smaller
than file size we just use ftruncate, I
don't see another possibility here. What
behavior do you expect in the shrink case ?

Jeremy.
Steve French
2014-07-19 04:49:04 UTC
Permalink
Post by Jeremy Allison
Post by Steve French
I created a patch to cifs.ko to add fallocate FALLOC_FL_KEEP_SIZE
support and did some tests against a Samba server (Samba 4.1.6 on ext4
on Ubuntu) and also a Windows 8.1 server (NTFS file system) and ran
into an obvious problem. How to tell if the allocation size is
changed? Neither stat on the Samba server local file system nor the
Windows 8.1 properties show the size on disk changing.
I am sending SMB3 SetInfo level 0x13 (set allocation size) and getting
success back from the Windows server and from Samba server.
If I set the length past the end of file I get no error, but the
properties of the file in Windows Explorer still show the same (e.g.
zero) as the file size. If I try setting it to a size smaller than
the size of the file, the file shrinks (by the way this is an awkward
behavior to work around since on Linux fallocate can't shrink the file
- so if you have any ideas short of revalidating the file size before
deciding whether to send the fallocate request to Windows ...).
Any ideas why Samba shows success but doesn't actually call ext4 to
update the allocation size?
smbd does use VFS_FALLOCATE_KEEP_SIZE, which maps
into fallocate FALLOC_FL_KEEP_SIZE if the underlying
storage supports it.
You need to set "strict allocate = true" on the
share in order to get this behavior though.
If you're setting allocation size smaller
than file size we just use ftruncate, I
don't see another possibility here. What
behavior do you expect in the shrink case ?
Windows shrinks the file (unlike Linux) when you do the allocate
before end of file, but when I tried the same call to
Samba it seemed to ignore it, return success and leave
file size alone.
--
Thanks,

Steve
Jeremy Allison
2014-07-19 05:14:28 UTC
Permalink
Post by Steve French
Windows shrinks the file (unlike Linux) when you do the allocate
before end of file, but when I tried the same call to
Samba it seemed to ignore it, return success and leave
file size alone.
That's a bug - the code does use ftruncate if
the new allocated size is less than file size.

Can you send me a wireshark trace of what
you're sending please ?
Steve French
2014-07-21 04:47:53 UTC
Permalink
wireshark trace sent to jra

Also related strange behavior to Samba 4.1.9 ... It is not just that I
see the allocation size not set when I send an allocation size of 5.4M
for a 2M file. I see the file size shrunk when I sent the request for
a MUCH smaller size. I sent a request to set allocation size to
length 10000 and the file size of the 2M file (and interestingly also
allocation size) was set to 1MB..
Post by Jeremy Allison
Post by Steve French
Windows shrinks the file (unlike Linux) when you do the allocate
before end of file, but when I tried the same call to
Samba it seemed to ignore it, return success and leave
file size alone.
That's a bug - the code does use ftruncate if
the new allocated size is less than file size.
Can you send me a wireshark trace of what
you're sending please ?
--
Thanks,

Steve
Jeremy Allison
2014-07-21 18:28:40 UTC
Permalink
Post by Steve French
wireshark trace sent to jra
"strict allocate = true" not set in the smb.conf,
so bug report isn't useful :-). No fallocate
calls will be made by smbd unless strict allocate
is set.

This might explain the problem (in case anyone
else is tracking :-).
Steve French
2014-07-21 18:43:12 UTC
Permalink
What about shrinking the file to the wrong size?
Post by Jeremy Allison
Post by Steve French
wireshark trace sent to jra
"strict allocate = true" not set in the smb.conf,
so bug report isn't useful :-). No fallocate
calls will be made by smbd unless strict allocate
is set.
This might explain the problem (in case anyone
else is tracking :-).
--
Thanks,

Steve
Jeremy Allison
2014-07-21 18:55:28 UTC
Permalink
Post by Steve French
What about shrinking the file to the wrong size?
In the set allocation path info it's going through:

if (allocation_size) {
allocation_size = smb_roundup(conn, allocation_size);
}

which by default uses 1MB allocation roundup values.

If you need to set the file length, set the file length :-).

It's arguable if the server can mess with allocation
requests on file shrink, but this hasn't caused a
problem in the SMB1/Windows SMB2 code paths so far,
so I'm guessing it might be allowable....

More research needed !
Steve French
2014-07-21 19:27:27 UTC
Permalink
So depending on the file sizes and with strict allocate enabled in
smb.conf it does shrink the file (I will also experiment with e.g.
allocation roundup size)

What I was trying to do was extend allocation for a 4MB file to 5.4MB,
shrink it to 10K (which ended up shrinking it to 1MB for the Samba
case).

[***@localhost cifs-2.6]$ stat /mnt/test/4M ; fallocate -n -l
5400000 /mnt/test/4M ; sleep 3 ; stat /mnt/test/4M ; fallocate -n -l
10000 /mnt/test/4M ; sleep 2; stat /mnt/test/4M
File: =E2=80=98/mnt/test/4M=E2=80=99
Size: 4194304 Blocks: 8192 IO Block: 16384 regular file
Device: 26h/38d Inode: 393820 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root=
)
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:19:30.596249500 -0500
Modify: 2014-07-21 14:19:30.731591000 -0500
Change: 2014-07-21 14:19:30.731591000 -0500
Birth: -

File: =E2=80=98/mnt/test/4M=E2=80=99 (after fallocate 5400000)
Size: 4194304 Blocks: 8192 IO Block: 16384 regular file
Device: 26h/38d Inode: 393820 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root=
)
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:19:30.596249500 -0500
Modify: 2014-07-21 14:20:17.141270500 -0500
Change: 2014-07-21 14:20:17.141270500 -0500
Birth: -

File: =E2=80=98/mnt/test/4M=E2=80=99 (after fallocate 10000)
Size: 1048576 Blocks: 2048 IO Block: 16384 regular file
Device: 26h/38d Inode: 393820 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root=
)
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:19:30.596249500 -0500
Modify: 2014-07-21 14:20:20.157755800 -0500
Change: 2014-07-21 14:20:20.157755800 -0500
Birth: -

(I will send jra the wireshark trace).
Post by Jeremy Allison
Post by Steve French
What about shrinking the file to the wrong size?
if (allocation_size) {
allocation_size =3D smb_roundup(conn, allocation_size=
);
Post by Jeremy Allison
}
which by default uses 1MB allocation roundup values.
If you need to set the file length, set the file length :-).
It's arguable if the server can mess with allocation
requests on file shrink, but this hasn't caused a
problem in the SMB1/Windows SMB2 code paths so far,
so I'm guessing it might be allowable....
More research needed !
--=20
Thanks,

Steve
Steve French
2014-07-21 19:41:58 UTC
Permalink
To Windows 8.1 it appears to round to 4K boundaries when shrinking but
also not extend the allocation size when allocating beyond end of file
as the documentation would imply

[***@localhost cifs-2.6]$ stat /mnt/test/4M ; fallocate -n -l
5400000 /mnt/test/4M ; sleep 3 ; stat /mnt/test/4M ; fallocate -n -l
10000 /mnt/test/4M ; sleep 2; stat /mnt/test/4M
File: =E2=80=98/mnt/test/4M=E2=80=99
Size: 4194304 Blocks: 8192 IO Block: 16384 regular file
Device: 26h/38d Inode: 1407374883618316 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root=
)
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:36:20.249486200 -0500
Modify: 2014-07-21 14:36:20.389204200 -0500
Change: 2014-07-21 14:36:20.389204200 -0500
Birth: -
File: =E2=80=98/mnt/test/4M=E2=80=99
Size: 4194304 Blocks: 8192 IO Block: 16384 regular file
Device: 26h/38d Inode: 1407374883618316 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root=
)
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:36:20.249486200 -0500
Modify: 2014-07-21 14:38:01.677837600 -0500
Change: 2014-07-21 14:38:01.677837600 -0500
Birth: -
File: =E2=80=98/mnt/test/4M=E2=80=99
Size: 12288 Blocks: 24 IO Block: 16384 regular file
Device: 26h/38d Inode: 1407374883618316 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root=
)
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:36:20.249486200 -0500
Modify: 2014-07-21 14:38:04.693266400 -0500
Change: 2014-07-21 14:38:04.693266400 -0500
Birth: -
Post by Steve French
So depending on the file sizes and with strict allocate enabled in
smb.conf it does shrink the file (I will also experiment with e.g.
allocation roundup size)
What I was trying to do was extend allocation for a 4MB file to 5.4MB=
,
Post by Steve French
shrink it to 10K (which ended up shrinking it to 1MB for the Samba
case).
5400000 /mnt/test/4M ; sleep 3 ; stat /mnt/test/4M ; fallocate -n -l
10000 /mnt/test/4M ; sleep 2; stat /mnt/test/4M
File: =E2=80=98/mnt/test/4M=E2=80=99
Size: 4194304 Blocks: 8192 IO Block: 16384 regular file
Device: 26h/38d Inode: 393820 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ ro=
ot)
Post by Steve French
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:19:30.596249500 -0500
Modify: 2014-07-21 14:19:30.731591000 -0500
Change: 2014-07-21 14:19:30.731591000 -0500
Birth: -
File: =E2=80=98/mnt/test/4M=E2=80=99 (after fallocate 5400000)
Size: 4194304 Blocks: 8192 IO Block: 16384 regular file
Device: 26h/38d Inode: 393820 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ ro=
ot)
Post by Steve French
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:19:30.596249500 -0500
Modify: 2014-07-21 14:20:17.141270500 -0500
Change: 2014-07-21 14:20:17.141270500 -0500
Birth: -
File: =E2=80=98/mnt/test/4M=E2=80=99 (after fallocate 10000)
Size: 1048576 Blocks: 2048 IO Block: 16384 regular file
Device: 26h/38d Inode: 393820 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ ro=
ot)
Post by Steve French
Context: system_u:object_r:cifs_t:s0
Access: 2014-07-21 14:19:30.596249500 -0500
Modify: 2014-07-21 14:20:20.157755800 -0500
Change: 2014-07-21 14:20:20.157755800 -0500
Birth: -
(I will send jra the wireshark trace).
Post by Jeremy Allison
Post by Steve French
What about shrinking the file to the wrong size?
if (allocation_size) {
allocation_size =3D smb_roundup(conn, allocation_siz=
e);
Post by Steve French
Post by Jeremy Allison
}
which by default uses 1MB allocation roundup values.
If you need to set the file length, set the file length :-).
It's arguable if the server can mess with allocation
requests on file shrink, but this hasn't caused a
problem in the SMB1/Windows SMB2 code paths so far,
so I'm guessing it might be allowable....
More research needed !
--
Thanks,
Steve
--=20
Thanks,

Steve
Jeremy Allison
2014-07-23 00:07:14 UTC
Permalink
Post by Steve French
To Windows 8.1 it appears to round to 4K boundaries when shrinking but
also not extend the allocation size when allocating beyond end of file
as the documentation would imply
You can make Samba do the same as Windows by setting:

allocation roundup size

to 4k.

Loading...