Merge tag '4.3-rc-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
[sfrench/cifs-2.6.git] / fs / cifs / connect.c
index ae6bae2ecb5dbc0081764b9ff8e79874b82a0006..a4830ced0f9899c35c89609b2ea25330a06693bd 100644 (file)
@@ -96,7 +96,8 @@ enum {
        Opt_multiuser, Opt_sloppy, Opt_nosharesock,
        Opt_persistent, Opt_nopersistent,
        Opt_resilient, Opt_noresilient,
-       Opt_domainauto, Opt_rdma,
+       Opt_domainauto, Opt_rdma, Opt_modesid,
+       Opt_compress,
 
        /* Mount options which take numeric value */
        Opt_backupuid, Opt_backupgid, Opt_uid,
@@ -175,6 +176,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_serverino, "serverino" },
        { Opt_noserverino, "noserverino" },
        { Opt_rwpidforward, "rwpidforward" },
+       { Opt_modesid, "modefromsid" },
        { Opt_cifsacl, "cifsacl" },
        { Opt_nocifsacl, "nocifsacl" },
        { Opt_acl, "acl" },
@@ -212,6 +214,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_echo_interval, "echo_interval=%s" },
        { Opt_max_credits, "max_credits=%s" },
        { Opt_snapshot, "snapshot=%s" },
+       { Opt_compress, "compress=%s" },
 
        { Opt_blank_user, "user=" },
        { Opt_blank_user, "username=" },
@@ -706,10 +709,10 @@ static bool
 server_unresponsive(struct TCP_Server_Info *server)
 {
        /*
-        * We need to wait 2 echo intervals to make sure we handle such
+        * We need to wait 3 echo intervals to make sure we handle such
         * situations right:
         * 1s  client sends a normal SMB request
-        * 2s  client gets a response
+        * 3s  client gets a response
         * 30s echo workqueue job pops, and decides we got a response recently
         *     and don't need to send another
         * ...
@@ -718,9 +721,9 @@ server_unresponsive(struct TCP_Server_Info *server)
         */
        if ((server->tcpStatus == CifsGood ||
            server->tcpStatus == CifsNeedNegotiate) &&
-           time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
+           time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
                cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
-                        server->hostname, (2 * server->echo_interval) / HZ);
+                        server->hostname, (3 * server->echo_interval) / HZ);
                cifs_reconnect(server);
                wake_up(&server->response_q);
                return true;
@@ -1223,11 +1226,11 @@ next_pdu:
                                         atomic_read(&midCount));
                                cifs_dump_mem("Received Data is: ", bufs[i],
                                              HEADER_SIZE(server));
+                               smb2_add_credits_from_hdr(bufs[i], server);
 #ifdef CONFIG_CIFS_DEBUG2
                                if (server->ops->dump_detail)
                                        server->ops->dump_detail(bufs[i],
                                                                 server);
-                               smb2_add_credits_from_hdr(bufs[i], server);
                                cifs_dump_mids(server);
 #endif /* CIFS_DEBUG2 */
                        }
@@ -1830,6 +1833,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_rwpidforward:
                        vol->rwpidforward = 1;
                        break;
+               case Opt_modesid:
+                       vol->mode_ace = 1;
+                       break;
                case Opt_cifsacl:
                        vol->cifs_acl = 1;
                        break;
@@ -1911,6 +1917,11 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_rdma:
                        vol->rdma = true;
                        break;
+               case Opt_compress:
+                       vol->compression = UNKNOWN_TYPE;
+                       cifs_dbg(VFS,
+                               "SMB3 compression support is experimental\n");
+                       break;
 
                /* Numeric Values */
                case Opt_backupuid:
@@ -2544,8 +2555,15 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
        if (vol->nosharesock)
                return 0;
 
-       /* BB update this for smb3any and default case */
-       if ((server->vals != vol->vals) || (server->ops != vol->ops))
+       /* If multidialect negotiation see if existing sessions match one */
+       if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
+               if (server->vals->protocol_id < SMB30_PROT_ID)
+                       return 0;
+       } else if (strcmp(vol->vals->version_string,
+                  SMBDEFAULT_VERSION_STRING) == 0) {
+               if (server->vals->protocol_id < SMB21_PROT_ID)
+                       return 0;
+       } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
                return 0;
 
        if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
@@ -2680,6 +2698,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        tcp_ses->sequence_number = 0;
        tcp_ses->reconnect_instance = 1;
        tcp_ses->lstrp = jiffies;
+       tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
        spin_lock_init(&tcp_ses->req_lock);
        INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
        INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
@@ -2992,7 +3011,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
        }
 
        cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
-       key = request_key(&key_type_logon, desc, "", NULL);
+       key = request_key(&key_type_logon, desc, "");
        if (IS_ERR(key)) {
                if (!ses->domainName) {
                        cifs_dbg(FYI, "domainName is NULL\n");
@@ -3003,7 +3022,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
                /* didn't work, try to find a domain key */
                sprintf(desc, "cifs:d:%s", ses->domainName);
                cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
-               key = request_key(&key_type_logon, desc, "", NULL);
+               key = request_key(&key_type_logon, desc, "");
                if (IS_ERR(key)) {
                        rc = PTR_ERR(key);
                        goto out_err;
@@ -3460,12 +3479,16 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
 {
        struct cifs_sb_info *old = CIFS_SB(sb);
        struct cifs_sb_info *new = mnt_data->cifs_sb;
+       unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
+       unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
 
        if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
                return 0;
 
-       if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
-           (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
+       if (old->mnt_cifs_serverino_autodisabled)
+               newflags &= ~CIFS_MOUNT_SERVER_INUM;
+
+       if (oldflags != newflags)
                return 0;
 
        /*
@@ -3965,6 +3988,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
        if (pvolume_info->rwpidforward)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
+       if (pvolume_info->mode_ace)
+               cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
        if (pvolume_info->cifs_acl)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
        if (pvolume_info->backupuid_specified) {
@@ -4459,11 +4484,13 @@ cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
                                        unsigned int xid,
                                        struct cifs_tcon *tcon,
                                        struct cifs_sb_info *cifs_sb,
-                                       char *full_path)
+                                       char *full_path,
+                                       int added_treename)
 {
        int rc;
        char *s;
        char sep, tmp;
+       int skip = added_treename ? 1 : 0;
 
        sep = CIFS_DIR_SEP(cifs_sb);
        s = full_path;
@@ -4478,7 +4505,14 @@ cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
                /* next separator */
                while (*s && *s != sep)
                        s++;
-
+               /*
+                * if the treename is added, we then have to skip the first
+                * part within the separators
+                */
+               if (skip) {
+                       skip = 0;
+                       continue;
+               }
                /*
                 * temporarily null-terminate the path at the end of
                 * the current component
@@ -4526,8 +4560,7 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
 
        if (rc != -EREMOTE) {
                rc = cifs_are_all_path_components_accessible(server, xid, tcon,
-                                                            cifs_sb,
-                                                            full_path);
+                       cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
                if (rc != 0) {
                        cifs_dbg(VFS, "cannot query dirs between root and final path, "
                                 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");