Commit 8abcaeae authored by Shyam Prasad N's avatar Shyam Prasad N Committed by Steve French
Browse files

cifs: always iterate smb sessions using primary channel



smb sessions and tcons currently hang off primary channel only.
Secondary channels have the lists as empty. Whenever there's a
need to iterate sessions or tcons, we should use the list in the
corresponding primary channel.

Signed-off-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Reviewed-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 30a0b95b
Loading
Loading
Loading
Loading
+5 −1
Original line number Original line Diff line number Diff line
@@ -400,6 +400,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
{
{
	struct smb_hdr *buf = (struct smb_hdr *)buffer;
	struct smb_hdr *buf = (struct smb_hdr *)buffer;
	struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
	struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
	struct TCP_Server_Info *pserver;
	struct cifs_ses *ses;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
	struct cifs_tcon *tcon;
	struct cifsInodeInfo *pCifsInode;
	struct cifsInodeInfo *pCifsInode;
@@ -464,9 +465,12 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
	if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
	if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
		return false;
		return false;


	/* If server is a channel, select the primary channel */
	pserver = CIFS_SERVER_IS_CHAN(srv) ? srv->primary_server : srv;

	/* look up tcon based on tid & uid */
	/* look up tcon based on tid & uid */
	spin_lock(&cifs_tcp_ses_lock);
	spin_lock(&cifs_tcp_ses_lock);
	list_for_each_entry(ses, &srv->smb_ses_list, smb_ses_list) {
	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
			if (tcon->tid != buf->Tid)
			if (tcon->tid != buf->Tid)
				continue;
				continue;
+10 −2
Original line number Original line Diff line number Diff line
@@ -135,6 +135,7 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len,
int
int
smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
{
{
	struct TCP_Server_Info *pserver;
	struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
	struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
	struct smb2_pdu *pdu = (struct smb2_pdu *)shdr;
	struct smb2_pdu *pdu = (struct smb2_pdu *)shdr;
	int hdr_size = sizeof(struct smb2_hdr);
	int hdr_size = sizeof(struct smb2_hdr);
@@ -143,6 +144,9 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
	__u32 calc_len; /* calculated length */
	__u32 calc_len; /* calculated length */
	__u64 mid;
	__u64 mid;


	/* If server is a channel, select the primary channel */
	pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;

	/*
	/*
	 * Add function to do table lookup of StructureSize by command
	 * Add function to do table lookup of StructureSize by command
	 * ie Validate the wct via smb2_struct_sizes table above
	 * ie Validate the wct via smb2_struct_sizes table above
@@ -155,7 +159,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)


		/* decrypt frame now that it is completely read in */
		/* decrypt frame now that it is completely read in */
		spin_lock(&cifs_tcp_ses_lock);
		spin_lock(&cifs_tcp_ses_lock);
		list_for_each_entry(iter, &server->smb_ses_list, smb_ses_list) {
		list_for_each_entry(iter, &pserver->smb_ses_list, smb_ses_list) {
			if (iter->Suid == le64_to_cpu(thdr->SessionId)) {
			if (iter->Suid == le64_to_cpu(thdr->SessionId)) {
				ses = iter;
				ses = iter;
				break;
				break;
@@ -671,6 +675,7 @@ bool
smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
{
{
	struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
	struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
	struct TCP_Server_Info *pserver;
	struct cifs_ses *ses;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
	struct cifs_tcon *tcon;
	struct cifsInodeInfo *cinode;
	struct cifsInodeInfo *cinode;
@@ -691,9 +696,12 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)


	cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel);
	cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel);


	/* If server is a channel, select the primary channel */
	pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;

	/* look up tcon based on tid & uid */
	/* look up tcon based on tid & uid */
	spin_lock(&cifs_tcp_ses_lock);
	spin_lock(&cifs_tcp_ses_lock);
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {


			spin_lock(&tcon->open_file_lock);
			spin_lock(&tcon->open_file_lock);
+5 −1
Original line number Original line Diff line number Diff line
@@ -2302,14 +2302,18 @@ static void
smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
{
{
	struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
	struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
	struct TCP_Server_Info *pserver;
	struct cifs_ses *ses;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
	struct cifs_tcon *tcon;


	if (shdr->Status != STATUS_NETWORK_NAME_DELETED)
	if (shdr->Status != STATUS_NETWORK_NAME_DELETED)
		return;
		return;


	/* If server is a channel, select the primary channel */
	pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;

	spin_lock(&cifs_tcp_ses_lock);
	spin_lock(&cifs_tcp_ses_lock);
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
			if (tcon->tid == le32_to_cpu(shdr->Id.SyncId.TreeId)) {
			if (tcon->tid == le32_to_cpu(shdr->Id.SyncId.TreeId)) {
				spin_lock(&tcon->tc_lock);
				spin_lock(&tcon->tc_lock);
+5 −1
Original line number Original line Diff line number Diff line
@@ -136,9 +136,13 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
static struct cifs_ses *
static struct cifs_ses *
smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
{
{
	struct TCP_Server_Info *pserver;
	struct cifs_ses *ses;
	struct cifs_ses *ses;


	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
	/* If server is a channel, select the primary channel */
	pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;

	list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
		if (ses->Suid != ses_id)
		if (ses->Suid != ses_id)
			continue;
			continue;
		++ses->ses_count;
		++ses->ses_count;