diff options
Diffstat (limited to 'fs/cifs/connect.c')
| -rw-r--r-- | fs/cifs/connect.c | 228 | 
1 files changed, 112 insertions, 116 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e1710673016..f428bf3bf1a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -49,8 +49,6 @@  #define CIFS_PORT 445  #define RFC1001_PORT 139 -static DECLARE_COMPLETION(cifsd_complete); -  extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,  			 unsigned char *p24); @@ -71,23 +69,23 @@ struct smb_vol {  	mode_t file_mode;  	mode_t dir_mode;  	unsigned secFlg; -	unsigned rw:1; -	unsigned retry:1; -	unsigned intr:1; -	unsigned setuids:1; -	unsigned override_uid:1; -	unsigned override_gid:1; -	unsigned noperm:1; -	unsigned no_psx_acl:1; /* set if posix acl support should be disabled */ -	unsigned cifs_acl:1; -	unsigned no_xattr:1;   /* set if xattr (EA) support should be disabled*/ -	unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ -	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 */ +	bool rw:1; +	bool retry:1; +	bool intr:1; +	bool setuids:1; +	bool override_uid:1; +	bool override_gid:1; +	bool noperm:1; +	bool no_psx_acl:1; /* set if posix acl support should be disabled */ +	bool cifs_acl:1; +	bool no_xattr:1;   /* set if xattr (EA) support should be disabled*/ +	bool server_ino:1; /* use inode numbers from server ie UniqueId */ +	bool direct_io:1; +	bool remap:1;     /* set to remap seven reserved chars in filenames */ +	bool posix_paths:1;   /* unset to not ask for posix pathnames. */ +	bool no_linux_ext:1; +	bool sfu_emul:1; +	bool nullauth:1; /* attempt to authenticate with null user */  	unsigned nocase;     /* request case insensitive filenames */  	unsigned nobrl;      /* disable sending byte range locks to srv */  	unsigned int rsize; @@ -345,18 +343,16 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)  	struct task_struct *task_to_wake = NULL;  	struct mid_q_entry *mid_entry;  	char temp; -	int isLargeBuf = FALSE; -	int isMultiRsp; +	bool isLargeBuf = false; +	bool isMultiRsp;  	int reconnect;  	current->flags |= PF_MEMALLOC; -	server->tsk = current;	/* save process info to wake at shutdown */  	cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));  	write_lock(&GlobalSMBSeslock);  	atomic_inc(&tcpSesAllocCount);  	length = tcpSesAllocCount.counter;  	write_unlock(&GlobalSMBSeslock); -	complete(&cifsd_complete);  	if (length  > 1)  		mempool_resize(cifs_req_poolp, length + cifs_min_rcv,  				GFP_KERNEL); @@ -390,8 +386,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)  		} else /* if existing small buf clear beginning */  			memset(smallbuf, 0, sizeof(struct smb_hdr)); -		isLargeBuf = FALSE; -		isMultiRsp = FALSE; +		isLargeBuf = false; +		isMultiRsp = false;  		smb_buffer = smallbuf;  		iov.iov_base = smb_buffer;  		iov.iov_len = 4; @@ -517,7 +513,7 @@ incomplete_rcv:  		reconnect = 0;  		if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { -			isLargeBuf = TRUE; +			isLargeBuf = true;  			memcpy(bigbuf, smallbuf, 4);  			smb_buffer = bigbuf;  		} @@ -582,16 +578,18 @@ incomplete_rcv:  			    (mid_entry->command == smb_buffer->Command)) {  				if (check2ndT2(smb_buffer,server->maxBuf) > 0) {  					/* We have a multipart transact2 resp */ -					isMultiRsp = TRUE; +					isMultiRsp = true;  					if (mid_entry->resp_buf) {  						/* merge response - fix up 1st*/  						if (coalesce_t2(smb_buffer,  							mid_entry->resp_buf)) { -							mid_entry->multiRsp = 1; +							mid_entry->multiRsp = +								 true;  							break;  						} else {  							/* all parts received */ -							mid_entry->multiEnd = 1; +							mid_entry->multiEnd = +								 true;  							goto multi_t2_fnd;  						}  					} else { @@ -603,17 +601,15 @@ incomplete_rcv:  							/* Have first buffer */  							mid_entry->resp_buf =  								 smb_buffer; -							mid_entry->largeBuf = 1; +							mid_entry->largeBuf = +								 true;  							bigbuf = NULL;  						}  					}  					break;  				}  				mid_entry->resp_buf = smb_buffer; -				if (isLargeBuf) -					mid_entry->largeBuf = 1; -				else -					mid_entry->largeBuf = 0; +				mid_entry->largeBuf = isLargeBuf;  multi_t2_fnd:  				task_to_wake = mid_entry->tsk;  				mid_entry->midState = MID_RESPONSE_RECEIVED; @@ -638,8 +634,8 @@ multi_t2_fnd:  					smallbuf = NULL;  			}  			wake_up_process(task_to_wake); -		} else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) -		    && (isMultiRsp == FALSE)) { +		} else if (!is_valid_oplock_break(smb_buffer, server) && +			   !isMultiRsp) {  			cERROR(1, ("No task to wake, unknown frame received! "  				   "NumMids %d", midCount.counter));  			cifs_dump_mem("Received Data is: ", (char *)smb_buffer, @@ -654,10 +650,20 @@ multi_t2_fnd:  	spin_lock(&GlobalMid_Lock);  	server->tcpStatus = CifsExiting; -	server->tsk = NULL; +	spin_unlock(&GlobalMid_Lock); + +	/* don't exit until kthread_stop is called */ +	set_current_state(TASK_UNINTERRUPTIBLE); +	while (!kthread_should_stop()) { +		schedule(); +		set_current_state(TASK_UNINTERRUPTIBLE); +	} +	set_current_state(TASK_RUNNING); +  	/* check if we have blocked requests that need to free */  	/* Note that cifs_max_pending is normally 50, but  	can be set at module install time to as little as two */ +	spin_lock(&GlobalMid_Lock);  	if (atomic_read(&server->inFlight) >= cifs_max_pending)  		atomic_set(&server->inFlight, cifs_max_pending - 1);  	/* We do not want to set the max_pending too low or we @@ -825,7 +831,7 @@ cifs_parse_mount_options(char *options, const char *devname,  	vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);  	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ -	vol->rw = TRUE; +	vol->rw = true;  	/* default is always to request posix paths. */  	vol->posix_paths = 1; @@ -1181,7 +1187,7 @@ cifs_parse_mount_options(char *options, const char *devname,  		} else if (strnicmp(data, "guest", 5) == 0) {  			/* ignore */  		} else if (strnicmp(data, "rw", 2) == 0) { -			vol->rw = TRUE; +			vol->rw = true;  		} else if ((strnicmp(data, "suid", 4) == 0) ||  				   (strnicmp(data, "nosuid", 6) == 0) ||  				   (strnicmp(data, "exec", 4) == 0) || @@ -1197,7 +1203,7 @@ cifs_parse_mount_options(char *options, const char *devname,  			    is ok to just ignore them */  			continue;  		} else if (strnicmp(data, "ro", 2) == 0) { -			vol->rw = FALSE; +			vol->rw = false;  		} else if (strnicmp(data, "hard", 4) == 0) {  			vol->retry = 1;  		} else if (strnicmp(data, "soft", 4) == 0) { @@ -1305,6 +1311,9 @@ cifs_parse_mount_options(char *options, const char *devname,  						    "begin with // or \\\\ \n");  				return 1;  			} +			value = strpbrk(vol->UNC+2, "/\\"); +			if (value) +				*value = '\\';  		} else {  			printk(KERN_WARNING "CIFS: UNC name too long\n");  			return 1; @@ -1318,42 +1327,43 @@ cifs_parse_mount_options(char *options, const char *devname,  static struct cifsSesInfo *  cifs_find_tcp_session(struct in_addr *target_ip_addr, -		struct in6_addr *target_ip6_addr, -		 char *userName, struct TCP_Server_Info **psrvTcp) +		      struct in6_addr *target_ip6_addr, +		      char *userName, struct TCP_Server_Info **psrvTcp)  {  	struct list_head *tmp;  	struct cifsSesInfo *ses; +  	*psrvTcp = NULL; -	read_lock(&GlobalSMBSeslock); +	read_lock(&GlobalSMBSeslock);  	list_for_each(tmp, &GlobalSMBSessionList) {  		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); -		if (ses->server) { -			if ((target_ip_addr && -				(ses->server->addr.sockAddr.sin_addr.s_addr -				  == target_ip_addr->s_addr)) || (target_ip6_addr -				&& memcmp(&ses->server->addr.sockAddr6.sin6_addr, -					target_ip6_addr, sizeof(*target_ip6_addr)))) { -				/* BB lock server and tcp session and increment -				      use count here?? */ +		if (!ses->server) +			continue; -				/* found a match on the TCP session */ -				*psrvTcp = ses->server; +		if (target_ip_addr && +		    ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr) +				continue; +		else if (target_ip6_addr && +			 memcmp(&ses->server->addr.sockAddr6.sin6_addr, +				target_ip6_addr, sizeof(*target_ip6_addr))) +				continue; +		/* BB lock server and tcp session; increment use count here?? */ -				/* BB check if reconnection needed */ -				if (strncmp -				    (ses->userName, userName, -				     MAX_USERNAME_SIZE) == 0){ -					read_unlock(&GlobalSMBSeslock); -					/* Found exact match on both TCP and -					   SMB sessions */ -					return ses; -				} -			} +		/* found a match on the TCP session */ +		*psrvTcp = ses->server; + +		/* BB check if reconnection needed */ +		if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) { +			read_unlock(&GlobalSMBSeslock); +			/* Found exact match on both TCP and +			   SMB sessions */ +			return ses;  		}  		/* else tcp and smb sessions need reconnection */  	}  	read_unlock(&GlobalSMBSeslock); +  	return NULL;  } @@ -1362,45 +1372,43 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)  {  	struct list_head *tmp;  	struct cifsTconInfo *tcon; +	__be32 old_ip;  	read_lock(&GlobalSMBSeslock); +  	list_for_each(tmp, &GlobalTreeConnectionList) {  		cFYI(1, ("Next tcon"));  		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); -		if (tcon->ses) { -			if (tcon->ses->server) { -				cFYI(1, -				     ("old ip addr: %x == new ip %x ?", -				      tcon->ses->server->addr.sockAddr.sin_addr. -				      s_addr, new_target_ip_addr)); -				if (tcon->ses->server->addr.sockAddr.sin_addr. -				    s_addr == new_target_ip_addr) { -	/* BB lock tcon, server and tcp session and increment use count here? */ -					/* found a match on the TCP session */ -					/* BB check if reconnection needed */ -					cFYI(1, -					      ("IP match, old UNC: %s new: %s", -					      tcon->treeName, uncName)); -					if (strncmp -					    (tcon->treeName, uncName, -					     MAX_TREE_SIZE) == 0) { -						cFYI(1, -						     ("and old usr: %s new: %s", -						      tcon->treeName, uncName)); -						if (strncmp -						    (tcon->ses->userName, -						     userName, -						     MAX_USERNAME_SIZE) == 0) { -							read_unlock(&GlobalSMBSeslock); -							/* matched smb session -							(user name */ -							return tcon; -						} -					} -				} -			} -		} +		if (!tcon->ses || !tcon->ses->server) +			continue; + +		old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr; +		cFYI(1, ("old ip addr: %x == new ip %x ?", +			old_ip, new_target_ip_addr)); + +		if (old_ip != new_target_ip_addr) +			continue; + +		/* BB lock tcon, server, tcp session and increment use count? */ +		/* found a match on the TCP session */ +		/* BB check if reconnection needed */ +		cFYI(1, ("IP match, old UNC: %s new: %s", +			tcon->treeName, uncName)); + +		if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE)) +			continue; + +		cFYI(1, ("and old usr: %s new: %s", +			tcon->treeName, uncName)); + +		if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE)) +			continue; + +		/* matched smb session (user name) */ +		read_unlock(&GlobalSMBSeslock); +		return tcon;  	} +  	read_unlock(&GlobalSMBSeslock);  	return NULL;  } @@ -1982,7 +1990,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,  				kfree(srvTcp->hostname);  				goto out;  			} -			wait_for_completion(&cifsd_complete);  			rc = 0;  			memcpy(srvTcp->workstation_RFC1001_name,  				volume_info.source_rfc1001_name, 16); @@ -2189,15 +2196,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,  			srvTcp->tcpStatus = CifsExiting;  			spin_unlock(&GlobalMid_Lock);  			if (srvTcp->tsk) { -				struct task_struct *tsk;  				/* If we could verify that kthread_stop would  				   always wake up processes blocked in  				   tcp in recv_mesg then we could remove the  				   send_sig call */  				force_sig(SIGKILL, srvTcp->tsk); -				tsk = srvTcp->tsk; -				if (tsk) -					kthread_stop(tsk); +				kthread_stop(srvTcp->tsk);  			}  		}  		 /* If find_unc succeeded then rc == 0 so we can not end */ @@ -2213,23 +2217,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,  					if ((temp_rc == -ESHUTDOWN) &&  					    (pSesInfo->server) &&  					    (pSesInfo->server->tsk)) { -						struct task_struct *tsk;  						force_sig(SIGKILL,  							pSesInfo->server->tsk); -						tsk = pSesInfo->server->tsk; -						if (tsk) -							kthread_stop(tsk); +						kthread_stop(pSesInfo->server->tsk);  					}  				} else {  					cFYI(1, ("No session or bad tcon"));  					if ((pSesInfo->server) &&  					    (pSesInfo->server->tsk)) { -						struct task_struct *tsk;  						force_sig(SIGKILL,  							pSesInfo->server->tsk); -						tsk = pSesInfo->server->tsk; -						if (tsk) -							kthread_stop(tsk); +						kthread_stop(pSesInfo->server->tsk);  					}  				}  				sesInfoFree(pSesInfo); @@ -2602,7 +2600,7 @@ sesssetup_nomem:	/* do not return an error on nomem for the info strings,  static int  CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, -			      struct cifsSesInfo *ses, int *pNTLMv2_flag, +			      struct cifsSesInfo *ses, bool *pNTLMv2_flag,  			      const struct nls_table *nls_codepage)  {  	struct smb_hdr *smb_buffer; @@ -2625,7 +2623,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,  	if (ses == NULL)  		return -EINVAL;  	domain = ses->domainName; -	*pNTLMv2_flag = FALSE; +	*pNTLMv2_flag = false;  	smb_buffer = cifs_buf_get();  	if (smb_buffer == NULL) {  		return -ENOMEM; @@ -2778,7 +2776,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,  				       CIFS_CRYPTO_KEY_SIZE);  				if (SecurityBlob2->NegotiateFlags &  					cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) -					*pNTLMv2_flag = TRUE; +					*pNTLMv2_flag = true;  				if ((SecurityBlob2->NegotiateFlags &  					cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) @@ -2939,7 +2937,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,  }  static int  CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, -			char *ntlm_session_key, int ntlmv2_flag, +			char *ntlm_session_key, bool ntlmv2_flag,  			const struct nls_table *nls_codepage)  {  	struct smb_hdr *smb_buffer; @@ -3556,8 +3554,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)  	cifs_sb->prepath = NULL;  	kfree(tmp);  	if (ses) -		schedule_timeout_interruptible(msecs_to_jiffies(500)); -	if (ses)  		sesInfoFree(ses);  	FreeXid(xid); @@ -3569,7 +3565,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,  {  	int rc = 0;  	char ntlm_session_key[CIFS_SESS_KEY_SIZE]; -	int ntlmv2_flag = FALSE; +	bool ntlmv2_flag = false;  	int first_time = 0;  	/* what if server changes its buffer size after dropping the session? */  |