Bug 9078 - Cifs share File corrupted after first use
Summary: Cifs share File corrupted after first use
Status: RESOLVED FIXED
Alias: None
Product: CifsVFS
Classification: Unclassified
Component: kernel fs (show other bugs)
Version: 2.6
Hardware: x86 Linux
: P5 critical
Target Milestone: ---
Assignee: Steve French
QA Contact: cifs QA contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-08-06 05:24 UTC by suvra
Modified: 2020-08-13 16:13 UTC (History)
1 user (show)

See Also:


Attachments
bug-cifs.c file output (15.38 KB, application/octet-stream)
2012-08-06 05:56 UTC, suvra
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description suvra 2012-08-06 05:24:03 UTC
After starting my vb6 application from linux desktop 1st time its working fine but after 1st login it get corrupted. My access database file located on windows xp machine which is on shared mode.

I am using the bellow command to access the windows shared folder from linux:

#mount -t cifs //172.22.2.99 /Linux/prdata /prdata -o rw,nounix,nobrl,serverino,rsize=16384,wsize=65536,user=admin

Required your help to resolve the issue.
Comment 1 suvra 2012-08-06 05:56:09 UTC
Created attachment 7739 [details]
bug-cifs.c file output

I am attaching the output of bug-cifs.c file, please find bellow the c program details :


#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;
}
Comment 2 suvra 2012-08-06 06:06:53 UTC
Hi,

Please find bellow the OS & Samba/cifs details:

OS: Novell SLED11SP2
Kernel Version : Linux linux-test1 2.6.32.12-0.7-pae #1 SMP 2010-05-20 11:14:20 +0200 i686 i686 i386 GNU/Linux
Samba/cifs version:
Comment 3 suvra 2012-08-06 06:13:02 UTC
Sorry forgot to add the cifs version:

mount.cifs version: 1.12-3.4.3-1.17.2-2359-SUSE-CODE11
Comment 4 suvra 2012-08-06 07:13:16 UTC
Hi,

Waiting for your update.

regards

Suvankar
Comment 5 Björn Jacke 2020-08-13 16:13:44 UTC
this seems to be fixed, can you confirm? I tried 10 runs againt an old XP box, all results OK.