]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/cifs/connect.c
CIFS: Set reconnect instance to one initially
[linux.git] / fs / cifs / connect.c
index 8463c940e0e59779390b210fa3ebba45df86f80b..46bee3b4eeed93ebb957292d9686abc8a3f1eaeb 100644 (file)
@@ -102,7 +102,7 @@ enum {
        Opt_backupuid, Opt_backupgid, Opt_uid,
        Opt_cruid, Opt_gid, Opt_file_mode,
        Opt_dirmode, Opt_port,
-       Opt_rsize, Opt_wsize, Opt_actimeo,
+       Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
        Opt_echo_interval, Opt_max_credits,
        Opt_snapshot,
 
@@ -204,6 +204,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_dirmode, "dirmode=%s" },
        { Opt_dirmode, "dir_mode=%s" },
        { Opt_port, "port=%s" },
+       { Opt_blocksize, "bsize=%s" },
        { Opt_rsize, "rsize=%s" },
        { Opt_wsize, "wsize=%s" },
        { Opt_actimeo, "actimeo=%s" },
@@ -348,7 +349,7 @@ static int reconn_set_ipaddr(struct TCP_Server_Info *server)
                cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
                return -ENOMEM;
        }
-       snprintf(unc, len, "\\\\%s", server->hostname);
+       scnprintf(unc, len, "\\\\%s", server->hostname);
 
        rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
        kfree(unc);
@@ -1053,7 +1054,7 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        }
 
        if (server->ops->is_status_pending &&
-           server->ops->is_status_pending(buf, server, length))
+           server->ops->is_status_pending(buf, server))
                return -1;
 
        if (!mid)
@@ -1063,6 +1064,26 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        return 0;
 }
 
+static void
+smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
+{
+       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
+
+       /*
+        * SMB1 does not use credits.
+        */
+       if (server->vals->header_preamble_size)
+               return;
+
+       if (shdr->CreditRequest) {
+               spin_lock(&server->req_lock);
+               server->credits += le16_to_cpu(shdr->CreditRequest);
+               spin_unlock(&server->req_lock);
+               wake_up(&server->request_q);
+       }
+}
+
+
 static int
 cifs_demultiplex_thread(void *p)
 {
@@ -1192,6 +1213,7 @@ cifs_demultiplex_thread(void *p)
                        } else if (server->ops->is_oplock_break &&
                                   server->ops->is_oplock_break(bufs[i],
                                                                server)) {
+                               smb2_add_credits_from_hdr(bufs[i], server);
                                cifs_dbg(FYI, "Received oplock break\n");
                        } else {
                                cifs_dbg(VFS, "No task to wake, unknown frame "
@@ -1203,6 +1225,7 @@ cifs_demultiplex_thread(void *p)
                                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 */
                        }
@@ -1486,6 +1509,11 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
        const char *delims = "/\\";
        size_t len;
 
+       if (unlikely(!devname || !*devname)) {
+               cifs_dbg(VFS, "Device name not specified.\n");
+               return -EINVAL;
+       }
+
        /* make sure we have a valid UNC double delimiter prefix */
        len = strspn(devname, delims);
        if (len != 2)
@@ -1571,7 +1599,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
        vol->cred_uid = current_uid();
        vol->linux_uid = current_uid();
        vol->linux_gid = current_gid();
-
+       vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
        /*
         * default to SFM style remapping of seven reserved characters
         * unless user overrides it or we negotiate CIFS POSIX where
@@ -1944,6 +1972,26 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        }
                        port = (unsigned short)option;
                        break;
+               case Opt_blocksize:
+                       if (get_option_ul(args, &option)) {
+                               cifs_dbg(VFS, "%s: Invalid blocksize value\n",
+                                       __func__);
+                               goto cifs_parse_mount_err;
+                       }
+                       /*
+                        * inode blocksize realistically should never need to be
+                        * less than 16K or greater than 16M and default is 1MB.
+                        * Note that small inode block sizes (e.g. 64K) can lead
+                        * to very poor performance of common tools like cp and scp
+                        */
+                       if ((option < CIFS_MAX_MSGSIZE) ||
+                          (option > (4 * SMB3_DEFAULT_IOSIZE))) {
+                               cifs_dbg(VFS, "%s: Invalid blocksize\n",
+                                       __func__);
+                               goto cifs_parse_mount_err;
+                       }
+                       vol->bsize = option;
+                       break;
                case Opt_rsize:
                        if (get_option_ul(args, &option)) {
                                cifs_dbg(VFS, "%s: Invalid rsize value\n",
@@ -2609,7 +2657,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
                volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
        tcp_ses->session_estab = false;
        tcp_ses->sequence_number = 0;
-       tcp_ses->reconnect_instance = 0;
+       tcp_ses->reconnect_instance = 1;
        tcp_ses->lstrp = jiffies;
        spin_lock_init(&tcp_ses->req_lock);
        INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
@@ -2770,7 +2818,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
        if (tcon == NULL)
                return -ENOMEM;
 
-       snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
+       scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
 
        /* cannot fail */
        nls_codepage = load_nls_default();
@@ -3839,6 +3887,7 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
        spin_lock_init(&cifs_sb->tlink_tree_lock);
        cifs_sb->tlink_tree = RB_ROOT;
 
+       cifs_sb->bsize = pvolume_info->bsize;
        /*
         * Temporarily set r/wsize for matching superblock. If we end up using
         * new sb then client will later negotiate it downward if needed.
@@ -4198,7 +4247,7 @@ static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
        new_unc = kmalloc(len, GFP_KERNEL);
        if (!new_unc)
                return -ENOMEM;
-       snprintf(new_unc, len, "\\%s", tgt);
+       scnprintf(new_unc, len, "\\%s", tgt);
 
        kfree(vol->UNC);
        vol->UNC = new_unc;