[linux-cifs-client] Re: timestamp problems with cp -p
Guenter Kukkukk
linux at kukkukk.com
Thu Mar 13 15:18:23 GMT 2008
Am Donnerstag, 13. März 2008 schrieb Steve French:
> > kukks: smfrench: the needed "sleep 1" in "stat localfile && cp -p localfile /mnt && sleep 1 && stat /mnt/localfile" is also a bit strange
> The 1 second timeout is needed since the local cache of the inode
> timestamps is kept for 1 second ... (and the write and setattr were in
> the correct order locally but the incorrect order remotely - so when
> we revalidated the cached inode it was wrong - the local copy of the
> timestamps would probably be fine as long as the file was open and
> oplocked)
>
> > kukks: smfrench: i had already posted another solution on the cifs mailing list for inode.c ---> cifs_setattr(), which is not patching cifs_unlink atm, where the same sequence for setpathinfo/setfileinfo is used.
>
> What is this issue? utimes itself fails to Windows when file open? I
> see http://rafb.net/p/0bzb2Y13.html but I don't recognize the high
> level problem. Will trace it to Windows tomorrow.
about a week ago i noticed, that 'cp -p ...' was not working, but
did my tests only against winNT and winXP.
Wrote that patch (see below) - and it worked for me...
Later i also did a test against samba3_2 using cifs.ko _not_ including
my patch - and noticed the ACL problem, we were talking about on irc.
So i used the "noacl" mount option to skip that acl settings, to just
test the time stamps problem - which was showing up, too.
Was just wondering that days about the necessity of "sleep 1", which i know
better now! :-)
As a last step i was testing against samba3_2 _including_ my cifs.ko patch -
and it was working for me!
As others noted recently, a different approach is needed at all...
--
Cause the pastebin might vanish very soon, i just add that changes here again:
------------------------------
diff against a version some days ago:
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 24eb4d3..4ae8391 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1591,42 +1591,34 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if (set_time || set_dosattr) {
time_buf.CreationTime = 0; /* do not change */
- /* In the future we should experiment - try setting timestamps
- via Handle (SetFileInfo) instead of by path */
- if (!(pTcon->ses->flags & CIFS_SES_NT4))
- rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
- else
- rc = -EOPNOTSUPP;
-
- if (rc == -EOPNOTSUPP) {
- int oplock = FALSE;
- __u16 netfid;
-
- cFYI(1, ("calling SetFileInfo since SetPathInfo for "
- "times not supported by this server"));
- /* BB we could scan to see if we already have it open
- and pass in pid of opener to function */
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
- SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
- CREATE_NOT_DIR, &netfid, &oplock,
- NULL, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (rc == 0) {
- rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
- netfid);
- CIFSSMBClose(xid, pTcon, netfid);
- } else {
- /* BB For even older servers we could convert time_buf
- into old DOS style which uses two second
- granularity */
-
- /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
- &time_buf, cifs_sb->local_nls); */
- }
+ /*
+ I have spent hours to track this down with servers
+ like winNT and winXP.
+ CONCLUSION:
+ When using "cp -p srcfile /mnt/tmp/" to preserve time stamps
+ (originated from utimes()), both former used alternatives
+ - CIFSSMBSetTimes() to use setpathinfo
+ - CIFSSMBOpen() -> CIFSSMBSetFileTimes() -> CIFSSMBClose()
+ to use setfileinfo
+ do not work properly.
+ Windows _is_ returning success on both variants, but _no_
+ time stamps have been set on the remote server!
+ It seems to be problematic to call these functions, when the
+ dest file is already open.
+ This new version is working for me.
+ */
+ open_file = find_writable_file(cifsInode);
+ if (open_file) {
+ cFYI(1,("cifs_setattr - open_file OK! Calling setfileinfo now!"));
+ rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
+ open_file->netfid);
+ atomic_dec(&open_file->wrtPending);
+ } else {
+ cFYI(1,("cifs_setattr - calling setpathinfo now!"));
+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
}
/* Even if error on time set, no sense failing the call if
the server would set the time to a reasonable value anyway,
More information about the linux-cifs-client
mailing list