diff options
| -rw-r--r-- | fs/cifs/cifs_debug.c | 53 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 17 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 6 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 1 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 22 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 226 | ||||
| -rw-r--r-- | fs/cifs/misc.c | 16 |
7 files changed, 175 insertions, 166 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 40b5108fb4f9..59841a68b0b6 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
| @@ -107,9 +107,9 @@ void cifs_dump_mids(struct TCP_Server_Info *server) | |||
| 107 | #ifdef CONFIG_PROC_FS | 107 | #ifdef CONFIG_PROC_FS |
| 108 | static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | 108 | static int cifs_debug_data_proc_show(struct seq_file *m, void *v) |
| 109 | { | 109 | { |
| 110 | struct list_head *tmp; | 110 | struct list_head *tmp, *tmp2, *tmp3; |
| 111 | struct list_head *tmp1; | ||
| 112 | struct mid_q_entry *mid_entry; | 111 | struct mid_q_entry *mid_entry; |
| 112 | struct TCP_Server_Info *server; | ||
| 113 | struct cifsSesInfo *ses; | 113 | struct cifsSesInfo *ses; |
| 114 | struct cifsTconInfo *tcon; | 114 | struct cifsTconInfo *tcon; |
| 115 | int i; | 115 | int i; |
| @@ -122,43 +122,45 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
| 122 | seq_printf(m, "Servers:"); | 122 | seq_printf(m, "Servers:"); |
| 123 | 123 | ||
| 124 | i = 0; | 124 | i = 0; |
| 125 | read_lock(&GlobalSMBSeslock); | 125 | read_lock(&cifs_tcp_ses_lock); |
| 126 | list_for_each(tmp, &GlobalSMBSessionList) { | 126 | list_for_each(tmp, &cifs_tcp_ses_list) { |
| 127 | server = list_entry(tmp, struct TCP_Server_Info, | ||
| 128 | tcp_ses_list); | ||
| 127 | i++; | 129 | i++; |
| 128 | ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); | 130 | list_for_each(tmp2, &server->smb_ses_list) { |
| 129 | if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) || | 131 | ses = list_entry(tmp2, struct cifsSesInfo, |
| 130 | (ses->serverNOS == NULL)) { | 132 | smb_ses_list); |
| 131 | seq_printf(m, "\nentry for %s not fully " | 133 | if ((ses->serverDomain == NULL) || |
| 132 | "displayed\n\t", ses->serverName); | 134 | (ses->serverOS == NULL) || |
| 133 | } else { | 135 | (ses->serverNOS == NULL)) { |
| 134 | seq_printf(m, | 136 | seq_printf(m, "\nentry for %s not fully " |
| 137 | "displayed\n\t", ses->serverName); | ||
| 138 | } else { | ||
| 139 | seq_printf(m, | ||
| 135 | "\n%d) Name: %s Domain: %s Mounts: %d OS:" | 140 | "\n%d) Name: %s Domain: %s Mounts: %d OS:" |
| 136 | " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB" | 141 | " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB" |
| 137 | " session status: %d\t", | 142 | " session status: %d\t", |
| 138 | i, ses->serverName, ses->serverDomain, | 143 | i, ses->serverName, ses->serverDomain, |
| 139 | atomic_read(&ses->inUse), | 144 | ses->ses_count, ses->serverOS, ses->serverNOS, |
| 140 | ses->serverOS, ses->serverNOS, | ||
| 141 | ses->capabilities, ses->status); | 145 | ses->capabilities, ses->status); |
| 142 | } | 146 | } |
| 143 | if (ses->server) { | ||
| 144 | seq_printf(m, "TCP status: %d\n\tLocal Users To " | 147 | seq_printf(m, "TCP status: %d\n\tLocal Users To " |
| 145 | "Server: %d SecMode: 0x%x Req On Wire: %d", | 148 | "Server: %d SecMode: 0x%x Req On Wire: %d", |
| 146 | ses->server->tcpStatus, | 149 | server->tcpStatus, server->srv_count, |
| 147 | ses->server->srv_count, | 150 | server->secMode, |
| 148 | ses->server->secMode, | 151 | atomic_read(&server->inFlight)); |
| 149 | atomic_read(&ses->server->inFlight)); | ||
| 150 | 152 | ||
| 151 | #ifdef CONFIG_CIFS_STATS2 | 153 | #ifdef CONFIG_CIFS_STATS2 |
| 152 | seq_printf(m, " In Send: %d In MaxReq Wait: %d", | 154 | seq_printf(m, " In Send: %d In MaxReq Wait: %d", |
| 153 | atomic_read(&ses->server->inSend), | 155 | atomic_read(&server->inSend), |
| 154 | atomic_read(&ses->server->num_waiters)); | 156 | atomic_read(&server->num_waiters)); |
| 155 | #endif | 157 | #endif |
| 156 | 158 | ||
| 157 | seq_puts(m, "\nMIDs:\n"); | 159 | seq_puts(m, "\nMIDs:\n"); |
| 158 | 160 | ||
| 159 | spin_lock(&GlobalMid_Lock); | 161 | spin_lock(&GlobalMid_Lock); |
| 160 | list_for_each(tmp1, &ses->server->pending_mid_q) { | 162 | list_for_each(tmp3, &server->pending_mid_q) { |
| 161 | mid_entry = list_entry(tmp1, struct | 163 | mid_entry = list_entry(tmp3, struct |
| 162 | mid_q_entry, | 164 | mid_q_entry, |
| 163 | qhead); | 165 | qhead); |
| 164 | seq_printf(m, "State: %d com: %d pid:" | 166 | seq_printf(m, "State: %d com: %d pid:" |
| @@ -171,9 +173,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
| 171 | } | 173 | } |
| 172 | spin_unlock(&GlobalMid_Lock); | 174 | spin_unlock(&GlobalMid_Lock); |
| 173 | } | 175 | } |
| 174 | |||
| 175 | } | 176 | } |
| 176 | read_unlock(&GlobalSMBSeslock); | 177 | read_unlock(&cifs_tcp_ses_lock); |
| 177 | seq_putc(m, '\n'); | 178 | seq_putc(m, '\n'); |
| 178 | 179 | ||
| 179 | seq_puts(m, "Shares:"); | 180 | seq_puts(m, "Shares:"); |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2946dab0718f..a1e96620b097 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -1031,24 +1031,24 @@ static int cifs_oplock_thread(void *dummyarg) | |||
| 1031 | static int cifs_dnotify_thread(void *dummyarg) | 1031 | static int cifs_dnotify_thread(void *dummyarg) |
| 1032 | { | 1032 | { |
| 1033 | struct list_head *tmp; | 1033 | struct list_head *tmp; |
| 1034 | struct cifsSesInfo *ses; | 1034 | struct TCP_Server_Info *server; |
| 1035 | 1035 | ||
| 1036 | do { | 1036 | do { |
| 1037 | if (try_to_freeze()) | 1037 | if (try_to_freeze()) |
| 1038 | continue; | 1038 | continue; |
| 1039 | set_current_state(TASK_INTERRUPTIBLE); | 1039 | set_current_state(TASK_INTERRUPTIBLE); |
| 1040 | schedule_timeout(15*HZ); | 1040 | schedule_timeout(15*HZ); |
| 1041 | read_lock(&GlobalSMBSeslock); | ||
| 1042 | /* check if any stuck requests that need | 1041 | /* check if any stuck requests that need |
| 1043 | to be woken up and wakeq so the | 1042 | to be woken up and wakeq so the |
| 1044 | thread can wake up and error out */ | 1043 | thread can wake up and error out */ |
| 1045 | list_for_each(tmp, &GlobalSMBSessionList) { | 1044 | read_lock(&cifs_tcp_ses_lock); |
| 1046 | ses = list_entry(tmp, struct cifsSesInfo, | 1045 | list_for_each(tmp, &cifs_tcp_ses_list) { |
| 1047 | cifsSessionList); | 1046 | server = list_entry(tmp, struct TCP_Server_Info, |
| 1048 | if (ses->server && atomic_read(&ses->server->inFlight)) | 1047 | tcp_ses_list); |
| 1049 | wake_up_all(&ses->server->response_q); | 1048 | if (atomic_read(&server->inFlight)) |
| 1049 | wake_up_all(&server->response_q); | ||
| 1050 | } | 1050 | } |
| 1051 | read_unlock(&GlobalSMBSeslock); | 1051 | read_unlock(&cifs_tcp_ses_lock); |
| 1052 | } while (!kthread_should_stop()); | 1052 | } while (!kthread_should_stop()); |
| 1053 | 1053 | ||
| 1054 | return 0; | 1054 | return 0; |
| @@ -1060,7 +1060,6 @@ init_cifs(void) | |||
| 1060 | int rc = 0; | 1060 | int rc = 0; |
| 1061 | cifs_proc_init(); | 1061 | cifs_proc_init(); |
| 1062 | INIT_LIST_HEAD(&cifs_tcp_ses_list); | 1062 | INIT_LIST_HEAD(&cifs_tcp_ses_list); |
| 1063 | INIT_LIST_HEAD(&GlobalSMBSessionList); /* BB to be removed by jl */ | ||
| 1064 | INIT_LIST_HEAD(&GlobalTreeConnectionList); /* BB to be removed by jl */ | 1063 | INIT_LIST_HEAD(&GlobalTreeConnectionList); /* BB to be removed by jl */ |
| 1065 | INIT_LIST_HEAD(&GlobalOplock_Q); | 1064 | INIT_LIST_HEAD(&GlobalOplock_Q); |
| 1066 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1065 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 313f7bfedec7..631a99f72f22 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -195,14 +195,14 @@ struct cifsUidInfo { | |||
| 195 | * Session structure. One of these for each uid session with a particular host | 195 | * Session structure. One of these for each uid session with a particular host |
| 196 | */ | 196 | */ |
| 197 | struct cifsSesInfo { | 197 | struct cifsSesInfo { |
| 198 | struct list_head cifsSessionList; | 198 | struct list_head smb_ses_list; |
| 199 | struct list_head tcon_list; | 199 | struct list_head tcon_list; |
| 200 | struct semaphore sesSem; | 200 | struct semaphore sesSem; |
| 201 | #if 0 | 201 | #if 0 |
| 202 | struct cifsUidInfo *uidInfo; /* pointer to user info */ | 202 | struct cifsUidInfo *uidInfo; /* pointer to user info */ |
| 203 | #endif | 203 | #endif |
| 204 | struct TCP_Server_Info *server; /* pointer to server info */ | 204 | struct TCP_Server_Info *server; /* pointer to server info */ |
| 205 | atomic_t inUse; /* # of mounts (tree connections) on this ses */ | 205 | int ses_count; /* reference counter */ |
| 206 | enum statusEnum status; | 206 | enum statusEnum status; |
| 207 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ | 207 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ |
| 208 | __u16 ipc_tid; /* special tid for connection to IPC share */ | 208 | __u16 ipc_tid; /* special tid for connection to IPC share */ |
| @@ -602,8 +602,6 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list; | |||
| 602 | 602 | ||
| 603 | /* protects cifs_tcp_ses_list and srv_count for each tcp session */ | 603 | /* protects cifs_tcp_ses_list and srv_count for each tcp session */ |
| 604 | GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock; | 604 | GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock; |
| 605 | |||
| 606 | GLOBAL_EXTERN struct list_head GlobalSMBSessionList; /* BB to be removed by jl*/ | ||
| 607 | GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; /* BB to be removed */ | 605 | GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; /* BB to be removed */ |
| 608 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ | 606 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ |
| 609 | 607 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0250a994c6e6..6f21ecb85ce5 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -102,7 +102,6 @@ extern void acl_to_uid_mode(struct inode *inode, const char *path, | |||
| 102 | const __u16 *pfid); | 102 | const __u16 *pfid); |
| 103 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 103 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); |
| 104 | 104 | ||
| 105 | extern void cifs_put_tcp_session(struct TCP_Server_Info *server); | ||
| 106 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 105 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
| 107 | const char *); | 106 | const char *); |
| 108 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | 107 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index cd9e9a145e4d..9c95617baa4d 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -799,20 +799,16 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
| 799 | int rc = 0; | 799 | int rc = 0; |
| 800 | 800 | ||
| 801 | cFYI(1, ("In SMBLogoff for session disconnect")); | 801 | cFYI(1, ("In SMBLogoff for session disconnect")); |
| 802 | if (ses) | ||
| 803 | down(&ses->sesSem); | ||
| 804 | else | ||
| 805 | return -EIO; | ||
| 806 | |||
| 807 | atomic_dec(&ses->inUse); | ||
| 808 | if (atomic_read(&ses->inUse) > 0) { | ||
| 809 | up(&ses->sesSem); | ||
| 810 | return -EBUSY; | ||
| 811 | } | ||
| 812 | 802 | ||
| 813 | if (ses->server == NULL) | 803 | /* |
| 804 | * BB: do we need to check validity of ses and server? They should | ||
| 805 | * always be valid since we have an active reference. If not, that | ||
| 806 | * should probably be a BUG() | ||
| 807 | */ | ||
| 808 | if (!ses || !ses->server) | ||
| 814 | return -EIO; | 809 | return -EIO; |
| 815 | 810 | ||
| 811 | down(&ses->sesSem); | ||
| 816 | if (ses->need_reconnect) | 812 | if (ses->need_reconnect) |
| 817 | goto session_already_dead; /* no need to send SMBlogoff if uid | 813 | goto session_already_dead; /* no need to send SMBlogoff if uid |
| 818 | already closed due to reconnect */ | 814 | already closed due to reconnect */ |
| @@ -833,10 +829,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
| 833 | pSMB->AndXCommand = 0xFF; | 829 | pSMB->AndXCommand = 0xFF; |
| 834 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); | 830 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); |
| 835 | session_already_dead: | 831 | session_already_dead: |
| 836 | if (ses->server) { | ||
| 837 | cifs_put_tcp_session(ses->server); | ||
| 838 | rc = 0; | ||
| 839 | } | ||
| 840 | up(&ses->sesSem); | 832 | up(&ses->sesSem); |
| 841 | 833 | ||
| 842 | /* if session dead then we do not need to do ulogoff, | 834 | /* if session dead then we do not need to do ulogoff, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a0314259f94d..44130e052e0b 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -144,23 +144,18 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 144 | 144 | ||
| 145 | /* before reconnecting the tcp session, mark the smb session (uid) | 145 | /* before reconnecting the tcp session, mark the smb session (uid) |
| 146 | and the tid bad so they are not used until reconnected */ | 146 | and the tid bad so they are not used until reconnected */ |
| 147 | read_lock(&GlobalSMBSeslock); | 147 | read_lock(&cifs_tcp_ses_lock); |
| 148 | list_for_each(tmp, &GlobalSMBSessionList) { | 148 | list_for_each(tmp, &server->smb_ses_list) { |
| 149 | ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); | 149 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); |
| 150 | if (ses->server) { | 150 | ses->need_reconnect = true; |
| 151 | if (ses->server == server) { | 151 | ses->ipc_tid = 0; |
| 152 | ses->need_reconnect = true; | ||
| 153 | ses->ipc_tid = 0; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | /* else tcp and smb sessions need reconnection */ | ||
| 157 | } | 152 | } |
| 153 | read_unlock(&cifs_tcp_ses_lock); | ||
| 158 | list_for_each(tmp, &GlobalTreeConnectionList) { | 154 | list_for_each(tmp, &GlobalTreeConnectionList) { |
| 159 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 155 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); |
| 160 | if ((tcon->ses) && (tcon->ses->server == server)) | 156 | if ((tcon->ses) && (tcon->ses->server == server)) |
| 161 | tcon->need_reconnect = true; | 157 | tcon->need_reconnect = true; |
| 162 | } | 158 | } |
| 163 | read_unlock(&GlobalSMBSeslock); | ||
| 164 | /* do not want to be sending data on a socket we are freeing */ | 159 | /* do not want to be sending data on a socket we are freeing */ |
| 165 | down(&server->tcpSem); | 160 | down(&server->tcpSem); |
| 166 | if (server->ssocket) { | 161 | if (server->ssocket) { |
| @@ -696,29 +691,29 @@ multi_t2_fnd: | |||
| 696 | if (smallbuf) /* no sense logging a debug message if NULL */ | 691 | if (smallbuf) /* no sense logging a debug message if NULL */ |
| 697 | cifs_small_buf_release(smallbuf); | 692 | cifs_small_buf_release(smallbuf); |
| 698 | 693 | ||
| 699 | read_lock(&GlobalSMBSeslock); | 694 | /* |
| 695 | * BB: we shouldn't have to do any of this. It shouldn't be | ||
| 696 | * possible to exit from the thread with active SMB sessions | ||
| 697 | */ | ||
| 698 | read_lock(&cifs_tcp_ses_lock); | ||
| 700 | if (list_empty(&server->pending_mid_q)) { | 699 | if (list_empty(&server->pending_mid_q)) { |
| 701 | /* loop through server session structures attached to this and | 700 | /* loop through server session structures attached to this and |
| 702 | mark them dead */ | 701 | mark them dead */ |
| 703 | list_for_each(tmp, &GlobalSMBSessionList) { | 702 | list_for_each(tmp, &server->smb_ses_list) { |
| 704 | ses = | 703 | ses = list_entry(tmp, struct cifsSesInfo, |
| 705 | list_entry(tmp, struct cifsSesInfo, | 704 | smb_ses_list); |
| 706 | cifsSessionList); | 705 | ses->status = CifsExiting; |
| 707 | if (ses->server == server) { | 706 | ses->server = NULL; |
| 708 | ses->status = CifsExiting; | ||
| 709 | ses->server = NULL; | ||
| 710 | } | ||
| 711 | } | 707 | } |
| 712 | read_unlock(&GlobalSMBSeslock); | 708 | read_unlock(&cifs_tcp_ses_lock); |
| 713 | } else { | 709 | } else { |
| 714 | /* although we can not zero the server struct pointer yet, | 710 | /* although we can not zero the server struct pointer yet, |
| 715 | since there are active requests which may depnd on them, | 711 | since there are active requests which may depnd on them, |
| 716 | mark the corresponding SMB sessions as exiting too */ | 712 | mark the corresponding SMB sessions as exiting too */ |
| 717 | list_for_each(tmp, &GlobalSMBSessionList) { | 713 | list_for_each(tmp, &server->smb_ses_list) { |
| 718 | ses = list_entry(tmp, struct cifsSesInfo, | 714 | ses = list_entry(tmp, struct cifsSesInfo, |
| 719 | cifsSessionList); | 715 | smb_ses_list); |
| 720 | if (ses->server == server) | 716 | ses->status = CifsExiting; |
| 721 | ses->status = CifsExiting; | ||
| 722 | } | 717 | } |
| 723 | 718 | ||
| 724 | spin_lock(&GlobalMid_Lock); | 719 | spin_lock(&GlobalMid_Lock); |
| @@ -733,7 +728,7 @@ multi_t2_fnd: | |||
| 733 | } | 728 | } |
| 734 | } | 729 | } |
| 735 | spin_unlock(&GlobalMid_Lock); | 730 | spin_unlock(&GlobalMid_Lock); |
| 736 | read_unlock(&GlobalSMBSeslock); | 731 | read_unlock(&cifs_tcp_ses_lock); |
| 737 | /* 1/8th of sec is more than enough time for them to exit */ | 732 | /* 1/8th of sec is more than enough time for them to exit */ |
| 738 | msleep(125); | 733 | msleep(125); |
| 739 | } | 734 | } |
| @@ -755,14 +750,13 @@ multi_t2_fnd: | |||
| 755 | if there are any pointing to this (e.g | 750 | if there are any pointing to this (e.g |
| 756 | if a crazy root user tried to kill cifsd | 751 | if a crazy root user tried to kill cifsd |
| 757 | kernel thread explicitly this might happen) */ | 752 | kernel thread explicitly this might happen) */ |
| 758 | write_lock(&GlobalSMBSeslock); | 753 | /* BB: This shouldn't be necessary, see above */ |
| 759 | list_for_each(tmp, &GlobalSMBSessionList) { | 754 | read_lock(&cifs_tcp_ses_lock); |
| 760 | ses = list_entry(tmp, struct cifsSesInfo, | 755 | list_for_each(tmp, &server->smb_ses_list) { |
| 761 | cifsSessionList); | 756 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); |
| 762 | if (ses->server == server) | 757 | ses->server = NULL; |
| 763 | ses->server = NULL; | ||
| 764 | } | 758 | } |
| 765 | write_unlock(&GlobalSMBSeslock); | 759 | read_unlock(&cifs_tcp_ses_lock); |
| 766 | 760 | ||
| 767 | kfree(server->hostname); | 761 | kfree(server->hostname); |
| 768 | task_to_wake = xchg(&server->tsk, NULL); | 762 | task_to_wake = xchg(&server->tsk, NULL); |
| @@ -1401,7 +1395,7 @@ cifs_find_tcp_session(struct sockaddr *addr) | |||
| 1401 | return NULL; | 1395 | return NULL; |
| 1402 | } | 1396 | } |
| 1403 | 1397 | ||
| 1404 | void | 1398 | static void |
| 1405 | cifs_put_tcp_session(struct TCP_Server_Info *server) | 1399 | cifs_put_tcp_session(struct TCP_Server_Info *server) |
| 1406 | { | 1400 | { |
| 1407 | struct task_struct *task; | 1401 | struct task_struct *task; |
| @@ -1424,6 +1418,50 @@ cifs_put_tcp_session(struct TCP_Server_Info *server) | |||
| 1424 | force_sig(SIGKILL, task); | 1418 | force_sig(SIGKILL, task); |
| 1425 | } | 1419 | } |
| 1426 | 1420 | ||
| 1421 | static struct cifsSesInfo * | ||
| 1422 | cifs_find_smb_ses(struct TCP_Server_Info *server, char *username) | ||
| 1423 | { | ||
| 1424 | struct list_head *tmp; | ||
| 1425 | struct cifsSesInfo *ses; | ||
| 1426 | |||
| 1427 | write_lock(&cifs_tcp_ses_lock); | ||
| 1428 | list_for_each(tmp, &server->smb_ses_list) { | ||
| 1429 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); | ||
| 1430 | if (strncmp(ses->userName, username, MAX_USERNAME_SIZE)) | ||
| 1431 | continue; | ||
| 1432 | |||
| 1433 | ++ses->ses_count; | ||
| 1434 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1435 | return ses; | ||
| 1436 | } | ||
| 1437 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1438 | return NULL; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | static void | ||
| 1442 | cifs_put_smb_ses(struct cifsSesInfo *ses) | ||
| 1443 | { | ||
| 1444 | int xid; | ||
| 1445 | struct TCP_Server_Info *server = ses->server; | ||
| 1446 | |||
| 1447 | write_lock(&cifs_tcp_ses_lock); | ||
| 1448 | if (--ses->ses_count > 0) { | ||
| 1449 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1450 | return; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | list_del_init(&ses->smb_ses_list); | ||
| 1454 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1455 | |||
| 1456 | if (ses->status == CifsGood) { | ||
| 1457 | xid = GetXid(); | ||
| 1458 | CIFSSMBLogoff(xid, ses); | ||
| 1459 | _FreeXid(xid); | ||
| 1460 | } | ||
| 1461 | sesInfoFree(ses); | ||
| 1462 | cifs_put_tcp_session(server); | ||
| 1463 | } | ||
| 1464 | |||
| 1427 | int | 1465 | int |
| 1428 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, | 1466 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, |
| 1429 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, | 1467 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, |
| @@ -1958,7 +1996,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1958 | struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr; | 1996 | struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr; |
| 1959 | struct smb_vol volume_info; | 1997 | struct smb_vol volume_info; |
| 1960 | struct cifsSesInfo *pSesInfo = NULL; | 1998 | struct cifsSesInfo *pSesInfo = NULL; |
| 1961 | struct cifsSesInfo *existingCifsSes = NULL; | ||
| 1962 | struct cifsTconInfo *tcon = NULL; | 1999 | struct cifsTconInfo *tcon = NULL; |
| 1963 | struct TCP_Server_Info *srvTcp = NULL; | 2000 | struct TCP_Server_Info *srvTcp = NULL; |
| 1964 | 2001 | ||
| @@ -2112,6 +2149,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2112 | volume_info.target_rfc1001_name, 16); | 2149 | volume_info.target_rfc1001_name, 16); |
| 2113 | srvTcp->sequence_number = 0; | 2150 | srvTcp->sequence_number = 0; |
| 2114 | INIT_LIST_HEAD(&srvTcp->tcp_ses_list); | 2151 | INIT_LIST_HEAD(&srvTcp->tcp_ses_list); |
| 2152 | INIT_LIST_HEAD(&srvTcp->smb_ses_list); | ||
| 2115 | ++srvTcp->srv_count; | 2153 | ++srvTcp->srv_count; |
| 2116 | write_lock(&cifs_tcp_ses_lock); | 2154 | write_lock(&cifs_tcp_ses_lock); |
| 2117 | list_add(&srvTcp->tcp_ses_list, | 2155 | list_add(&srvTcp->tcp_ses_list, |
| @@ -2120,10 +2158,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2120 | } | 2158 | } |
| 2121 | } | 2159 | } |
| 2122 | 2160 | ||
| 2123 | if (existingCifsSes) { | 2161 | pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username); |
| 2124 | pSesInfo = existingCifsSes; | 2162 | if (pSesInfo) { |
| 2125 | cFYI(1, ("Existing smb sess found (status=%d)", | 2163 | cFYI(1, ("Existing smb sess found (status=%d)", |
| 2126 | pSesInfo->status)); | 2164 | pSesInfo->status)); |
| 2165 | /* | ||
| 2166 | * The existing SMB session already has a reference to srvTcp, | ||
| 2167 | * so we can put back the extra one we got before | ||
| 2168 | */ | ||
| 2169 | cifs_put_tcp_session(srvTcp); | ||
| 2170 | |||
| 2127 | down(&pSesInfo->sesSem); | 2171 | down(&pSesInfo->sesSem); |
| 2128 | if (pSesInfo->need_reconnect) { | 2172 | if (pSesInfo->need_reconnect) { |
| 2129 | cFYI(1, ("Session needs reconnect")); | 2173 | cFYI(1, ("Session needs reconnect")); |
| @@ -2134,41 +2178,44 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2134 | } else if (!rc) { | 2178 | } else if (!rc) { |
| 2135 | cFYI(1, ("Existing smb sess not found")); | 2179 | cFYI(1, ("Existing smb sess not found")); |
| 2136 | pSesInfo = sesInfoAlloc(); | 2180 | pSesInfo = sesInfoAlloc(); |
| 2137 | if (pSesInfo == NULL) | 2181 | if (pSesInfo == NULL) { |
| 2138 | rc = -ENOMEM; | 2182 | rc = -ENOMEM; |
| 2139 | else { | 2183 | goto mount_fail_check; |
| 2140 | pSesInfo->server = srvTcp; | ||
| 2141 | sprintf(pSesInfo->serverName, "%u.%u.%u.%u", | ||
| 2142 | NIPQUAD(sin_server->sin_addr.s_addr)); | ||
| 2143 | } | 2184 | } |
| 2144 | 2185 | ||
| 2145 | if (!rc) { | 2186 | /* new SMB session uses our srvTcp ref */ |
| 2146 | /* volume_info.password freed at unmount */ | 2187 | pSesInfo->server = srvTcp; |
| 2147 | if (volume_info.password) { | 2188 | sprintf(pSesInfo->serverName, "%u.%u.%u.%u", |
| 2148 | pSesInfo->password = volume_info.password; | 2189 | NIPQUAD(sin_server->sin_addr.s_addr)); |
| 2149 | /* set to NULL to prevent freeing on exit */ | 2190 | |
| 2150 | volume_info.password = NULL; | 2191 | write_lock(&cifs_tcp_ses_lock); |
| 2151 | } | 2192 | list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list); |
| 2152 | if (volume_info.username) | 2193 | write_unlock(&cifs_tcp_ses_lock); |
| 2153 | strncpy(pSesInfo->userName, | 2194 | |
| 2154 | volume_info.username, | 2195 | /* volume_info.password freed at unmount */ |
| 2155 | MAX_USERNAME_SIZE); | 2196 | if (volume_info.password) { |
| 2156 | if (volume_info.domainname) { | 2197 | pSesInfo->password = volume_info.password; |
| 2157 | int len = strlen(volume_info.domainname); | 2198 | /* set to NULL to prevent freeing on exit */ |
| 2158 | pSesInfo->domainName = | 2199 | volume_info.password = NULL; |
| 2159 | kmalloc(len + 1, GFP_KERNEL); | 2200 | } |
| 2160 | if (pSesInfo->domainName) | 2201 | if (volume_info.username) |
| 2161 | strcpy(pSesInfo->domainName, | 2202 | strncpy(pSesInfo->userName, volume_info.username, |
| 2162 | volume_info.domainname); | 2203 | MAX_USERNAME_SIZE); |
| 2163 | } | 2204 | if (volume_info.domainname) { |
| 2164 | pSesInfo->linux_uid = volume_info.linux_uid; | 2205 | int len = strlen(volume_info.domainname); |
| 2165 | pSesInfo->overrideSecFlg = volume_info.secFlg; | 2206 | pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL); |
| 2166 | down(&pSesInfo->sesSem); | 2207 | if (pSesInfo->domainName) |
| 2167 | /* BB FIXME need to pass vol->secFlgs BB */ | 2208 | strcpy(pSesInfo->domainName, |
| 2168 | rc = cifs_setup_session(xid, pSesInfo, | 2209 | volume_info.domainname); |
| 2169 | cifs_sb->local_nls); | 2210 | } |
| 2170 | up(&pSesInfo->sesSem); | 2211 | pSesInfo->linux_uid = volume_info.linux_uid; |
| 2171 | } | 2212 | pSesInfo->overrideSecFlg = volume_info.secFlg; |
| 2213 | down(&pSesInfo->sesSem); | ||
| 2214 | |||
| 2215 | /* BB FIXME need to pass vol->secFlgs BB */ | ||
| 2216 | rc = cifs_setup_session(xid, pSesInfo, | ||
| 2217 | cifs_sb->local_nls); | ||
| 2218 | up(&pSesInfo->sesSem); | ||
| 2172 | } | 2219 | } |
| 2173 | 2220 | ||
| 2174 | /* search for existing tcon to this server share */ | 2221 | /* search for existing tcon to this server share */ |
| @@ -2209,11 +2256,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2209 | tcon->Flags)); | 2256 | tcon->Flags)); |
| 2210 | } | 2257 | } |
| 2211 | } | 2258 | } |
| 2212 | if (!rc) { | 2259 | if (rc) |
| 2213 | atomic_inc(&pSesInfo->inUse); | ||
| 2214 | tcon->seal = volume_info.seal; | ||
| 2215 | } else | ||
| 2216 | goto mount_fail_check; | 2260 | goto mount_fail_check; |
| 2261 | tcon->seal = volume_info.seal; | ||
| 2217 | } | 2262 | } |
| 2218 | 2263 | ||
| 2219 | /* we can have only one retry value for a connection | 2264 | /* we can have only one retry value for a connection |
| @@ -2234,29 +2279,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2234 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | 2279 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ |
| 2235 | sb->s_time_gran = 100; | 2280 | sb->s_time_gran = 100; |
| 2236 | 2281 | ||
| 2237 | /* on error free sesinfo and tcon struct if needed */ | ||
| 2238 | mount_fail_check: | 2282 | mount_fail_check: |
| 2283 | /* on error free sesinfo and tcon struct if needed */ | ||
| 2239 | if (rc) { | 2284 | if (rc) { |
| 2240 | /* If find_unc succeeded then rc == 0 so we can not end */ | 2285 | /* If find_unc succeeded then rc == 0 so we can not end */ |
| 2241 | /* up accidently freeing someone elses tcon struct */ | 2286 | /* up accidently freeing someone elses tcon struct */ |
| 2242 | if (tcon) | 2287 | if (tcon) |
| 2243 | tconInfoFree(tcon); | 2288 | tconInfoFree(tcon); |
| 2244 | 2289 | ||
| 2245 | if (existingCifsSes == NULL) { | 2290 | /* should also end up putting our tcp session ref if needed */ |
| 2246 | if (pSesInfo) { | 2291 | if (pSesInfo) |
| 2247 | if ((pSesInfo->server) && | 2292 | cifs_put_smb_ses(pSesInfo); |
| 2248 | (pSesInfo->status == CifsGood)) | 2293 | else |
| 2249 | CIFSSMBLogoff(xid, pSesInfo); | 2294 | cifs_put_tcp_session(srvTcp); |
| 2250 | else { | ||
| 2251 | cFYI(1, ("No session or bad tcon")); | ||
| 2252 | if (pSesInfo->server) | ||
| 2253 | cifs_put_tcp_session( | ||
| 2254 | pSesInfo->server); | ||
| 2255 | } | ||
| 2256 | sesInfoFree(pSesInfo); | ||
| 2257 | /* pSesInfo = NULL; */ | ||
| 2258 | } | ||
| 2259 | } | ||
| 2260 | } else { | 2295 | } else { |
| 2261 | atomic_inc(&tcon->useCount); | 2296 | atomic_inc(&tcon->useCount); |
| 2262 | cifs_sb->tcon = tcon; | 2297 | cifs_sb->tcon = tcon; |
| @@ -3551,16 +3586,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
| 3551 | } | 3586 | } |
| 3552 | DeleteTconOplockQEntries(cifs_sb->tcon); | 3587 | DeleteTconOplockQEntries(cifs_sb->tcon); |
| 3553 | tconInfoFree(cifs_sb->tcon); | 3588 | tconInfoFree(cifs_sb->tcon); |
| 3554 | if ((ses) && (ses->server)) { | 3589 | cifs_put_smb_ses(ses); |
| 3555 | /* save off task so we do not refer to ses later */ | ||
| 3556 | cFYI(1, ("About to do SMBLogoff ")); | ||
| 3557 | rc = CIFSSMBLogoff(xid, ses); | ||
| 3558 | if (rc == -EBUSY) { | ||
| 3559 | FreeXid(xid); | ||
| 3560 | return 0; | ||
| 3561 | } | ||
| 3562 | } else | ||
| 3563 | cFYI(1, ("No session or bad tcon")); | ||
| 3564 | } | 3590 | } |
| 3565 | 3591 | ||
| 3566 | cifs_sb->tcon = NULL; | 3592 | cifs_sb->tcon = NULL; |
| @@ -3568,8 +3594,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
| 3568 | cifs_sb->prepathlen = 0; | 3594 | cifs_sb->prepathlen = 0; |
| 3569 | cifs_sb->prepath = NULL; | 3595 | cifs_sb->prepath = NULL; |
| 3570 | kfree(tmp); | 3596 | kfree(tmp); |
| 3571 | if (ses) | ||
| 3572 | sesInfoFree(ses); | ||
| 3573 | 3597 | ||
| 3574 | FreeXid(xid); | 3598 | FreeXid(xid); |
| 3575 | return rc; | 3599 | return rc; |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 88786ba02d27..46c8c7baccba 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -75,12 +75,11 @@ sesInfoAlloc(void) | |||
| 75 | 75 | ||
| 76 | ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); | 76 | ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); |
| 77 | if (ret_buf) { | 77 | if (ret_buf) { |
| 78 | write_lock(&GlobalSMBSeslock); | ||
| 79 | atomic_inc(&sesInfoAllocCount); | 78 | atomic_inc(&sesInfoAllocCount); |
| 80 | ret_buf->status = CifsNew; | 79 | ret_buf->status = CifsNew; |
| 81 | list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList); | 80 | ++ret_buf->ses_count; |
| 81 | INIT_LIST_HEAD(&ret_buf->smb_ses_list); | ||
| 82 | init_MUTEX(&ret_buf->sesSem); | 82 | init_MUTEX(&ret_buf->sesSem); |
| 83 | write_unlock(&GlobalSMBSeslock); | ||
| 84 | } | 83 | } |
| 85 | return ret_buf; | 84 | return ret_buf; |
| 86 | } | 85 | } |
| @@ -93,10 +92,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free) | |||
| 93 | return; | 92 | return; |
| 94 | } | 93 | } |
| 95 | 94 | ||
| 96 | write_lock(&GlobalSMBSeslock); | ||
| 97 | atomic_dec(&sesInfoAllocCount); | 95 | atomic_dec(&sesInfoAllocCount); |
| 98 | list_del(&buf_to_free->cifsSessionList); | ||
| 99 | write_unlock(&GlobalSMBSeslock); | ||
| 100 | kfree(buf_to_free->serverOS); | 96 | kfree(buf_to_free->serverOS); |
| 101 | kfree(buf_to_free->serverDomain); | 97 | kfree(buf_to_free->serverDomain); |
| 102 | kfree(buf_to_free->serverNOS); | 98 | kfree(buf_to_free->serverNOS); |
| @@ -350,9 +346,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
| 350 | if (current->fsuid != treeCon->ses->linux_uid) { | 346 | if (current->fsuid != treeCon->ses->linux_uid) { |
| 351 | cFYI(1, ("Multiuser mode and UID " | 347 | cFYI(1, ("Multiuser mode and UID " |
| 352 | "did not match tcon uid")); | 348 | "did not match tcon uid")); |
| 353 | read_lock(&GlobalSMBSeslock); | 349 | read_lock(&cifs_tcp_ses_lock); |
| 354 | list_for_each(temp_item, &GlobalSMBSessionList) { | 350 | list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) { |
| 355 | ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); | 351 | ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list); |
| 356 | if (ses->linux_uid == current->fsuid) { | 352 | if (ses->linux_uid == current->fsuid) { |
| 357 | if (ses->server == treeCon->ses->server) { | 353 | if (ses->server == treeCon->ses->server) { |
| 358 | cFYI(1, ("found matching uid substitute right smb_uid")); | 354 | cFYI(1, ("found matching uid substitute right smb_uid")); |
| @@ -364,7 +360,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
| 364 | } | 360 | } |
| 365 | } | 361 | } |
| 366 | } | 362 | } |
| 367 | read_unlock(&GlobalSMBSeslock); | 363 | read_unlock(&cifs_tcp_ses_lock); |
| 368 | } | 364 | } |
| 369 | } | 365 | } |
| 370 | } | 366 | } |
