[linux-cifs-client] [PATCH 2/6] cifs: move allocation of new
TCP_Server_Info into separate function
Jeff Layton
jlayton at redhat.com
Sun Nov 30 13:57:21 GMT 2008
Clean up cifs_mount a bit by moving the code that creates new TCP
sessions into a separate function. Have that function search for an
existing socket and then create a new one if one isn't found.
Also reorganize the initializion of TCP_Server_Info a bit to prepare
for cleanup of the socket connection code.
Signed-off-by: Jeff Layton <jlayton at redhat.com>
---
fs/cifs/connect.c | 199 +++++++++++++++++++++++++++++------------------------
1 files changed, 110 insertions(+), 89 deletions(-)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f61d620..812fe38 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1417,6 +1417,111 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
force_sig(SIGKILL, task);
}
+static struct TCP_Server_Info *
+cifs_get_tcp_session(struct smb_vol *volume_info, struct sockaddr *addr)
+{
+ struct TCP_Server_Info *srvTcp;
+ struct sockaddr_in *sin_server = (struct sockaddr_in *) addr;
+ struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) addr;
+ int rc;
+
+ srvTcp = cifs_find_tcp_session(addr);
+ if (srvTcp)
+ return srvTcp;
+
+ srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
+ if (!srvTcp) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+
+ srvTcp->noblocksnd = volume_info->noblocksnd;
+ srvTcp->noautotune = volume_info->noautotune;
+
+ srvTcp->hostname = extract_hostname(volume_info->UNC);
+ if (IS_ERR(srvTcp->hostname)) {
+ rc = PTR_ERR(srvTcp->hostname);
+ goto out_err;
+ }
+
+ atomic_set(&srvTcp->inFlight, 0);
+ init_waitqueue_head(&srvTcp->response_q);
+ init_waitqueue_head(&srvTcp->request_q);
+ INIT_LIST_HEAD(&srvTcp->pending_mid_q);
+ mutex_init(&srvTcp->tcpMutex);
+ memcpy(srvTcp->workstation_RFC1001_name,
+ volume_info->source_rfc1001_name,
+ RFC1001_NAME_LEN_WITH_NULL);
+ memcpy(srvTcp->server_RFC1001_name,
+ volume_info->target_rfc1001_name,
+ RFC1001_NAME_LEN_WITH_NULL);
+ srvTcp->sequence_number = 0;
+ INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
+ INIT_LIST_HEAD(&srvTcp->smb_ses_list);
+
+ /* at this point we are the only ones with the pointer
+ to the struct since the kernel thread not created yet
+ no need to spinlock this init of tcpStatus or refcnt */
+ srvTcp->tcpStatus = CifsNew;
+ ++srvTcp->srv_count;
+
+ if (addr->sa_family == 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 */
+ memcpy(&srvTcp->addr.sockAddr6, sin_server6,
+ sizeof(struct sockaddr_in6));
+ sin_server6->sin6_port = htons(volume_info->port);
+ rc = ipv6_connect(sin_server6, &srvTcp->ssocket,
+ volume_info->noblocksnd);
+ } else {
+ memcpy(&srvTcp->addr.sockAddr, sin_server,
+ sizeof(struct sockaddr_in));
+ sin_server->sin_port = htons(volume_info->port);
+ rc = ipv4_connect(sin_server, &srvTcp->ssocket,
+ volume_info->source_rfc1001_name,
+ volume_info->target_rfc1001_name,
+ volume_info->noblocksnd,
+ volume_info->noautotune);
+ }
+ if (rc < 0) {
+ cERROR(1, ("Error connecting to socket. "
+ "Aborting operation"));
+ goto out_err;
+ }
+
+ /*
+ * since we're in a cifs function already, we know that
+ * this will succeed. No need for try_module_get().
+ */
+ __module_get(THIS_MODULE);
+ 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));
+ module_put(THIS_MODULE);
+ goto out_err;
+ }
+
+ /* thread spawned, put it on the list */
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&srvTcp->tcp_ses_list, &cifs_tcp_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ return srvTcp;
+
+out_err:
+ if (srvTcp) {
+ kfree(srvTcp->hostname);
+ if (srvTcp->ssocket)
+ sock_release(srvTcp->ssocket);
+ kfree(srvTcp);
+ }
+ return ERR_PTR(rc);
+}
+
+
static struct cifsSesInfo *
cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
{
@@ -2043,7 +2148,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
{
int rc = 0;
int xid;
- struct socket *csocket = NULL;
struct sockaddr addr;
struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
@@ -2128,94 +2232,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
- srvTcp = cifs_find_tcp_session(&addr);
- if (!srvTcp) { /* create socket */
- if (addr.sa_family == 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 */
- sin_server6->sin6_port = htons(volume_info.port);
- rc = ipv6_connect(sin_server6, &csocket,
- volume_info.noblocksnd);
- } else {
- sin_server->sin_port = htons(volume_info.port);
- rc = ipv4_connect(sin_server, &csocket,
- volume_info.source_rfc1001_name,
- volume_info.target_rfc1001_name,
- volume_info.noblocksnd,
- volume_info.noautotune);
- }
- if (rc < 0) {
- cERROR(1, ("Error connecting to socket. "
- "Aborting operation"));
- if (csocket != NULL)
- sock_release(csocket);
- goto out;
- }
-
- srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
- if (!srvTcp) {
- rc = -ENOMEM;
- sock_release(csocket);
- goto out;
- } else {
- srvTcp->noblocksnd = volume_info.noblocksnd;
- srvTcp->noautotune = volume_info.noautotune;
- if (addr.sa_family == AF_INET6)
- memcpy(&srvTcp->addr.sockAddr6, sin_server6,
- sizeof(struct sockaddr_in6));
- else
- 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->hostname = extract_hostname(volume_info.UNC);
- if (IS_ERR(srvTcp->hostname)) {
- rc = PTR_ERR(srvTcp->hostname);
- sock_release(csocket);
- goto out;
- }
- 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;
- mutex_init(&srvTcp->tcpMutex);
-
- /*
- * since we're in a cifs function already, we know that
- * this will succeed. No need for try_module_get().
- */
- __module_get(THIS_MODULE);
- 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));
- module_put(THIS_MODULE);
- srvTcp->tsk = NULL;
- sock_release(csocket);
- kfree(srvTcp->hostname);
- goto out;
- }
- rc = 0;
- memcpy(srvTcp->workstation_RFC1001_name,
- volume_info.source_rfc1001_name,
- RFC1001_NAME_LEN_WITH_NULL);
- memcpy(srvTcp->server_RFC1001_name,
- volume_info.target_rfc1001_name,
- RFC1001_NAME_LEN_WITH_NULL);
- 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,
- &cifs_tcp_ses_list);
- write_unlock(&cifs_tcp_ses_lock);
- }
+ /* get a reference to a tcp session */
+ srvTcp = cifs_get_tcp_session(&volume_info, &addr);
+ if (IS_ERR(srvTcp)) {
+ rc = PTR_ERR(srvTcp);
+ goto out;
}
pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
--
1.5.5.1
More information about the linux-cifs-client
mailing list