Bug 2823 - incorrect hardlink count
incorrect hardlink count
Status: RESOLVED FIXED
Product: CifsVFS
Classification: Unclassified
Component: kernel fs
2.6
x86 Linux
: P3 normal
: ---
Assigned To: Steve French
:
: 2748 (view as bug list)
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2005-06-25 10:38 UTC by Rene Tapia
Modified: 2006-11-18 10:08 UTC (History)
1 user (show)

See Also:


Attachments
patch to fix problem (patch against 2.6.19-rc6) (1.61 KB, patch)
2006-11-16 14:48 UTC, Steve French
no flags Details
script to test locking (672 bytes, application/x-perl)
2006-11-18 10:08 UTC, Martin Koeppe
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rene Tapia 2005-06-25 10:38:53 UTC
Hello,

This bug could be the same as bug#2748, but I am logging it anyway in case it is
a different issue, or that it may add more information.

Client:
Debian 2.6.11
cifs-1.34

Server:
Debian 2.4.27-2
3.0.10-1

STEPS TO REPRODUCE:
In a cifs mount, execute the following code (see below for complete listing):
open ("file.LCK", O_RDWR | O_CREAT | O_EXCL , 0);
link ("file.LCK", "file.LNK");
stat ("file.LCK", &statbuf);

RESULT:
statbuf.st_nlink == 1

EXPECTED:
statbuf.st_nlink == 2

Note 1:
This happens even with the serverino option turned on.

Note 2:
I also noticed that executing a directory listing between the open, link, and
stat calls, solves the problem. In other words, the following code works fine: 

open ("file.LCK", O_RDWR | O_CREAT | O_EXCL , 0);
system("ls -la");
link ("file.LCK", "file.LNK");
system("ls -la");
stat ("file.LCK", &statbuf);
 
RESULT: statbuf.st_nlink == 2

Thanks.


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    struct stat statbuf;
    int rc;
    int fd;
    
    fd = open ("file.LCK", O_RDWR | O_CREAT | O_EXCL , 0);
    if (fd < 0)
    {
        printf ("Error: %d\n", errno);
        return 1;
    }

    rc = link ("file.LCK", "file.LNK");
    if (rc)
    {
        printf ("Error: %d\n", errno);
        return 1;
    }

    rc = stat ("file.LCK", &statbuf);
    if (rc)
    {
        printf ("Error: %d\n", errno);
        return 1;
    }

    if (statbuf.st_nlink != 2)
    {
        printf ("Opps...\n");
    }

    printf("statbuf.st_nlink: %d\n", statbuf.st_nlink);

    close (fd);

    return 0;
}
Comment 1 Steve French 2005-07-17 08:06:29 UTC
*** Bug 2748 has been marked as a duplicate of this bug. ***
Comment 2 Martin Koeppe 2005-07-17 14:46:57 UTC
Hello Steve,

you closed bug 2748, but I found something wrong related to the inode number in
between. I think it's related to this bug, however, so I won't reopen 2748:

(kernel 2.6.11, cifs 1.34a, serverino, W2K3 server)

martin@debian:/mnt/wintmp/0$ echo hello > link0
martin@debian:/mnt/wintmp/0$ ls -lin
total 1
1263639 -rw-r--r--  1 0 0 6 2005-07-17 23:25 link0
martin@debian:/mnt/wintmp/0$ cd ..
martin@debian:/mnt/wintmp$ ln 0/link0 1/link1
martin@debian:/mnt/wintmp$ find . -size 6c -exec ls -lin {} \;
1263639 -rw-r--r--  1 0 0 6 2005-07-17 23:25 ./0/link0
81585 -rw-r--r--  1 0 0 6 2005-07-17 23:25 ./1/link1

Here, 81585 is the correct inode number (the same as reported by interix), but
1263639 seems to be a bogus one. I further observed that, if inode number is
correct, then the link count is always 1. Sometimes the link count happens to be
correct even if greater than 1, but then I always saw a wrong inode number.
Or as above, both values are wrong.

Martin
Comment 3 Steve French 2006-11-16 13:51:56 UTC
turned out to be pretty obvious - when the file is open on the client and cached (oplock) we were not going back to the server to get the updated link count, so we need to make sure it is updated locally for BOTH source and target of the link.

Am checking now if that is possible.
Comment 4 Steve French 2006-11-16 14:48:01 UTC
Created attachment 2221 [details]
patch to fix problem (patch against 2.6.19-rc6)

let me know if this does not fix it - but it seems straightforward
Comment 5 Steve French 2006-11-16 14:50:02 UTC
Is there a big need to get this in before 2.6.19?

Seems fairly minor (as the hardlink count is refreshed from server when oplock is lost or file closed - and only applies to nlink on a cached source file)
Comment 6 Rene Tapia 2006-11-17 10:45:15 UTC
> Is there a big need to get this in before 2.6.19?

No, this is a very minor issue indeed. I noticed this while opening a GNU Cash file on a cifs share. GNU Cash gives a warning saying that it could not lock the file. But other than that, I can open the file and work with it just fine.
Comment 7 Martin Koeppe 2006-11-18 10:08:38 UTC
Created attachment 2226 [details]
script to test locking

I veto against closing this bug!

I tested the patch against 2.6.18 (cifs 1.45) without success. I think, however, that the underlying problem is a bigger one, and that this issue will disappear automatically, when the bigger one is resolved. (So I think it's too late for 2.6.19 anyway.)

Test environment is still the same as before 1,5 years: Linux client, Win2K client, Win 2K3 server, serverino,directio mount option.

I did on Linux 2.6.18 (cifs-1.45 + patch):
$ cd /misc/wintmp
$ find 0 1 -exec ls -lin {} \;
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:26 0/link0
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:26 1/link1
(already existing before starting Linux)

$ ln 0/link0 0/link2
$ find 0 1 -exec ls -lin {} \;
84011 -rw-r--r-- 3 0 0 6 Nov 18 15:26 0/link0
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:26 0/link2
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:26 1/link1

$ touch 1/link1
$ find 0 1 -exec ls -lin {} \;
84011 -rw-r--r-- 3 0 0 6 Nov 18 15:38 0/link0
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:26 0/link2
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:38 1/link1

$ ln 1/link1 1/link3
$ find 0 1 -exec ls -lin {} \;
84011 -rw-r--r-- 4 0 0 6 Nov 18 15:38 0/link0
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:26 0/link2
84011 -rw-r--r-- 4 0 0 6 Nov 18 15:38 1/link1
84011 -rw-r--r-- 1 0 0 6 Nov 18 15:38 1/link3

I then further did some locking tests, e.g. exclusively lock one link, and then try to exclusively lock a second link, see the attachment for the test script.

$ locktest.pl
/misc/wintmp/0/link0(a): successfully locked exclusive
/misc/wintmp/0/link0(b): failed to lock exclusive
/misc/wintmp/1/link1: successfully locked exclusive

Unfortunately, the result is wrong. Testing the same on the Win2K client within interix (or on Linux and a nfs share) shows the expected:
/misc/wintmp/0/link0(a): successfully locked exclusive
/misc/wintmp/0/link0(b): failed to lock exclusive
/misc/wintmp/1/link1: failed to lock exclusive

Apparently, linux-cifs doesn't cache the file infos with a key like (server,device,inode) which it I think should for correctness, at least if serverino is given.

Martin