When smbd receives SMB Transact2 SetFileInfo command setting the modification timestamp of the opened file, it keeps the timestamp in the pending_modtime field and skips file_utime(). (See call_trans2setfilepathinfo() in "source/smbd/trans2.c".) Thus, the follow-on SMB Transact2 QueryFileInfo command (by the same process and others) asking the modtime of this opened file returns the stale information (despite the fact that SetFileInfo command succeeded). The modtime is updated when SMB CloseFile command is received, but by that time the clients may have already cached the last modtime (which is stale!). This behavior breaks the applications which rely on the modtime to detect the file change. smbd should call file_utime() after saving the pending_modtime. (Note: The pending_modtime is still needed to set it at SMB CloseFile.) Here is the sample test program. #include <windows.h> #include <tchar.h> #include <stdio.h> #include <stdlib.h> #ifdef _UNICODE int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) #else int main(int argc, char *argv[], char *envp[]) #endif { HANDLE fh = INVALID_HANDLE_VALUE; const DWORD da = GENERIC_READ|GENERIC_WRITE; const DWORD sm = FILE_SHARE_READ|FILE_SHARE_WRITE; TCHAR *fp = NULL; DWORD n = 1; FILETIME lwt; DWORD i; BOOL failed = FALSE; if (argc < 2) { _ftprintf(stderr, _TEXT("Usage: %s pathname [count]\n"), argv[0]); exit(2); } fp = argv[1]; if (argc > 2) n = _tcstoul((const TCHAR *)argv[2], NULL, 0); _ftprintf(stdout, _TEXT("%s %u\n"), fp, n); if ((fh = CreateFile(fp, da, sm, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE) { _ftprintf(stderr, _TEXT("CreateFile(%s): %u\n"), fp, GetLastError()); return 1; } if (!GetFileTime(fh, NULL, NULL, &lwt)) { _ftprintf(stderr, _TEXT("GetFileTime(%s): %u\n"), fp, GetLastError()); return 1; } for (i = 0; i < n; i++) { FILETIME wt = lwt; FILETIME new_t; DWORDLONG t; t = ((DWORDLONG)(wt.dwHighDateTime) << 32) | (DWORDLONG)(wt.dwLowDateTime); t += (10*1000*1000); /* +1 second */ new_t.dwHighDateTime = (DWORD)((t >> 32) & 0xffffffff); new_t.dwLowDateTime = (DWORD)(t & 0xffffffff); if (!SetFileTime(fh, NULL, NULL, &new_t)) { _ftprintf(stderr, _TEXT("SetFileTime(%s): %u\n"), fp, GetLastError()); return 1; } if (!GetFileTime(fh, NULL, NULL, &lwt)) { _ftprintf(stderr, _TEXT("GetFileTime(%s): %u\n"), fp, GetLastError()); return 1; } if (CompareFileTime(&lwt, &new_t) != 0) { _ftprintf(stderr, _TEXT("**** The new time is different!\n")); failed = TRUE; } if (CompareFileTime(&lwt, &wt) == 0) { _ftprintf(stderr, _TEXT("**** Not changed from the previous!\n")); failed = TRUE; } } if (!CloseHandle(fh)) { _ftprintf(stderr, _TEXT("CloseHandle(): %u\n"), GetLastError()); return 1; } if (failed) { FILETIME wt = lwt; if ((fh = CreateFile(fp, da, sm, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE) { _ftprintf(stderr, _TEXT("CreateFile(%s): %u\n"), fp, GetLastError()); return 1; } if (!GetFileTime(fh, NULL, NULL, &lwt)) { _ftprintf(stderr, _TEXT("GetFileTime(%s): %u\n"), fp, GetLastError()); return 1; } if (CompareFileTime(&lwt, &wt) != 0) _ftprintf(stderr, _TEXT("**** Changed after CloseHandle()!\n")); if (!CloseHandle(fh)) { _ftprintf(stderr, _TEXT("CloseHandle(): %u\n"), GetLastError()); return 1; } } return 0; }
We (Swiss Life, Zurich, Switzerland) would like to reference against this bug. We have an interop ClearCase environment, using Samba 2.2.8a on ClearCase 2003.06.00 Solaris 5.8 servers, and are receiving out-of-sync errors from the Eclipse IDE when writing to files. This behaviour was originally thought to be an Eclipse problem. However, the support, resp. research from IBM proved this assumption to be wrong and identified it as a samba bug. Paul Jesze paul.jesze@swisslife.ch
Correction to our last comment: This was thought to be a problem with ClearCase and/or the ClearCase-Eclipse plugin. Paul Jesze paul.jesze@swisslife.ch
Created attachment 805 [details] Patch for smbd/trans2.c The attached patch worked for me and solved the bug demonstrated by the above-mentioned test application. In the function that handles query_path_info transactions, it first checks if it has a pending_modtime on this opened file, and if so - returns it instead of the stale st_mtime. Please consider adding this patch to the next release
This patch (or something very similar) has gone into the SVN and will be in Samba 3.0.10. Jeremy.
Has this pach gone in? I am getting similar problems using eclipse editing files on a samba share, even after updating to samba 3.0.10 (debian unstable), I cannot find the patch in the file trans2.c, but havent looked too hard for something similar.
I have rebuilt samba-3.0.10 on debian unstable with the patch applied, and it seems to fix the problems I have been having (although strangely, changing back to the old smbd does not yeild as many (only 1) out-of-sync errors... hmm). Has this patch been lost in the ether? perhaps consider re-opening this until the patch is applied.
Unfortunately this patch didn't make it into 3.0.10 as this was a security-only release. This fix will officially be in 3.0.11 (so long as there isn't another security release :-). Jeremy.
sorry for the same, cleaning up the database to prevent unecessary reopens of bugs.