PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/fs/cifs/cifs_debug.c

https://gitlab.com/LiquidSmooth-Devices/android_kernel_htc_msm8974
C | 751 lines | 645 code | 85 blank | 21 comment | 133 complexity | 8d6d3b5f42e742c3b48051bf7924e892 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * fs/cifs_debug.c
  3. *
  4. * Copyright (C) International Business Machines Corp., 2000,2005
  5. *
  6. * Modified by Steve French (sfrench@us.ibm.com)
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  16. * the GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #include <linux/fs.h>
  23. #include <linux/string.h>
  24. #include <linux/ctype.h>
  25. #include <linux/module.h>
  26. #include <linux/proc_fs.h>
  27. #include <asm/uaccess.h>
  28. #include "cifspdu.h"
  29. #include "cifsglob.h"
  30. #include "cifsproto.h"
  31. #include "cifs_debug.h"
  32. #include "cifsfs.h"
  33. void
  34. cifs_dump_mem(char *label, void *data, int length)
  35. {
  36. int i, j;
  37. int *intptr = data;
  38. char *charptr = data;
  39. char buf[10], line[80];
  40. printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
  41. label, length, data);
  42. for (i = 0; i < length; i += 16) {
  43. line[0] = 0;
  44. for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
  45. sprintf(buf, " %08x", intptr[i / 4 + j]);
  46. strcat(line, buf);
  47. }
  48. buf[0] = ' ';
  49. buf[2] = 0;
  50. for (j = 0; (j < 16) && (i + j < length); j++) {
  51. buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
  52. strcat(line, buf);
  53. }
  54. printk(KERN_DEBUG "%s\n", line);
  55. }
  56. }
  57. #ifdef CONFIG_CIFS_DEBUG2
  58. void cifs_dump_detail(void *buf)
  59. {
  60. struct smb_hdr *smb = (struct smb_hdr *)buf;
  61. cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
  62. smb->Command, smb->Status.CifsError,
  63. smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
  64. cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb));
  65. }
  66. void cifs_dump_mids(struct TCP_Server_Info *server)
  67. {
  68. struct list_head *tmp;
  69. struct mid_q_entry *mid_entry;
  70. if (server == NULL)
  71. return;
  72. cERROR(1, "Dump pending requests:");
  73. spin_lock(&GlobalMid_Lock);
  74. list_for_each(tmp, &server->pending_mid_q) {
  75. mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
  76. cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu",
  77. mid_entry->mid_state,
  78. le16_to_cpu(mid_entry->command),
  79. mid_entry->pid,
  80. mid_entry->callback_data,
  81. mid_entry->mid);
  82. #ifdef CONFIG_CIFS_STATS2
  83. cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld",
  84. mid_entry->large_buf,
  85. mid_entry->resp_buf,
  86. mid_entry->when_received,
  87. jiffies);
  88. #endif
  89. cERROR(1, "IsMult: %d IsEnd: %d", mid_entry->multiRsp,
  90. mid_entry->multiEnd);
  91. if (mid_entry->resp_buf) {
  92. cifs_dump_detail(mid_entry->resp_buf);
  93. cifs_dump_mem("existing buf: ",
  94. mid_entry->resp_buf, 62);
  95. }
  96. }
  97. spin_unlock(&GlobalMid_Lock);
  98. }
  99. #endif
  100. #ifdef CONFIG_PROC_FS
  101. static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
  102. {
  103. struct list_head *tmp1, *tmp2, *tmp3;
  104. struct mid_q_entry *mid_entry;
  105. struct TCP_Server_Info *server;
  106. struct cifs_ses *ses;
  107. struct cifs_tcon *tcon;
  108. int i, j;
  109. __u32 dev_type;
  110. seq_puts(m,
  111. "Display Internal CIFS Data Structures for Debugging\n"
  112. "---------------------------------------------------\n");
  113. seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
  114. seq_printf(m, "Features:");
  115. #ifdef CONFIG_CIFS_DFS_UPCALL
  116. seq_printf(m, " dfs");
  117. #endif
  118. #ifdef CONFIG_CIFS_FSCACHE
  119. seq_printf(m, " fscache");
  120. #endif
  121. #ifdef CONFIG_CIFS_WEAK_PW_HASH
  122. seq_printf(m, " lanman");
  123. #endif
  124. #ifdef CONFIG_CIFS_POSIX
  125. seq_printf(m, " posix");
  126. #endif
  127. #ifdef CONFIG_CIFS_UPCALL
  128. seq_printf(m, " spnego");
  129. #endif
  130. #ifdef CONFIG_CIFS_XATTR
  131. seq_printf(m, " xattr");
  132. #endif
  133. #ifdef CONFIG_CIFS_ACL
  134. seq_printf(m, " acl");
  135. #endif
  136. seq_putc(m, '\n');
  137. seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
  138. seq_printf(m, "Servers:");
  139. i = 0;
  140. spin_lock(&cifs_tcp_ses_lock);
  141. list_for_each(tmp1, &cifs_tcp_ses_list) {
  142. server = list_entry(tmp1, struct TCP_Server_Info,
  143. tcp_ses_list);
  144. i++;
  145. list_for_each(tmp2, &server->smb_ses_list) {
  146. ses = list_entry(tmp2, struct cifs_ses,
  147. smb_ses_list);
  148. if ((ses->serverDomain == NULL) ||
  149. (ses->serverOS == NULL) ||
  150. (ses->serverNOS == NULL)) {
  151. seq_printf(m, "\n%d) entry for %s not fully "
  152. "displayed\n\t", i, ses->serverName);
  153. } else {
  154. seq_printf(m,
  155. "\n%d) Name: %s Domain: %s Uses: %d OS:"
  156. " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB"
  157. " session status: %d\t",
  158. i, ses->serverName, ses->serverDomain,
  159. ses->ses_count, ses->serverOS, ses->serverNOS,
  160. ses->capabilities, ses->status);
  161. }
  162. seq_printf(m, "TCP status: %d\n\tLocal Users To "
  163. "Server: %d SecMode: 0x%x Req On Wire: %d",
  164. server->tcpStatus, server->srv_count,
  165. server->sec_mode, in_flight(server));
  166. #ifdef CONFIG_CIFS_STATS2
  167. seq_printf(m, " In Send: %d In MaxReq Wait: %d",
  168. atomic_read(&server->in_send),
  169. atomic_read(&server->num_waiters));
  170. #endif
  171. seq_puts(m, "\n\tShares:");
  172. j = 0;
  173. list_for_each(tmp3, &ses->tcon_list) {
  174. tcon = list_entry(tmp3, struct cifs_tcon,
  175. tcon_list);
  176. ++j;
  177. dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
  178. seq_printf(m, "\n\t%d) %s Mounts: %d ", j,
  179. tcon->treeName, tcon->tc_count);
  180. if (tcon->nativeFileSystem) {
  181. seq_printf(m, "Type: %s ",
  182. tcon->nativeFileSystem);
  183. }
  184. seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
  185. "\nPathComponentMax: %d Status: 0x%d",
  186. le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
  187. le32_to_cpu(tcon->fsAttrInfo.Attributes),
  188. le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
  189. tcon->tidStatus);
  190. if (dev_type == FILE_DEVICE_DISK)
  191. seq_puts(m, " type: DISK ");
  192. else if (dev_type == FILE_DEVICE_CD_ROM)
  193. seq_puts(m, " type: CDROM ");
  194. else
  195. seq_printf(m, " type: %d ", dev_type);
  196. if (tcon->need_reconnect)
  197. seq_puts(m, "\tDISCONNECTED ");
  198. seq_putc(m, '\n');
  199. }
  200. seq_puts(m, "\n\tMIDs:\n");
  201. spin_lock(&GlobalMid_Lock);
  202. list_for_each(tmp3, &server->pending_mid_q) {
  203. mid_entry = list_entry(tmp3, struct mid_q_entry,
  204. qhead);
  205. seq_printf(m, "\tState: %d com: %d pid:"
  206. " %d cbdata: %p mid %llu\n",
  207. mid_entry->mid_state,
  208. le16_to_cpu(mid_entry->command),
  209. mid_entry->pid,
  210. mid_entry->callback_data,
  211. mid_entry->mid);
  212. }
  213. spin_unlock(&GlobalMid_Lock);
  214. }
  215. }
  216. spin_unlock(&cifs_tcp_ses_lock);
  217. seq_putc(m, '\n');
  218. return 0;
  219. }
  220. static int cifs_debug_data_proc_open(struct inode *inode, struct file *file)
  221. {
  222. return single_open(file, cifs_debug_data_proc_show, NULL);
  223. }
  224. static const struct file_operations cifs_debug_data_proc_fops = {
  225. .owner = THIS_MODULE,
  226. .open = cifs_debug_data_proc_open,
  227. .read = seq_read,
  228. .llseek = seq_lseek,
  229. .release = single_release,
  230. };
  231. #ifdef CONFIG_CIFS_STATS
  232. static ssize_t cifs_stats_proc_write(struct file *file,
  233. const char __user *buffer, size_t count, loff_t *ppos)
  234. {
  235. char c;
  236. int rc;
  237. struct list_head *tmp1, *tmp2, *tmp3;
  238. struct TCP_Server_Info *server;
  239. struct cifs_ses *ses;
  240. struct cifs_tcon *tcon;
  241. rc = get_user(c, buffer);
  242. if (rc)
  243. return rc;
  244. if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
  245. #ifdef CONFIG_CIFS_STATS2
  246. atomic_set(&totBufAllocCount, 0);
  247. atomic_set(&totSmBufAllocCount, 0);
  248. #endif
  249. spin_lock(&cifs_tcp_ses_lock);
  250. list_for_each(tmp1, &cifs_tcp_ses_list) {
  251. server = list_entry(tmp1, struct TCP_Server_Info,
  252. tcp_ses_list);
  253. list_for_each(tmp2, &server->smb_ses_list) {
  254. ses = list_entry(tmp2, struct cifs_ses,
  255. smb_ses_list);
  256. list_for_each(tmp3, &ses->tcon_list) {
  257. tcon = list_entry(tmp3,
  258. struct cifs_tcon,
  259. tcon_list);
  260. atomic_set(&tcon->num_smbs_sent, 0);
  261. atomic_set(&tcon->num_writes, 0);
  262. atomic_set(&tcon->num_reads, 0);
  263. atomic_set(&tcon->num_oplock_brks, 0);
  264. atomic_set(&tcon->num_opens, 0);
  265. atomic_set(&tcon->num_posixopens, 0);
  266. atomic_set(&tcon->num_posixmkdirs, 0);
  267. atomic_set(&tcon->num_closes, 0);
  268. atomic_set(&tcon->num_deletes, 0);
  269. atomic_set(&tcon->num_mkdirs, 0);
  270. atomic_set(&tcon->num_rmdirs, 0);
  271. atomic_set(&tcon->num_renames, 0);
  272. atomic_set(&tcon->num_t2renames, 0);
  273. atomic_set(&tcon->num_ffirst, 0);
  274. atomic_set(&tcon->num_fnext, 0);
  275. atomic_set(&tcon->num_fclose, 0);
  276. atomic_set(&tcon->num_hardlinks, 0);
  277. atomic_set(&tcon->num_symlinks, 0);
  278. atomic_set(&tcon->num_locks, 0);
  279. }
  280. }
  281. }
  282. spin_unlock(&cifs_tcp_ses_lock);
  283. }
  284. return count;
  285. }
  286. static int cifs_stats_proc_show(struct seq_file *m, void *v)
  287. {
  288. int i;
  289. struct list_head *tmp1, *tmp2, *tmp3;
  290. struct TCP_Server_Info *server;
  291. struct cifs_ses *ses;
  292. struct cifs_tcon *tcon;
  293. seq_printf(m,
  294. "Resources in use\nCIFS Session: %d\n",
  295. sesInfoAllocCount.counter);
  296. seq_printf(m, "Share (unique mount targets): %d\n",
  297. tconInfoAllocCount.counter);
  298. seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
  299. bufAllocCount.counter,
  300. cifs_min_rcv + tcpSesAllocCount.counter);
  301. seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
  302. smBufAllocCount.counter, cifs_min_small);
  303. #ifdef CONFIG_CIFS_STATS2
  304. seq_printf(m, "Total Large %d Small %d Allocations\n",
  305. atomic_read(&totBufAllocCount),
  306. atomic_read(&totSmBufAllocCount));
  307. #endif
  308. seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount));
  309. seq_printf(m,
  310. "\n%d session %d share reconnects\n",
  311. tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
  312. seq_printf(m,
  313. "Total vfs operations: %d maximum at one time: %d\n",
  314. GlobalCurrentXid, GlobalMaxActiveXid);
  315. i = 0;
  316. spin_lock(&cifs_tcp_ses_lock);
  317. list_for_each(tmp1, &cifs_tcp_ses_list) {
  318. server = list_entry(tmp1, struct TCP_Server_Info,
  319. tcp_ses_list);
  320. list_for_each(tmp2, &server->smb_ses_list) {
  321. ses = list_entry(tmp2, struct cifs_ses,
  322. smb_ses_list);
  323. list_for_each(tmp3, &ses->tcon_list) {
  324. tcon = list_entry(tmp3,
  325. struct cifs_tcon,
  326. tcon_list);
  327. i++;
  328. seq_printf(m, "\n%d) %s", i, tcon->treeName);
  329. if (tcon->need_reconnect)
  330. seq_puts(m, "\tDISCONNECTED ");
  331. seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
  332. atomic_read(&tcon->num_smbs_sent),
  333. atomic_read(&tcon->num_oplock_brks));
  334. seq_printf(m, "\nReads: %d Bytes: %lld",
  335. atomic_read(&tcon->num_reads),
  336. (long long)(tcon->bytes_read));
  337. seq_printf(m, "\nWrites: %d Bytes: %lld",
  338. atomic_read(&tcon->num_writes),
  339. (long long)(tcon->bytes_written));
  340. seq_printf(m, "\nFlushes: %d",
  341. atomic_read(&tcon->num_flushes));
  342. seq_printf(m, "\nLocks: %d HardLinks: %d "
  343. "Symlinks: %d",
  344. atomic_read(&tcon->num_locks),
  345. atomic_read(&tcon->num_hardlinks),
  346. atomic_read(&tcon->num_symlinks));
  347. seq_printf(m, "\nOpens: %d Closes: %d "
  348. "Deletes: %d",
  349. atomic_read(&tcon->num_opens),
  350. atomic_read(&tcon->num_closes),
  351. atomic_read(&tcon->num_deletes));
  352. seq_printf(m, "\nPosix Opens: %d "
  353. "Posix Mkdirs: %d",
  354. atomic_read(&tcon->num_posixopens),
  355. atomic_read(&tcon->num_posixmkdirs));
  356. seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
  357. atomic_read(&tcon->num_mkdirs),
  358. atomic_read(&tcon->num_rmdirs));
  359. seq_printf(m, "\nRenames: %d T2 Renames %d",
  360. atomic_read(&tcon->num_renames),
  361. atomic_read(&tcon->num_t2renames));
  362. seq_printf(m, "\nFindFirst: %d FNext %d "
  363. "FClose %d",
  364. atomic_read(&tcon->num_ffirst),
  365. atomic_read(&tcon->num_fnext),
  366. atomic_read(&tcon->num_fclose));
  367. }
  368. }
  369. }
  370. spin_unlock(&cifs_tcp_ses_lock);
  371. seq_putc(m, '\n');
  372. return 0;
  373. }
  374. static int cifs_stats_proc_open(struct inode *inode, struct file *file)
  375. {
  376. return single_open(file, cifs_stats_proc_show, NULL);
  377. }
  378. static const struct file_operations cifs_stats_proc_fops = {
  379. .owner = THIS_MODULE,
  380. .open = cifs_stats_proc_open,
  381. .read = seq_read,
  382. .llseek = seq_lseek,
  383. .release = single_release,
  384. .write = cifs_stats_proc_write,
  385. };
  386. #endif
  387. static struct proc_dir_entry *proc_fs_cifs;
  388. static const struct file_operations cifsFYI_proc_fops;
  389. static const struct file_operations cifs_lookup_cache_proc_fops;
  390. static const struct file_operations traceSMB_proc_fops;
  391. static const struct file_operations cifs_multiuser_mount_proc_fops;
  392. static const struct file_operations cifs_security_flags_proc_fops;
  393. static const struct file_operations cifs_linux_ext_proc_fops;
  394. void
  395. cifs_proc_init(void)
  396. {
  397. proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
  398. if (proc_fs_cifs == NULL)
  399. return;
  400. proc_create("DebugData", 0, proc_fs_cifs, &cifs_debug_data_proc_fops);
  401. #ifdef CONFIG_CIFS_STATS
  402. proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops);
  403. #endif
  404. proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops);
  405. proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops);
  406. proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs,
  407. &cifs_linux_ext_proc_fops);
  408. proc_create("MultiuserMount", 0, proc_fs_cifs,
  409. &cifs_multiuser_mount_proc_fops);
  410. proc_create("SecurityFlags", 0, proc_fs_cifs,
  411. &cifs_security_flags_proc_fops);
  412. proc_create("LookupCacheEnabled", 0, proc_fs_cifs,
  413. &cifs_lookup_cache_proc_fops);
  414. }
  415. void
  416. cifs_proc_clean(void)
  417. {
  418. if (proc_fs_cifs == NULL)
  419. return;
  420. remove_proc_entry("DebugData", proc_fs_cifs);
  421. remove_proc_entry("cifsFYI", proc_fs_cifs);
  422. remove_proc_entry("traceSMB", proc_fs_cifs);
  423. #ifdef CONFIG_CIFS_STATS
  424. remove_proc_entry("Stats", proc_fs_cifs);
  425. #endif
  426. remove_proc_entry("MultiuserMount", proc_fs_cifs);
  427. remove_proc_entry("SecurityFlags", proc_fs_cifs);
  428. remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
  429. remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
  430. remove_proc_entry("fs/cifs", NULL);
  431. }
  432. static int cifsFYI_proc_show(struct seq_file *m, void *v)
  433. {
  434. seq_printf(m, "%d\n", cifsFYI);
  435. return 0;
  436. }
  437. static int cifsFYI_proc_open(struct inode *inode, struct file *file)
  438. {
  439. return single_open(file, cifsFYI_proc_show, NULL);
  440. }
  441. static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
  442. size_t count, loff_t *ppos)
  443. {
  444. char c;
  445. int rc;
  446. rc = get_user(c, buffer);
  447. if (rc)
  448. return rc;
  449. if (c == '0' || c == 'n' || c == 'N')
  450. cifsFYI = 0;
  451. else if (c == '1' || c == 'y' || c == 'Y')
  452. cifsFYI = 1;
  453. else if ((c > '1') && (c <= '9'))
  454. cifsFYI = (int) (c - '0');
  455. return count;
  456. }
  457. static const struct file_operations cifsFYI_proc_fops = {
  458. .owner = THIS_MODULE,
  459. .open = cifsFYI_proc_open,
  460. .read = seq_read,
  461. .llseek = seq_lseek,
  462. .release = single_release,
  463. .write = cifsFYI_proc_write,
  464. };
  465. static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
  466. {
  467. seq_printf(m, "%d\n", linuxExtEnabled);
  468. return 0;
  469. }
  470. static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
  471. {
  472. return single_open(file, cifs_linux_ext_proc_show, NULL);
  473. }
  474. static ssize_t cifs_linux_ext_proc_write(struct file *file,
  475. const char __user *buffer, size_t count, loff_t *ppos)
  476. {
  477. char c;
  478. int rc;
  479. rc = get_user(c, buffer);
  480. if (rc)
  481. return rc;
  482. if (c == '0' || c == 'n' || c == 'N')
  483. linuxExtEnabled = 0;
  484. else if (c == '1' || c == 'y' || c == 'Y')
  485. linuxExtEnabled = 1;
  486. return count;
  487. }
  488. static const struct file_operations cifs_linux_ext_proc_fops = {
  489. .owner = THIS_MODULE,
  490. .open = cifs_linux_ext_proc_open,
  491. .read = seq_read,
  492. .llseek = seq_lseek,
  493. .release = single_release,
  494. .write = cifs_linux_ext_proc_write,
  495. };
  496. static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
  497. {
  498. seq_printf(m, "%d\n", lookupCacheEnabled);
  499. return 0;
  500. }
  501. static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
  502. {
  503. return single_open(file, cifs_lookup_cache_proc_show, NULL);
  504. }
  505. static ssize_t cifs_lookup_cache_proc_write(struct file *file,
  506. const char __user *buffer, size_t count, loff_t *ppos)
  507. {
  508. char c;
  509. int rc;
  510. rc = get_user(c, buffer);
  511. if (rc)
  512. return rc;
  513. if (c == '0' || c == 'n' || c == 'N')
  514. lookupCacheEnabled = 0;
  515. else if (c == '1' || c == 'y' || c == 'Y')
  516. lookupCacheEnabled = 1;
  517. return count;
  518. }
  519. static const struct file_operations cifs_lookup_cache_proc_fops = {
  520. .owner = THIS_MODULE,
  521. .open = cifs_lookup_cache_proc_open,
  522. .read = seq_read,
  523. .llseek = seq_lseek,
  524. .release = single_release,
  525. .write = cifs_lookup_cache_proc_write,
  526. };
  527. static int traceSMB_proc_show(struct seq_file *m, void *v)
  528. {
  529. seq_printf(m, "%d\n", traceSMB);
  530. return 0;
  531. }
  532. static int traceSMB_proc_open(struct inode *inode, struct file *file)
  533. {
  534. return single_open(file, traceSMB_proc_show, NULL);
  535. }
  536. static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
  537. size_t count, loff_t *ppos)
  538. {
  539. char c;
  540. int rc;
  541. rc = get_user(c, buffer);
  542. if (rc)
  543. return rc;
  544. if (c == '0' || c == 'n' || c == 'N')
  545. traceSMB = 0;
  546. else if (c == '1' || c == 'y' || c == 'Y')
  547. traceSMB = 1;
  548. return count;
  549. }
  550. static const struct file_operations traceSMB_proc_fops = {
  551. .owner = THIS_MODULE,
  552. .open = traceSMB_proc_open,
  553. .read = seq_read,
  554. .llseek = seq_lseek,
  555. .release = single_release,
  556. .write = traceSMB_proc_write,
  557. };
  558. static int cifs_multiuser_mount_proc_show(struct seq_file *m, void *v)
  559. {
  560. seq_printf(m, "%d\n", multiuser_mount);
  561. return 0;
  562. }
  563. static int cifs_multiuser_mount_proc_open(struct inode *inode, struct file *fh)
  564. {
  565. return single_open(fh, cifs_multiuser_mount_proc_show, NULL);
  566. }
  567. static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
  568. const char __user *buffer, size_t count, loff_t *ppos)
  569. {
  570. char c;
  571. int rc;
  572. static bool warned;
  573. rc = get_user(c, buffer);
  574. if (rc)
  575. return rc;
  576. if (c == '0' || c == 'n' || c == 'N')
  577. multiuser_mount = 0;
  578. else if (c == '1' || c == 'y' || c == 'Y') {
  579. multiuser_mount = 1;
  580. if (!warned) {
  581. warned = true;
  582. printk(KERN_WARNING "CIFS VFS: The legacy multiuser "
  583. "mount code is scheduled to be deprecated in "
  584. "3.5. Please switch to using the multiuser "
  585. "mount option.");
  586. }
  587. }
  588. return count;
  589. }
  590. static const struct file_operations cifs_multiuser_mount_proc_fops = {
  591. .owner = THIS_MODULE,
  592. .open = cifs_multiuser_mount_proc_open,
  593. .read = seq_read,
  594. .llseek = seq_lseek,
  595. .release = single_release,
  596. .write = cifs_multiuser_mount_proc_write,
  597. };
  598. static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
  599. {
  600. seq_printf(m, "0x%x\n", global_secflags);
  601. return 0;
  602. }
  603. static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
  604. {
  605. return single_open(file, cifs_security_flags_proc_show, NULL);
  606. }
  607. static ssize_t cifs_security_flags_proc_write(struct file *file,
  608. const char __user *buffer, size_t count, loff_t *ppos)
  609. {
  610. unsigned int flags;
  611. char flags_string[12];
  612. char c;
  613. if ((count < 1) || (count > 11))
  614. return -EINVAL;
  615. memset(flags_string, 0, 12);
  616. if (copy_from_user(flags_string, buffer, count))
  617. return -EFAULT;
  618. if (count < 3) {
  619. c = flags_string[0];
  620. if (c == '0' || c == 'n' || c == 'N') {
  621. global_secflags = CIFSSEC_DEF;
  622. return count;
  623. } else if (c == '1' || c == 'y' || c == 'Y') {
  624. global_secflags = CIFSSEC_MAX;
  625. return count;
  626. } else if (!isdigit(c)) {
  627. cERROR(1, "invalid flag %c", c);
  628. return -EINVAL;
  629. }
  630. }
  631. flags = simple_strtoul(flags_string, NULL, 0);
  632. cFYI(1, "sec flags 0x%x", flags);
  633. if (flags <= 0) {
  634. cERROR(1, "invalid security flags %s", flags_string);
  635. return -EINVAL;
  636. }
  637. if (flags & ~CIFSSEC_MASK) {
  638. cERROR(1, "attempt to set unsupported security flags 0x%x",
  639. flags & ~CIFSSEC_MASK);
  640. return -EINVAL;
  641. }
  642. global_secflags = flags;
  643. if (global_secflags & CIFSSEC_MUST_SIGN) {
  644. global_secflags |= CIFSSEC_MAY_SIGN;
  645. cFYI(1, "packet signing now required");
  646. } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
  647. cFYI(1, "packet signing disabled");
  648. }
  649. return count;
  650. }
  651. static const struct file_operations cifs_security_flags_proc_fops = {
  652. .owner = THIS_MODULE,
  653. .open = cifs_security_flags_proc_open,
  654. .read = seq_read,
  655. .llseek = seq_lseek,
  656. .release = single_release,
  657. .write = cifs_security_flags_proc_write,
  658. };
  659. #else
  660. inline void cifs_proc_init(void)
  661. {
  662. }
  663. inline void cifs_proc_clean(void)
  664. {
  665. }
  666. #endif