[CIFS] Allow disabling CIFS Unix Extensions as mount option
authorSteve French <sfrench@us.ibm.com>
Wed, 18 Jul 2007 23:21:09 +0000 (23:21 +0000)
committerSteve French <sfrench@us.ibm.com>
Wed, 18 Jul 2007 23:21:09 +0000 (23:21 +0000)
Previously the only way to do this was to umount all mounts to that server,
turn off a proc setting (/proc/fs/cifs/LinuxExtensionsEnabled).

Fixes Samba bugzilla bug number: 4582 (and also 2008)

Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/readdir.c

index a0a2f31..1cebb7e 100644 (file)
@@ -316,10 +316,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
                        seq_printf(s, ",posixpaths");
                if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
-                  !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
+                  !(cifs_sb->tcon->unix_ext))
                        seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
                if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
-                  !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
+                  !(cifs_sb->tcon->unix_ext))
                        seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
                seq_printf(s, ",rsize=%d", cifs_sb->rsize);
                seq_printf(s, ",wsize=%d", cifs_sb->wsize);
index 0a78131..b98742f 100644 (file)
@@ -281,7 +281,9 @@ struct cifsTconInfo {
        FILE_SYSTEM_UNIX_INFO fsUnixInfo;
        unsigned retry:1;
        unsigned nocase:1;
-       /* BB add field for back pointer to sb struct? */
+       unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
+                               for this mount even if server would support */
+       /* BB add field for back pointer to sb struct(s)? */
 };
 
 /*
index a6ff406..8eb102f 100644 (file)
@@ -132,10 +132,10 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                /* Give Demultiplex thread up to 10 seconds to
                                   reconnect, should be greater than cifs socket
                                   timeout which is 7 seconds */
-                       while(tcon->ses->server->tcpStatus ==
+                       while (tcon->ses->server->tcpStatus ==
                                                         CifsNeedReconnect) {
                                wait_event_interruptible_timeout(tcon->ses->server->response_q,
-                                       (tcon->ses->server->tcpStatus == 
+                                       (tcon->ses->server->tcpStatus ==
                                                        CifsGood), 10 * HZ);
                                if (tcon->ses->server->tcpStatus ==
                                                        CifsNeedReconnect) {
@@ -213,7 +213,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
        }
 
        header_assemble((struct smb_hdr *) *request_buf, smb_command,
-                       tcon,wct);
+                       tcon, wct);
 
        if (tcon != NULL)
                cifs_stats_inc(&tcon->num_smbs_sent);
@@ -387,7 +387,7 @@ static int validate_t2(struct smb_t2_rsp *pSMB)
                        /* check that bcc is less than negotiated smb buffer */
                        total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
                        if (total_size < 512) {
-                               total_size += 
+                               total_size +=
                                        le16_to_cpu(pSMB->t2_rsp.DataCount);
                                /* BCC le converted in SendReceive */
                                pBCC = (pSMB->hdr.WordCount * 2) +
@@ -2758,7 +2758,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
                return 0;
 
        count = posix_acl_xattr_count((size_t)buflen);
-       cFYI(1,("setting acl with %d entries from buf of length %d and "
+       cFYI(1, ("setting acl with %d entries from buf of length %d and "
                "version of %d",
                count, buflen, le32_to_cpu(local_acl->a_version)));
        if (le32_to_cpu(local_acl->a_version) != 2) {
@@ -3638,15 +3638,6 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        pSMB->SearchHandle = searchHandle;      /* always kept as le */
        pSMB->SearchCount =
                cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
-       /* test for Unix extensions */
-/*     if (tcon->ses->capabilities & CAP_UNIX) {
-               pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
-               psrch_inf->info_level = SMB_FIND_FILE_UNIX;
-       } else {
-               pSMB->InformationLevel =
-                  cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
-               psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
-       } */
        pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
        pSMB->ResumeKey = psrch_inf->resume_key;
        pSMB->SearchFlags =
@@ -3966,7 +3957,7 @@ getDFSRetry:
                                        (8 /* sizeof start of data block */ +
                                        data_offset +
                                        (char *) &pSMBr->hdr.Protocol);
-                       cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \n"
+                       cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
                                "for referral one refer size: 0x%x srv "
                                "type: 0x%x refer flags: 0x%x ttl: 0x%x",
                                le16_to_cpu(pSMBr->NumberOfReferrals),
index 8b341a8..e93da7a 100644 (file)
@@ -85,6 +85,7 @@ struct smb_vol {
        unsigned direct_io:1;
        unsigned remap:1;   /* set to remap seven reserved chars in filenames */
        unsigned posix_paths:1;   /* unset to not ask for posix pathnames. */
+       unsigned no_linux_ext:1;
        unsigned sfu_emul:1;
        unsigned nullauth:1; /* attempt to authenticate with null user */
        unsigned nocase;     /* request case insensitive filenames */
@@ -1192,6 +1193,10 @@ cifs_parse_mount_options(char *options, const char *devname,
                        vol->posix_paths = 1;
                } else if (strnicmp(data, "noposixpaths", 12) == 0) {
                        vol->posix_paths = 0;
+               } else if (strnicmp(data, "nounix", 6) == 0) {
+                       vol->no_linux_ext = 1;
+               } else if (strnicmp(data, "nolinux", 7) == 0) {
+                       vol->no_linux_ext = 1;
                } else if ((strnicmp(data, "nocase", 6) == 0) ||
                           (strnicmp(data, "ignorecase", 10)  == 0)) {
                        vol->nocase = 1;
@@ -1665,6 +1670,18 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
         * and once without posixacls or posix paths? */
        __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
 
+       if (vol_info && vol_info->no_linux_ext) {
+               tcon->fsUnixInfo.Capability = 0;
+               tcon->unix_ext = 0; /* Unix Extensions disabled */
+               cFYI(1, ("Linux protocol extensions disabled"));
+               return;
+       } else if (vol_info)
+               tcon->unix_ext = 1; /* Unix Extensions supported */
+
+       if (tcon->unix_ext == 0) {
+               cFYI(1, ("Unix extensions disabled so not set on reconnect"));
+               return;
+       }
 
        if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
                __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
@@ -1678,10 +1695,6 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
                                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;
@@ -2176,13 +2189,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 
                /* tell server which Unix caps we support */
                if (tcon->ses->capabilities & CAP_UNIX)
+                       /* reset of caps checks mount to see if unix extensions
+                          disabled for just this mount */
                        reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
-               else if (cifs_sb->rsize > (1024 * 127)) {
+               else
+                       tcon->unix_ext = 0; /* server does not support them */
+
+               if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
                        cifs_sb->rsize = 1024 * 127;
 #ifdef CONFIG_CIFS_DEBUG2
-                       cFYI(1, ("no very large read support, rsize 127K"));
+                       cFYI(1, ("no very large read support, rsize now 127K"));
 #endif
-
                }
                if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
                        cifs_sb->wsize = min(cifs_sb->wsize,
index def89f2..4830acc 100644 (file)
@@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        } else {
                /* If Open reported that we actually created a file
                then we now have to set the mode if possible */
-               if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
-                       (oplock & CIFS_CREATE_ACTION)) {
+               if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
                        mode &= ~current->fs->umask;
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                                CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
@@ -235,8 +234,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                        /* Could set r/o dos attribute if mode & 0222 == 0 */
                }
 
-       /* BB server might mask mode so we have to query for Unix case*/
-               if (pTcon->ses->capabilities & CAP_UNIX)
+               /* server might mask mode so we have to query for it */
+               if (pTcon->unix_ext)
                        rc = cifs_get_inode_info_unix(&newinode, full_path,
                                                 inode->i_sb, xid);
                else {
@@ -337,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL)
                rc = -ENOMEM;
-       else if (pTcon->ses->capabilities & CAP_UNIX) {
+       else if (pTcon->unix_ext) {
                mode &= ~current->fs->umask;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                        rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
@@ -491,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        cFYI(1,
             (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
 
-       if (pTcon->ses->capabilities & CAP_UNIX)
+       if (pTcon->unix_ext)
                rc = cifs_get_inode_info_unix(&newInode, full_path,
                                              parent_dir_inode->i_sb, xid);
        else
diff --cc fs/cifs/file.c
Simple merge
diff --cc fs/cifs/inode.c
Simple merge
diff --cc fs/cifs/link.c
Simple merge
Simple merge