Samba共享传输大文件(ex:1G)失败的问题
1:问题描述
1.1 基本信息
遇见这样一个bug,路由器有USB share的功能,可将U盘内的文件通过samba和LAN端PC机中文件进行共享,测试发现小文件可正常共享,一旦文件大了(比如1G左右),window端便显示一直在计算文件大小,最后客户端(LAN pc)会因为服务器许久不回一个Subcommand:SET_FILE_INFO(0x0008)的报文而出现timeout,导致文件传输失败.

过了一段时间后客户端发出timeout [RST] 报文(windows会弹出异常对话框取消文件传输)

重要的是对于NTFS的格式的U盘是正常的,只有FAT32格式的U盘有这个问题.
2:解决方法
2.1 刚开始我觉得FAT32与NTFS的分区方式不同,可是了解到FAT32分区方式单个文件最大是4G,所以排除U盘本身问题,问题还是出在Samba服务器或者linux系统中(之所以怀疑linux系统是因为我在任何PC机上拷文件到此U盘都没问题)
2.2 然后先debug samba源码,重点注意有关文件size和fat格式处理的相关代码,然后再源码中(\samba-3.0.24\source\smbd\vfs-wrap.c)看见了这个:
int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
{
int result = -;
SMB_STRUCT_STAT st;
char c = ;
SMB_OFF_T currpos; START_PROFILE(syscall_ftruncate); if (lp_strict_allocate(SNUM(fsp->conn))) {
result = strict_allocate_ftruncate(handle, fsp, fd, len);
END_PROFILE(syscall_ftruncate);
return result;
} /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
sys_ftruncate if the system supports it. Then I discovered that
you can have some filesystems that support ftruncate
expansion and some that don't! On Linux fat can't do
ftruncate extend but ext2 can. */ result = sys_ftruncate(fd, len);
if (result == 0)
goto done; /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
extend a file with ftruncate. Provide alternate implementation
for this */
currpos = SMB_VFS_LSEEK(fsp, fd, , SEEK_CUR);
if (currpos == -) {
goto done;
} /* Do an fstat to see if the file is longer than the requested
size in which case the ftruncate above should have
succeeded or shorter, in which case seek to len - 1 and
write 1 byte of zero */
if (SMB_VFS_FSTAT(fsp, fd, &st) == -) {
goto done;
} #ifdef S_ISFIFO
if (S_ISFIFO(st.st_mode)) {
result = ;
goto done;
}
#endif if (st.st_size == len) {
result = ;
goto done;
} if (st.st_size > len) {
/* the sys_ftruncate should have worked */
goto done;
} if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1)
goto done; if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1)
goto done; /* Seek to where we were */
if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
goto done;
result = ; done: END_PROFILE(syscall_ftruncate);
return result;
}
红色的两个函数是关键,在调试中发现,sys_ftruncate和SMB_VFS_WRITE在创建大一点的文件时会耗费很多的时间,这也是服务器迟迟不回复客户端SET_FILE_INFO请求的原因。所以将这两个函数屏蔽之后就正常了.
也可以不屏蔽sys_ftruncate,可以将kernel的ftruncate函数实现修改一下:\linux-3.14\fs\fat\file.c 中函数fat_setattr
if (attr->ia_valid & ATTR_SIZE) {
if (attr->ia_size > inode->i_size) {//if current size grenter than old size,extend it
// if we allow this, fat ftruncate extend large size will cause samba wait a long long time.
#if 1
error = -EPERM;
goto out;
#else
error = fat_cont_expand(inode, attr->ia_size);
if (error || attr->ia_valid == ATTR_SIZE)
goto out;
attr->ia_valid &= ~ATTR_SIZE;
#endif
}
}
这样也可以解决问题.
总结:
不管是FAT32还是NTFS都是先接收数据然后写入到文件系统中,所以samba使用ftruncate函数扩展文件到文件系统中,我猜测可能是FAT32是把文件一次性使用fat_setattr函数写到文件系统中(大文件导致写入的时间过长),而NTFS是收到多少写入多少.这样导致FAT32不行而NTFS可行.
Samba共享传输大文件(ex:1G)失败的问题的更多相关文章
- 基于RMI服务传输大文件的完整解决方案
基于RMI服务传输大文件,分为上传和下载两种操作,需要注意的技术点主要有三方面,第一,RMI服务中传输的数据必须是可序列化的.第二,在传输大文件的过程中应该有进度提醒机制,对于大文件传输来说,这点很重 ...
- linux传输大文件
http://dreamway.blog.51cto.com/1281816/1151886 linux传输大文件
- C# 的 WCF文章 消息契约(Message Contract)在流(Stream )传输大文件中的应用
我也遇到同样问题,所以抄下做MARK http://www.cnblogs.com/lmjq/archive/2011/07/19/2110319.html 刚做完一个binding为netTcpBi ...
- WCF 用netTcpbinding,basicHttpBinding 传输大文件
问题:WCF如何传输大文件 方案:主要有几种绑定方式netTcpbinding,basicHttpBinding,wsHttpbinding,设置相关的传输max消息选项,服务端和客户端都要设置,tr ...
- 使用QQ传输大文件
现在在公网上能传输大文件并且稳定支持断点续传的软件非常少了,可以使用qq来做这件事. qq传输单个文件有时候提示不能超过4g有时候提示不能超过60g,没搞明白具体怎么样. 可以使用qq的传输文件夹功能 ...
- php大文件上传失败的原因及解决方法
为什么上传大文件总是失败,上传小文件就没有问题.关于PHP大文件上传失败的原因及解决方法如下: 第1种情况:文件上传时存放文件的临时目录必须是开启的并且是 PHP 进程所有者用户可写的目录.如果未指定 ...
- TCP协议传输大文件读取时候的问题
TCP协议传输大文件读取时候的问题 大文件传不完的bug 我们在定义的时候定义服务端每次文件读取大小为10240, 客户端每次接受大小为10240 我们想当然的认为客户端每次读取大小就是10240而把 ...
- github下载大文件太慢/失败
场景 github下载大文件,使用浏览器下载zip包到本地在下载到1G时失败, 使用 git clone ssh下载速度20k/s以下,已fq. 解决方法(亲测) 1.下载Github Desktop ...
- rsync增量传输大文件优化技巧
问题 rsync用来同步数据非常的好用,特别是增量同步.但是有一种情况如果不增加特定的参数就不是很好用了.比如你要同步多个几十个G的文件,然后网络突然断开了一下,这时候你重新启动增量同步.但是发现等了 ...
随机推荐
- leetcode-二进制手表
二进制手表顶部有 4 个 LED 代表小时(0-11),底部的 6 个 LED 代表分钟(0-59). 每个 LED 代表一个 0 或 1,最低位在右侧. 例如,上面的二进制手表读取 “3:25”. ...
- Laxcus大数据管理系统2.0(7)- 第五章 数据构建
第五章 数据构建 在数据处理过程,我们经常会遇到这样的情况:大多数时候,用户最初输入的数据会含有大量无意义的.杂乱的信息,需要经过提炼.收集.汇总等一系列手段,才能产生有意义和用户可识别的数据内容:当 ...
- 十面阿里,七面头条,六个Offer,春招结束
作者:jkgeekjack链接:https://www.nowcoder.com/discuss/80156?type=0&order=0&pos=13&page=2来源:牛客 ...
- [LeetCode] 53. Maximum Subarray 解题思路
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
- HDU 1403 Longest Common Substring(后缀自动机——附讲解 or 后缀数组)
Description Given two strings, you have to tell the length of the Longest Common Substring of them. ...
- node包管理相关
切换npm数据源 镜像使用方法(三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候配置还在): 1.通过config命令 npm config set registry https ...
- return阻止js继续向下执行
终止JS运行有如下几种可能: 终止函数的运行的方式有两种 在函数中使用return,则当遇到return时,函数终止执行,控制权继续向下运行 在函数中使用try-catch异常处理,需要结束时,使用t ...
- C++并行编程2
启动线程 查看线程构造函数,接受一个返回值为void的函数.如下: void do_some_work(); std::thread my_thread(do_some_work); 也可以接受一个重 ...
- phpcms V9如何判断用户是否登录以及登陆后的标签写法问题
首先要获取userid {php$userid=param::get_cookie('_userid');} 然后再判断是否为空 {if $userid}...这里写已经登录之后的代码...{els ...
- 新建maven工程问题001
这周一直在研究SpringMVC+Mybatis,有些心得,记录一下. Ⅰ:建maven遇到的问题. 1.1 新建maven时选中[Create a simple project]这样,后面[Pack ...