I've been debugging a failure in xfstests generic/286 whereby llseek() return -EIO and am thinking that the bug is in Samba. The test can be distilled to: mount //my/share /mnt -ooptions truncate -s 100M /mnt/a for i in $(seq 0 5 100); do xfs_io -c "w ${i}M 1M" /mnt/a; done xfstests-dev/src/seek_copy_test /mnt/a /mnt/b This creates a big sparse file, makes 21 1MiB extents at 5MiB intervals and then tries to copy them one at a time, using SEEK_DATA/SEEK_HOLE to enumerate each extent. I can see the error in the protocol being returned from the server: 16 2.353013398 192.168.6.2 → 192.168.6.1 SMB2 206 Ioctl Request FSCTL_QUERY_ALLOCATED_RANGES File: a 17 2.353220936 192.168.6.1 → 192.168.6.2 SMB2 143 Ioctl Response, Error: STATUS_BUFFER_TOO_SMALL Stracing Samba shows: lseek(30, 94371840, SEEK_HOLE) = 95420416 lseek(30, 95420416, SEEK_DATA) = 99614720 lseek(30, 99614720, SEEK_HOLE) = 100663296 lseek(30, 100663296, SEEK_DATA) = 104857600 lseek(30, 104857600, SEEK_HOLE) = 105906176 sendmsg(35, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0\0\0I", iov_len=4}, {iov_base=NULL, iov_len=0}, {iov_base="\376SMB@\0\1\0#\0\0\300\v\0\n\0\1\0\0\0\0\0\0\0\265\2\0\0\0\0\0\0"..., iov_len=64}, {iov_base="\t\0\0\0\0\0\0\0", iov_len=8}, {iov_base="\0", iov_len=1}], msg_iovlen=5, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 77 You can see the error code in the sendmsg() as "...#\0\0\300...". Turning debugging on on Samba shows: [2024/05/21 23:56:58.727547, 2] ../../source3/smbd/smb2_ioctl_filesys.c:707(fsctl_qar) QAR output len 336 exceeds max 16 [2024/05/21 23:56:58.727652, 3] ../../source3/smbd/smb2_server.c:4031(smbd_smb2_request_error_ex) smbd_smb2_request_error_ex: smbd_smb2_request_error_ex: idx[1] status[NT_STATUS_BUFFER_TOO_SMALL] || at ../../source3/smbd/smb2_ioctl.c:353 The "exceeds max 16" indicates the "Max Ioctl Out Size" setting passed in the Ioctl Request frame (which can be seen as 16 in the full packet trace). 336 is 21 * 16. This stems from the smb2_llseek() function in the cifs filesystem in the Linux kernel calling: rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, FSCTL_QUERY_ALLOCATED_RANGES, (char *)&in_data, sizeof(in_data), sizeof(struct file_allocated_range_buffer), (char **)&out_data, &out_data_len); where the max_out_data_len parameter is sizeof() you can see, allowing for just a single element to be returned. The file_allocated_range_buffer struct is just: struct file_allocated_range_buffer { __le64 file_offset; __le64 length; } __packed; which is 16 bytes - hence the maximum output data seen by Samba. Now, cifs only wants the next extent. It fills in the input data with the base file position and the EOF: in_data.file_offset = cpu_to_le64(offset); in_data.length = cpu_to_le64(i_size_read(inode)); and asks the server to retrieve the first allocated extent within this range. In Samba, however, fsctl_qar() does not pass in_max_output to fsctl_qar_seek_fill() and therefore doesn't limit the amount returned. The fill loop seems only to be limited by the maximum file offset and not the max buffer size. The: if (out_output->length > in_max_output) { DEBUG(2, ("QAR output len %lu exceeds max %lu\n", (unsigned long)out_output->length, (unsigned long)in_max_output)); data_blob_free(out_output); return NT_STATUS_BUFFER_TOO_SMALL; } check at the end of fsctl_qar() generates the complaint. I think that fsctl_qar() should probably just discard the excess records. Looking at: https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_query_allocated_ranges it's not obvious what should be done if the available records won't fit. Samba: samba-4.19.6-1.fc39.x86_64 Linux: 6.10 pre -rc1. David