diff options
author | Jeff Layton <jlayton@redhat.com> | 2008-11-15 11:12:47 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-11-16 22:14:12 -0500 |
commit | f1987b44f642e96176adc88b7ce23a1d74806f89 (patch) | |
tree | fceaebf6b6d7eb1d1150120c44a842cbce8347f6 /fs/cifs/cifs_debug.c | |
parent | d82c2df54e2f7e447476350848d8eccc8d2fe46a (diff) |
cifs: reinstate sharing of tree connections
Use a similar approach to the SMB session sharing. Add a list of tcons
attached to each SMB session. Move the refcount to non-atomic. Protect
all of the above with the cifs_tcp_ses_lock. Add functions to
properly find and put references to the tcons.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/cifs_debug.c')
-rw-r--r-- | fs/cifs/cifs_debug.c | 236 |
1 files changed, 128 insertions, 108 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 59841a68b0b6..1d6dfa8923ca 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -107,12 +107,13 @@ 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, *tmp2, *tmp3; | 110 | struct list_head *tmp1, *tmp2, *tmp3; |
111 | struct mid_q_entry *mid_entry; | 111 | struct mid_q_entry *mid_entry; |
112 | struct TCP_Server_Info *server; | 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, j; |
116 | __u32 dev_type; | ||
116 | 117 | ||
117 | seq_puts(m, | 118 | seq_puts(m, |
118 | "Display Internal CIFS Data Structures for Debugging\n" | 119 | "Display Internal CIFS Data Structures for Debugging\n" |
@@ -123,8 +124,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
123 | 124 | ||
124 | i = 0; | 125 | i = 0; |
125 | read_lock(&cifs_tcp_ses_lock); | 126 | read_lock(&cifs_tcp_ses_lock); |
126 | list_for_each(tmp, &cifs_tcp_ses_list) { | 127 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
127 | server = list_entry(tmp, struct TCP_Server_Info, | 128 | server = list_entry(tmp1, struct TCP_Server_Info, |
128 | tcp_ses_list); | 129 | tcp_ses_list); |
129 | i++; | 130 | i++; |
130 | list_for_each(tmp2, &server->smb_ses_list) { | 131 | list_for_each(tmp2, &server->smb_ses_list) { |
@@ -133,12 +134,12 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
133 | if ((ses->serverDomain == NULL) || | 134 | if ((ses->serverDomain == NULL) || |
134 | (ses->serverOS == NULL) || | 135 | (ses->serverOS == NULL) || |
135 | (ses->serverNOS == NULL)) { | 136 | (ses->serverNOS == NULL)) { |
136 | seq_printf(m, "\nentry for %s not fully " | 137 | seq_printf(m, "\n%d) entry for %s not fully " |
137 | "displayed\n\t", ses->serverName); | 138 | "displayed\n\t", i, ses->serverName); |
138 | } else { | 139 | } else { |
139 | seq_printf(m, | 140 | seq_printf(m, |
140 | "\n%d) Name: %s Domain: %s Mounts: %d OS:" | 141 | "\n%d) Name: %s Domain: %s Uses: %d OS:" |
141 | " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB" | 142 | " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB" |
142 | " session status: %d\t", | 143 | " session status: %d\t", |
143 | i, ses->serverName, ses->serverDomain, | 144 | i, ses->serverName, ses->serverDomain, |
144 | ses->ses_count, ses->serverOS, ses->serverNOS, | 145 | ses->ses_count, ses->serverOS, ses->serverNOS, |
@@ -156,14 +157,44 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
156 | atomic_read(&server->num_waiters)); | 157 | atomic_read(&server->num_waiters)); |
157 | #endif | 158 | #endif |
158 | 159 | ||
159 | seq_puts(m, "\nMIDs:\n"); | 160 | seq_puts(m, "\n\tShares:"); |
161 | j = 0; | ||
162 | list_for_each(tmp3, &ses->tcon_list) { | ||
163 | tcon = list_entry(tmp3, struct cifsTconInfo, | ||
164 | tcon_list); | ||
165 | ++j; | ||
166 | dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); | ||
167 | seq_printf(m, "\n\t%d) %s Mounts: %d ", j, | ||
168 | tcon->treeName, tcon->tc_count); | ||
169 | if (tcon->nativeFileSystem) { | ||
170 | seq_printf(m, "Type: %s ", | ||
171 | tcon->nativeFileSystem); | ||
172 | } | ||
173 | seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" | ||
174 | "\nPathComponentMax: %d Status: 0x%d", | ||
175 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), | ||
176 | le32_to_cpu(tcon->fsAttrInfo.Attributes), | ||
177 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), | ||
178 | tcon->tidStatus); | ||
179 | if (dev_type == FILE_DEVICE_DISK) | ||
180 | seq_puts(m, " type: DISK "); | ||
181 | else if (dev_type == FILE_DEVICE_CD_ROM) | ||
182 | seq_puts(m, " type: CDROM "); | ||
183 | else | ||
184 | seq_printf(m, " type: %d ", dev_type); | ||
185 | |||
186 | if (tcon->need_reconnect) | ||
187 | seq_puts(m, "\tDISCONNECTED "); | ||
188 | seq_putc(m, '\n'); | ||
189 | } | ||
190 | |||
191 | seq_puts(m, "\n\tMIDs:\n"); | ||
160 | 192 | ||
161 | spin_lock(&GlobalMid_Lock); | 193 | spin_lock(&GlobalMid_Lock); |
162 | list_for_each(tmp3, &server->pending_mid_q) { | 194 | list_for_each(tmp3, &server->pending_mid_q) { |
163 | mid_entry = list_entry(tmp3, struct | 195 | mid_entry = list_entry(tmp3, struct mid_q_entry, |
164 | mid_q_entry, | ||
165 | qhead); | 196 | qhead); |
166 | seq_printf(m, "State: %d com: %d pid:" | 197 | seq_printf(m, "\tState: %d com: %d pid:" |
167 | " %d tsk: %p mid %d\n", | 198 | " %d tsk: %p mid %d\n", |
168 | mid_entry->midState, | 199 | mid_entry->midState, |
169 | (int)mid_entry->command, | 200 | (int)mid_entry->command, |
@@ -177,41 +208,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
177 | read_unlock(&cifs_tcp_ses_lock); | 208 | read_unlock(&cifs_tcp_ses_lock); |
178 | seq_putc(m, '\n'); | 209 | seq_putc(m, '\n'); |
179 | 210 | ||
180 | seq_puts(m, "Shares:"); | ||
181 | |||
182 | i = 0; | ||
183 | read_lock(&GlobalSMBSeslock); | ||
184 | list_for_each(tmp, &GlobalTreeConnectionList) { | ||
185 | __u32 dev_type; | ||
186 | i++; | ||
187 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | ||
188 | dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); | ||
189 | seq_printf(m, "\n%d) %s Uses: %d ", i, | ||
190 | tcon->treeName, atomic_read(&tcon->useCount)); | ||
191 | if (tcon->nativeFileSystem) { | ||
192 | seq_printf(m, "Type: %s ", | ||
193 | tcon->nativeFileSystem); | ||
194 | } | ||
195 | seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" | ||
196 | "\nPathComponentMax: %d Status: %d", | ||
197 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), | ||
198 | le32_to_cpu(tcon->fsAttrInfo.Attributes), | ||
199 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), | ||
200 | tcon->tidStatus); | ||
201 | if (dev_type == FILE_DEVICE_DISK) | ||
202 | seq_puts(m, " type: DISK "); | ||
203 | else if (dev_type == FILE_DEVICE_CD_ROM) | ||
204 | seq_puts(m, " type: CDROM "); | ||
205 | else | ||
206 | seq_printf(m, " type: %d ", dev_type); | ||
207 | |||
208 | if (tcon->need_reconnect) | ||
209 | seq_puts(m, "\tDISCONNECTED "); | ||
210 | } | ||
211 | read_unlock(&GlobalSMBSeslock); | ||
212 | |||
213 | seq_putc(m, '\n'); | ||
214 | |||
215 | /* BB add code to dump additional info such as TCP session info now */ | 211 | /* BB add code to dump additional info such as TCP session info now */ |
216 | return 0; | 212 | return 0; |
217 | } | 213 | } |
@@ -235,7 +231,9 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
235 | { | 231 | { |
236 | char c; | 232 | char c; |
237 | int rc; | 233 | int rc; |
238 | struct list_head *tmp; | 234 | struct list_head *tmp1, *tmp2, *tmp3; |
235 | struct TCP_Server_Info *server; | ||
236 | struct cifsSesInfo *ses; | ||
239 | struct cifsTconInfo *tcon; | 237 | struct cifsTconInfo *tcon; |
240 | 238 | ||
241 | rc = get_user(c, buffer); | 239 | rc = get_user(c, buffer); |
@@ -243,33 +241,42 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
243 | return rc; | 241 | return rc; |
244 | 242 | ||
245 | if (c == '1' || c == 'y' || c == 'Y' || c == '0') { | 243 | if (c == '1' || c == 'y' || c == 'Y' || c == '0') { |
246 | read_lock(&GlobalSMBSeslock); | ||
247 | #ifdef CONFIG_CIFS_STATS2 | 244 | #ifdef CONFIG_CIFS_STATS2 |
248 | atomic_set(&totBufAllocCount, 0); | 245 | atomic_set(&totBufAllocCount, 0); |
249 | atomic_set(&totSmBufAllocCount, 0); | 246 | atomic_set(&totSmBufAllocCount, 0); |
250 | #endif /* CONFIG_CIFS_STATS2 */ | 247 | #endif /* CONFIG_CIFS_STATS2 */ |
251 | list_for_each(tmp, &GlobalTreeConnectionList) { | 248 | read_lock(&cifs_tcp_ses_lock); |
252 | tcon = list_entry(tmp, struct cifsTconInfo, | 249 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
253 | cifsConnectionList); | 250 | server = list_entry(tmp1, struct TCP_Server_Info, |
254 | atomic_set(&tcon->num_smbs_sent, 0); | 251 | tcp_ses_list); |
255 | atomic_set(&tcon->num_writes, 0); | 252 | list_for_each(tmp2, &server->smb_session_list) { |
256 | atomic_set(&tcon->num_reads, 0); | 253 | ses = list_entry(tmp2, struct cifsSesInfo, |
257 | atomic_set(&tcon->num_oplock_brks, 0); | 254 | smb_session_list); |
258 | atomic_set(&tcon->num_opens, 0); | 255 | list_for_each(tmp3, &ses->tcon_list) { |
259 | atomic_set(&tcon->num_closes, 0); | 256 | tcon = list_entry(tmp3, |
260 | atomic_set(&tcon->num_deletes, 0); | 257 | struct cifsTconInfo, |
261 | atomic_set(&tcon->num_mkdirs, 0); | 258 | tcon_list); |
262 | atomic_set(&tcon->num_rmdirs, 0); | 259 | atomic_set(&tcon->num_smbs_sent, 0); |
263 | atomic_set(&tcon->num_renames, 0); | 260 | atomic_set(&tcon->num_writes, 0); |
264 | atomic_set(&tcon->num_t2renames, 0); | 261 | atomic_set(&tcon->num_reads, 0); |
265 | atomic_set(&tcon->num_ffirst, 0); | 262 | atomic_set(&tcon->num_oplock_brks, 0); |
266 | atomic_set(&tcon->num_fnext, 0); | 263 | atomic_set(&tcon->num_opens, 0); |
267 | atomic_set(&tcon->num_fclose, 0); | 264 | atomic_set(&tcon->num_closes, 0); |
268 | atomic_set(&tcon->num_hardlinks, 0); | 265 | atomic_set(&tcon->num_deletes, 0); |
269 | atomic_set(&tcon->num_symlinks, 0); | 266 | atomic_set(&tcon->num_mkdirs, 0); |
270 | atomic_set(&tcon->num_locks, 0); | 267 | atomic_set(&tcon->num_rmdirs, 0); |
268 | atomic_set(&tcon->num_renames, 0); | ||
269 | atomic_set(&tcon->num_t2renames, 0); | ||
270 | atomic_set(&tcon->num_ffirst, 0); | ||
271 | atomic_set(&tcon->num_fnext, 0); | ||
272 | atomic_set(&tcon->num_fclose, 0); | ||
273 | atomic_set(&tcon->num_hardlinks, 0); | ||
274 | atomic_set(&tcon->num_symlinks, 0); | ||
275 | atomic_set(&tcon->num_locks, 0); | ||
276 | } | ||
277 | } | ||
271 | } | 278 | } |
272 | read_unlock(&GlobalSMBSeslock); | 279 | read_unlock(&cifs_tcp_ses_lock); |
273 | } | 280 | } |
274 | 281 | ||
275 | return count; | 282 | return count; |
@@ -278,7 +285,9 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
278 | static int cifs_stats_proc_show(struct seq_file *m, void *v) | 285 | static int cifs_stats_proc_show(struct seq_file *m, void *v) |
279 | { | 286 | { |
280 | int i; | 287 | int i; |
281 | struct list_head *tmp; | 288 | struct list_head *tmp1, *tmp2, *tmp3; |
289 | struct TCP_Server_Info *server; | ||
290 | struct cifsSesInfo *ses; | ||
282 | struct cifsTconInfo *tcon; | 291 | struct cifsTconInfo *tcon; |
283 | 292 | ||
284 | seq_printf(m, | 293 | seq_printf(m, |
@@ -307,44 +316,55 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) | |||
307 | GlobalCurrentXid, GlobalMaxActiveXid); | 316 | GlobalCurrentXid, GlobalMaxActiveXid); |
308 | 317 | ||
309 | i = 0; | 318 | i = 0; |
310 | read_lock(&GlobalSMBSeslock); | 319 | read_lock(&cifs_tcp_ses_lock); |
311 | list_for_each(tmp, &GlobalTreeConnectionList) { | 320 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
312 | i++; | 321 | server = list_entry(tmp1, struct TCP_Server_Info, |
313 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 322 | tcp_ses_list); |
314 | seq_printf(m, "\n%d) %s", i, tcon->treeName); | 323 | list_for_each(tmp2, &server->smb_ses_list) { |
315 | if (tcon->need_reconnect) | 324 | ses = list_entry(tmp2, struct cifsSesInfo, |
316 | seq_puts(m, "\tDISCONNECTED "); | 325 | smb_ses_list); |
317 | seq_printf(m, "\nSMBs: %d Oplock Breaks: %d", | 326 | list_for_each(tmp3, &ses->tcon_list) { |
318 | atomic_read(&tcon->num_smbs_sent), | 327 | tcon = list_entry(tmp3, |
319 | atomic_read(&tcon->num_oplock_brks)); | 328 | struct cifsTconInfo, |
320 | seq_printf(m, "\nReads: %d Bytes: %lld", | 329 | tcon_list); |
321 | atomic_read(&tcon->num_reads), | 330 | i++; |
322 | (long long)(tcon->bytes_read)); | 331 | seq_printf(m, "\n%d) %s", i, tcon->treeName); |
323 | seq_printf(m, "\nWrites: %d Bytes: %lld", | 332 | if (tcon->need_reconnect) |
324 | atomic_read(&tcon->num_writes), | 333 | seq_puts(m, "\tDISCONNECTED "); |
325 | (long long)(tcon->bytes_written)); | 334 | seq_printf(m, "\nSMBs: %d Oplock Breaks: %d", |
326 | seq_printf(m, | 335 | atomic_read(&tcon->num_smbs_sent), |
327 | "\nLocks: %d HardLinks: %d Symlinks: %d", | 336 | atomic_read(&tcon->num_oplock_brks)); |
328 | atomic_read(&tcon->num_locks), | 337 | seq_printf(m, "\nReads: %d Bytes: %lld", |
329 | atomic_read(&tcon->num_hardlinks), | 338 | atomic_read(&tcon->num_reads), |
330 | atomic_read(&tcon->num_symlinks)); | 339 | (long long)(tcon->bytes_read)); |
331 | 340 | seq_printf(m, "\nWrites: %d Bytes: %lld", | |
332 | seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d", | 341 | atomic_read(&tcon->num_writes), |
333 | atomic_read(&tcon->num_opens), | 342 | (long long)(tcon->bytes_written)); |
334 | atomic_read(&tcon->num_closes), | 343 | seq_printf(m, "\nLocks: %d HardLinks: %d " |
335 | atomic_read(&tcon->num_deletes)); | 344 | "Symlinks: %d", |
336 | seq_printf(m, "\nMkdirs: %d Rmdirs: %d", | 345 | atomic_read(&tcon->num_locks), |
337 | atomic_read(&tcon->num_mkdirs), | 346 | atomic_read(&tcon->num_hardlinks), |
338 | atomic_read(&tcon->num_rmdirs)); | 347 | atomic_read(&tcon->num_symlinks)); |
339 | seq_printf(m, "\nRenames: %d T2 Renames %d", | 348 | seq_printf(m, "\nOpens: %d Closes: %d" |
340 | atomic_read(&tcon->num_renames), | 349 | "Deletes: %d", |
341 | atomic_read(&tcon->num_t2renames)); | 350 | atomic_read(&tcon->num_opens), |
342 | seq_printf(m, "\nFindFirst: %d FNext %d FClose %d", | 351 | atomic_read(&tcon->num_closes), |
343 | atomic_read(&tcon->num_ffirst), | 352 | atomic_read(&tcon->num_deletes)); |
344 | atomic_read(&tcon->num_fnext), | 353 | seq_printf(m, "\nMkdirs: %d Rmdirs: %d", |
345 | atomic_read(&tcon->num_fclose)); | 354 | atomic_read(&tcon->num_mkdirs), |
355 | atomic_read(&tcon->num_rmdirs)); | ||
356 | seq_printf(m, "\nRenames: %d T2 Renames %d", | ||
357 | atomic_read(&tcon->num_renames), | ||
358 | atomic_read(&tcon->num_t2renames)); | ||
359 | seq_printf(m, "\nFindFirst: %d FNext %d " | ||
360 | "FClose %d", | ||
361 | atomic_read(&tcon->num_ffirst), | ||
362 | atomic_read(&tcon->num_fnext), | ||
363 | atomic_read(&tcon->num_fclose)); | ||
364 | } | ||
365 | } | ||
346 | } | 366 | } |
347 | read_unlock(&GlobalSMBSeslock); | 367 | read_unlock(&cifs_tcp_ses_lock); |
348 | 368 | ||
349 | seq_putc(m, '\n'); | 369 | seq_putc(m, '\n'); |
350 | return 0; | 370 | return 0; |