Commit 0f9d140a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '5.0-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "A set of cifs/smb3 fixes, 4 for stable, most from Pavel. His patches
  fix an important set of crediting (flow control) problems, and also
  two problems in cifs_writepages, ddressing some large i/o and also
  compounding issues"

* tag '5.0-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update internal module version number
  CIFS: Fix error paths in writeback code
  CIFS: Move credit processing to mid callbacks for SMB3
  CIFS: Fix credits calculation for cancelled requests
  cifs: Fix potential OOB access of lock element array
  cifs: Limit memory used by lock request calls to a page
  cifs: move large array from stack to heap
  CIFS: Do not hide EINTR after sending network packets
  CIFS: Fix credit computation for compounded requests
  CIFS: Do not set credits to 1 if the server didn't grant anything
  CIFS: Fix adjustment of credits for MTU requests
  cifs: Fix a tiny potential memory leak
  cifs: Fix a debug message
parents e1706720 48d2ba62
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -150,5 +150,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */

#define CIFS_VERSION   "2.15"
#define CIFS_VERSION   "2.16"
#endif				/* _CIFSFS_H */
+20 −0
Original line number Diff line number Diff line
@@ -1438,6 +1438,7 @@ struct mid_q_entry {
	int mid_state;	/* wish this were enum but can not pass to wait_event */
	unsigned int mid_flags;
	__le16 command;		/* smb command code */
	unsigned int optype;	/* operation type */
	bool large_buf:1;	/* if valid response, is pointer to large buf */
	bool multiRsp:1;	/* multiple trans2 responses for one request  */
	bool multiEnd:1;	/* both received */
@@ -1574,6 +1575,25 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
	kfree(param);
}

static inline bool is_interrupt_error(int error)
{
	switch (error) {
	case -EINTR:
	case -ERESTARTSYS:
	case -ERESTARTNOHAND:
	case -ERESTARTNOINTR:
		return true;
	}
	return false;
}

static inline bool is_retryable_error(int error)
{
	if (is_interrupt_error(error) || error == -EAGAIN)
		return true;
	return false;
}

#define   MID_FREE 0
#define   MID_REQUEST_ALLOCATED 1
#define   MID_REQUEST_SUBMITTED 2
+20 −10
Original line number Diff line number Diff line
@@ -128,24 +128,31 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
	int rc;
	struct dfs_cache_tgt_list tl;
	struct dfs_cache_tgt_iterator *it = NULL;
	char tree[MAX_TREE_SIZE + 1];
	char *tree;
	const char *tcp_host;
	size_t tcp_host_len;
	const char *dfs_host;
	size_t dfs_host_len;

	tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
	if (!tree)
		return -ENOMEM;

	if (tcon->ipc) {
		snprintf(tree, sizeof(tree), "\\\\%s\\IPC$",
		snprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
			 tcon->ses->server->hostname);
		return CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
		rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
		goto out;
	}

	if (!tcon->dfs_path)
		return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
	if (!tcon->dfs_path) {
		rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
		goto out;
	}

	rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
	if (rc)
		return rc;
		goto out;

	extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
			     &tcp_host_len);
@@ -165,7 +172,7 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
			continue;
		}

		snprintf(tree, sizeof(tree), "\\%s", tgt);
		snprintf(tree, MAX_TREE_SIZE, "\\%s", tgt);

		rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
		if (!rc)
@@ -182,6 +189,8 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
			rc = -ENOENT;
	}
	dfs_cache_free_tgts(&tl);
out:
	kfree(tree);
	return rc;
}
#else
@@ -2114,7 +2123,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)

		for (j = 0; j < nr_pages; j++) {
			unlock_page(wdata2->pages[j]);
			if (rc != 0 && rc != -EAGAIN) {
			if (rc != 0 && !is_retryable_error(rc)) {
				SetPageError(wdata2->pages[j]);
				end_page_writeback(wdata2->pages[j]);
				put_page(wdata2->pages[j]);
@@ -2123,7 +2132,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)

		if (rc) {
			kref_put(&wdata2->refcount, cifs_writedata_release);
			if (rc == -EAGAIN)
			if (is_retryable_error(rc))
				continue;
			break;
		}
@@ -2132,6 +2141,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
		i += nr_pages;
	} while (i < wdata->nr_pages);

	if (rc != 0 && !is_retryable_error(rc))
		mapping_set_error(inode->i_mapping, rc);
	kref_put(&wdata->refcount, cifs_writedata_release);
}
+4 −3
Original line number Diff line number Diff line
@@ -433,9 +433,10 @@ static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
	kfree(server->hostname);

	server->hostname = extract_hostname(name);
	if (!server->hostname) {
		cifs_dbg(FYI, "%s: failed to extract hostname from target: %d\n",
			 __func__, -ENOMEM);
	if (IS_ERR(server->hostname)) {
		cifs_dbg(FYI,
			 "%s: failed to extract hostname from target: %ld\n",
			 __func__, PTR_ERR(server->hostname));
	}
}

+1 −0
Original line number Diff line number Diff line
@@ -776,6 +776,7 @@ static int get_tgt_list(const struct dfs_cache_entry *ce,
		it->it_name = kstrndup(t->t_name, strlen(t->t_name),
				       GFP_KERNEL);
		if (!it->it_name) {
			kfree(it);
			rc = -ENOMEM;
			goto err_free_it;
		}
Loading