Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=8af18971584d1e05770560206cfdfd1d6ba8a17f
Commit:     8af18971584d1e05770560206cfdfd1d6ba8a17f
Parent:     7ba526316ae122e60c0c7a40793491f71b9ec590
Author:     Steve French <[EMAIL PROTECTED]>
AuthorDate: Wed Feb 14 04:42:51 2007 +0000
Committer:  Steve French <[EMAIL PROTECTED]>
CommitDate: Wed Feb 14 04:42:51 2007 +0000

    [CIFS] on reconnect to Samba - reset the unix capabilities
    
    After temporary server or network failure and reconneciton, we were not
    resending the unix capabilities via SetFSInfo - which confused Samba posix
    byte range locking code.
    
    Discovered by jra
    
    Signed-off-by: Steve French <[EMAIL PROTECTED]>
---
 fs/Kconfig          |   29 ++++-------
 fs/cifs/CHANGES     |    7 ++-
 fs/cifs/TODO        |    8 +++
 fs/cifs/cifsfs.h    |    2 +-
 fs/cifs/cifspdu.h   |    2 +-
 fs/cifs/cifsproto.h |    3 +
 fs/cifs/cifssmb.c   |   16 ++++++-
 fs/cifs/connect.c   |  130 +++++++++++++++++++++++++++++++++-----------------
 8 files changed, 130 insertions(+), 67 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index 8cd2417..d57f363 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1871,20 +1871,14 @@ config CIFS
          file servers such as Windows 2000 (including Windows 2003, NT 4  
          and Windows XP) as well by Samba (which provides excellent CIFS
          server support for Linux and many other operating systems). Limited
-         support for Windows ME and similar servers is provided as well. 
-         You must use the smbfs client filesystem to access older SMB servers
-         such as OS/2 and DOS.
+         support for OS/2 and Windows ME and similar servers is provided as 
well.
 
          The intent of the cifs module is to provide an advanced
-         network file system client for mounting to CIFS compliant servers, 
+         network file system client for mounting to CIFS compliant servers,
          including support for dfs (hierarchical name space), secure per-user
          session establishment, safe distributed caching (oplock), optional
-         packet signing, Unicode and other internationalization improvements, 
-         and optional Winbind (nsswitch) integration. You do not need to enable
-         cifs if running only a (Samba) server. It is possible to enable both
-         smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003
-         and Samba 3 servers, and smbfs for accessing old servers). If you 
need 
-         to mount to Samba or Windows from this machine, say Y.
+         packet signing, Unicode and other internationalization improvements. 
+         If you need to mount to Samba or Windows from this machine, say Y.
 
 config CIFS_STATS
         bool "CIFS statistics"
@@ -1977,14 +1971,13 @@ config CIFS_EXPERIMENTAL
          depends on CIFS && EXPERIMENTAL
          help
            Enables cifs features under testing. These features are
-           experimental and currently include support for writepages
-           (multipage writebehind performance improvements) and directory
-           change notification ie fcntl(F_DNOTIFY) as well as some security
-           improvements.  Some also depend on setting at runtime the
-           pseudo-file /proc/fs/cifs/Experimental (which is disabled by
-           default). See the file fs/cifs/README for more details.
-
-           If unsure, say N.
+           experimental and currently include DFS support and directory 
+           change notification ie fcntl(F_DNOTIFY), as well as the upcall
+           mechanism which will be used for Kerberos session negotiation
+           and uid remapping.  Some of these features also may depend on 
+           setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
+           (which is disabled by default). See the file fs/cifs/README 
+           for more details.  If unsure, say N.
 
 config CIFS_UPCALL
          bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index a1fb03f..5fe1359 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -4,7 +4,12 @@ Fix oops in list_del during mount caused by unaligned string.
 Fix file corruption which could occur on some large file
 copies caused by writepages page i/o completion bug.
 Seek to SEEK_END forces check for update of file size for non-cached
-files.
+files. Allow file size to be updated on remote extend of locally open,
+non-cached file.  Fix reconnect to newer Samba servers (or other servers
+which support the CIFS Unix/POSIX extensions) so that we again tell the
+server the Unix/POSIX cifs capabilities which we support (SetFSInfo).
+Add experimental support for new POSIX Open/Mkdir (which returns
+stat information on the open, and allows setting the mode).
 
 Version 1.46
 ------------
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index fc34c74..6837294 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -128,3 +128,11 @@ negotiated size) and send larger write sizes to modern 
servers.
 
 4) More exhaustively test against less common servers.  More testing
 against Windows 9x, Windows ME servers.
+
+DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for 
this too)
+
+mount check for unmatched uids - and uid override
+
+Add mount option for Linux extension disable per mount, and partial disable 
per mount (uid off, symlink/fifo/mknod on but what about posix acls?) 
+
+Free threads at umount --force that are stuck on the sesSem
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 8aa66dc..e36b0d4 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern ssize_t      cifs_getxattr(struct dentry *, const 
char *, void *, size_t);
 extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
                       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.47"
+#define CIFS_VERSION   "1.48"
 #endif                         /* _CIFSFS_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 529a000..7d95054 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2108,7 +2108,7 @@ typedef struct {
 
 typedef struct {
        /* reply varies based on requested level */
-} __atribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
+} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
 
 
 struct file_internal_info {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1108f17..6148b82 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -23,6 +23,7 @@
 #include <linux/nls.h>
 
 struct statfs;
+struct smb_vol;
 
 /*
  *****************************************************************
@@ -147,6 +148,8 @@ extern int get_dfs_path(int xid, struct cifsSesInfo 
*pSesInfo,
                        unsigned int *pnum_referrals, 
                        unsigned char ** preferrals,
                        int remap);
+extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
+                                struct super_block * sb, struct smb_vol * vol);
 extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
                        struct kstatfs *FSData);
 extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 472e33e..b8e9147 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -158,9 +158,15 @@ small_smb_init(int smb_command, int wct, struct 
cifsTconInfo *tcon,
                                                        nls_codepage);
                        if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
                                mark_open_files_invalid(tcon);
-                               rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
-                                       , nls_codepage);
+                               rc = CIFSTCon(0, tcon->ses, tcon->treeName, 
+                                             tcon, nls_codepage);
                                up(&tcon->ses->sesSem);
+                               /* tell server which Unix caps we support */
+                               if (tcon->ses->capabilities & CAP_UNIX)
+                                       reset_cifs_unix_caps(0 /* no xid */,
+                                               tcon, 
+                                               NULL /* we do not know sb */,
+                                               NULL /* no vol info */);        
                                /* BB FIXME add code to check if wsize needs
                                   update due to negotiated smb buffer size
                                   shrinking */
@@ -298,6 +304,12 @@ smb_init(int smb_command, int wct, struct cifsTconInfo 
*tcon,
                                rc = CIFSTCon(0, tcon->ses, tcon->treeName,
                                              tcon, nls_codepage);
                                up(&tcon->ses->sesSem);
+                               /* tell server which Unix caps we support */
+                               if (tcon->ses->capabilities & CAP_UNIX)
+                                       reset_cifs_unix_caps(0 /* no xid */,
+                                               tcon, 
+                                               NULL /* do not know sb */,
+                                               NULL /* no vol info */);
                                /* BB FIXME add code to check if wsize needs
                                update due to negotiated smb buffer size
                                shrinking */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2caca06..20ba7dc 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1613,6 +1613,76 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct 
socket **csocket)
        return rc;
 }
 
+void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon, 
+                         struct super_block * sb, struct smb_vol * vol_info)
+{
+       /* if we are reconnecting then should we check to see if
+        * any requested capabilities changed locally e.g. via
+        * remount but we can not do much about it here
+        * if they have (even if we could detect it by the following)
+        * Perhaps we could add a backpointer to array of sb from tcon
+        * or if we change to make all sb to same share the same
+        * sb as NFS - then we only have one backpointer to sb.
+        * What if we wanted to mount the server share twice once with
+        * and once without posixacls or posix paths? */
+       __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+          
+        
+       if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
+               __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+               
+               /* check for reconnect case in which we do not
+                  want to change the mount behavior if we can avoid it */
+               if(vol_info == NULL) {
+                       /* turn off POSIX ACL and PATHNAMES if not set 
+                          originally at mount time */
+                       if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
+                               cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+                       if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
+                               cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+                               
+
+                        
+                       
+               }
+               
+               cap &= CIFS_UNIX_CAP_MASK;
+               if(vol_info && vol_info->no_psx_acl)
+                       cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+               else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
+                       cFYI(1,("negotiated posix acl support"));
+                       if(sb)
+                               sb->s_flags |= MS_POSIXACL;
+               }
+
+               if(vol_info && vol_info->posix_paths == 0)
+                       cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+               else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+                       cFYI(1,("negotiate posix pathnames"));
+                       if(sb)
+                               CIFS_SB(sb)->mnt_cifs_flags |= 
+                                       CIFS_MOUNT_POSIX_PATHS;
+               }
+                       
+               cFYI(1,("Negotiate caps 0x%x",(int)cap));
+#ifdef CONFIG_CIFS_DEBUG2
+               if(cap & CIFS_UNIX_FCNTL_CAP)
+                       cFYI(1,("FCNTL cap"));
+               if(cap & CIFS_UNIX_EXTATTR_CAP)
+                       cFYI(1,("EXTATTR cap"));
+               if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
+                       cFYI(1,("POSIX path cap"));
+               if(cap & CIFS_UNIX_XATTR_CAP)
+                       cFYI(1,("XATTR cap"));
+               if(cap & CIFS_UNIX_POSIX_ACL_CAP)
+                       cFYI(1,("POSIX ACL cap"));
+#endif /* CIFS_DEBUG2 */
+               if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
+                       cFYI(1,("setting capabilities failed"));
+               }
+       }
+}
+
 int
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
           char *mount_data, const char *devname)
@@ -1928,20 +1998,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info 
*cifs_sb,
                        if (tcon == NULL)
                                rc = -ENOMEM;
                        else {
-                               /* check for null share name ie connect to dfs 
root */
+                               /* check for null share name ie connecting to 
+                                * dfs root */
 
-                               /* BB check if this works for exactly length 
three strings */
+                               /* BB check if this works for exactly length 
+                                * three strings */
                                if ((strchr(volume_info.UNC + 3, '\\') == NULL)
                                    && (strchr(volume_info.UNC + 3, '/') ==
                                        NULL)) {
                                        rc = connect_to_dfs_path(xid, pSesInfo,
-                                                       "", cifs_sb->local_nls,
-                                                       cifs_sb->mnt_cifs_flags 
& 
-                                                         
CIFS_MOUNT_MAP_SPECIAL_CHR);
+                                               "", cifs_sb->local_nls,
+                                               cifs_sb->mnt_cifs_flags & 
+                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
                                        kfree(volume_info.UNC);
                                        FreeXid(xid);
                                        return -ENODEV;
                                } else {
+                                       /* BB Do we need to wrap sesSem around
+                                        * this TCon call and Unix SetFS as
+                                        * we do on SessSetup and reconnect? */
                                        rc = CIFSTCon(xid, pSesInfo, 
                                                volume_info.UNC,
                                                tcon, cifs_sb->local_nls);
@@ -1962,6 +2037,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info 
*cifs_sb,
                        sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
        }
 
+       /* BB FIXME fix time_gran to be larger for LANMAN sessions */
        sb->s_time_gran = 100;
 
 /* on error free sesinfo and tcon struct if needed */
@@ -2006,45 +2082,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info 
*cifs_sb,
                /* do not care if following two calls succeed - informational */
                CIFSSMBQFSDeviceInfo(xid, tcon);
                CIFSSMBQFSAttributeInfo(xid, tcon);
-
-               if (tcon->ses->capabilities & CAP_UNIX) {
-                       if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
-                               __u64 cap = 
-                                      le64_to_cpu(tcon->fsUnixInfo.Capability);
-                               cap &= CIFS_UNIX_CAP_MASK;
-                               if(volume_info.no_psx_acl)
-                                       cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
-                               else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
-                                       cFYI(1,("negotiated posix acl 
support"));
-                                       sb->s_flags |= MS_POSIXACL;
-                               }
-
-                               if(volume_info.posix_paths == 0)
-                                       cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
-                               else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
-                                       cFYI(1,("negotiate posix pathnames"));
-                                       cifs_sb->mnt_cifs_flags |= 
-                                               CIFS_MOUNT_POSIX_PATHS;
-                               }
-                                       
-                               cFYI(1,("Negotiate caps 0x%x",(int)cap));
-#ifdef CONFIG_CIFS_DEBUG2
-                               if(cap & CIFS_UNIX_FCNTL_CAP)
-                                       cFYI(1,("FCNTL cap"));
-                               if(cap & CIFS_UNIX_EXTATTR_CAP)
-                                       cFYI(1,("EXTATTR cap"));
-                               if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
-                                       cFYI(1,("POSIX path cap"));
-                               if(cap & CIFS_UNIX_XATTR_CAP)
-                                       cFYI(1,("XATTR cap"));
-                               if(cap & CIFS_UNIX_POSIX_ACL_CAP)
-                                       cFYI(1,("POSIX ACL cap"));
-#endif /* CIFS_DEBUG2 */
-                               if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
-                                       cFYI(1,("setting capabilities failed"));
-                               }
-                       }
-               }
+               
+               /* tell server which Unix caps we support */
+               if (tcon->ses->capabilities & CAP_UNIX)
+                       reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
+               
                if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
                        cifs_sb->wsize = min(cifs_sb->wsize,
                                             (tcon->ses->server->maxBuf -
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to