Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e14e833 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  prevent cifs_writepages() from skipping unwritten pages
  Fixed parsing of mount options when doing DFS submount
  [CIFS] Fix check for tcon seal setting and fix oops on failed mount from earlier patch
  [CIFS] Fix build break
  cifs: reinstate sharing of tree connections
  [CIFS] minor cleanup to cifs_mount
  cifs: reinstate sharing of SMB sessions sans races
  cifs: disable sharing session and tcon and add new TCP sharing code
  [CIFS] clean up server protocol handling
  [CIFS] remove unused list, add new cifs sock list to prepare for mount/umount fix
  [CIFS] Fix cifs reconnection flags
  [CIFS] Can't rely on iov length and base when kernel_recvmsg returns error
parents 65ecc14a b066a48c
Loading
Loading
Loading
Loading
+149 −128
Original line number Diff line number Diff line
@@ -107,12 +107,13 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
#ifdef CONFIG_PROC_FS
static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
{
	struct list_head *tmp;
	struct list_head *tmp1;
	struct list_head *tmp1, *tmp2, *tmp3;
	struct mid_q_entry *mid_entry;
	struct TCP_Server_Info *server;
	struct cifsSesInfo *ses;
	struct cifsTconInfo *tcon;
	int i;
	int i, j;
	__u32 dev_type;

	seq_puts(m,
		    "Display Internal CIFS Data Structures for Debugging\n"
@@ -122,77 +123,55 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
	seq_printf(m, "Servers:");

	i = 0;
	read_lock(&GlobalSMBSeslock);
	list_for_each(tmp, &GlobalSMBSessionList) {
	read_lock(&cifs_tcp_ses_lock);
	list_for_each(tmp1, &cifs_tcp_ses_list) {
		server = list_entry(tmp1, struct TCP_Server_Info,
				    tcp_ses_list);
		i++;
		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
		if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
		list_for_each(tmp2, &server->smb_ses_list) {
			ses = list_entry(tmp2, struct cifsSesInfo,
					 smb_ses_list);
			if ((ses->serverDomain == NULL) ||
				(ses->serverOS == NULL) ||
				(ses->serverNOS == NULL)) {
			seq_printf(m, "\nentry for %s not fully "
					"displayed\n\t", ses->serverName);
				seq_printf(m, "\n%d) entry for %s not fully "
					   "displayed\n\t", i, ses->serverName);
			} else {
				seq_printf(m,
				    "\n%d) Name: %s  Domain: %s Mounts: %d OS:"
				    "\n%d) Name: %s  Domain: %s Uses: %d OS:"
				    " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB"
				    " session status: %d\t",
				i, ses->serverName, ses->serverDomain,
				atomic_read(&ses->inUse),
				ses->serverOS, ses->serverNOS,
				ses->ses_count, ses->serverOS, ses->serverNOS,
				ses->capabilities, ses->status);
			}
		if (ses->server) {
			seq_printf(m, "TCP status: %d\n\tLocal Users To "
				   "Server: %d SecMode: 0x%x Req On Wire: %d",
				ses->server->tcpStatus,
				atomic_read(&ses->server->socketUseCount),
				ses->server->secMode,
				atomic_read(&ses->server->inFlight));
				   server->tcpStatus, server->srv_count,
				   server->secMode,
				   atomic_read(&server->inFlight));

#ifdef CONFIG_CIFS_STATS2
			seq_printf(m, " In Send: %d In MaxReq Wait: %d",
				atomic_read(&ses->server->inSend),
				atomic_read(&ses->server->num_waiters));
				atomic_read(&server->inSend),
				atomic_read(&server->num_waiters));
#endif

			seq_puts(m, "\nMIDs:\n");

			spin_lock(&GlobalMid_Lock);
			list_for_each(tmp1, &ses->server->pending_mid_q) {
				mid_entry = list_entry(tmp1, struct
					mid_q_entry,
					qhead);
				seq_printf(m, "State: %d com: %d pid:"
						" %d tsk: %p mid %d\n",
						mid_entry->midState,
						(int)mid_entry->command,
						mid_entry->pid,
						mid_entry->tsk,
						mid_entry->mid);
			}
			spin_unlock(&GlobalMid_Lock);
		}

	}
	read_unlock(&GlobalSMBSeslock);
	seq_putc(m, '\n');

	seq_puts(m, "Shares:");

	i = 0;
	read_lock(&GlobalSMBSeslock);
	list_for_each(tmp, &GlobalTreeConnectionList) {
		__u32 dev_type;
		i++;
		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
			seq_puts(m, "\n\tShares:");
			j = 0;
			list_for_each(tmp3, &ses->tcon_list) {
				tcon = list_entry(tmp3, struct cifsTconInfo,
						  tcon_list);
				++j;
				dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
		seq_printf(m, "\n%d) %s Uses: %d ", i,
				 tcon->treeName, atomic_read(&tcon->useCount));
				seq_printf(m, "\n\t%d) %s Mounts: %d ", j,
					   tcon->treeName, tcon->tc_count);
				if (tcon->nativeFileSystem) {
					seq_printf(m, "Type: %s ",
						   tcon->nativeFileSystem);
				}
				seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
				 "\nPathComponentMax: %d Status: %d",
					"\nPathComponentMax: %d Status: 0x%d",
					le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
					le32_to_cpu(tcon->fsAttrInfo.Attributes),
					le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
@@ -204,11 +183,29 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
				else
					seq_printf(m, " type: %d ", dev_type);

		if (tcon->tidStatus == CifsNeedReconnect)
				if (tcon->need_reconnect)
					seq_puts(m, "\tDISCONNECTED ");
				seq_putc(m, '\n');
			}
	read_unlock(&GlobalSMBSeslock);

			seq_puts(m, "\n\tMIDs:\n");

			spin_lock(&GlobalMid_Lock);
			list_for_each(tmp3, &server->pending_mid_q) {
				mid_entry = list_entry(tmp3, struct mid_q_entry,
					qhead);
				seq_printf(m, "\tState: %d com: %d pid:"
						" %d tsk: %p mid %d\n",
						mid_entry->midState,
						(int)mid_entry->command,
						mid_entry->pid,
						mid_entry->tsk,
						mid_entry->mid);
			}
			spin_unlock(&GlobalMid_Lock);
		}
	}
	read_unlock(&cifs_tcp_ses_lock);
	seq_putc(m, '\n');

	/* BB add code to dump additional info such as TCP session info now */
@@ -234,7 +231,9 @@ static ssize_t cifs_stats_proc_write(struct file *file,
{
	char c;
	int rc;
	struct list_head *tmp;
	struct list_head *tmp1, *tmp2, *tmp3;
	struct TCP_Server_Info *server;
	struct cifsSesInfo *ses;
	struct cifsTconInfo *tcon;

	rc = get_user(c, buffer);
@@ -242,14 +241,21 @@ static ssize_t cifs_stats_proc_write(struct file *file,
		return rc;

	if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
		read_lock(&GlobalSMBSeslock);
#ifdef CONFIG_CIFS_STATS2
		atomic_set(&totBufAllocCount, 0);
		atomic_set(&totSmBufAllocCount, 0);
#endif /* CONFIG_CIFS_STATS2 */
		list_for_each(tmp, &GlobalTreeConnectionList) {
			tcon = list_entry(tmp, struct cifsTconInfo,
					cifsConnectionList);
		read_lock(&cifs_tcp_ses_lock);
		list_for_each(tmp1, &cifs_tcp_ses_list) {
			server = list_entry(tmp1, struct TCP_Server_Info,
					    tcp_ses_list);
			list_for_each(tmp2, &server->smb_ses_list) {
				ses = list_entry(tmp2, struct cifsSesInfo,
						 smb_ses_list);
				list_for_each(tmp3, &ses->tcon_list) {
					tcon = list_entry(tmp3,
							  struct cifsTconInfo,
							  tcon_list);
					atomic_set(&tcon->num_smbs_sent, 0);
					atomic_set(&tcon->num_writes, 0);
					atomic_set(&tcon->num_reads, 0);
@@ -268,7 +274,9 @@ static ssize_t cifs_stats_proc_write(struct file *file,
					atomic_set(&tcon->num_symlinks, 0);
					atomic_set(&tcon->num_locks, 0);
				}
		read_unlock(&GlobalSMBSeslock);
			}
		}
		read_unlock(&cifs_tcp_ses_lock);
	}

	return count;
@@ -277,7 +285,9 @@ static ssize_t cifs_stats_proc_write(struct file *file,
static int cifs_stats_proc_show(struct seq_file *m, void *v)
{
	int i;
	struct list_head *tmp;
	struct list_head *tmp1, *tmp2, *tmp3;
	struct TCP_Server_Info *server;
	struct cifsSesInfo *ses;
	struct cifsTconInfo *tcon;

	seq_printf(m,
@@ -306,12 +316,20 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
		GlobalCurrentXid, GlobalMaxActiveXid);

	i = 0;
	read_lock(&GlobalSMBSeslock);
	list_for_each(tmp, &GlobalTreeConnectionList) {
	read_lock(&cifs_tcp_ses_lock);
	list_for_each(tmp1, &cifs_tcp_ses_list) {
		server = list_entry(tmp1, struct TCP_Server_Info,
				    tcp_ses_list);
		list_for_each(tmp2, &server->smb_ses_list) {
			ses = list_entry(tmp2, struct cifsSesInfo,
					 smb_ses_list);
			list_for_each(tmp3, &ses->tcon_list) {
				tcon = list_entry(tmp3,
						  struct cifsTconInfo,
						  tcon_list);
				i++;
		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
				seq_printf(m, "\n%d) %s", i, tcon->treeName);
		if (tcon->tidStatus == CifsNeedReconnect)
				if (tcon->need_reconnect)
					seq_puts(m, "\tDISCONNECTED ");
				seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
					atomic_read(&tcon->num_smbs_sent),
@@ -322,13 +340,13 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
				seq_printf(m, "\nWrites: %d Bytes: %lld",
					atomic_read(&tcon->num_writes),
					(long long)(tcon->bytes_written));
		seq_printf(m,
			"\nLocks: %d HardLinks: %d Symlinks: %d",
				seq_printf(m, "\nLocks: %d HardLinks: %d "
					      "Symlinks: %d",
					atomic_read(&tcon->num_locks),
					atomic_read(&tcon->num_hardlinks),
					atomic_read(&tcon->num_symlinks));

		seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
				seq_printf(m, "\nOpens: %d Closes: %d"
					      "Deletes: %d",
					atomic_read(&tcon->num_opens),
					atomic_read(&tcon->num_closes),
					atomic_read(&tcon->num_deletes));
@@ -338,12 +356,15 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
				seq_printf(m, "\nRenames: %d T2 Renames %d",
					atomic_read(&tcon->num_renames),
					atomic_read(&tcon->num_t2renames));
		seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
				seq_printf(m, "\nFindFirst: %d FNext %d "
					      "FClose %d",
					atomic_read(&tcon->num_ffirst),
					atomic_read(&tcon->num_fnext),
					atomic_read(&tcon->num_fclose));
			}
	read_unlock(&GlobalSMBSeslock);
		}
	}
	read_unlock(&cifs_tcp_ses_lock);

	seq_putc(m, '\n');
	return 0;
+47 −24
Original line number Diff line number Diff line
@@ -106,7 +106,8 @@ static char *cifs_get_share_name(const char *node_name)
/**
 * compose_mount_options	-	creates mount options for refferral
 * @sb_mountdata:	parent/root DFS mount options (template)
 * @ref_unc:		refferral server UNC
 * @dentry:		point where we are going to mount
 * @ref:		server's referral
 * @devname:		pointer for saving device name
 *
 * creates mount options for submount based on template options sb_mountdata
@@ -116,7 +117,8 @@ static char *cifs_get_share_name(const char *node_name)
 * Caller is responcible for freeing retunrned value if it is not error.
 */
static char *compose_mount_options(const char *sb_mountdata,
				   const char *ref_unc,
				   struct dentry *dentry,
				   const struct dfs_info3_param *ref,
				   char **devname)
{
	int rc;
@@ -126,11 +128,12 @@ static char *compose_mount_options(const char *sb_mountdata,
	char *srvIP = NULL;
	char sep = ',';
	int off, noff;
	char *fullpath;

	if (sb_mountdata == NULL)
		return ERR_PTR(-EINVAL);

	*devname = cifs_get_share_name(ref_unc);
	*devname = cifs_get_share_name(ref->node_name);
	rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
	if (rc != 0) {
		cERROR(1, ("%s: Failed to resolve server part of %s to IP",
@@ -138,7 +141,12 @@ static char *compose_mount_options(const char *sb_mountdata,
		mountdata = ERR_PTR(rc);
		goto compose_mount_options_out;
	}
	md_len = strlen(sb_mountdata) + strlen(srvIP) + strlen(ref_unc) + 3;
	/* md_len = strlen(...) + 12 for 'sep+prefixpath='
	 * assuming that we have 'unc=' and 'ip=' in
	 * the original sb_mountdata
	 */
	md_len = strlen(sb_mountdata) + strlen(srvIP) +
		strlen(ref->node_name) + 12;
	mountdata = kzalloc(md_len+1, GFP_KERNEL);
	if (mountdata == NULL) {
		mountdata = ERR_PTR(-ENOMEM);
@@ -152,8 +160,14 @@ static char *compose_mount_options(const char *sb_mountdata,
			strncpy(mountdata, sb_mountdata, 5);
			off += 5;
	}
	while ((tkn_e = strchr(sb_mountdata+off, sep))) {
		noff = (tkn_e - (sb_mountdata+off)) + 1;

	do {
		tkn_e = strchr(sb_mountdata + off, sep);
		if (tkn_e == NULL)
			noff = strlen(sb_mountdata + off);
		else
			noff = tkn_e - (sb_mountdata + off) + 1;

		if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) {
			off += noff;
			continue;
@@ -162,31 +176,40 @@ static char *compose_mount_options(const char *sb_mountdata,
			off += noff;
			continue;
		}
		if (strnicmp(sb_mountdata+off, "prefixpath=", 3) == 0) {
		if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
			off += noff;
			continue;
		}
		strncat(mountdata, sb_mountdata + off, noff);
		off += noff;
	}
	} while (tkn_e);
	strcat(mountdata, sb_mountdata + off);
	mountdata[md_len] = '\0';

	/* copy new IP and ref share name */
	strcat(mountdata, ",ip=");
	if (mountdata[strlen(mountdata) - 1] != sep)
		strncat(mountdata, &sep, 1);
	strcat(mountdata, "ip=");
	strcat(mountdata, srvIP);
	strcat(mountdata, ",unc=");
	strncat(mountdata, &sep, 1);
	strcat(mountdata, "unc=");
	strcat(mountdata, *devname);

	/* find & copy prefixpath */
	tkn_e = strchr(ref_unc+2, '\\');
	if (tkn_e) {
	tkn_e = strchr(ref->node_name + 2, '\\');
	if (tkn_e == NULL) /* invalid unc, missing share name*/
		goto compose_mount_options_out;

	fullpath = build_path_from_dentry(dentry);
	tkn_e = strchr(tkn_e + 1, '\\');
		if (tkn_e) {
			strcat(mountdata, ",prefixpath=");
	if (tkn_e || strlen(fullpath) - (ref->path_consumed)) {
		strncat(mountdata, &sep, 1);
		strcat(mountdata, "prefixpath=");
		if (tkn_e)
			strcat(mountdata, tkn_e + 1);
		strcat(mountdata, fullpath + (ref->path_consumed));
	}
	}
	kfree(fullpath);

	/*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
	/*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
@@ -198,7 +221,7 @@ static char *compose_mount_options(const char *sb_mountdata,


static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
		struct dentry *dentry, char *ref_unc)
		struct dentry *dentry, const struct dfs_info3_param *ref)
{
	struct cifs_sb_info *cifs_sb;
	struct vfsmount *mnt;
@@ -207,7 +230,7 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,

	cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
	mountdata = compose_mount_options(cifs_sb->mountdata,
						ref_unc, &devname);
						dentry, ref, &devname);

	if (IS_ERR(mountdata))
		return (struct vfsmount *)mountdata;
@@ -310,7 +333,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
			}
			mnt = cifs_dfs_do_refmount(nd->path.mnt,
						nd->path.dentry,
						referrals[i].node_name);
						referrals + i);
			cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
					 __func__,
					referrals[i].node_name, mnt));
+2 −2
Original line number Diff line number Diff line
@@ -73,8 +73,8 @@ struct key_type cifs_spnego_key_type = {
 * strlen(";sec=ntlmsspi") */
#define MAX_MECH_STR_LEN	13

/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */
#define MAX_IPV6_ADDR_LEN	42
/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */
#define MAX_IPV6_ADDR_LEN	43

/* strlen of "host=" */
#define HOST_KEY_LEN		5
+15 −15
Original line number Diff line number Diff line
@@ -514,10 +514,11 @@ static void cifs_umount_begin(struct super_block *sb)
	tcon = cifs_sb->tcon;
	if (tcon == NULL)
		return;
	down(&tcon->tconSem);
	if (atomic_read(&tcon->useCount) == 1)

	read_lock(&cifs_tcp_ses_lock);
	if (tcon->tc_count == 1)
		tcon->tidStatus = CifsExiting;
	up(&tcon->tconSem);
	read_unlock(&cifs_tcp_ses_lock);

	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
	/* cancel_notify_requests(tcon); */
@@ -1013,7 +1014,7 @@ static int cifs_oplock_thread(void *dummyarg)
				not bother sending an oplock release if session
				to server still is disconnected since oplock
				already released by the server in that case */
			if (pTcon->tidStatus != CifsNeedReconnect) {
			if (!pTcon->need_reconnect) {
				rc = CIFSSMBLock(0, pTcon, netfid,
						0 /* len */ , 0 /* offset */, 0,
						0, LOCKING_ANDX_OPLOCK_RELEASE,
@@ -1031,24 +1032,24 @@ static int cifs_oplock_thread(void *dummyarg)
static int cifs_dnotify_thread(void *dummyarg)
{
	struct list_head *tmp;
	struct cifsSesInfo *ses;
	struct TCP_Server_Info *server;

	do {
		if (try_to_freeze())
			continue;
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(15*HZ);
		read_lock(&GlobalSMBSeslock);
		/* check if any stuck requests that need
		   to be woken up and wakeq so the
		   thread can wake up and error out */
		list_for_each(tmp, &GlobalSMBSessionList) {
			ses = list_entry(tmp, struct cifsSesInfo,
				cifsSessionList);
			if (ses->server && atomic_read(&ses->server->inFlight))
				wake_up_all(&ses->server->response_q);
		}
		read_unlock(&GlobalSMBSeslock);
		read_lock(&cifs_tcp_ses_lock);
		list_for_each(tmp, &cifs_tcp_ses_list) {
			server = list_entry(tmp, struct TCP_Server_Info,
					 tcp_ses_list);
			if (atomic_read(&server->inFlight))
				wake_up_all(&server->response_q);
		}
		read_unlock(&cifs_tcp_ses_lock);
	} while (!kthread_should_stop());

	return 0;
@@ -1059,9 +1060,7 @@ init_cifs(void)
{
	int rc = 0;
	cifs_proc_init();
/*	INIT_LIST_HEAD(&GlobalServerList);*/	/* BB not implemented yet */
	INIT_LIST_HEAD(&GlobalSMBSessionList);
	INIT_LIST_HEAD(&GlobalTreeConnectionList);
	INIT_LIST_HEAD(&cifs_tcp_ses_list);
	INIT_LIST_HEAD(&GlobalOplock_Q);
#ifdef CONFIG_CIFS_EXPERIMENTAL
	INIT_LIST_HEAD(&GlobalDnotifyReqList);
@@ -1089,6 +1088,7 @@ init_cifs(void)
	GlobalMaxActiveXid = 0;
	memset(Local_System_Name, 0, 15);
	rwlock_init(&GlobalSMBSeslock);
	rwlock_init(&cifs_tcp_ses_lock);
	spin_lock_init(&GlobalMid_Lock);

	if (cifs_max_pending < 2) {
+22 −19
Original line number Diff line number Diff line
@@ -85,8 +85,7 @@ enum securityEnum {
};

enum protocolEnum {
	IPV4 = 0,
	IPV6,
	TCP = 0,
	SCTP
	/* Netbios frames protocol not supported at this time */
};
@@ -122,6 +121,9 @@ struct cifs_cred {
 */

struct TCP_Server_Info {
	struct list_head tcp_ses_list;
	struct list_head smb_ses_list;
	int srv_count; /* reference counter */
	/* 15 character server name + 0x20 16th byte indicating type = srv */
	char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
	char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
@@ -143,7 +145,6 @@ struct TCP_Server_Info {
	bool svlocal:1;			/* local server or remote */
	bool noblocksnd;		/* use blocking sendmsg */
	bool noautotune;		/* do not autotune send buf sizes */
	atomic_t socketUseCount; /* number of open cifs sessions on socket */
	atomic_t inFlight;  /* number of requests on the wire to server */
#ifdef CONFIG_CIFS_STATS2
	atomic_t inSend; /* requests trying to send */
@@ -194,13 +195,14 @@ struct cifsUidInfo {
 * Session structure.  One of these for each uid session with a particular host
 */
struct cifsSesInfo {
	struct list_head cifsSessionList;
	struct list_head smb_ses_list;
	struct list_head tcon_list;
	struct semaphore sesSem;
#if 0
	struct cifsUidInfo *uidInfo;	/* pointer to user info */
#endif
	struct TCP_Server_Info *server;	/* pointer to server info */
	atomic_t inUse; /* # of mounts (tree connections) on this ses */
	int ses_count;		/* reference counter */
	enum statusEnum status;
	unsigned overrideSecFlg;  /* if non-zero override global sec flags */
	__u16 ipc_tid;		/* special tid for connection to IPC share */
@@ -216,6 +218,7 @@ struct cifsSesInfo {
	char userName[MAX_USERNAME_SIZE + 1];
	char *domainName;
	char *password;
	bool need_reconnect:1; /* connection reset, uid now invalid */
};
/* no more than one of the following three session flags may be set */
#define CIFS_SES_NT4 1
@@ -230,16 +233,15 @@ struct cifsSesInfo {
 * session
 */
struct cifsTconInfo {
	struct list_head cifsConnectionList;
	struct list_head tcon_list;
	int tc_count;
	struct list_head openFileList;
	struct semaphore tconSem;
	struct cifsSesInfo *ses;	/* pointer to session associated with */
	char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
	char *nativeFileSystem;
	__u16 tid;		/* The 2 byte tree id */
	__u16 Flags;		/* optional support bits */
	enum statusEnum tidStatus;
	atomic_t useCount;	/* how many explicit/implicit mounts to share */
#ifdef CONFIG_CIFS_STATS
	atomic_t num_smbs_sent;
	atomic_t num_writes;
@@ -288,6 +290,7 @@ struct cifsTconInfo {
	bool unix_ext:1;  /* if false disable Linux extensions to CIFS protocol
				for this mount even if server would support */
	bool local_lease:1; /* check leases (only) on local system not remote */
	bool need_reconnect:1; /* connection reset, tid now invalid */
	/* BB add field for back pointer to sb struct(s)? */
};

@@ -588,21 +591,21 @@ require use of the stronger protocol */
#endif

/*
 * The list of servers that did not respond with NT LM 0.12.
 * This list helps improve performance and eliminate the messages indicating
 * that we had a communications error talking to the server in this list.
 * the list of TCP_Server_Info structures, ie each of the sockets
 * connecting our client to a distinct server (ip address), is
 * chained together by cifs_tcp_ses_list. The list of all our SMB
 * sessions (and from that the tree connections) can be found
 * by iterating over cifs_tcp_ses_list
 */
/* Feature not supported */
/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
GLOBAL_EXTERN struct list_head		cifs_tcp_ses_list;

/*
 * The following is a hash table of all the users we know about.
 * This lock protects the cifs_tcp_ses_list, the list of smb sessions per
 * tcp session, and the list of tcon's per smb session. It also protects
 * the reference counters for the server, smb session, and tcon. Finally,
 * changes to the tcon->tidStatus should be done while holding this lock.
 */
GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];

/* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */
GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
GLOBAL_EXTERN rwlock_t		cifs_tcp_ses_lock;
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;  /* protects list inserts on 3 above */

GLOBAL_EXTERN struct list_head GlobalOplock_Q;
Loading