diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 219 |
1 files changed, 182 insertions, 37 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 47360156cc54..d74367a08d51 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/mempool.h> | 30 | #include <linux/mempool.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/completion.h> | ||
33 | #include <linux/pagevec.h> | ||
32 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
33 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
34 | #include "cifspdu.h" | 36 | #include "cifspdu.h" |
@@ -44,6 +46,8 @@ | |||
44 | #define CIFS_PORT 445 | 46 | #define CIFS_PORT 445 |
45 | #define RFC1001_PORT 139 | 47 | #define RFC1001_PORT 139 |
46 | 48 | ||
49 | static DECLARE_COMPLETION(cifsd_complete); | ||
50 | |||
47 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | 51 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, |
48 | unsigned char *p24); | 52 | unsigned char *p24); |
49 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 53 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, |
@@ -60,6 +64,7 @@ struct smb_vol { | |||
60 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ | 64 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ |
61 | char *iocharset; /* local code page for mapping to and from Unicode */ | 65 | char *iocharset; /* local code page for mapping to and from Unicode */ |
62 | char source_rfc1001_name[16]; /* netbios name of client */ | 66 | char source_rfc1001_name[16]; /* netbios name of client */ |
67 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ | ||
63 | uid_t linux_uid; | 68 | uid_t linux_uid; |
64 | gid_t linux_gid; | 69 | gid_t linux_gid; |
65 | mode_t file_mode; | 70 | mode_t file_mode; |
@@ -74,6 +79,10 @@ struct smb_vol { | |||
74 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ | 79 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ |
75 | unsigned direct_io:1; | 80 | unsigned direct_io:1; |
76 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ | 81 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ |
82 | unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ | ||
83 | unsigned sfu_emul:1; | ||
84 | unsigned nocase; /* request case insensitive filenames */ | ||
85 | unsigned nobrl; /* disable sending byte range locks to srv */ | ||
77 | unsigned int rsize; | 86 | unsigned int rsize; |
78 | unsigned int wsize; | 87 | unsigned int wsize; |
79 | unsigned int sockopt; | 88 | unsigned int sockopt; |
@@ -82,7 +91,8 @@ struct smb_vol { | |||
82 | 91 | ||
83 | static int ipv4_connect(struct sockaddr_in *psin_server, | 92 | static int ipv4_connect(struct sockaddr_in *psin_server, |
84 | struct socket **csocket, | 93 | struct socket **csocket, |
85 | char * netb_name); | 94 | char * netb_name, |
95 | char * server_netb_name); | ||
86 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 96 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
87 | struct socket **csocket); | 97 | struct socket **csocket); |
88 | 98 | ||
@@ -175,9 +185,11 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
175 | } else { | 185 | } else { |
176 | rc = ipv4_connect(&server->addr.sockAddr, | 186 | rc = ipv4_connect(&server->addr.sockAddr, |
177 | &server->ssocket, | 187 | &server->ssocket, |
178 | server->workstation_RFC1001_name); | 188 | server->workstation_RFC1001_name, |
189 | server->server_RFC1001_name); | ||
179 | } | 190 | } |
180 | if(rc) { | 191 | if(rc) { |
192 | cFYI(1,("reconnect error %d",rc)); | ||
181 | msleep(3000); | 193 | msleep(3000); |
182 | } else { | 194 | } else { |
183 | atomic_inc(&tcpSesReconnectCount); | 195 | atomic_inc(&tcpSesReconnectCount); |
@@ -293,12 +305,12 @@ static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB) | |||
293 | byte_count += total_in_buf2; | 305 | byte_count += total_in_buf2; |
294 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); | 306 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); |
295 | 307 | ||
296 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); | 308 | byte_count = pTargetSMB->smb_buf_length; |
297 | byte_count += total_in_buf2; | 309 | byte_count += total_in_buf2; |
298 | 310 | ||
299 | /* BB also add check that we are not beyond maximum buffer size */ | 311 | /* BB also add check that we are not beyond maximum buffer size */ |
300 | 312 | ||
301 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | 313 | pTargetSMB->smb_buf_length = byte_count; |
302 | 314 | ||
303 | if(remaining == total_in_buf2) { | 315 | if(remaining == total_in_buf2) { |
304 | cFYI(1,("found the last secondary response")); | 316 | cFYI(1,("found the last secondary response")); |
@@ -323,7 +335,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
323 | struct cifsSesInfo *ses; | 335 | struct cifsSesInfo *ses; |
324 | struct task_struct *task_to_wake = NULL; | 336 | struct task_struct *task_to_wake = NULL; |
325 | struct mid_q_entry *mid_entry; | 337 | struct mid_q_entry *mid_entry; |
326 | char *temp; | 338 | char temp; |
327 | int isLargeBuf = FALSE; | 339 | int isLargeBuf = FALSE; |
328 | int isMultiRsp; | 340 | int isMultiRsp; |
329 | int reconnect; | 341 | int reconnect; |
@@ -337,6 +349,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
337 | atomic_inc(&tcpSesAllocCount); | 349 | atomic_inc(&tcpSesAllocCount); |
338 | length = tcpSesAllocCount.counter; | 350 | length = tcpSesAllocCount.counter; |
339 | write_unlock(&GlobalSMBSeslock); | 351 | write_unlock(&GlobalSMBSeslock); |
352 | complete(&cifsd_complete); | ||
340 | if(length > 1) { | 353 | if(length > 1) { |
341 | mempool_resize(cifs_req_poolp, | 354 | mempool_resize(cifs_req_poolp, |
342 | length + cifs_min_rcv, | 355 | length + cifs_min_rcv, |
@@ -424,22 +437,32 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
424 | continue; | 437 | continue; |
425 | } | 438 | } |
426 | 439 | ||
427 | /* the right amount was read from socket - 4 bytes */ | 440 | /* The right amount was read from socket - 4 bytes */ |
441 | /* so we can now interpret the length field */ | ||
442 | |||
443 | /* the first byte big endian of the length field, | ||
444 | is actually not part of the length but the type | ||
445 | with the most common, zero, as regular data */ | ||
446 | temp = *((char *) smb_buffer); | ||
428 | 447 | ||
448 | /* Note that FC 1001 length is big endian on the wire, | ||
449 | but we convert it here so it is always manipulated | ||
450 | as host byte order */ | ||
429 | pdu_length = ntohl(smb_buffer->smb_buf_length); | 451 | pdu_length = ntohl(smb_buffer->smb_buf_length); |
430 | cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); | 452 | smb_buffer->smb_buf_length = pdu_length; |
453 | |||
454 | cFYI(1,("rfc1002 length 0x%x)", pdu_length+4)); | ||
431 | 455 | ||
432 | temp = (char *) smb_buffer; | 456 | if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { |
433 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { | ||
434 | continue; | 457 | continue; |
435 | } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { | 458 | } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { |
436 | cFYI(1,("Good RFC 1002 session rsp")); | 459 | cFYI(1,("Good RFC 1002 session rsp")); |
437 | continue; | 460 | continue; |
438 | } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | 461 | } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { |
439 | /* we get this from Windows 98 instead of | 462 | /* we get this from Windows 98 instead of |
440 | an error on SMB negprot response */ | 463 | an error on SMB negprot response */ |
441 | cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", | 464 | cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", |
442 | temp[4])); | 465 | pdu_length)); |
443 | if(server->tcpStatus == CifsNew) { | 466 | if(server->tcpStatus == CifsNew) { |
444 | /* if nack on negprot (rather than | 467 | /* if nack on negprot (rather than |
445 | ret of smb negprot error) reconnecting | 468 | ret of smb negprot error) reconnecting |
@@ -461,9 +484,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
461 | wake_up(&server->response_q); | 484 | wake_up(&server->response_q); |
462 | continue; | 485 | continue; |
463 | } | 486 | } |
464 | } else if (temp[0] != (char) 0) { | 487 | } else if (temp != (char) 0) { |
465 | cERROR(1,("Unknown RFC 1002 frame")); | 488 | cERROR(1,("Unknown RFC 1002 frame")); |
466 | cifs_dump_mem(" Received Data: ", temp, length); | 489 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, |
490 | length); | ||
467 | cifs_reconnect(server); | 491 | cifs_reconnect(server); |
468 | csocket = server->ssocket; | 492 | csocket = server->ssocket; |
469 | continue; | 493 | continue; |
@@ -533,7 +557,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
533 | 557 | ||
534 | dump_smb(smb_buffer, length); | 558 | dump_smb(smb_buffer, length); |
535 | if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { | 559 | if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { |
536 | cERROR(1, ("Bad SMB Received ")); | 560 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); |
537 | continue; | 561 | continue; |
538 | } | 562 | } |
539 | 563 | ||
@@ -581,6 +605,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
581 | multi_t2_fnd: | 605 | multi_t2_fnd: |
582 | task_to_wake = mid_entry->tsk; | 606 | task_to_wake = mid_entry->tsk; |
583 | mid_entry->midState = MID_RESPONSE_RECEIVED; | 607 | mid_entry->midState = MID_RESPONSE_RECEIVED; |
608 | #ifdef CONFIG_CIFS_STATS2 | ||
609 | mid_entry->when_received = jiffies; | ||
610 | #endif | ||
584 | break; | 611 | break; |
585 | } | 612 | } |
586 | } | 613 | } |
@@ -598,7 +625,8 @@ multi_t2_fnd: | |||
598 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) | 625 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) |
599 | && (isMultiRsp == FALSE)) { | 626 | && (isMultiRsp == FALSE)) { |
600 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | 627 | cERROR(1, ("No task to wake, unknown frame rcvd!")); |
601 | cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); | 628 | cifs_dump_mem("Received Data is: ",(char *)smb_buffer, |
629 | sizeof(struct smb_hdr)); | ||
602 | } | 630 | } |
603 | } /* end while !EXITING */ | 631 | } /* end while !EXITING */ |
604 | 632 | ||
@@ -676,7 +704,7 @@ multi_t2_fnd: | |||
676 | msleep(125); | 704 | msleep(125); |
677 | } | 705 | } |
678 | 706 | ||
679 | if (list_empty(&server->pending_mid_q)) { | 707 | if (!list_empty(&server->pending_mid_q)) { |
680 | /* mpx threads have not exited yet give them | 708 | /* mpx threads have not exited yet give them |
681 | at least the smb send timeout time for long ops */ | 709 | at least the smb send timeout time for long ops */ |
682 | /* due to delays on oplock break requests, we need | 710 | /* due to delays on oplock break requests, we need |
@@ -713,7 +741,7 @@ multi_t2_fnd: | |||
713 | GFP_KERNEL); | 741 | GFP_KERNEL); |
714 | } | 742 | } |
715 | 743 | ||
716 | msleep(250); | 744 | complete_and_exit(&cifsd_complete, 0); |
717 | return 0; | 745 | return 0; |
718 | } | 746 | } |
719 | 747 | ||
@@ -737,7 +765,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
737 | toupper(system_utsname.nodename[i]); | 765 | toupper(system_utsname.nodename[i]); |
738 | } | 766 | } |
739 | vol->source_rfc1001_name[15] = 0; | 767 | vol->source_rfc1001_name[15] = 0; |
740 | 768 | /* null target name indicates to use *SMBSERVR default called name | |
769 | if we end up sending RFC1001 session initialize */ | ||
770 | vol->target_rfc1001_name[0] = 0; | ||
741 | vol->linux_uid = current->uid; /* current->euid instead? */ | 771 | vol->linux_uid = current->uid; /* current->euid instead? */ |
742 | vol->linux_gid = current->gid; | 772 | vol->linux_gid = current->gid; |
743 | vol->dir_mode = S_IRWXUGO; | 773 | vol->dir_mode = S_IRWXUGO; |
@@ -747,6 +777,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
747 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 777 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
748 | vol->rw = TRUE; | 778 | vol->rw = TRUE; |
749 | 779 | ||
780 | /* default is always to request posix paths. */ | ||
781 | vol->posix_paths = 1; | ||
782 | |||
750 | if (!options) | 783 | if (!options) |
751 | return 1; | 784 | return 1; |
752 | 785 | ||
@@ -987,7 +1020,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
987 | /* The string has 16th byte zero still from | 1020 | /* The string has 16th byte zero still from |
988 | set at top of the function */ | 1021 | set at top of the function */ |
989 | if((i==15) && (value[i] != 0)) | 1022 | if((i==15) && (value[i] != 0)) |
990 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); | 1023 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n"); |
1024 | } | ||
1025 | } else if (strnicmp(data, "servern", 7) == 0) { | ||
1026 | /* servernetbiosname specified override *SMBSERVER */ | ||
1027 | if (!value || !*value || (*value == ' ')) { | ||
1028 | cFYI(1,("empty server netbiosname specified")); | ||
1029 | } else { | ||
1030 | /* last byte, type, is 0x20 for servr type */ | ||
1031 | memset(vol->target_rfc1001_name,0x20,16); | ||
1032 | |||
1033 | for(i=0;i<15;i++) { | ||
1034 | /* BB are there cases in which a comma can be | ||
1035 | valid in this workstation netbios name (and need | ||
1036 | special handling)? */ | ||
1037 | |||
1038 | /* user or mount helper must uppercase netbiosname */ | ||
1039 | if (value[i]==0) | ||
1040 | break; | ||
1041 | else | ||
1042 | vol->target_rfc1001_name[i] = value[i]; | ||
1043 | } | ||
1044 | /* The string has 16th byte zero still from | ||
1045 | set at top of the function */ | ||
1046 | if((i==15) && (value[i] != 0)) | ||
1047 | printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n"); | ||
991 | } | 1048 | } |
992 | } else if (strnicmp(data, "credentials", 4) == 0) { | 1049 | } else if (strnicmp(data, "credentials", 4) == 0) { |
993 | /* ignore */ | 1050 | /* ignore */ |
@@ -1025,6 +1082,27 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
1025 | vol->remap = 1; | 1082 | vol->remap = 1; |
1026 | } else if (strnicmp(data, "nomapchars", 10) == 0) { | 1083 | } else if (strnicmp(data, "nomapchars", 10) == 0) { |
1027 | vol->remap = 0; | 1084 | vol->remap = 0; |
1085 | } else if (strnicmp(data, "sfu", 3) == 0) { | ||
1086 | vol->sfu_emul = 1; | ||
1087 | } else if (strnicmp(data, "nosfu", 5) == 0) { | ||
1088 | vol->sfu_emul = 0; | ||
1089 | } else if (strnicmp(data, "posixpaths", 10) == 0) { | ||
1090 | vol->posix_paths = 1; | ||
1091 | } else if (strnicmp(data, "noposixpaths", 12) == 0) { | ||
1092 | vol->posix_paths = 0; | ||
1093 | } else if ((strnicmp(data, "nocase", 6) == 0) || | ||
1094 | (strnicmp(data, "ignorecase", 10) == 0)) { | ||
1095 | vol->nocase = 1; | ||
1096 | } else if (strnicmp(data, "brl", 3) == 0) { | ||
1097 | vol->nobrl = 0; | ||
1098 | } else if ((strnicmp(data, "nobrl", 5) == 0) || | ||
1099 | (strnicmp(data, "nolock", 6) == 0)) { | ||
1100 | vol->nobrl = 1; | ||
1101 | /* turn off mandatory locking in mode | ||
1102 | if remote locking is turned off since the | ||
1103 | local vfs will do advisory */ | ||
1104 | if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP))) | ||
1105 | vol->file_mode = S_IALLUGO; | ||
1028 | } else if (strnicmp(data, "setuids", 7) == 0) { | 1106 | } else if (strnicmp(data, "setuids", 7) == 0) { |
1029 | vol->setuids = 1; | 1107 | vol->setuids = 1; |
1030 | } else if (strnicmp(data, "nosetuids", 9) == 0) { | 1108 | } else if (strnicmp(data, "nosetuids", 9) == 0) { |
@@ -1244,7 +1322,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length) | |||
1244 | 1322 | ||
1245 | static int | 1323 | static int |
1246 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1324 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, |
1247 | char * netbios_name) | 1325 | char * netbios_name, char * target_name) |
1248 | { | 1326 | { |
1249 | int rc = 0; | 1327 | int rc = 0; |
1250 | int connected = 0; | 1328 | int connected = 0; |
@@ -1309,10 +1387,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1309 | /* Eventually check for other socket options to change from | 1387 | /* Eventually check for other socket options to change from |
1310 | the default. sock_setsockopt not used because it expects | 1388 | the default. sock_setsockopt not used because it expects |
1311 | user space buffer */ | 1389 | user space buffer */ |
1390 | cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf, | ||
1391 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); | ||
1312 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1392 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
1393 | /* make the bufsizes depend on wsize/rsize and max requests */ | ||
1394 | if((*csocket)->sk->sk_sndbuf < (200 * 1024)) | ||
1395 | (*csocket)->sk->sk_sndbuf = 200 * 1024; | ||
1396 | if((*csocket)->sk->sk_rcvbuf < (140 * 1024)) | ||
1397 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | ||
1313 | 1398 | ||
1314 | /* send RFC1001 sessinit */ | 1399 | /* send RFC1001 sessinit */ |
1315 | |||
1316 | if(psin_server->sin_port == htons(RFC1001_PORT)) { | 1400 | if(psin_server->sin_port == htons(RFC1001_PORT)) { |
1317 | /* some servers require RFC1001 sessinit before sending | 1401 | /* some servers require RFC1001 sessinit before sending |
1318 | negprot - BB check reconnection in case where second | 1402 | negprot - BB check reconnection in case where second |
@@ -1322,8 +1406,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1322 | ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); | 1406 | ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); |
1323 | if(ses_init_buf) { | 1407 | if(ses_init_buf) { |
1324 | ses_init_buf->trailer.session_req.called_len = 32; | 1408 | ses_init_buf->trailer.session_req.called_len = 32; |
1325 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | 1409 | if(target_name && (target_name[0] != 0)) { |
1326 | DEFAULT_CIFS_CALLED_NAME,16); | 1410 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, |
1411 | target_name, 16); | ||
1412 | } else { | ||
1413 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | ||
1414 | DEFAULT_CIFS_CALLED_NAME,16); | ||
1415 | } | ||
1416 | |||
1327 | ses_init_buf->trailer.session_req.calling_len = 32; | 1417 | ses_init_buf->trailer.session_req.calling_len = 32; |
1328 | /* calling name ends in null (byte 16) from old smb | 1418 | /* calling name ends in null (byte 16) from old smb |
1329 | convention. */ | 1419 | convention. */ |
@@ -1556,7 +1646,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1556 | sin_server.sin_port = htons(volume_info.port); | 1646 | sin_server.sin_port = htons(volume_info.port); |
1557 | else | 1647 | else |
1558 | sin_server.sin_port = 0; | 1648 | sin_server.sin_port = 0; |
1559 | rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); | 1649 | rc = ipv4_connect(&sin_server,&csocket, |
1650 | volume_info.source_rfc1001_name, | ||
1651 | volume_info.target_rfc1001_name); | ||
1560 | if (rc < 0) { | 1652 | if (rc < 0) { |
1561 | cERROR(1, | 1653 | cERROR(1, |
1562 | ("Error connecting to IPv4 socket. Aborting operation")); | 1654 | ("Error connecting to IPv4 socket. Aborting operation")); |
@@ -1606,9 +1698,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1606 | kfree(volume_info.password); | 1698 | kfree(volume_info.password); |
1607 | FreeXid(xid); | 1699 | FreeXid(xid); |
1608 | return rc; | 1700 | return rc; |
1609 | } else | 1701 | } |
1610 | rc = 0; | 1702 | wait_for_completion(&cifsd_complete); |
1703 | rc = 0; | ||
1611 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); | 1704 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); |
1705 | memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16); | ||
1612 | srvTcp->sequence_number = 0; | 1706 | srvTcp->sequence_number = 0; |
1613 | } | 1707 | } |
1614 | } | 1708 | } |
@@ -1653,17 +1747,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1653 | 1747 | ||
1654 | /* search for existing tcon to this server share */ | 1748 | /* search for existing tcon to this server share */ |
1655 | if (!rc) { | 1749 | if (!rc) { |
1656 | if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) | 1750 | if(volume_info.rsize > CIFSMaxBufSize) { |
1751 | cERROR(1,("rsize %d too large, using MaxBufSize", | ||
1752 | volume_info.rsize)); | ||
1753 | cifs_sb->rsize = CIFSMaxBufSize; | ||
1754 | } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) | ||
1657 | cifs_sb->rsize = volume_info.rsize; | 1755 | cifs_sb->rsize = volume_info.rsize; |
1658 | else | 1756 | else /* default */ |
1659 | cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ | 1757 | cifs_sb->rsize = CIFSMaxBufSize; |
1660 | if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize)) | 1758 | |
1759 | if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) { | ||
1760 | cERROR(1,("wsize %d too large using 4096 instead", | ||
1761 | volume_info.wsize)); | ||
1762 | cifs_sb->wsize = 4096; | ||
1763 | } else if(volume_info.wsize) | ||
1661 | cifs_sb->wsize = volume_info.wsize; | 1764 | cifs_sb->wsize = volume_info.wsize; |
1662 | else | 1765 | else |
1663 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ | 1766 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ |
1664 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { | 1767 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { |
1665 | cifs_sb->rsize = PAGE_CACHE_SIZE; | 1768 | cifs_sb->rsize = PAGE_CACHE_SIZE; |
1666 | cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); | 1769 | /* Windows ME does this */ |
1770 | cFYI(1,("Attempt to set readsize for mount to less than one page (4096)")); | ||
1667 | } | 1771 | } |
1668 | cifs_sb->mnt_uid = volume_info.linux_uid; | 1772 | cifs_sb->mnt_uid = volume_info.linux_uid; |
1669 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1773 | cifs_sb->mnt_gid = volume_info.linux_gid; |
@@ -1681,8 +1785,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1681 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | 1785 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; |
1682 | if(volume_info.no_xattr) | 1786 | if(volume_info.no_xattr) |
1683 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | 1787 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; |
1788 | if(volume_info.sfu_emul) | ||
1789 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | ||
1790 | if(volume_info.nobrl) | ||
1791 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | ||
1792 | |||
1684 | if(volume_info.direct_io) { | 1793 | if(volume_info.direct_io) { |
1685 | cERROR(1,("mounting share using direct i/o")); | 1794 | cFYI(1,("mounting share using direct i/o")); |
1686 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 1795 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
1687 | } | 1796 | } |
1688 | 1797 | ||
@@ -1696,6 +1805,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1696 | to the same server share the last value passed in | 1805 | to the same server share the last value passed in |
1697 | for the retry flag is used */ | 1806 | for the retry flag is used */ |
1698 | tcon->retry = volume_info.retry; | 1807 | tcon->retry = volume_info.retry; |
1808 | tcon->nocase = volume_info.nocase; | ||
1699 | } else { | 1809 | } else { |
1700 | tcon = tconInfoAlloc(); | 1810 | tcon = tconInfoAlloc(); |
1701 | if (tcon == NULL) | 1811 | if (tcon == NULL) |
@@ -1724,6 +1834,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1724 | if (!rc) { | 1834 | if (!rc) { |
1725 | atomic_inc(&pSesInfo->inUse); | 1835 | atomic_inc(&pSesInfo->inUse); |
1726 | tcon->retry = volume_info.retry; | 1836 | tcon->retry = volume_info.retry; |
1837 | tcon->nocase = volume_info.nocase; | ||
1727 | } | 1838 | } |
1728 | } | 1839 | } |
1729 | } | 1840 | } |
@@ -1745,8 +1856,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1745 | spin_lock(&GlobalMid_Lock); | 1856 | spin_lock(&GlobalMid_Lock); |
1746 | srvTcp->tcpStatus = CifsExiting; | 1857 | srvTcp->tcpStatus = CifsExiting; |
1747 | spin_unlock(&GlobalMid_Lock); | 1858 | spin_unlock(&GlobalMid_Lock); |
1748 | if(srvTcp->tsk) | 1859 | if(srvTcp->tsk) { |
1749 | send_sig(SIGKILL,srvTcp->tsk,1); | 1860 | send_sig(SIGKILL,srvTcp->tsk,1); |
1861 | wait_for_completion(&cifsd_complete); | ||
1862 | } | ||
1750 | } | 1863 | } |
1751 | /* If find_unc succeeded then rc == 0 so we can not end */ | 1864 | /* If find_unc succeeded then rc == 0 so we can not end */ |
1752 | if (tcon) /* up accidently freeing someone elses tcon struct */ | 1865 | if (tcon) /* up accidently freeing someone elses tcon struct */ |
@@ -1759,8 +1872,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1759 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); | 1872 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); |
1760 | /* if the socketUseCount is now zero */ | 1873 | /* if the socketUseCount is now zero */ |
1761 | if((temp_rc == -ESHUTDOWN) && | 1874 | if((temp_rc == -ESHUTDOWN) && |
1762 | (pSesInfo->server->tsk)) | 1875 | (pSesInfo->server->tsk)) { |
1763 | send_sig(SIGKILL,pSesInfo->server->tsk,1); | 1876 | send_sig(SIGKILL,pSesInfo->server->tsk,1); |
1877 | wait_for_completion(&cifsd_complete); | ||
1878 | } | ||
1764 | } else | 1879 | } else |
1765 | cFYI(1, ("No session or bad tcon")); | 1880 | cFYI(1, ("No session or bad tcon")); |
1766 | sesInfoFree(pSesInfo); | 1881 | sesInfoFree(pSesInfo); |
@@ -1783,8 +1898,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1783 | cFYI(1,("server negotiated posix acl support")); | 1898 | cFYI(1,("server negotiated posix acl support")); |
1784 | sb->s_flags |= MS_POSIXACL; | 1899 | sb->s_flags |= MS_POSIXACL; |
1785 | } | 1900 | } |
1901 | |||
1902 | /* Try and negotiate POSIX pathnames if we can. */ | ||
1903 | if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & | ||
1904 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | ||
1905 | if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { | ||
1906 | cFYI(1,("negotiated posix pathnames support")); | ||
1907 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; | ||
1908 | } else { | ||
1909 | cFYI(1,("posix pathnames support requested but not supported")); | ||
1910 | } | ||
1911 | } | ||
1786 | } | 1912 | } |
1787 | } | 1913 | } |
1914 | if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) | ||
1915 | cifs_sb->wsize = min(cifs_sb->wsize, | ||
1916 | (tcon->ses->server->maxBuf - | ||
1917 | MAX_CIFS_HDR_SIZE)); | ||
1918 | if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) | ||
1919 | cifs_sb->rsize = min(cifs_sb->rsize, | ||
1920 | (tcon->ses->server->maxBuf - | ||
1921 | MAX_CIFS_HDR_SIZE)); | ||
1788 | } | 1922 | } |
1789 | 1923 | ||
1790 | /* volume_info.password is freed above when existing session found | 1924 | /* volume_info.password is freed above when existing session found |
@@ -1832,6 +1966,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1832 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 1966 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
1833 | NULL /* no tCon exists yet */ , 13 /* wct */ ); | 1967 | NULL /* no tCon exists yet */ , 13 /* wct */ ); |
1834 | 1968 | ||
1969 | smb_buffer->Mid = GetNextMid(ses->server); | ||
1835 | pSMB->req_no_secext.AndXCommand = 0xFF; | 1970 | pSMB->req_no_secext.AndXCommand = 0xFF; |
1836 | pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 1971 | pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
1837 | pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 1972 | pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
@@ -2107,6 +2242,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2107 | /* send SMBsessionSetup here */ | 2242 | /* send SMBsessionSetup here */ |
2108 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2243 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
2109 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2244 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
2245 | |||
2246 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2110 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2247 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
2111 | pSMB->req.AndXCommand = 0xFF; | 2248 | pSMB->req.AndXCommand = 0xFF; |
2112 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 2249 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
@@ -2373,6 +2510,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2373 | /* send SMBsessionSetup here */ | 2510 | /* send SMBsessionSetup here */ |
2374 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2511 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
2375 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2512 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
2513 | |||
2514 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2376 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2515 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
2377 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | 2516 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); |
2378 | 2517 | ||
@@ -2715,6 +2854,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2715 | /* send SMBsessionSetup here */ | 2854 | /* send SMBsessionSetup here */ |
2716 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2855 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
2717 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2856 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
2857 | |||
2858 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2718 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | 2859 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); |
2719 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2860 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
2720 | pSMB->req.AndXCommand = 0xFF; | 2861 | pSMB->req.AndXCommand = 0xFF; |
@@ -3086,6 +3227,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3086 | 3227 | ||
3087 | header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, | 3228 | header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, |
3088 | NULL /*no tid */ , 4 /*wct */ ); | 3229 | NULL /*no tid */ , 4 /*wct */ ); |
3230 | |||
3231 | smb_buffer->Mid = GetNextMid(ses->server); | ||
3089 | smb_buffer->Uid = ses->Suid; | 3232 | smb_buffer->Uid = ses->Suid; |
3090 | pSMB = (TCONX_REQ *) smb_buffer; | 3233 | pSMB = (TCONX_REQ *) smb_buffer; |
3091 | pSMBr = (TCONX_RSP *) smb_buffer_response; | 3234 | pSMBr = (TCONX_RSP *) smb_buffer_response; |
@@ -3207,8 +3350,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3207 | return 0; | 3350 | return 0; |
3208 | } else if (rc == -ESHUTDOWN) { | 3351 | } else if (rc == -ESHUTDOWN) { |
3209 | cFYI(1,("Waking up socket by sending it signal")); | 3352 | cFYI(1,("Waking up socket by sending it signal")); |
3210 | if(cifsd_task) | 3353 | if(cifsd_task) { |
3211 | send_sig(SIGKILL,cifsd_task,1); | 3354 | send_sig(SIGKILL,cifsd_task,1); |
3355 | wait_for_completion(&cifsd_complete); | ||
3356 | } | ||
3212 | rc = 0; | 3357 | rc = 0; |
3213 | } /* else - we have an smb session | 3358 | } /* else - we have an smb session |
3214 | left on this socket do not kill cifsd */ | 3359 | left on this socket do not kill cifsd */ |