⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connect.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 5 页
字号:
		smb_msg.msg_controllen = 0;		pdu_length = 4; /* enought to get RFC1001 header */incomplete_rcv:#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)		smb_msg.msg_iov = &iov;		smb_msg.msg_iovlen = 1;		length =			sock_recvmsg(csocket, &smb_msg, pdu_length, 0);#else		length =		    kernel_recvmsg(csocket, &smb_msg,				&iov, 1, pdu_length, 0 /* BB other flags? */);#endif		if (kthread_should_stop()) {			break;		} else if (server->tcpStatus == CifsNeedReconnect) {			cFYI(1, ("Reconnect after server stopped responding"));			cifs_reconnect(server);			cFYI(1, ("call to reconnect done"));			csocket = server->ssocket;			continue;		} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {			msleep(1); /* minimum sleep to prevent looping				allowing socket to clear and app threads to set				tcpStatus CifsNeedReconnect if server hung */			continue;		} else if (length <= 0) {			if (server->tcpStatus == CifsNew) {				cFYI(1, ("tcp session abend after SMBnegprot"));				/* some servers kill the TCP session rather than				   returning an SMB negprot error, in which				   case reconnecting here is not going to help,				   and so simply return error to mount */				break;			}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)			if (!try_to_freeze() && (length == -EINTR)) {#else			if (length == -EINTR) {#endif				cFYI(1, ("cifsd thread killed"));				break;			}			cFYI(1, ("Reconnect after unexpected peek error %d",				length));			cifs_reconnect(server);			csocket = server->ssocket;			wake_up(&server->response_q);			continue;		} else if (length < 4) {			cFYI(1, ("less than four bytes received (%d bytes)",			      length));			pdu_length -= length;			msleep(1);			goto incomplete_rcv;		}		/* The right amount was read from socket - 4 bytes */		/* so we can now interpret the length field */		/* the first byte big endian of the length field,		is actually not part of the length but the type		with the most common, zero, as regular data */		temp = *((char *) smb_buffer);		/* Note that FC 1001 length is big endian on the wire,		but we convert it here so it is always manipulated		as host byte order */		pdu_length = ntohl(smb_buffer->smb_buf_length);		smb_buffer->smb_buf_length = pdu_length;		cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));		if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {			continue;		} else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {			cFYI(1, ("Good RFC 1002 session rsp"));			continue;		} else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {			/* we get this from Windows 98 instead of			   an error on SMB negprot response */			cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",				pdu_length));			if (server->tcpStatus == CifsNew) {				/* if nack on negprot (rather than				ret of smb negprot error) reconnecting				not going to help, ret error to mount */				break;			} else {				/* give server a second to				clean up before reconnect attempt */				msleep(1000);				/* always try 445 first on reconnect				since we get NACK on some if we ever				connected to port 139 (the NACK is				since we do not begin with RFC1001				session initialize frame) */				server->addr.sockAddr.sin_port =					htons(CIFS_PORT);				cifs_reconnect(server);				csocket = server->ssocket;				wake_up(&server->response_q);				continue;			}		} else if (temp != (char) 0) {			cERROR(1, ("Unknown RFC 1002 frame"));			cifs_dump_mem(" Received Data: ", (char *)smb_buffer,				      length);			cifs_reconnect(server);			csocket = server->ssocket;			continue;		}		/* else we have an SMB response */		if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||			    (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {			cERROR(1, ("Invalid size SMB length %d pdu_length %d",					length, pdu_length+4));			cifs_reconnect(server);			csocket = server->ssocket;			wake_up(&server->response_q);			continue;		}		/* else length ok */		reconnect = 0;		if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {			isLargeBuf = TRUE;			memcpy(bigbuf, smallbuf, 4);			smb_buffer = bigbuf;		}		length = 0;		iov.iov_base = 4 + (char *)smb_buffer;		iov.iov_len = pdu_length;		for (total_read = 0; total_read < pdu_length;		     total_read += length) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)			length = sock_recvmsg(csocket, &smb_msg,				pdu_length - total_read, 0);#else			length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,						pdu_length - total_read, 0);#endif			if (kthread_should_stop() ||			    (length == -EINTR)) {				/* then will exit */				reconnect = 2;				break;			} else if (server->tcpStatus == CifsNeedReconnect) {				cifs_reconnect(server);				csocket = server->ssocket;				/* Reconnect wakes up rspns q */				/* Now we will reread sock */				reconnect = 1;				break;			} else if ((length == -ERESTARTSYS) ||				   (length == -EAGAIN)) {				msleep(1); /* minimum sleep to prevent looping,					      allowing socket to clear and app					      threads to set tcpStatus					      CifsNeedReconnect if server hung*/				continue;			} else if (length <= 0) {				cERROR(1, ("Received no data, expecting %d",					      pdu_length - total_read));				cifs_reconnect(server);				csocket = server->ssocket;				reconnect = 1;				break;			}		}		if (reconnect == 2)			break;		else if (reconnect == 1)			continue;		length += 4; /* account for rfc1002 hdr */		dump_smb(smb_buffer, length);		if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {			cifs_dump_mem("Bad SMB: ", smb_buffer, 48);			continue;		}		task_to_wake = NULL;		spin_lock(&GlobalMid_Lock);		list_for_each(tmp, &server->pending_mid_q) {			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);			if ((mid_entry->mid == smb_buffer->Mid) &&			    (mid_entry->midState == MID_REQUEST_SUBMITTED) &&			    (mid_entry->command == smb_buffer->Command)) {				if (check2ndT2(smb_buffer,server->maxBuf) > 0) {					/* We have a multipart transact2 resp */					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;							break;						} else {							/* all parts received */							mid_entry->multiEnd = 1;							goto multi_t2_fnd;						}					} else {						if (!isLargeBuf) {							cERROR(1,("1st trans2 resp needs bigbuf"));					/* BB maybe we can fix this up,  switch					   to already allocated large buffer? */						} else {							/* Have first buffer */							mid_entry->resp_buf =								 smb_buffer;							mid_entry->largeBuf = 1;							bigbuf = NULL;						}					}					break;				}				mid_entry->resp_buf = smb_buffer;				if (isLargeBuf)					mid_entry->largeBuf = 1;				else					mid_entry->largeBuf = 0;multi_t2_fnd:				task_to_wake = mid_entry->tsk;				mid_entry->midState = MID_RESPONSE_RECEIVED;#ifdef CONFIG_CIFS_STATS2				mid_entry->when_received = jiffies;#endif				/* so we do not time out requests to  server				which is still responding (since server could				be busy but not dead) */				server->lstrp = jiffies;				break;			}		}		spin_unlock(&GlobalMid_Lock);		if (task_to_wake) {			/* Was previous buf put in mpx struct for multi-rsp? */			if (!isMultiRsp) {				/* smb buffer will be freed by user thread */				if (isLargeBuf)					bigbuf = NULL;				else					smallbuf = NULL;			}			wake_up_process(task_to_wake);		} else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)		    && (isMultiRsp == FALSE)) {			cERROR(1, ("No task to wake, unknown frame received! "				   "NumMids %d", midCount.counter));			cifs_dump_mem("Received Data is: ", (char *)smb_buffer,				      sizeof(struct smb_hdr));#ifdef CONFIG_CIFS_DEBUG2			cifs_dump_detail(smb_buffer);			cifs_dump_mids(server);#endif /* CIFS_DEBUG2 */		}	} /* end while !EXITING */	spin_lock(&GlobalMid_Lock);	server->tcpStatus = CifsExiting;	server->tsk = NULL;	/* 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 */	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	could end up with the counter going negative */	spin_unlock(&GlobalMid_Lock);	/* Although there should not be any requests blocked on	this queue it can not hurt to be paranoid and try to wake up requests	that may haven been blocked when more than 50 at time were on the wire	to the same server - they now will see the session is in exit state	and get out of SendReceive.  */	wake_up_all(&server->request_q);	/* give those requests time to exit */	msleep(125);	if (server->ssocket) {		sock_release(csocket);		server->ssocket = NULL;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)	set_fs(temp_fs);#endif	/* buffer usuallly freed in free_mid - need to free it here on exit */	if (bigbuf != NULL)		cifs_buf_release(bigbuf);	if (smallbuf != NULL)		cifs_small_buf_release(smallbuf);	read_lock(&GlobalSMBSeslock);	if (list_empty(&server->pending_mid_q)) {		/* loop through server session structures attached to this and		    mark them dead */		list_for_each(tmp, &GlobalSMBSessionList) {			ses =			    list_entry(tmp, struct cifsSesInfo,				       cifsSessionList);			if (ses->server == server) {				ses->status = CifsExiting;				ses->server = NULL;			}		}		read_unlock(&GlobalSMBSeslock);	} else {		/* although we can not zero the server struct pointer yet,		since there are active requests which may depnd on them,		mark the corresponding SMB sessions as exiting too */		list_for_each(tmp, &GlobalSMBSessionList) {			ses = list_entry(tmp, struct cifsSesInfo,					 cifsSessionList);			if (ses->server == server)				ses->status = CifsExiting;		}		spin_lock(&GlobalMid_Lock);		list_for_each(tmp, &server->pending_mid_q) {		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);			if (mid_entry->midState == MID_REQUEST_SUBMITTED) {				cFYI(1, ("Clearing Mid 0x%x - waking up ",					 mid_entry->mid));				task_to_wake = mid_entry->tsk;				if (task_to_wake)					wake_up_process(task_to_wake);			}		}		spin_unlock(&GlobalMid_Lock);		read_unlock(&GlobalSMBSeslock);		/* 1/8th of sec is more than enough time for them to exit */		msleep(125);	}	if (!list_empty(&server->pending_mid_q)) {		/* mpx threads have not exited yet give them		at least the smb send timeout time for long ops */		/* due to delays on oplock break requests, we need		to wait at least 45 seconds before giving up		on a request getting a response and going ahead		and killing cifsd */		cFYI(1, ("Wait for exit from demultiplex thread"));		msleep(46000);		/* if threads still have not exited they are probably never		coming home not much else we can do but free the memory */	}	write_lock(&GlobalSMBSeslock);	atomic_dec(&tcpSesAllocCount);	length = tcpSesAllocCount.counter;	/* last chance to mark ses pointers invalid	if there are any pointing to this (e.g	if a crazy root user tried to kill cifsd	kernel thread explicitly this might happen) */	list_for_each(tmp, &GlobalSMBSessionList) {		ses = list_entry(tmp, struct cifsSesInfo,				cifsSessionList);		if (ses->server == server)			ses->server = NULL;	}	write_unlock(&GlobalSMBSeslock);	kfree(server);#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	if (length  > 0)		mempool_resize(cifs_req_poolp, length + cifs_min_rcv,				GFP_KERNEL);#endif	/* BB PORT - do we need complete_and_exit here? BB */	return 0;}static intcifs_parse_mount_options(char *options, const char *devname,			 struct smb_vol *vol){	char *value;	char *data;	unsigned int  temp_len, i, j;	char separator[2];	separator[0] = ',';	separator[1] = 0;	if (Local_System_Name[0] != 0)		memcpy(vol->source_rfc1001_name, Local_System_Name, 15);	else {#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)		char *nodename = utsname()->nodename;#else		char *nodename = system_utsname.nodename;#endif		int n = strnlen(nodename, 15);		memset(vol->source_rfc1001_name, 0x20, 15);		for (i = 0; i < n; i++) {			/* does not have to be perfect mapping since field is			informational, only used for servers that do not support			port 445 and it can be overridden at mount time */			vol->source_rfc1001_name[i] = toupper(nodename[i]);		}	}	vol->source_rfc1001_name[15] = 0;	/* null target name indicates to use *SMBSERVR default called name	   if we end up sending RFC1001 session initialize */	vol->target_rfc1001_name[0] = 0;	vol->linux_uid = current->uid;	/* current->euid instead? */	vol->linux_gid = current->gid;	vol->dir_mode = S_IRWXUGO;	/* 2767 perms indicate mandatory locking support */	vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */	vol->rw = TRUE;	/* default is always to request posix paths. */	vol->posix_paths = 1;	if (!options)		return 1;	if (strncmp(options, "sep=", 4) == 0) {		if (options[4] != 0) {			separator[0] = options[4];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -