The Samba-Bugzilla – Attachment 5404 Details for
Bug 7162
high risk of corruption when writing a file with a lock on cifs
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Program to reproduce the bug
bug-cifs.c (text/x-csrc), 5.17 KB, created by
fdupoux
on 2010-02-20 02:35:02 UTC
(
hide
)
Description:
Program to reproduce the bug
Filename:
MIME Type:
Creator:
fdupoux
Created:
2010-02-20 02:35:02 UTC
Size:
5.17 KB
patch
obsolete
>#define _REENTRANT >#define _FILE_OFFSET_BITS 64 >#define _LARGEFILE64_SOURCE >#define _GNU_SOURCE > >#include <stdio.h> >#include <sys/types.h> >#include <sys/stat.h> >#include <fcntl.h> >#include <stdlib.h> >#include <limits.h> >#include <unistd.h> >#include <stdbool.h> > >/* > * Program that reproduces a bug with cifs on linux-2.6.32.8 > * This program writes two copies of random data blocks to two files. > * If one file is written to the local disk and the other on a cifs > * mounted directory, then there is a very high risk of corruption on > * the file written to the cifs mounted directory. We expect the two > * files to be strictly identical at the end, but this program > * demonstrates that they sometimes differ. If may be necessary to > * run this program multiples times to get the bug, but in general it's > * quite frequent and it does not take a lot of time to reproduce it. > * This problem only happens when the files are locked using > * lockf(fd, F_LOCK, 0). If we don't lock the files, the corruption > * on cifs disappears and the two files are identical. > * > * Configuration: > * cifs client: linux-2.6.32.8 > * cifs server: windows xp sp3 > * > * How to compile this program: > * gcc -o bug-cifs bug-cifs.c -Wall > * > * How to reproduce the problem: > * mount command: mount -t cifs //winxp/sharename /mnt/cifs > * command line: ./bug-cifs /mnt/cifs/file1 /var/tmp/file2 > * > * Other information: > * error in syslog: "CIFS VFS: Write2 ret -13, wrote 0" > * > */ > >#define LOCK_THE_FILES /* remove that line to fix the problem */ > >#define max(a,b) ((a>b)?(a):(b)) >#define MAX_BLOCKSIZE 2*1024*1024 > >int main(int argc, char *argv[]) >{ > char filepath1[PATH_MAX]; > char filepath2[PATH_MAX]; > struct stat stat1, stat2; > long long pos; > char *block; > long cursize=0; > long blockno=0; > int fd1, fd2; > long lres, i; > char c1, c2; > bool identical; > > // get two filenames from the command line > if (argc!=3) > { > printf("syntax: %s <local-file> <remote-file>\n", argv[0]); > return -1; > } > > snprintf(filepath1, PATH_MAX, "%s", argv[1]); > snprintf(filepath2, PATH_MAX, "%s", argv[2]); > > // allocate memory and initialize buffer with random data > if ((block=malloc(MAX_BLOCKSIZE))==NULL) > { > printf("malloc(%ld) failed\n", (long)MAX_BLOCKSIZE); > return -1; > } > > for (i=0; i<sizeof(MAX_BLOCKSIZE); i++) > block[i]=i%128; > > // open files > fd1=open64(filepath1, O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); > if (fd1 < 0) > { > printf("cannot create file1 %s\n", filepath1); > return -1; > } > > fd2=open64(filepath2, O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); > if (fd2 < 0) > { > printf("cannot create file2 %s\n", filepath2); > return -1; > } > > // lock the two files >#ifdef LOCK_THE_FILES > if (lockf(fd1, F_LOCK, 0)!=0) > { > printf("Cannot lock file1\n"); > return -1; > } > > if (lockf(fd2, F_LOCK, 0)!=0) > { > printf("Cannot lock file2\n"); > return -1; > } >#endif > > // write random identical blocks to these two files > drand48(); > for (blockno=0; blockno<64; blockno++) > { > cursize=max(1024, ((float)MAX_BLOCKSIZE)*drand48()); > > if ((lres=write(fd1, block, cursize))!=cursize) > { > printf("write(fd1=%d, size=%ld)=%ld failed on file1 at blockno=%ld\n", fd1, (long)cursize, lres, blockno); > return -1; > } > > if ((lres=write(fd2, block, cursize))!=cursize) > { > printf("write(fd2=%d, size=%ld)=%ld failed on file2 at blockno=%ld\n", fd2, (long)cursize, lres, blockno); > return -1; > } > > sleep(1); > } > > // unlock the files >#ifdef LOCK_THE_FILES > lockf(fd1, F_ULOCK, 0); > lockf(fd2, F_ULOCK, 0); >#endif > > // free ressources > free(block); > > fsync(fd1); > fsync(fd2); > > close(fd1); > close(fd2); > > // reopen files as read-only > fd1=open64(filepath1, O_RDONLY|O_LARGEFILE); > if (fd1 < 0) > { > printf("cannot open file1 %s\n", filepath1); > return -1; > } > > fd2=open64(filepath2, O_RDONLY|O_LARGEFILE); > if (fd2 < 0) > { > printf("cannot open file2 %s\n", filepath2); > return -1; > } > > // compare the two files > if (fstat(fd1, &stat1)!=0 || fstat(fd2, &stat2)!=0) > { > printf("cannot fstat files\n"); > return -1; > } > > identical=true; > > if (stat1.st_size != stat2.st_size) > { > identical=false; > printf("CHECK: different sizes: file1=%lld and file2=%lld\n", (long long)stat1.st_size, (long long)stat2.st_size); > } > > for (pos=0; pos<stat1.st_size; pos++) > { > if (read(fd1, &c1, 1)!=1 || read(fd2, &c2, 1)!=1) > { > printf("verification: cannot read files\n"); > return -1; > } > > if (c1!=c2) > { > printf("verification: found different bytes at offset=%lld\n", (long long)pos); > identical=false; > break; > } > } > > // close files > close(fd1); > close(fd2); > > // print final result: has the file been corrupt ? > printf ("RESULT: %s\n", identical?"OK":"CORRUPTION"); > > return 0; >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 7162
: 5404