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可行.

最新文章

  1. JDBC_part2_DML以及预编译_编写DBUtil工具类
  2. linux分享六:字符串处理
  3. Extjs中处理mouseover的闪烁问题
  4. 一个LINUX狂人的语录(个人认为很精辟)
  5. nodejs的mysql模块学习(四)断开数据库连接
  6. POJ1838
  7. iOS 数据持久化(3):Core Data
  8. Android checkBox
  9. CompletableFuture CompletableFuture.supplyAsync 异常处理
  10. 解决Java getResource 路径中含有中文的情况
  11. github第一次引用开源的库
  12. Qunar入职前自学笔记
  13. C++ OpenMp的并行编程
  14. linux添加新磁盘和创建分区
  15. 「Java基本功」一文读懂Java内部类的用法和原理
  16. 【洛谷P3469】BLO
  17. spring cloud服务发现注解之@EnableDiscoveryClient与@EnableEurekaClient
  18. xe5 android sample 中的 SimpleList 是怎样绑定的 [转]
  19. JMeter测试工具中的参数化使用[函数助手]
  20. git-采集编码搜索

热门文章

  1. 统计学习三:2.K近邻法代码实现(以最近邻法为例)
  2. cenos环境变量配置
  3. truffle框架快速开发合约步骤
  4. [C++] in-class initializer
  5. HTMLTestRunner解决UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 108: ordinal not in range(128)
  6. Python函数的内省-Introspection
  7. su和sudo的使用
  8. wf效能分析
  9. TensorFlow源码框架 杂记
  10. 第二次作业 编程题 PAT 1001A+B Format