public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: Justin Forbes <jmforbes@linuxtx.org>,
	Zwane Mwaikambo <zwane@arm.linux.org.uk>,
	"Theodore Ts'o" <tytso@mit.edu>,
	Randy Dunlap <rdunlap@xenotime.net>,
	Dave Jones <davej@redhat.com>,
	Chuck Wolber <chuckw@quantumlinux.com>,
	Chris Wedgwood <reviews@ml.cw.f00f.org>,
	Michael Krufky <mkrufky@linuxtv.org>,
	Chuck Ebbert <cebbert@redhat.com>,
	Domenico Andreoli <cavokz@gmail.com>, Willy Tarreau <w@1wt.eu>,
	Rodrigo Rubira Branco <rbranco@la.checkpoint.com>,
	Jake Edge <jake@lwn.net>, Eugene Teo <eteo@redhat.com>,
	torvalds@linux-foundation.org, akpm@linux-foundation.org,
	alan@lxorguk.ukuu.org.uk, Steve French <smfrench@gmail.com>,
	Jeff Layton <jlayton@redhat.com>,
	Steve French <sfrench@us.ibm.com>,
	Suresh Jayaraman <sjayaraman@suse.de>
Subject: [patch 072/104] cifs: reinstate sharing of SMB sessions sans races
Date: Wed, 3 Dec 2008 11:53:34 -0800	[thread overview]
Message-ID: <20081203195334.GU8950@kroah.com> (raw)
In-Reply-To: <20081203194725.GA8950@kroah.com>

[-- Attachment #1: cifs-reinstate-sharing-of-smb-sessions-sans-races.patch --]
[-- Type: text/plain, Size: 20786 bytes --]

2.6.27-stable review patch.  If anyone has any objections, please let us know.

------------------
From: Jeff Layton <jlayton@redhat.com>

commit 14fbf50d695207754daeb96270b3027a3821121f upstream

We do this by abandoning the global list of SMB sessions and instead
moving to a per-server list. This entails adding a new list head to the
TCP_Server_Info struct. The refcounting for the cifsSesInfo is moved to
a non-atomic variable. We have to protect it by a lock anyway, so there's
no benefit to making it an atomic. The list and refcount are protected
by the global cifs_tcp_ses_lock.

The patch also adds a new routines to find and put SMB sessions and
that properly take and put references under the lock.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Cc: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 fs/cifs/cifs_debug.c |   53 ++++++------
 fs/cifs/cifsfs.c     |   17 +--
 fs/cifs/cifsglob.h   |    6 -
 fs/cifs/cifsproto.h  |    1 
 fs/cifs/cifssmb.c    |   22 +---
 fs/cifs/connect.c    |  225 ++++++++++++++++++++++++++++-----------------------
 fs/cifs/misc.c       |   16 +--
 7 files changed, 174 insertions(+), 166 deletions(-)

--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -107,9 +107,9 @@ void cifs_dump_mids(struct TCP_Server_In
 #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 *tmp, *tmp2, *tmp3;
 	struct mid_q_entry *mid_entry;
+	struct TCP_Server_Info *server;
 	struct cifsSesInfo *ses;
 	struct cifsTconInfo *tcon;
 	int i;
@@ -122,43 +122,45 @@ static int cifs_debug_data_proc_show(str
 	seq_printf(m, "Servers:");
 
 	i = 0;
-	read_lock(&GlobalSMBSeslock);
-	list_for_each(tmp, &GlobalSMBSessionList) {
+	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);
 		i++;
-		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
-		if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
-		   (ses->serverNOS == NULL)) {
-			seq_printf(m, "\nentry for %s not fully "
-					"displayed\n\t", ses->serverName);
-		} else {
-			seq_printf(m,
+		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);
+			} else {
+				seq_printf(m,
 				    "\n%d) Name: %s  Domain: %s Mounts: %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,
-				ses->server->srv_count,
-				ses->server->secMode,
-				atomic_read(&ses->server->inFlight));
+				   "Server: %d SecMode: 0x%x Req On Wire: %d",
+				   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
+			list_for_each(tmp3, &server->pending_mid_q) {
+				mid_entry = list_entry(tmp3, struct
 					mid_q_entry,
 					qhead);
 				seq_printf(m, "State: %d com: %d pid:"
@@ -171,9 +173,8 @@ static int cifs_debug_data_proc_show(str
 			}
 			spin_unlock(&GlobalMid_Lock);
 		}
-
 	}
-	read_unlock(&GlobalSMBSeslock);
+	read_unlock(&cifs_tcp_ses_lock);
 	seq_putc(m, '\n');
 
 	seq_puts(m, "Shares:");
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -985,24 +985,24 @@ static int cifs_oplock_thread(void *dumm
 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_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(&GlobalSMBSeslock);
+		read_unlock(&cifs_tcp_ses_lock);
 	} while (!kthread_should_stop());
 
 	return 0;
@@ -1014,7 +1014,6 @@ init_cifs(void)
 	int rc = 0;
 	cifs_proc_init();
 	INIT_LIST_HEAD(&cifs_tcp_ses_list);
-	INIT_LIST_HEAD(&GlobalSMBSessionList); /* BB to be removed by jl */
 	INIT_LIST_HEAD(&GlobalTreeConnectionList); /* BB to be removed by jl */
 	INIT_LIST_HEAD(&GlobalOplock_Q);
 #ifdef CONFIG_CIFS_EXPERIMENTAL
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -195,14 +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 */
@@ -600,8 +600,6 @@ GLOBAL_EXTERN struct list_head		cifs_tcp
 
 /* protects cifs_tcp_ses_list and srv_count for each tcp session */
 GLOBAL_EXTERN rwlock_t		cifs_tcp_ses_lock;
-
-GLOBAL_EXTERN struct list_head GlobalSMBSessionList; /* BB to be removed by jl*/
 GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; /* BB to be removed */
 GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;  /* protects list inserts on 3 above */
 
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -102,7 +102,6 @@ extern void acl_to_uid_mode(struct inode
 			    const __u16 *pfid);
 extern int mode_to_acl(struct inode *inode, const char *path, __u64);
 
-extern void cifs_put_tcp_session(struct TCP_Server_Info *server);
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
 			const char *);
 extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -799,20 +799,16 @@ CIFSSMBLogoff(const int xid, struct cifs
 	int rc = 0;
 
 	cFYI(1, ("In SMBLogoff for session disconnect"));
-	if (ses)
-		down(&ses->sesSem);
-	else
-		return -EIO;
-
-	atomic_dec(&ses->inUse);
-	if (atomic_read(&ses->inUse) > 0) {
-		up(&ses->sesSem);
-		return -EBUSY;
-	}
 
-	if (ses->server == NULL)
+	/*
+	 * BB: do we need to check validity of ses and server? They should
+	 * always be valid since we have an active reference. If not, that
+	 * should probably be a BUG()
+	 */
+	if (!ses || !ses->server)
 		return -EIO;
 
+	down(&ses->sesSem);
 	if (ses->need_reconnect)
 		goto session_already_dead; /* no need to send SMBlogoff if uid
 					      already closed due to reconnect */
@@ -833,10 +829,6 @@ CIFSSMBLogoff(const int xid, struct cifs
 	pSMB->AndXCommand = 0xFF;
 	rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
 session_already_dead:
-	if (ses->server) {
-		cifs_put_tcp_session(ses->server);
-		rc = 0;
-	}
 	up(&ses->sesSem);
 
 	/* if session dead then we do not need to do ulogoff,
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -142,23 +142,18 @@ cifs_reconnect(struct TCP_Server_Info *s
 
 	/* before reconnecting the tcp session, mark the smb session (uid)
 		and the tid bad so they are not used until reconnected */
-	read_lock(&GlobalSMBSeslock);
-	list_for_each(tmp, &GlobalSMBSessionList) {
-		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
-		if (ses->server) {
-			if (ses->server == server) {
-				ses->need_reconnect = true;
-				ses->ipc_tid = 0;
-			}
-		}
-		/* else tcp and smb sessions need reconnection */
+	read_lock(&cifs_tcp_ses_lock);
+	list_for_each(tmp, &server->smb_ses_list) {
+		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+		ses->need_reconnect = true;
+		ses->ipc_tid = 0;
 	}
+	read_unlock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &GlobalTreeConnectionList) {
 		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
 		if ((tcon->ses) && (tcon->ses->server == server))
 			tcon->need_reconnect = true;
 	}
-	read_unlock(&GlobalSMBSeslock);
 	/* do not want to be sending data on a socket we are freeing */
 	down(&server->tcpSem);
 	if (server->ssocket) {
@@ -702,29 +697,29 @@ multi_t2_fnd:
 	if (smallbuf) /* no sense logging a debug message if NULL */
 		cifs_small_buf_release(smallbuf);
 
-	read_lock(&GlobalSMBSeslock);
+	/*
+	 * BB: we shouldn't have to do any of this. It shouldn't be
+	 * possible to exit from the thread with active SMB sessions
+	 */
+	read_lock(&cifs_tcp_ses_lock);
 	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;
-			}
+		list_for_each(tmp, &server->smb_ses_list) {
+			ses = list_entry(tmp, struct cifsSesInfo,
+					 smb_ses_list);
+			ses->status = CifsExiting;
+			ses->server = NULL;
 		}
-		read_unlock(&GlobalSMBSeslock);
+		read_unlock(&cifs_tcp_ses_lock);
 	} 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) {
+		list_for_each(tmp, &server->smb_ses_list) {
 			ses = list_entry(tmp, struct cifsSesInfo,
-					 cifsSessionList);
-			if (ses->server == server)
-				ses->status = CifsExiting;
+					 smb_ses_list);
+			ses->status = CifsExiting;
 		}
 
 		spin_lock(&GlobalMid_Lock);
@@ -739,7 +734,7 @@ multi_t2_fnd:
 			}
 		}
 		spin_unlock(&GlobalMid_Lock);
-		read_unlock(&GlobalSMBSeslock);
+		read_unlock(&cifs_tcp_ses_lock);
 		/* 1/8th of sec is more than enough time for them to exit */
 		msleep(125);
 	}
@@ -761,14 +756,13 @@ multi_t2_fnd:
 	if there are any pointing to this (e.g
 	if a crazy root user tried to kill cifsd
 	kernel thread explicitly this might happen) */
-	write_lock(&GlobalSMBSeslock);
-	list_for_each(tmp, &GlobalSMBSessionList) {
-		ses = list_entry(tmp, struct cifsSesInfo,
-				cifsSessionList);
-		if (ses->server == server)
-			ses->server = NULL;
+	/* BB: This shouldn't be necessary, see above */
+	read_lock(&cifs_tcp_ses_lock);
+	list_for_each(tmp, &server->smb_ses_list) {
+		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+		ses->server = NULL;
 	}
-	write_unlock(&GlobalSMBSeslock);
+	read_unlock(&cifs_tcp_ses_lock);
 
 	kfree(server->hostname);
 	kfree(server);
@@ -1390,7 +1384,7 @@ cifs_find_tcp_session(struct sockaddr *a
 	return NULL;
 }
 
-void
+static void
 cifs_put_tcp_session(struct TCP_Server_Info *server)
 {
 	struct task_struct *task;
@@ -1413,6 +1407,50 @@ cifs_put_tcp_session(struct TCP_Server_I
 		force_sig(SIGKILL, task);
 }
 
+static struct cifsSesInfo *
+cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
+{
+	struct list_head *tmp;
+	struct cifsSesInfo *ses;
+
+	write_lock(&cifs_tcp_ses_lock);
+	list_for_each(tmp, &server->smb_ses_list) {
+		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
+		if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
+			continue;
+
+		++ses->ses_count;
+		write_unlock(&cifs_tcp_ses_lock);
+		return ses;
+	}
+	write_unlock(&cifs_tcp_ses_lock);
+	return NULL;
+}
+
+static void
+cifs_put_smb_ses(struct cifsSesInfo *ses)
+{
+	int xid;
+	struct TCP_Server_Info *server = ses->server;
+
+	write_lock(&cifs_tcp_ses_lock);
+	if (--ses->ses_count > 0) {
+		write_unlock(&cifs_tcp_ses_lock);
+		return;
+	}
+
+	list_del_init(&ses->smb_ses_list);
+	write_unlock(&cifs_tcp_ses_lock);
+
+	if (ses->status == CifsGood) {
+		xid = GetXid();
+		CIFSSMBLogoff(xid, ses);
+		_FreeXid(xid);
+	}
+	sesInfoFree(ses);
+	cifs_put_tcp_session(server);
+}
+
 int
 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
 	     const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -1945,7 +1983,6 @@ cifs_mount(struct super_block *sb, struc
 	struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
 	struct smb_vol volume_info;
 	struct cifsSesInfo *pSesInfo = NULL;
-	struct cifsSesInfo *existingCifsSes = NULL;
 	struct cifsTconInfo *tcon = NULL;
 	struct TCP_Server_Info *srvTcp = NULL;
 
@@ -2099,6 +2136,7 @@ cifs_mount(struct super_block *sb, struc
 				volume_info.target_rfc1001_name, 16);
 			srvTcp->sequence_number = 0;
 			INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
+			INIT_LIST_HEAD(&srvTcp->smb_ses_list);
 			++srvTcp->srv_count;
 			write_lock(&cifs_tcp_ses_lock);
 			list_add(&srvTcp->tcp_ses_list,
@@ -2107,10 +2145,16 @@ cifs_mount(struct super_block *sb, struc
 		}
 	}
 
-	if (existingCifsSes) {
-		pSesInfo = existingCifsSes;
+	pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
+	if (pSesInfo) {
 		cFYI(1, ("Existing smb sess found (status=%d)",
 			pSesInfo->status));
+		/*
+		 * The existing SMB session already has a reference to srvTcp,
+		 * so we can put back the extra one we got before
+		 */
+		cifs_put_tcp_session(srvTcp);
+
 		down(&pSesInfo->sesSem);
 		if (pSesInfo->need_reconnect) {
 			cFYI(1, ("Session needs reconnect"));
@@ -2121,41 +2165,44 @@ cifs_mount(struct super_block *sb, struc
 	} else if (!rc) {
 		cFYI(1, ("Existing smb sess not found"));
 		pSesInfo = sesInfoAlloc();
-		if (pSesInfo == NULL)
+		if (pSesInfo == NULL) {
 			rc = -ENOMEM;
-		else {
-			pSesInfo->server = srvTcp;
-			sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
-				NIPQUAD(sin_server->sin_addr.s_addr));
+			goto mount_fail_check;
 		}
 
-		if (!rc) {
-			/* volume_info.password freed at unmount */
-			if (volume_info.password) {
-				pSesInfo->password = volume_info.password;
-				/* set to NULL to prevent freeing on exit */
-				volume_info.password = NULL;
-			}
-			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);
+		/* new SMB session uses our srvTcp ref */
+		pSesInfo->server = srvTcp;
+		sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
+			NIPQUAD(sin_server->sin_addr.s_addr));
+
+		write_lock(&cifs_tcp_ses_lock);
+		list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
+		write_unlock(&cifs_tcp_ses_lock);
+
+		/* volume_info.password freed at unmount */
+		if (volume_info.password) {
+			pSesInfo->password = volume_info.password;
+			/* set to NULL to prevent freeing on exit */
+			volume_info.password = NULL;
+		}
+		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);
 	}
 
 	/* search for existing tcon to this server share */
@@ -2190,11 +2237,9 @@ cifs_mount(struct super_block *sb, struc
 					      tcon, cifs_sb->local_nls);
 				cFYI(1, ("CIFS Tcon rc = %d", rc));
 			}
-			if (!rc) {
-				atomic_inc(&pSesInfo->inUse);
-				tcon->seal = volume_info.seal;
-			} else
+			if (rc)
 				goto mount_fail_check;
+			tcon->seal = volume_info.seal;
 		}
 
 		/* we can have only one retry value for a connection
@@ -2214,7 +2259,7 @@ cifs_mount(struct super_block *sb, struc
 	/* BB FIXME fix time_gran to be larger for LANMAN sessions */
 	sb->s_time_gran = 100;
 
-/* on error free sesinfo and tcon struct if needed */
+	/* on error free sesinfo and tcon struct if needed */
 mount_fail_check:
 	if (rc) {
 		 /* If find_unc succeeded then rc == 0 so we can not end */
@@ -2222,21 +2267,11 @@ mount_fail_check:
 		if (tcon)
 			tconInfoFree(tcon);
 
-		if (existingCifsSes == NULL) {
-			if (pSesInfo) {
-				if ((pSesInfo->server) &&
-				    (pSesInfo->status == CifsGood))
-					CIFSSMBLogoff(xid, pSesInfo);
-				else {
-					cFYI(1, ("No session or bad tcon"));
-				}
-					if (pSesInfo->server)
-						cifs_put_tcp_session(
-							pSesInfo->server);
-				sesInfoFree(pSesInfo);
-				/* pSesInfo = NULL; */
-			}
-		}
+		/* should also end up putting our tcp session ref if needed */
+		if (pSesInfo)
+			cifs_put_smb_ses(pSesInfo);
+		else
+			cifs_put_tcp_session(srvTcp);
 	} else {
 		atomic_inc(&tcon->useCount);
 		cifs_sb->tcon = tcon;
@@ -3532,17 +3567,7 @@ cifs_umount(struct super_block *sb, stru
 		}
 		DeleteTconOplockQEntries(cifs_sb->tcon);
 		tconInfoFree(cifs_sb->tcon);
-		if ((ses) && (ses->server)) {
-			/* save off task so we do not refer to ses later */
-			cifsd_task = ses->server->tsk;
-			cFYI(1, ("About to do SMBLogoff "));
-			rc = CIFSSMBLogoff(xid, ses);
-			if (rc == -EBUSY) {
-				FreeXid(xid);
-				return 0;
-			}
-		} else
-			cFYI(1, ("No session or bad tcon"));
+		cifs_put_smb_ses(ses);
 	}
 
 	cifs_sb->tcon = NULL;
@@ -3550,8 +3575,6 @@ cifs_umount(struct super_block *sb, stru
 	cifs_sb->prepathlen = 0;
 	cifs_sb->prepath = NULL;
 	kfree(tmp);
-	if (ses)
-		sesInfoFree(ses);
 
 	FreeXid(xid);
 	return rc;
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -75,12 +75,11 @@ sesInfoAlloc(void)
 
 	ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
 	if (ret_buf) {
-		write_lock(&GlobalSMBSeslock);
 		atomic_inc(&sesInfoAllocCount);
 		ret_buf->status = CifsNew;
-		list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
+		++ret_buf->ses_count;
+		INIT_LIST_HEAD(&ret_buf->smb_ses_list);
 		init_MUTEX(&ret_buf->sesSem);
-		write_unlock(&GlobalSMBSeslock);
 	}
 	return ret_buf;
 }
@@ -93,10 +92,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_f
 		return;
 	}
 
-	write_lock(&GlobalSMBSeslock);
 	atomic_dec(&sesInfoAllocCount);
-	list_del(&buf_to_free->cifsSessionList);
-	write_unlock(&GlobalSMBSeslock);
 	kfree(buf_to_free->serverOS);
 	kfree(buf_to_free->serverDomain);
 	kfree(buf_to_free->serverNOS);
@@ -354,9 +350,9 @@ header_assemble(struct smb_hdr *buffer, 
 				if (current->fsuid != treeCon->ses->linux_uid) {
 					cFYI(1, ("Multiuser mode and UID "
 						 "did not match tcon uid"));
-					read_lock(&GlobalSMBSeslock);
-					list_for_each(temp_item, &GlobalSMBSessionList) {
-						ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
+					read_lock(&cifs_tcp_ses_lock);
+					list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
+						ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
 						if (ses->linux_uid == current->fsuid) {
 							if (ses->server == treeCon->ses->server) {
 								cFYI(1, ("found matching uid substitute right smb_uid"));
@@ -368,7 +364,7 @@ header_assemble(struct smb_hdr *buffer, 
 							}
 						}
 					}
-					read_unlock(&GlobalSMBSeslock);
+					read_unlock(&cifs_tcp_ses_lock);
 				}
 			}
 		}


  parent reply	other threads:[~2008-12-03 20:18 UTC|newest]

Thread overview: 190+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20081203193901.715896543@mini.kroah.org>
2008-12-03 19:47 ` [patch 000/104] 2.6.27-stable review Greg KH
2008-12-03 19:48   ` [patch 001/104] USB: gadget rndis: send notifications Greg KH
2008-12-03 19:48   ` [patch 002/104] USB: gadget rndis: stop windows self-immolation Greg KH
2008-12-03 19:48   ` [patch 003/104] USB: usbmon: fix read(2) Greg KH
2008-12-03 19:48   ` [patch 004/104] USB: fix SB700 usb subsystem hang bug Greg KH
2008-12-03 19:48   ` [patch 005/104] USB: fix SB600 USB " Greg KH
2008-12-03 19:48   ` [patch 006/104] atl1e: fix broken multicast by removing unnecessary crc inversion Greg KH
2008-12-03 19:48   ` [patch 007/104] cpuset: fix regression when failed to generate sched domains Greg KH
2008-12-03 19:48   ` [patch 008/104] cgroups: fix a serious bug in cgroupstats Greg KH
2008-12-03 19:48   ` [patch 009/104] eCryptfs: Allocate up to two scatterlists for crypto ops on keys Greg KH
2008-12-03 19:48   ` [patch 010/104] pxa2xx_spi: bugfix full duplex dma data corruption Greg KH
2008-12-03 19:48   ` [patch 011/104] fbdev: clean the penguins dirty feet Greg KH
2008-12-05 12:58     ` Pavel Machek
2008-12-05 19:29       ` Henrique de Moraes Holschuh
2008-12-06  0:26       ` Greg KH
2008-12-06  2:44       ` Andrew Morton
2008-12-03 19:48   ` [patch 012/104] gpiolib: extend gpio label column width in debugfs file Greg KH
2008-12-03 19:48   ` [patch 013/104] lib/scatterlist.c: fix kunmap() argument in sg_miter_stop() Greg KH
2008-12-03 19:48   ` [patch 014/104] sysvipc: fix the ipc structures initialization Greg KH
2008-12-03 19:48   ` [patch 015/104] parisc: fix kernel crash when unwinding a userspace process Greg KH
2008-12-03 19:48   ` [patch 016/104] epoll: introduce resource usage limits Greg KH
2009-01-23  4:51     ` Bron Gondwana
2009-01-23  5:16       ` Greg KH
2009-01-23  9:47         ` Bron Gondwana
2009-01-23 17:06           ` Greg KH
2009-01-23 17:24             ` Bastien ROUCARIES
2009-01-23 19:36               ` Davide Libenzi
2009-01-24  3:50             ` Bron Gondwana
2009-01-24  8:36               ` Vegard Nossum
2009-01-24 13:03             ` Bron Gondwana
2009-01-25 11:01               ` Bron Gondwana
2009-01-25 12:20                 ` Bron Gondwana
2009-01-28  0:35                   ` Greg KH
2009-01-28  3:38                     ` Bron Gondwana
2009-01-28  3:46                       ` Davide Libenzi
2009-01-28  3:57                         ` Bron Gondwana
2009-01-28  4:10                           ` Davide Libenzi
2009-01-28  5:26                             ` Greg KH
2009-01-28  5:36                               ` Willy Tarreau
2009-01-28  5:48                                 ` Davide Libenzi
2009-01-28  6:20                                   ` Willy Tarreau
2009-01-28  6:36                                     ` Davide Libenzi
2009-01-28  6:59                                       ` Willy Tarreau
2009-01-28  6:38                               ` Davide Libenzi
2009-01-28  6:52                                 ` Bron Gondwana
2009-01-28  7:34                                   ` Davide Libenzi
2009-01-28 10:45                                     ` Bron Gondwana
2009-01-28  6:57                                 ` Davide Libenzi
2009-01-28  9:24                                   ` Bron Gondwana
2009-01-28 16:56                                     ` Davide Libenzi
2009-01-28 21:46                         ` Chris Adams
2009-01-28 23:54                           ` Davide Libenzi
2009-01-28  3:47                       ` [PATCH 1/3] epoll: increase default max_user_instances to 1024 Bron Gondwana
2009-01-28  4:00                         ` Davide Libenzi
2009-01-28  4:07                           ` Ray Lee
2009-01-28  4:14                             ` Davide Libenzi
2009-01-28  4:55                               ` Bron Gondwana
2009-01-28  5:30                                 ` Davide Libenzi
2009-01-28  5:38                             ` Bron Gondwana
2009-01-28 10:16                             ` Alan Cox
2009-01-28 10:59                               ` Bron Gondwana
2009-01-28 11:36                                 ` Alan Cox
2009-01-28 13:28                                   ` Bron Gondwana
2009-01-28  4:39                           ` Bron Gondwana
2009-01-28  5:32                           ` Bron Gondwana
2009-01-28 11:08                             ` Vegard Nossum
2009-01-28 16:52                               ` Davide Libenzi
2009-01-28 20:51                                 ` Bron Gondwana
2009-01-28 23:51                                   ` Davide Libenzi
2009-01-29  0:28                                     ` Bron Gondwana
2009-01-28  3:47                       ` [PATCH 2/3] epoll: allow 0 for "unlimited" on epoll limits Bron Gondwana
2009-01-28  3:47                       ` [PATCH 3/3] epoll: add /proc/sys/fs/epoll/limits interface Bron Gondwana
2009-01-25 12:03             ` [patch 016/104] epoll: introduce resource usage limits Bron Gondwana
2009-01-23 19:28           ` Davide Libenzi
2008-12-03 19:48   ` [patch 017/104] Fix inotify watch removal/umount races Greg KH
2008-12-03 19:48   ` [patch 018/104] IA64: fix boot panic caused by offline CPUs Greg KH
2008-12-03 19:49   ` [patch 019/104] V4L/DVB (9352): Add some missing compat32 ioctls Greg KH
2008-12-03 19:49   ` [patch 020/104] Input: atkbd - add keymap quirk for Inventec Symphony systems Greg KH
2008-12-03 19:49   ` [patch 021/104] lib/idr.c: fix rcu related race with idr_find Greg KH
2008-12-09 21:40     ` Dave Airlie
2008-12-09 22:47       ` Linus Torvalds
2008-12-10  0:43         ` Dave Airlie
2008-12-10  1:46           ` Dave Airlie
2008-12-10  2:02             ` Andrew Morton
2008-12-10  2:08               ` Dave Airlie
2008-12-10  2:32                 ` Andrew Morton
2008-12-10 17:33                 ` Manfred Spraul
2008-12-03 19:49   ` [patch 022/104] parport_serial: fix array overflow Greg KH
2008-12-03 19:49   ` [patch 023/104] x86: more general identifier for Phoenix BIOS Greg KH
2008-12-03 19:49   ` [patch 024/104] x86: always define DECLARE_PCI_UNMAP* macros Greg KH
2008-12-03 19:49   ` [patch 025/104] ath9k: Fix SW-IOMMU bounce buffer starvation Greg KH
2008-12-03 19:50   ` [patch 026/104] ath9k: correct expected max RX buffer size Greg KH
2008-12-03 19:50   ` [patch 027/104] axnet_cs / pcnet_cs: moving PCMCIA_DEVICE_PROD_ID for Netgear FA411 Greg KH
2008-12-03 22:06     ` Cord Walter
2008-12-03 19:50   ` [patch 028/104] PCI Hotplug core: add name param pci_hp_register interface Greg KH
2008-12-03 19:50   ` [patch 029/104] PCI: update pci_create_slot() to take a hotplug param Greg KH
2008-12-03 19:50   ` [patch 030/104] PCI Hotplug: serialize pci_hp_register and pci_hp_deregister Greg KH
2008-12-03 19:50   ` [patch 031/104] PCI: prevent duplicate slot names Greg KH
2008-12-04 22:10     ` Alex Chiang
2008-12-05 18:27       ` [stable] " Greg KH
2008-12-09 22:41         ` Jesse Barnes
2008-12-03 19:50   ` [patch 032/104] PCI, PCI Hotplug: introduce slot_name helpers Greg KH
2008-12-03 19:50   ` [patch 033/104] PCI: acpiphp: remove name parameter Greg KH
2008-12-03 19:50   ` [patch 034/104] PCI: cpci_hotplug: stop managing hotplug_slot->name Greg KH
2008-12-03 22:15     ` Scott Murray
2008-12-03 19:50   ` [patch 035/104] PCI: cpqphp: " Greg KH
2008-12-03 19:51   ` [patch 036/104] PCI: fakephp: remove name parameter Greg KH
2008-12-03 19:51   ` [patch 037/104] PCI: ibmphp: stop managing hotplug_slot->name Greg KH
2008-12-03 19:51   ` [patch 038/104] PCI: pciehp: remove name parameter Greg KH
2008-12-03 19:51   ` [patch 039/104] PCI: rpaphp: kmalloc/kfree slot->name directly Greg KH
2008-12-03 19:51   ` [patch 040/104] PCI: SGI Hotplug: stop managing bss_hotplug_slot->name Greg KH
2008-12-03 19:51   ` [patch 041/104] PCI: shcphp: remove name parameter Greg KH
2008-12-03 19:51   ` [patch 042/104] PCI: Hotplug core: remove name Greg KH
2008-12-03 19:51   ` [patch 043/104] CPUFREQ: powernow-k8: ignore out-of-range PstateStatus value Greg KH
2008-12-03 19:51   ` [patch 044/104] xen: do not reserve 2 pages of padding between hypervisor and fixmap Greg KH
2008-12-03 19:51   ` [patch 045/104] x86: Hibernate: Fix breakage on x86_32 with CONFIG_NUMA set Greg KH
2008-12-03 19:51   ` [patch 046/104] x86: SB600: skip ACPI IRQ0 override if it is not routed to INT2 of IOAPIC Greg KH
2008-12-03 19:51   ` [patch 047/104] libata: Avoid overflow in libata when tf->hba_lbal > 127 Greg KH
2008-12-03 19:51   ` [patch 048/104] x86: call dmi-quirks for HP Laptops after early-quirks are executed Greg KH
2008-12-03 19:51   ` [patch 049/104] igb: Use device_set_wakeup_enable Greg KH
2008-12-03 19:51   ` [patch 050/104] e1000: " Greg KH
2008-12-03 19:52   ` [patch 051/104] e1000e: " Greg KH
2008-12-03 19:52   ` [patch 052/104] libata: blacklist Seagate drives which time out FLUSH_CACHE when used with NCQ Greg KH
2008-12-03 19:52   ` [patch 053/104] rtl8187: add device ID 0bda:8198 Greg KH
2008-12-03 19:52   ` [patch 054/104] rtl8187: Add USB ID for Belkin F5D7050 with RTL8187B chip Greg KH
2008-12-03 19:52   ` [patch 055/104] cifs: Reduce number of socket retries in large write path Greg KH
2008-12-03 19:52   ` [patch 056/104] cifs: Fix error in smb_send2 Greg KH
2008-12-03 19:52   ` [patch 057/104] powerpc/spufs: Fix spinning in spufs_ps_fault on signal Greg KH
2008-12-03 19:52   ` [patch 058/104] powerpc/spufs: add a missing mutex_unlock Greg KH
2008-12-03 19:52   ` [patch 059/104] WATCHDOG: hpwdt: set the mapped BIOS address space as executable Greg KH
2008-12-03 19:52   ` [patch 060/104] WATCHDOG: hpwdt: Fix kdump when using hpwdt Greg KH
2008-12-03 19:52   ` [patch 061/104] Remove -mno-spe flags as they dont belong Greg KH
2008-12-03 19:53   ` [patch 062/104] ACPI: EC: count interrupts only if called from interrupt handler Greg KH
2008-12-05 13:06     ` Pavel Machek
2008-12-06  0:26       ` Greg KH
2008-12-03 19:53   ` [patch 063/104] ieee1394: sbp2: another iPod mini quirk entry Greg KH
2008-12-03 19:53   ` [patch 064/104] firewire: fw-sbp2: " Greg KH
2008-12-03 19:53   ` [patch 065/104] IB/mlx4: Fix MTT leakage in resize CQ Greg KH
2008-12-03 19:53   ` [patch 066/104] net: Fix soft lockups/OOM issues w/ unix garbage collector (CVE-2008-5300) Greg KH
2008-12-03 19:53   ` [patch 067/104] libata: improve phantom device detection Greg KH
2008-12-04  4:20     ` Tejun Heo
2008-12-05 18:36       ` [stable] " Greg KH
2008-12-06  5:24         ` Tejun Heo
2008-12-03 19:53   ` [patch 068/104] cifs: Fix cifs reconnection flags Greg KH
2008-12-03 19:53   ` [patch 069/104] cifs: remove unused list, add new cifs sock list to prepare for mount/umount fix Greg KH
2008-12-03 19:53   ` [patch 070/104] cifs: clean up server protocol handling Greg KH
2008-12-03 19:53   ` [patch 071/104] cifs: disable sharing session and tcon and add new TCP sharing code Greg KH
2008-12-03 19:53   ` Greg KH [this message]
2008-12-03 19:53   ` [patch 073/104] cifs: minor cleanup to cifs_mount Greg KH
2008-12-03 19:53   ` [patch 074/104] cifs: reinstate sharing of tree connections Greg KH
2008-12-03 19:53   ` [patch 075/104] cifs: Fix build break Greg KH
2008-12-03 19:55   ` [patch 076/104] cifs: Fix check for tcon seal setting and fix oops on failed mount from earlier patch Greg KH
2008-12-03 19:56   ` [patch 077/104] cifs: prevent cifs_writepages() from skipping unwritten pages Greg KH
2008-12-03 19:56   ` [patch 078/104] cifs: fix check for dead tcon in smb_init Greg KH
2008-12-03 19:56   ` [patch 079/104] ext4: Update flex_bg free blocks and free inodes counters when resizing Greg KH
2008-12-03 19:56   ` [patch 080/104] ext4: fix #11321: create /proc/ext4/*/stats more carefully Greg KH
2008-12-03 19:56   ` [patch 081/104] jbd2: fix /proc setup for devices that contain / in their names Greg KH
2008-12-03 19:56   ` [patch 082/104] ext4: add missing unlock in ext4_check_descriptors() on error path Greg KH
2008-12-03 19:56   ` [patch 083/104] ext4: elevate write count for migrate ioctl Greg KH
2008-12-03 19:56   ` [patch 084/104] ext4: Renumber EXT4_IOC_MIGRATE Greg KH
2008-12-03 19:56   ` [patch 085/104] ext4/jbd2: Avoid WARN() messages when failing to write to the superblock Greg KH
2008-12-03 19:56   ` [patch 086/104] ext4: fix initialization of UNINIT bitmap blocks Greg KH
2008-12-04  4:10     ` Theodore Tso
2008-12-05 18:36       ` [stable] " Greg KH
2008-12-03 19:56   ` [patch 087/104] jbd2: abort instead of waiting for nonexistent transaction Greg KH
2008-12-03 19:56   ` [patch 088/104] jbd2: Fix buffer head leak when writing the commit block Greg KH
2008-12-03 19:56   ` [patch 089/104] ext4: fix xattr deadlock Greg KH
2008-12-03 19:56   ` [patch 090/104] ext4: Free ext4_prealloc_space using kmem_cache_free Greg KH
2008-12-03 19:56   ` [patch 091/104] ext4: Do mballoc init before doing filesystem recovery Greg KH
2008-12-03 19:56   ` [patch 092/104] ext4: Fix duplicate entries returned from getdents() system call Greg KH
2008-12-03 19:56   ` [patch 093/104] jbd2: dont give up looking for space so easily in __jbd2_log_wait_for_space Greg KH
2008-12-03 19:56   ` [patch 094/104] ext4: Convert to host order before using the values Greg KH
2008-12-03 19:56   ` [patch 095/104] ext4: wait on all pending commits in ext4_sync_fs() Greg KH
2008-12-03 19:56   ` [patch 096/104] ext4: calculate journal credits correctly Greg KH
2008-12-03 19:56   ` [patch 097/104] ext4: Mark the buffer_heads as dirty and uptodate after prepare_write Greg KH
2008-12-03 19:56   ` [patch 098/104] ext4: add checksum calculation when clearing UNINIT flag in ext4_new_inode Greg KH
2008-12-03 19:56   ` [patch 099/104] ext3: fix ext3_dx_readdir hash collision handling Greg KH
2008-12-03 19:56   ` [patch 100/104] ext3: Fix duplicate entries returned from getdents() system call Greg KH
2008-12-03 19:56   ` [patch 101/104] ext3: dont try to resize if there are no reserved gdt blocks left Greg KH
2008-12-04 22:07     ` Valdis.Kletnieks
2008-12-03 19:56   ` [patch 102/104] ext2: fix ext2 block reservation early ENOSPC issue Greg KH
2008-12-03 19:56   ` [patch 103/104] ext3: fix ext3 " Greg KH
2008-12-03 19:56   ` [patch 104/104] jbd: ordered data integrity fix Greg KH
2008-12-03 21:39   ` [patch 000/104] 2.6.27-stable review Rafael J. Wysocki
2008-12-03 22:10     ` Michael Tokarev
2008-12-03 23:18       ` Rafael J. Wysocki
2008-12-05  0:33     ` Rafael J. Wysocki
2008-12-09 17:58       ` [stable] " Greg KH
2008-12-03 22:06   ` Michael Tokarev
2008-12-03 23:19     ` Greg KH
     [not found] <bF63r-1nB-59@gated-at.bofh.it>
     [not found] ` <bXmsS-4eW-1@gated-at.bofh.it>
     [not found]   ` <bXmMj-4HC-7@gated-at.bofh.it>
     [not found]     ` <bXqQ1-2GV-49@gated-at.bofh.it>
     [not found]       ` <bXxHH-5zl-23@gated-at.bofh.it>
     [not found]         ` <bXQqZ-1hm-9@gated-at.bofh.it>
     [not found]           ` <bYb2q-8bp-21@gated-at.bofh.it>
     [not found]             ` <bYchR-1AT-3@gated-at.bofh.it>
     [not found]               ` <bZ6Di-6ZV-1@gated-at.bofh.it>

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081203195334.GU8950@kroah.com \
    --to=gregkh@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=cavokz@gmail.com \
    --cc=cebbert@redhat.com \
    --cc=chuckw@quantumlinux.com \
    --cc=davej@redhat.com \
    --cc=eteo@redhat.com \
    --cc=jake@lwn.net \
    --cc=jlayton@redhat.com \
    --cc=jmforbes@linuxtx.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mkrufky@linuxtv.org \
    --cc=rbranco@la.checkpoint.com \
    --cc=rdunlap@xenotime.net \
    --cc=reviews@ml.cw.f00f.org \
    --cc=sfrench@us.ibm.com \
    --cc=sjayaraman@suse.de \
    --cc=smfrench@gmail.com \
    --cc=stable@kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=tytso@mit.edu \
    --cc=w@1wt.eu \
    --cc=zwane@arm.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox