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

📄 connect.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 5 页
字号:
	return rc;}void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,			  struct super_block *sb, struct smb_vol *vol_info){	/* if we are reconnecting then should we check to see if	 * any requested capabilities changed locally e.g. via	 * remount but we can not do much about it here	 * if they have (even if we could detect it by the following)	 * Perhaps we could add a backpointer to array of sb from tcon	 * or if we change to make all sb to same share the same	 * sb as NFS - then we only have one backpointer to sb.	 * What if we wanted to mount the server share twice once with	 * and once without posixacls or posix paths? */	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);	if (vol_info && vol_info->no_linux_ext) {		tcon->fsUnixInfo.Capability = 0;		tcon->unix_ext = 0; /* Unix Extensions disabled */		cFYI(1, ("Linux protocol extensions disabled"));		return;	} else if (vol_info)		tcon->unix_ext = 1; /* Unix Extensions supported */	if (tcon->unix_ext == 0) {		cFYI(1, ("Unix extensions disabled so not set on reconnect"));		return;	}	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);		/* check for reconnect case in which we do not		   want to change the mount behavior if we can avoid it */		if (vol_info == NULL) {			/* turn off POSIX ACL and PATHNAMES if not set			   originally at mount time */			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;		}		cap &= CIFS_UNIX_CAP_MASK;		if (vol_info && vol_info->no_psx_acl)			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)						cFYI(1, ("negotiated posix acl support"));			if (sb)				sb->s_flags |= MS_POSIXACL;#else				cFYI(1,("ACLs not supported"));#endif		}		if (vol_info && vol_info->posix_paths == 0)			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {			cFYI(1, ("negotiate posix pathnames"));			if (sb)				CIFS_SB(sb)->mnt_cifs_flags |=					CIFS_MOUNT_POSIX_PATHS;		}		/* We might be setting the path sep back to a different		form if we are reconnecting and the server switched its		posix path capability for this share */		if (sb && (CIFS_SB(sb)->prepathlen > 0))			CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));		if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {			if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {				CIFS_SB(sb)->rsize = 127 * 1024;#ifdef CONFIG_CIFS_DEBUG2				cFYI(1, ("larger reads not supported by srv"));#endif			}		}		cFYI(1, ("Negotiate caps 0x%x", (int)cap));#ifdef CONFIG_CIFS_DEBUG2		if (cap & CIFS_UNIX_FCNTL_CAP)			cFYI(1, ("FCNTL cap"));		if (cap & CIFS_UNIX_EXTATTR_CAP)			cFYI(1, ("EXTATTR cap"));		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)			cFYI(1, ("POSIX path cap"));		if (cap & CIFS_UNIX_XATTR_CAP)			cFYI(1, ("XATTR cap"));		if (cap & CIFS_UNIX_POSIX_ACL_CAP)			cFYI(1, ("POSIX ACL cap"));		if (cap & CIFS_UNIX_LARGE_READ_CAP)			cFYI(1, ("very large read cap"));		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)			cFYI(1, ("very large write cap"));#endif /* CIFS_DEBUG2 */		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {			if (vol_info == NULL)				cFYI(1, ("resetting capabilities failed"));			else				cERROR(1, ("Negotiating Unix capabilities "					   "with the server failed.  Consider "					   "mounting with the Unix Extensions\n"					   "disabled, if problems are found, "					   "by specifying the nounix mount "					   "option."));		}	}}intcifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,	   char *mount_data, const char *devname){	int rc = 0;	int xid;	int address_type = AF_INET;	struct socket *csocket = NULL;	struct sockaddr_in sin_server;	struct sockaddr_in6 sin_server6;	struct smb_vol volume_info;	struct cifsSesInfo *pSesInfo = NULL;	struct cifsSesInfo *existingCifsSes = NULL;	struct cifsTconInfo *tcon = NULL;	struct TCP_Server_Info *srvTcp = NULL;	xid = GetXid();/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */	memset(&volume_info, 0, sizeof(struct smb_vol));	if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {		kfree(volume_info.UNC);		kfree(volume_info.password);		kfree(volume_info.prepath);		FreeXid(xid);		return -EINVAL;	}	if (volume_info.nullauth) {		cFYI(1, ("null user"));		volume_info.username = NULL;	} else if (volume_info.username) {		/* BB fixme parse for domain name here */		cFYI(1, ("Username: %s", volume_info.username));	} else {		cifserror("No username specified");	/* In userspace mount helper we can get user name from alternate	   locations such as env variables and files on disk */		kfree(volume_info.UNC);		kfree(volume_info.password);		kfree(volume_info.prepath);		FreeXid(xid);		return -EINVAL;	}	if (volume_info.UNCip && volume_info.UNC) {		rc = cifs_inet_pton(AF_INET, volume_info.UNCip,				    &sin_server.sin_addr.s_addr);		if (rc <= 0) {			/* not ipv4 address, try ipv6 */			rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,					    &sin_server6.sin6_addr.in6_u);			if (rc > 0)				address_type = AF_INET6;		} else {			address_type = AF_INET;		}		if (rc <= 0) {			/* we failed translating address */			kfree(volume_info.UNC);			kfree(volume_info.password);			kfree(volume_info.prepath);			FreeXid(xid);			return -EINVAL;		}		cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));		/* success */		rc = 0;	} else if (volume_info.UNCip) {		/* BB using ip addr as server name to connect to the		   DFS root below */		cERROR(1, ("Connecting to DFS root not implemented yet"));		kfree(volume_info.UNC);		kfree(volume_info.password);		kfree(volume_info.prepath);		FreeXid(xid);		return -EINVAL;	} else /* which servers DFS root would we conect to */ {		cERROR(1,		       ("CIFS mount error: No UNC path (e.g. -o "			"unc=//192.168.1.100/public) specified"));		kfree(volume_info.UNC);		kfree(volume_info.password);		kfree(volume_info.prepath);		FreeXid(xid);		return -EINVAL;	}	/* this is needed for ASCII cp to Unicode converts */	if (volume_info.iocharset == NULL) {		cifs_sb->local_nls = load_nls_default();	/* load_nls_default can not return null */	} else {		cifs_sb->local_nls = load_nls(volume_info.iocharset);		if (cifs_sb->local_nls == NULL) {			cERROR(1, ("CIFS mount error: iocharset %s not found",				 volume_info.iocharset));			kfree(volume_info.UNC);			kfree(volume_info.password);			kfree(volume_info.prepath);			FreeXid(xid);			return -ELIBACC;		}	}	if (address_type == AF_INET)		existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,			NULL /* no ipv6 addr */,			volume_info.username, &srvTcp);	else if (address_type == AF_INET6) {		cFYI(1, ("looking for ipv6 address"));		existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,			&sin_server6.sin6_addr,			volume_info.username, &srvTcp);	} else {		kfree(volume_info.UNC);		kfree(volume_info.password);		kfree(volume_info.prepath);		FreeXid(xid);		return -EINVAL;	}	if (srvTcp) {		cFYI(1, ("Existing tcp session with server found"));	} else {	/* create socket */		if (volume_info.port)			sin_server.sin_port = htons(volume_info.port);		else			sin_server.sin_port = 0;		if (address_type == AF_INET6) {			cFYI(1, ("attempting ipv6 connect"));			/* BB should we allow ipv6 on port 139? */			/* other OS never observed in Wild doing 139 with v6 */			rc = ipv6_connect(&sin_server6, &csocket);		} else			rc = ipv4_connect(&sin_server, &csocket,				  volume_info.source_rfc1001_name,				  volume_info.target_rfc1001_name);		if (rc < 0) {			cERROR(1, ("Error connecting to IPv4 socket. "				   "Aborting operation"));			if (csocket != NULL)				sock_release(csocket);			kfree(volume_info.UNC);			kfree(volume_info.password);			kfree(volume_info.prepath);			FreeXid(xid);			return rc;		}		srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);		if (srvTcp == NULL) {			rc = -ENOMEM;			sock_release(csocket);			kfree(volume_info.UNC);			kfree(volume_info.password);			kfree(volume_info.prepath);			FreeXid(xid);			return rc;		} else {			memset(srvTcp, 0, sizeof (struct TCP_Server_Info));			memcpy(&srvTcp->addr.sockAddr, &sin_server,				sizeof (struct sockaddr_in));			atomic_set(&srvTcp->inFlight, 0);			/* BB Add code for ipv6 case too */			srvTcp->ssocket = csocket;			srvTcp->protocolType = IPV4;			init_waitqueue_head(&srvTcp->response_q);			init_waitqueue_head(&srvTcp->request_q);			INIT_LIST_HEAD(&srvTcp->pending_mid_q);			/* at this point we are the only ones with the pointer			to the struct since the kernel thread not created yet			so no need to spinlock this init of tcpStatus */			srvTcp->tcpStatus = CifsNew;			init_MUTEX(&srvTcp->tcpSem);			srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");			if ( IS_ERR(srvTcp->tsk) ) {				rc = PTR_ERR(srvTcp->tsk);				cERROR(1, ("error %d create cifsd thread", rc));				srvTcp->tsk = NULL;				sock_release(csocket);				kfree(volume_info.UNC);				kfree(volume_info.password);				kfree(volume_info.prepath);				FreeXid(xid);				return rc;			}			wait_for_completion(&cifsd_complete);			rc = 0;			memcpy(srvTcp->workstation_RFC1001_name,				volume_info.source_rfc1001_name, 16);			memcpy(srvTcp->server_RFC1001_name,				volume_info.target_rfc1001_name, 16);			srvTcp->sequence_number = 0;		}	}	if (existingCifsSes) {		pSesInfo = existingCifsSes;		cFYI(1, ("Existing smb sess found"));		kfree(volume_info.password);		/* volume_info.UNC freed at end of function */	} else if (!rc) {		cFYI(1, ("Existing smb sess not found"));		pSesInfo = sesInfoAlloc();		if (pSesInfo == NULL)			rc = -ENOMEM;		else {			pSesInfo->server = srvTcp;			sprintf(pSesInfo->serverName, "%u.%u.%u.%u",				NIPQUAD(sin_server.sin_addr.s_addr));		}		if (!rc) {			/* volume_info.password freed at unmount */			if (volume_info.password)				pSesInfo->password = volume_info.password;			if (volume_info.username)				strncpy(pSesInfo->userName,					volume_info.username,					MAX_USERNAME_SIZE);			if (volume_info.domainname) {				int len = strlen(volume_info.domainname);				pSesInfo->domainName =					kmalloc(len + 1, GFP_KERNEL);				if (pSesInfo->domainName)					strcpy(pSesInfo->domainName,						volume_info.domainname);			}			pSesInfo->linux_uid = volume_info.linux_uid;			pSesInfo->overrideSecFlg = volume_info.secFlg;			down(&pSesInfo->sesSem);			/* BB FIXME need to pass vol->secFlgs BB */			rc = cifs_setup_session(xid, pSesInfo,						cifs_sb->local_nls);			up(&pSesInfo->sesSem);			if (!rc)				atomic_inc(&srvTcp->socketUseCount);		} else			kfree(volume_info.password);	}	/* search for existing tcon to this server share */	if (!rc) {		if (volume_info.rsize > CIFSMaxBufSize) {			cERROR(1, ("rsize %d too large, using MaxBufSize",				volume_info.rsize));			cifs_sb->rsize = CIFSMaxBufSize;		} else if ((volume_info.rsize) &&				(volume_info.rsize <= CIFSMaxBufSize))			cifs_sb->rsize = volume_info.rsize;		else /* default */			cifs_sb->rsize = CIFSMaxBufSize;		if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {			cERROR(1, ("wsize %d too large, using 4096 instead",				  volume_info.wsize));			cifs_sb->wsize = 4096;		} else if (volume_info.wsize)			cifs_sb->wsize = volume_info.wsize;		else			cifs_sb->wsize =				min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,					127*1024);			/* old default of CIFSMaxBufSize was too small now			   that SMB Write2 can send multiple pages in kvec.			   RFC1001 does not describe what happens when frame			   bigger than 128K is sent so use that as max in			   conjunction with 52K kvec constraint on arch with 4K			   page size  */		if (cifs_sb->rsize < 2048) {			cifs_sb->rsize = 2048;			/* Windows ME may prefer this */			cFYI(1, ("readsize set to minimum: 2048"));		}		/* calculate prepath */		cifs_sb->prepath = volume_info.prepath;		if (cifs_sb->prepath) {			cifs_sb->prepathlen = strlen(cifs_sb->prepath);			cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);			volume_info.prepath = NULL;		} else			cifs_sb->prepathlen = 0;		cifs_sb->mnt_uid = volume_info.linux_uid;		cifs_sb->mnt_gid = volume_info.linux_gid;		cifs_sb->mnt_file_mode = volume_info.file_mode;		cifs_sb->mnt_dir_mode = volume_info.dir_mode;		cFYI(1, ("file mode: 0x%x  dir mode: 0x%x",			cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));		if (volume_info.noperm)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;		if (volume_info.setuids)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;		if (volume_info.server_ino)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;		if (volume_info.remap)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;		if (volume_info.no_xattr)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;		if (volume_info.sfu_emul)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;		if (volume_info.nobrl)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;		if (volume_info.cifs_acl)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;		if (volume_info.override_uid)			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;		if (volume_info.override_gid)			cifs_sb->mnt_cifs_flags

⌨️ 快捷键说明

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