diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/CHANGES | 8 | ||||
-rw-r--r-- | fs/cifs/asn1.c | 258 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 53 | ||||
-rw-r--r-- | fs/cifs/cifs_spnego.c | 18 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 71 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 24 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 46 | ||||
-rw-r--r-- | fs/cifs/connect.c | 173 | ||||
-rw-r--r-- | fs/cifs/dir.c | 67 | ||||
-rw-r--r-- | fs/cifs/file.c | 19 | ||||
-rw-r--r-- | fs/cifs/inode.c | 419 | ||||
-rw-r--r-- | fs/cifs/transport.c | 1 |
14 files changed, 652 insertions, 509 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 1f3465201fdf..f5d0083e09fa 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,3 +1,11 @@ | |||
1 | Version 1.54 | ||
2 | ------------ | ||
3 | Fix premature write failure on congested networks (we would give up | ||
4 | on EAGAIN from the socket too quickly on large writes). | ||
5 | Cifs_mkdir and cifs_create now respect the setgid bit on parent dir. | ||
6 | Fix endian problems in acl (mode from/to cifs acl) on bigendian | ||
7 | architectures. | ||
8 | |||
1 | Version 1.53 | 9 | Version 1.53 |
2 | ------------ | 10 | ------------ |
3 | DFS support added (Microsoft Distributed File System client support needed | 11 | DFS support added (Microsoft Distributed File System client support needed |
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 6bb440b257b0..5fabd2caf93c 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c | |||
@@ -483,6 +483,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
483 | 483 | ||
484 | asn1_open(&ctx, security_blob, length); | 484 | asn1_open(&ctx, security_blob, length); |
485 | 485 | ||
486 | /* GSSAPI header */ | ||
486 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 487 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
487 | cFYI(1, ("Error decoding negTokenInit header")); | 488 | cFYI(1, ("Error decoding negTokenInit header")); |
488 | return 0; | 489 | return 0; |
@@ -490,153 +491,142 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
490 | || (tag != ASN1_EOC)) { | 491 | || (tag != ASN1_EOC)) { |
491 | cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag)); | 492 | cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag)); |
492 | return 0; | 493 | return 0; |
493 | } else { | 494 | } |
494 | /* remember to free obj->oid */ | ||
495 | rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); | ||
496 | if (rc) { | ||
497 | if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { | ||
498 | rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); | ||
499 | if (rc) { | ||
500 | rc = compare_oid(oid, oidlen, | ||
501 | SPNEGO_OID, | ||
502 | SPNEGO_OID_LEN); | ||
503 | kfree(oid); | ||
504 | } | ||
505 | } else | ||
506 | rc = 0; | ||
507 | } | ||
508 | 495 | ||
509 | if (!rc) { | 496 | /* Check for SPNEGO OID -- remember to free obj->oid */ |
510 | cFYI(1, ("Error decoding negTokenInit header")); | 497 | rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); |
511 | return 0; | 498 | if (rc) { |
512 | } | 499 | if ((tag == ASN1_OJI) && (con == ASN1_PRI) && |
500 | (cls == ASN1_UNI)) { | ||
501 | rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); | ||
502 | if (rc) { | ||
503 | rc = compare_oid(oid, oidlen, SPNEGO_OID, | ||
504 | SPNEGO_OID_LEN); | ||
505 | kfree(oid); | ||
506 | } | ||
507 | } else | ||
508 | rc = 0; | ||
509 | } | ||
513 | 510 | ||
514 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 511 | /* SPNEGO OID not present or garbled -- bail out */ |
515 | cFYI(1, ("Error decoding negTokenInit")); | 512 | if (!rc) { |
516 | return 0; | 513 | cFYI(1, ("Error decoding negTokenInit header")); |
517 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON) | 514 | return 0; |
518 | || (tag != ASN1_EOC)) { | 515 | } |
519 | cFYI(1, | ||
520 | ("cls = %d con = %d tag = %d end = %p (%d) exit 0", | ||
521 | cls, con, tag, end, *end)); | ||
522 | return 0; | ||
523 | } | ||
524 | 516 | ||
525 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 517 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
526 | cFYI(1, ("Error decoding negTokenInit")); | 518 | cFYI(1, ("Error decoding negTokenInit")); |
527 | return 0; | 519 | return 0; |
528 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) | 520 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON) |
529 | || (tag != ASN1_SEQ)) { | 521 | || (tag != ASN1_EOC)) { |
530 | cFYI(1, | 522 | cFYI(1, |
531 | ("cls = %d con = %d tag = %d end = %p (%d) exit 1", | 523 | ("cls = %d con = %d tag = %d end = %p (%d) exit 0", |
532 | cls, con, tag, end, *end)); | 524 | cls, con, tag, end, *end)); |
533 | return 0; | 525 | return 0; |
534 | } | 526 | } |
535 | 527 | ||
536 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 528 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
537 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); | 529 | cFYI(1, ("Error decoding negTokenInit")); |
538 | return 0; | 530 | return 0; |
539 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON) | 531 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) |
540 | || (tag != ASN1_EOC)) { | 532 | || (tag != ASN1_SEQ)) { |
541 | cFYI(1, | 533 | cFYI(1, |
542 | ("cls = %d con = %d tag = %d end = %p (%d) exit 0", | 534 | ("cls = %d con = %d tag = %d end = %p (%d) exit 1", |
543 | cls, con, tag, end, *end)); | 535 | cls, con, tag, end, *end)); |
544 | return 0; | 536 | return 0; |
545 | } | 537 | } |
546 | 538 | ||
547 | if (asn1_header_decode | 539 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
548 | (&ctx, &sequence_end, &cls, &con, &tag) == 0) { | 540 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); |
549 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); | 541 | return 0; |
550 | return 0; | 542 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON) |
551 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) | 543 | || (tag != ASN1_EOC)) { |
552 | || (tag != ASN1_SEQ)) { | 544 | cFYI(1, |
553 | cFYI(1, | 545 | ("cls = %d con = %d tag = %d end = %p (%d) exit 0", |
554 | ("cls = %d con = %d tag = %d end = %p (%d) exit 1", | 546 | cls, con, tag, end, *end)); |
555 | cls, con, tag, end, *end)); | 547 | return 0; |
556 | return 0; | 548 | } |
557 | } | ||
558 | 549 | ||
559 | while (!asn1_eoc_decode(&ctx, sequence_end)) { | 550 | if (asn1_header_decode |
560 | rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); | 551 | (&ctx, &sequence_end, &cls, &con, &tag) == 0) { |
561 | if (!rc) { | 552 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); |
562 | cFYI(1, | 553 | return 0; |
563 | ("Error decoding negTokenInit hdr exit2")); | 554 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) |
564 | return 0; | 555 | || (tag != ASN1_SEQ)) { |
565 | } | 556 | cFYI(1, |
566 | if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { | 557 | ("cls = %d con = %d tag = %d end = %p (%d) exit 1", |
567 | if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { | 558 | cls, con, tag, end, *end)); |
568 | 559 | return 0; | |
569 | cFYI(1, | 560 | } |
570 | ("OID len = %d oid = 0x%lx 0x%lx " | ||
571 | "0x%lx 0x%lx", | ||
572 | oidlen, *oid, *(oid + 1), | ||
573 | *(oid + 2), *(oid + 3))); | ||
574 | |||
575 | if (compare_oid(oid, oidlen, | ||
576 | MSKRB5_OID, | ||
577 | MSKRB5_OID_LEN)) | ||
578 | use_kerberos = true; | ||
579 | else if (compare_oid(oid, oidlen, | ||
580 | KRB5_OID, | ||
581 | KRB5_OID_LEN)) | ||
582 | use_kerberos = true; | ||
583 | else if (compare_oid(oid, oidlen, | ||
584 | NTLMSSP_OID, | ||
585 | NTLMSSP_OID_LEN)) | ||
586 | use_ntlmssp = true; | ||
587 | |||
588 | kfree(oid); | ||
589 | } | ||
590 | } else { | ||
591 | cFYI(1, ("Should be an oid what is going on?")); | ||
592 | } | ||
593 | } | ||
594 | 561 | ||
595 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 562 | while (!asn1_eoc_decode(&ctx, sequence_end)) { |
596 | cFYI(1, | 563 | rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); |
597 | ("Error decoding last part negTokenInit exit3")); | 564 | if (!rc) { |
598 | return 0; | ||
599 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { | ||
600 | /* tag = 3 indicating mechListMIC */ | ||
601 | cFYI(1, | 565 | cFYI(1, |
602 | ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", | 566 | ("Error decoding negTokenInit hdr exit2")); |
603 | cls, con, tag, end, *end)); | ||
604 | return 0; | 567 | return 0; |
605 | } | 568 | } |
606 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 569 | if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { |
607 | cFYI(1, | 570 | if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { |
608 | ("Error decoding last part negTokenInit exit5")); | 571 | |
609 | return 0; | 572 | cFYI(1, ("OID len = %d oid = 0x%lx 0x%lx " |
610 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) | 573 | "0x%lx 0x%lx", oidlen, *oid, |
611 | || (tag != ASN1_SEQ)) { | 574 | *(oid + 1), *(oid + 2), *(oid + 3))); |
612 | cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", | 575 | |
613 | cls, con, tag, end, *end)); | 576 | if (compare_oid(oid, oidlen, MSKRB5_OID, |
577 | MSKRB5_OID_LEN)) | ||
578 | use_kerberos = true; | ||
579 | else if (compare_oid(oid, oidlen, KRB5_OID, | ||
580 | KRB5_OID_LEN)) | ||
581 | use_kerberos = true; | ||
582 | else if (compare_oid(oid, oidlen, NTLMSSP_OID, | ||
583 | NTLMSSP_OID_LEN)) | ||
584 | use_ntlmssp = true; | ||
585 | |||
586 | kfree(oid); | ||
587 | } | ||
588 | } else { | ||
589 | cFYI(1, ("Should be an oid what is going on?")); | ||
614 | } | 590 | } |
591 | } | ||
615 | 592 | ||
616 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 593 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
617 | cFYI(1, | 594 | cFYI(1, ("Error decoding last part negTokenInit exit3")); |
618 | ("Error decoding last part negTokenInit exit 7")); | 595 | return 0; |
619 | return 0; | 596 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { |
620 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { | 597 | /* tag = 3 indicating mechListMIC */ |
621 | cFYI(1, | 598 | cFYI(1, ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", |
622 | ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)", | 599 | cls, con, tag, end, *end)); |
623 | cls, con, tag, end, *end)); | 600 | return 0; |
624 | return 0; | 601 | } |
625 | } | 602 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
626 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 603 | cFYI(1, ("Error decoding last part negTokenInit exit5")); |
627 | cFYI(1, | 604 | return 0; |
628 | ("Error decoding last part negTokenInit exit9")); | 605 | } else if ((cls != ASN1_UNI) || (con != ASN1_CON) |
629 | return 0; | 606 | || (tag != ASN1_SEQ)) { |
630 | } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) | 607 | cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", |
631 | || (tag != ASN1_GENSTR)) { | 608 | cls, con, tag, end, *end)); |
632 | cFYI(1, | 609 | } |
633 | ("Exit10 cls = %d con = %d tag = %d end = %p (%d)", | 610 | |
634 | cls, con, tag, end, *end)); | 611 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
635 | return 0; | 612 | cFYI(1, ("Error decoding last part negTokenInit exit 7")); |
636 | } | 613 | return 0; |
637 | cFYI(1, ("Need to call asn1_octets_decode() function for %s", | 614 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { |
638 | ctx.pointer)); /* is this UTF-8 or ASCII? */ | 615 | cFYI(1, ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)", |
616 | cls, con, tag, end, *end)); | ||
617 | return 0; | ||
618 | } | ||
619 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | ||
620 | cFYI(1, ("Error decoding last part negTokenInit exit9")); | ||
621 | return 0; | ||
622 | } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) | ||
623 | || (tag != ASN1_GENSTR)) { | ||
624 | cFYI(1, ("Exit10 cls = %d con = %d tag = %d end = %p (%d)", | ||
625 | cls, con, tag, end, *end)); | ||
626 | return 0; | ||
639 | } | 627 | } |
628 | cFYI(1, ("Need to call asn1_octets_decode() function for %s", | ||
629 | ctx.pointer)); /* is this UTF-8 or ASCII? */ | ||
640 | 630 | ||
641 | if (use_kerberos) | 631 | if (use_kerberos) |
642 | *secType = Kerberos; | 632 | *secType = Kerberos; |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 688a2d42153f..69a12aae91d3 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -79,27 +79,25 @@ void cifs_dump_mids(struct TCP_Server_Info *server) | |||
79 | spin_lock(&GlobalMid_Lock); | 79 | spin_lock(&GlobalMid_Lock); |
80 | list_for_each(tmp, &server->pending_mid_q) { | 80 | list_for_each(tmp, &server->pending_mid_q) { |
81 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 81 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
82 | if (mid_entry) { | 82 | cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", |
83 | cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", | 83 | mid_entry->midState, |
84 | mid_entry->midState, | 84 | (int)mid_entry->command, |
85 | (int)mid_entry->command, | 85 | mid_entry->pid, |
86 | mid_entry->pid, | 86 | mid_entry->tsk, |
87 | mid_entry->tsk, | 87 | mid_entry->mid)); |
88 | mid_entry->mid)); | ||
89 | #ifdef CONFIG_CIFS_STATS2 | 88 | #ifdef CONFIG_CIFS_STATS2 |
90 | cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld", | 89 | cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld", |
91 | mid_entry->largeBuf, | 90 | mid_entry->largeBuf, |
92 | mid_entry->resp_buf, | 91 | mid_entry->resp_buf, |
93 | mid_entry->when_received, | 92 | mid_entry->when_received, |
94 | jiffies)); | 93 | jiffies)); |
95 | #endif /* STATS2 */ | 94 | #endif /* STATS2 */ |
96 | cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp, | 95 | cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp, |
97 | mid_entry->multiEnd)); | 96 | mid_entry->multiEnd)); |
98 | if (mid_entry->resp_buf) { | 97 | if (mid_entry->resp_buf) { |
99 | cifs_dump_detail(mid_entry->resp_buf); | 98 | cifs_dump_detail(mid_entry->resp_buf); |
100 | cifs_dump_mem("existing buf: ", | 99 | cifs_dump_mem("existing buf: ", |
101 | mid_entry->resp_buf, 62); | 100 | mid_entry->resp_buf, 62); |
102 | } | ||
103 | } | 101 | } |
104 | } | 102 | } |
105 | spin_unlock(&GlobalMid_Lock); | 103 | spin_unlock(&GlobalMid_Lock); |
@@ -163,16 +161,13 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
163 | mid_entry = list_entry(tmp1, struct | 161 | mid_entry = list_entry(tmp1, struct |
164 | mid_q_entry, | 162 | mid_q_entry, |
165 | qhead); | 163 | qhead); |
166 | if (mid_entry) { | 164 | seq_printf(m, "State: %d com: %d pid:" |
167 | seq_printf(m, | 165 | " %d tsk: %p mid %d\n", |
168 | "State: %d com: %d pid:" | 166 | mid_entry->midState, |
169 | " %d tsk: %p mid %d\n", | 167 | (int)mid_entry->command, |
170 | mid_entry->midState, | 168 | mid_entry->pid, |
171 | (int)mid_entry->command, | 169 | mid_entry->tsk, |
172 | mid_entry->pid, | 170 | mid_entry->mid); |
173 | mid_entry->tsk, | ||
174 | mid_entry->mid); | ||
175 | } | ||
176 | } | 171 | } |
177 | spin_unlock(&GlobalMid_Lock); | 172 | spin_unlock(&GlobalMid_Lock); |
178 | } | 173 | } |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 7013aaff6aed..2434ab0e8791 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -66,8 +66,8 @@ struct key_type cifs_spnego_key_type = { | |||
66 | .describe = user_describe, | 66 | .describe = user_describe, |
67 | }; | 67 | }; |
68 | 68 | ||
69 | #define MAX_VER_STR_LEN 9 /* length of longest version string e.g. | 69 | #define MAX_VER_STR_LEN 8 /* length of longest version string e.g. |
70 | strlen(";ver=0xFF") */ | 70 | strlen("ver=0xFF") */ |
71 | #define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg | 71 | #define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg |
72 | in future could have strlen(";sec=ntlmsspi") */ | 72 | in future could have strlen(";sec=ntlmsspi") */ |
73 | #define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ | 73 | #define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ |
@@ -81,11 +81,15 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
81 | struct key *spnego_key; | 81 | struct key *spnego_key; |
82 | const char *hostname = server->hostname; | 82 | const char *hostname = server->hostname; |
83 | 83 | ||
84 | /* BB: come up with better scheme for determining length */ | 84 | /* length of fields (with semicolons): ver=0xyz ip4=ipaddress |
85 | /* length of fields (with semicolons): ver=0xyz ipv4= ipaddress host= | 85 | host=hostname sec=mechanism uid=0xFF user=username */ |
86 | hostname sec=mechanism uid=0x uid */ | 86 | desc_len = MAX_VER_STR_LEN + |
87 | desc_len = MAX_VER_STR_LEN + 5 + MAX_IPV6_ADDR_LEN + 1 + 6 + | 87 | 6 /* len of "host=" */ + strlen(hostname) + |
88 | strlen(hostname) + MAX_MECH_STR_LEN + 8 + (sizeof(uid_t) * 2); | 88 | 5 /* len of ";ipv4=" */ + MAX_IPV6_ADDR_LEN + |
89 | MAX_MECH_STR_LEN + | ||
90 | 7 /* len of ";uid=0x" */ + (sizeof(uid_t) * 2) + | ||
91 | 6 /* len of ";user=" */ + strlen(sesInfo->userName) + 1; | ||
92 | |||
89 | spnego_key = ERR_PTR(-ENOMEM); | 93 | spnego_key = ERR_PTR(-ENOMEM); |
90 | description = kzalloc(desc_len, GFP_KERNEL); | 94 | description = kzalloc(desc_len, GFP_KERNEL); |
91 | if (description == NULL) | 95 | if (description == NULL) |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 1ec7076f7b24..e8da4ee761b5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -930,36 +930,34 @@ static int cifs_oplock_thread(void *dummyarg) | |||
930 | schedule_timeout(39*HZ); | 930 | schedule_timeout(39*HZ); |
931 | } else { | 931 | } else { |
932 | oplock_item = list_entry(GlobalOplock_Q.next, | 932 | oplock_item = list_entry(GlobalOplock_Q.next, |
933 | struct oplock_q_entry, qhead); | 933 | struct oplock_q_entry, qhead); |
934 | if (oplock_item) { | 934 | cFYI(1, ("found oplock item to write out")); |
935 | cFYI(1, ("found oplock item to write out")); | 935 | pTcon = oplock_item->tcon; |
936 | pTcon = oplock_item->tcon; | 936 | inode = oplock_item->pinode; |
937 | inode = oplock_item->pinode; | 937 | netfid = oplock_item->netfid; |
938 | netfid = oplock_item->netfid; | 938 | spin_unlock(&GlobalMid_Lock); |
939 | spin_unlock(&GlobalMid_Lock); | 939 | DeleteOplockQEntry(oplock_item); |
940 | DeleteOplockQEntry(oplock_item); | 940 | /* can not grab inode sem here since it would |
941 | /* can not grab inode sem here since it would | ||
942 | deadlock when oplock received on delete | 941 | deadlock when oplock received on delete |
943 | since vfs_unlink holds the i_mutex across | 942 | since vfs_unlink holds the i_mutex across |
944 | the call */ | 943 | the call */ |
945 | /* mutex_lock(&inode->i_mutex);*/ | 944 | /* mutex_lock(&inode->i_mutex);*/ |
946 | if (S_ISREG(inode->i_mode)) { | 945 | if (S_ISREG(inode->i_mode)) { |
947 | rc = | 946 | rc = filemap_fdatawrite(inode->i_mapping); |
948 | filemap_fdatawrite(inode->i_mapping); | 947 | if (CIFS_I(inode)->clientCanCacheRead == 0) { |
949 | if (CIFS_I(inode)->clientCanCacheRead | 948 | waitrc = filemap_fdatawait( |
950 | == 0) { | 949 | inode->i_mapping); |
951 | waitrc = filemap_fdatawait(inode->i_mapping); | 950 | invalidate_remote_inode(inode); |
952 | invalidate_remote_inode(inode); | 951 | } |
953 | } | 952 | if (rc == 0) |
954 | if (rc == 0) | 953 | rc = waitrc; |
955 | rc = waitrc; | 954 | } else |
956 | } else | 955 | rc = 0; |
957 | rc = 0; | 956 | /* mutex_unlock(&inode->i_mutex);*/ |
958 | /* mutex_unlock(&inode->i_mutex);*/ | 957 | if (rc) |
959 | if (rc) | 958 | CIFS_I(inode)->write_behind_rc = rc; |
960 | CIFS_I(inode)->write_behind_rc = rc; | 959 | cFYI(1, ("Oplock flush inode %p rc %d", |
961 | cFYI(1, ("Oplock flush inode %p rc %d", | 960 | inode, rc)); |
962 | inode, rc)); | ||
963 | 961 | ||
964 | /* releasing stale oplock after recent reconnect | 962 | /* releasing stale oplock after recent reconnect |
965 | of smb session using a now incorrect file | 963 | of smb session using a now incorrect file |
@@ -967,15 +965,13 @@ static int cifs_oplock_thread(void *dummyarg) | |||
967 | not bother sending an oplock release if session | 965 | not bother sending an oplock release if session |
968 | to server still is disconnected since oplock | 966 | to server still is disconnected since oplock |
969 | already released by the server in that case */ | 967 | already released by the server in that case */ |
970 | if (pTcon->tidStatus != CifsNeedReconnect) { | 968 | if (pTcon->tidStatus != CifsNeedReconnect) { |
971 | rc = CIFSSMBLock(0, pTcon, netfid, | 969 | rc = CIFSSMBLock(0, pTcon, netfid, |
972 | 0 /* len */ , 0 /* offset */, 0, | 970 | 0 /* len */ , 0 /* offset */, 0, |
973 | 0, LOCKING_ANDX_OPLOCK_RELEASE, | 971 | 0, LOCKING_ANDX_OPLOCK_RELEASE, |
974 | false /* wait flag */); | 972 | false /* wait flag */); |
975 | cFYI(1, ("Oplock release rc = %d", rc)); | 973 | cFYI(1, ("Oplock release rc = %d", rc)); |
976 | } | 974 | } |
977 | } else | ||
978 | spin_unlock(&GlobalMid_Lock); | ||
979 | set_current_state(TASK_INTERRUPTIBLE); | 975 | set_current_state(TASK_INTERRUPTIBLE); |
980 | schedule_timeout(1); /* yield in case q were corrupt */ | 976 | schedule_timeout(1); /* yield in case q were corrupt */ |
981 | } | 977 | } |
@@ -1001,8 +997,7 @@ static int cifs_dnotify_thread(void *dummyarg) | |||
1001 | list_for_each(tmp, &GlobalSMBSessionList) { | 997 | list_for_each(tmp, &GlobalSMBSessionList) { |
1002 | ses = list_entry(tmp, struct cifsSesInfo, | 998 | ses = list_entry(tmp, struct cifsSesInfo, |
1003 | cifsSessionList); | 999 | cifsSessionList); |
1004 | if (ses && ses->server && | 1000 | if (ses->server && atomic_read(&ses->server->inFlight)) |
1005 | atomic_read(&ses->server->inFlight)) | ||
1006 | wake_up_all(&ses->server->response_q); | 1001 | wake_up_all(&ses->server->response_q); |
1007 | } | 1002 | } |
1008 | read_unlock(&GlobalSMBSeslock); | 1003 | read_unlock(&GlobalSMBSeslock); |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 25a6cbd15529..135c965c4137 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -101,5 +101,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
101 | extern const struct export_operations cifs_export_ops; | 101 | extern const struct export_operations cifs_export_ops; |
102 | #endif /* EXPERIMENTAL */ | 102 | #endif /* EXPERIMENTAL */ |
103 | 103 | ||
104 | #define CIFS_VERSION "1.53" | 104 | #define CIFS_VERSION "1.54" |
105 | #endif /* _CIFSFS_H */ | 105 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 409abce12732..d2a073edd1b8 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -262,7 +262,7 @@ | |||
262 | */ | 262 | */ |
263 | #define CIFS_NO_HANDLE 0xFFFF | 263 | #define CIFS_NO_HANDLE 0xFFFF |
264 | 264 | ||
265 | #define NO_CHANGE_64 cpu_to_le64(0xFFFFFFFFFFFFFFFFULL) | 265 | #define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL |
266 | #define NO_CHANGE_32 0xFFFFFFFFUL | 266 | #define NO_CHANGE_32 0xFFFFFFFFUL |
267 | 267 | ||
268 | /* IPC$ in ASCII */ | 268 | /* IPC$ in ASCII */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b9f5e935f821..a729d083e6f4 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -172,12 +172,13 @@ extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon); | |||
172 | extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 172 | extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, |
173 | struct kstatfs *FSData); | 173 | struct kstatfs *FSData); |
174 | 174 | ||
175 | extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, | 175 | extern int CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, |
176 | const char *fileName, const FILE_BASIC_INFO *data, | 176 | const char *fileName, const FILE_BASIC_INFO *data, |
177 | const struct nls_table *nls_codepage, | 177 | const struct nls_table *nls_codepage, |
178 | int remap_special_chars); | 178 | int remap_special_chars); |
179 | extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | 179 | extern int CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
180 | const FILE_BASIC_INFO *data, __u16 fid); | 180 | const FILE_BASIC_INFO *data, __u16 fid, |
181 | __u32 pid_of_opener); | ||
181 | #if 0 | 182 | #if 0 |
182 | extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, | 183 | extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, |
183 | char *fileName, __u16 dos_attributes, | 184 | char *fileName, __u16 dos_attributes, |
@@ -191,9 +192,20 @@ extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, | |||
191 | extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, | 192 | extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, |
192 | __u64 size, __u16 fileHandle, __u32 opener_pid, | 193 | __u64 size, __u16 fileHandle, __u32 opener_pid, |
193 | bool AllocSizeFlag); | 194 | bool AllocSizeFlag); |
194 | extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, | 195 | |
195 | char *full_path, __u64 mode, __u64 uid, | 196 | struct cifs_unix_set_info_args { |
196 | __u64 gid, dev_t dev, | 197 | __u64 ctime; |
198 | __u64 atime; | ||
199 | __u64 mtime; | ||
200 | __u64 mode; | ||
201 | __u64 uid; | ||
202 | __u64 gid; | ||
203 | dev_t device; | ||
204 | }; | ||
205 | |||
206 | extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon, | ||
207 | char *fileName, | ||
208 | const struct cifs_unix_set_info_args *args, | ||
197 | const struct nls_table *nls_codepage, | 209 | const struct nls_table *nls_codepage, |
198 | int remap_special_chars); | 210 | int remap_special_chars); |
199 | 211 | ||
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index c621ffa2ca90..994de7c90474 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -128,8 +128,7 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon) | |||
128 | write_lock(&GlobalSMBSeslock); | 128 | write_lock(&GlobalSMBSeslock); |
129 | list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { | 129 | list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { |
130 | open_file = list_entry(tmp, struct cifsFileInfo, tlist); | 130 | open_file = list_entry(tmp, struct cifsFileInfo, tlist); |
131 | if (open_file) | 131 | open_file->invalidHandle = true; |
132 | open_file->invalidHandle = true; | ||
133 | } | 132 | } |
134 | write_unlock(&GlobalSMBSeslock); | 133 | write_unlock(&GlobalSMBSeslock); |
135 | /* BB Add call to invalidate_inodes(sb) for all superblocks mounted | 134 | /* BB Add call to invalidate_inodes(sb) for all superblocks mounted |
@@ -4816,8 +4815,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4816 | time and resort to the original setpathinfo level which takes the ancient | 4815 | time and resort to the original setpathinfo level which takes the ancient |
4817 | DOS time format with 2 second granularity */ | 4816 | DOS time format with 2 second granularity */ |
4818 | int | 4817 | int |
4819 | CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | 4818 | CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
4820 | const FILE_BASIC_INFO *data, __u16 fid) | 4819 | const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener) |
4821 | { | 4820 | { |
4822 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4821 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4823 | char *data_offset; | 4822 | char *data_offset; |
@@ -4830,11 +4829,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4830 | if (rc) | 4829 | if (rc) |
4831 | return rc; | 4830 | return rc; |
4832 | 4831 | ||
4833 | /* At this point there is no need to override the current pid | 4832 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); |
4834 | with the pid of the opener, but that could change if we someday | 4833 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); |
4835 | use an existing handle (rather than opening one on the fly) */ | ||
4836 | /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | ||
4837 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/ | ||
4838 | 4834 | ||
4839 | params = 6; | 4835 | params = 6; |
4840 | pSMB->MaxSetupCount = 0; | 4836 | pSMB->MaxSetupCount = 0; |
@@ -4882,9 +4878,9 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4882 | 4878 | ||
4883 | 4879 | ||
4884 | int | 4880 | int |
4885 | CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 4881 | CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, |
4886 | const FILE_BASIC_INFO *data, | 4882 | const char *fileName, const FILE_BASIC_INFO *data, |
4887 | const struct nls_table *nls_codepage, int remap) | 4883 | const struct nls_table *nls_codepage, int remap) |
4888 | { | 4884 | { |
4889 | TRANSACTION2_SPI_REQ *pSMB = NULL; | 4885 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
4890 | TRANSACTION2_SPI_RSP *pSMBr = NULL; | 4886 | TRANSACTION2_SPI_RSP *pSMBr = NULL; |
@@ -5013,10 +5009,9 @@ SetAttrLgcyRetry: | |||
5013 | #endif /* temporarily unneeded SetAttr legacy function */ | 5009 | #endif /* temporarily unneeded SetAttr legacy function */ |
5014 | 5010 | ||
5015 | int | 5011 | int |
5016 | CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, | 5012 | CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, |
5017 | char *fileName, __u64 mode, __u64 uid, __u64 gid, | 5013 | const struct cifs_unix_set_info_args *args, |
5018 | dev_t device, const struct nls_table *nls_codepage, | 5014 | const struct nls_table *nls_codepage, int remap) |
5019 | int remap) | ||
5020 | { | 5015 | { |
5021 | TRANSACTION2_SPI_REQ *pSMB = NULL; | 5016 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
5022 | TRANSACTION2_SPI_RSP *pSMBr = NULL; | 5017 | TRANSACTION2_SPI_RSP *pSMBr = NULL; |
@@ -5025,6 +5020,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, | |||
5025 | int bytes_returned = 0; | 5020 | int bytes_returned = 0; |
5026 | FILE_UNIX_BASIC_INFO *data_offset; | 5021 | FILE_UNIX_BASIC_INFO *data_offset; |
5027 | __u16 params, param_offset, offset, count, byte_count; | 5022 | __u16 params, param_offset, offset, count, byte_count; |
5023 | __u64 mode = args->mode; | ||
5028 | 5024 | ||
5029 | cFYI(1, ("In SetUID/GID/Mode")); | 5025 | cFYI(1, ("In SetUID/GID/Mode")); |
5030 | setPermsRetry: | 5026 | setPermsRetry: |
@@ -5080,16 +5076,16 @@ setPermsRetry: | |||
5080 | set file size and do not want to truncate file size to zero | 5076 | set file size and do not want to truncate file size to zero |
5081 | accidently as happened on one Samba server beta by putting | 5077 | accidently as happened on one Samba server beta by putting |
5082 | zero instead of -1 here */ | 5078 | zero instead of -1 here */ |
5083 | data_offset->EndOfFile = NO_CHANGE_64; | 5079 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); |
5084 | data_offset->NumOfBytes = NO_CHANGE_64; | 5080 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); |
5085 | data_offset->LastStatusChange = NO_CHANGE_64; | 5081 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); |
5086 | data_offset->LastAccessTime = NO_CHANGE_64; | 5082 | data_offset->LastAccessTime = cpu_to_le64(args->atime); |
5087 | data_offset->LastModificationTime = NO_CHANGE_64; | 5083 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); |
5088 | data_offset->Uid = cpu_to_le64(uid); | 5084 | data_offset->Uid = cpu_to_le64(args->uid); |
5089 | data_offset->Gid = cpu_to_le64(gid); | 5085 | data_offset->Gid = cpu_to_le64(args->gid); |
5090 | /* better to leave device as zero when it is */ | 5086 | /* better to leave device as zero when it is */ |
5091 | data_offset->DevMajor = cpu_to_le64(MAJOR(device)); | 5087 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); |
5092 | data_offset->DevMinor = cpu_to_le64(MINOR(device)); | 5088 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); |
5093 | data_offset->Permissions = cpu_to_le64(mode); | 5089 | data_offset->Permissions = cpu_to_le64(mode); |
5094 | 5090 | ||
5095 | if (S_ISREG(mode)) | 5091 | if (S_ISREG(mode)) |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index b51d5777cde6..0711db65afe8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -151,7 +151,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
151 | } | 151 | } |
152 | list_for_each(tmp, &GlobalTreeConnectionList) { | 152 | list_for_each(tmp, &GlobalTreeConnectionList) { |
153 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 153 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); |
154 | if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) | 154 | if ((tcon->ses) && (tcon->ses->server == server)) |
155 | tcon->tidStatus = CifsNeedReconnect; | 155 | tcon->tidStatus = CifsNeedReconnect; |
156 | } | 156 | } |
157 | read_unlock(&GlobalSMBSeslock); | 157 | read_unlock(&GlobalSMBSeslock); |
@@ -173,14 +173,12 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
173 | mid_entry = list_entry(tmp, struct | 173 | mid_entry = list_entry(tmp, struct |
174 | mid_q_entry, | 174 | mid_q_entry, |
175 | qhead); | 175 | qhead); |
176 | if (mid_entry) { | 176 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { |
177 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { | ||
178 | /* Mark other intransit requests as needing | 177 | /* Mark other intransit requests as needing |
179 | retry so we do not immediately mark the | 178 | retry so we do not immediately mark the |
180 | session bad again (ie after we reconnect | 179 | session bad again (ie after we reconnect |
181 | below) as they timeout too */ | 180 | below) as they timeout too */ |
182 | mid_entry->midState = MID_RETRY_NEEDED; | 181 | mid_entry->midState = MID_RETRY_NEEDED; |
183 | } | ||
184 | } | 182 | } |
185 | } | 183 | } |
186 | spin_unlock(&GlobalMid_Lock); | 184 | spin_unlock(&GlobalMid_Lock); |
@@ -351,11 +349,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
351 | 349 | ||
352 | current->flags |= PF_MEMALLOC; | 350 | current->flags |= PF_MEMALLOC; |
353 | cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); | 351 | cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); |
354 | write_lock(&GlobalSMBSeslock); | 352 | |
355 | atomic_inc(&tcpSesAllocCount); | 353 | length = atomic_inc_return(&tcpSesAllocCount); |
356 | length = tcpSesAllocCount.counter; | 354 | if (length > 1) |
357 | write_unlock(&GlobalSMBSeslock); | ||
358 | if (length > 1) | ||
359 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, | 355 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
360 | GFP_KERNEL); | 356 | GFP_KERNEL); |
361 | 357 | ||
@@ -745,14 +741,11 @@ multi_t2_fnd: | |||
745 | coming home not much else we can do but free the memory */ | 741 | coming home not much else we can do but free the memory */ |
746 | } | 742 | } |
747 | 743 | ||
748 | write_lock(&GlobalSMBSeslock); | ||
749 | atomic_dec(&tcpSesAllocCount); | ||
750 | length = tcpSesAllocCount.counter; | ||
751 | |||
752 | /* last chance to mark ses pointers invalid | 744 | /* last chance to mark ses pointers invalid |
753 | if there are any pointing to this (e.g | 745 | if there are any pointing to this (e.g |
754 | if a crazy root user tried to kill cifsd | 746 | if a crazy root user tried to kill cifsd |
755 | kernel thread explicitly this might happen) */ | 747 | kernel thread explicitly this might happen) */ |
748 | write_lock(&GlobalSMBSeslock); | ||
756 | list_for_each(tmp, &GlobalSMBSessionList) { | 749 | list_for_each(tmp, &GlobalSMBSessionList) { |
757 | ses = list_entry(tmp, struct cifsSesInfo, | 750 | ses = list_entry(tmp, struct cifsSesInfo, |
758 | cifsSessionList); | 751 | cifsSessionList); |
@@ -763,6 +756,8 @@ multi_t2_fnd: | |||
763 | 756 | ||
764 | kfree(server->hostname); | 757 | kfree(server->hostname); |
765 | kfree(server); | 758 | kfree(server); |
759 | |||
760 | length = atomic_dec_return(&tcpSesAllocCount); | ||
766 | if (length > 0) | 761 | if (length > 0) |
767 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, | 762 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
768 | GFP_KERNEL); | 763 | GFP_KERNEL); |
@@ -3623,97 +3618,91 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3623 | } | 3618 | } |
3624 | first_time = 1; | 3619 | first_time = 1; |
3625 | } | 3620 | } |
3626 | if (!rc) { | 3621 | |
3627 | pSesInfo->flags = 0; | 3622 | if (rc) |
3628 | pSesInfo->capabilities = pSesInfo->server->capabilities; | 3623 | goto ss_err_exit; |
3629 | if (linuxExtEnabled == 0) | 3624 | |
3630 | pSesInfo->capabilities &= (~CAP_UNIX); | 3625 | pSesInfo->flags = 0; |
3626 | pSesInfo->capabilities = pSesInfo->server->capabilities; | ||
3627 | if (linuxExtEnabled == 0) | ||
3628 | pSesInfo->capabilities &= (~CAP_UNIX); | ||
3631 | /* pSesInfo->sequence_number = 0;*/ | 3629 | /* pSesInfo->sequence_number = 0;*/ |
3632 | cFYI(1, | 3630 | cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", |
3633 | ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", | 3631 | pSesInfo->server->secMode, |
3634 | pSesInfo->server->secMode, | 3632 | pSesInfo->server->capabilities, |
3635 | pSesInfo->server->capabilities, | 3633 | pSesInfo->server->timeAdj)); |
3636 | pSesInfo->server->timeAdj)); | 3634 | if (experimEnabled < 2) |
3637 | if (experimEnabled < 2) | 3635 | rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); |
3638 | rc = CIFS_SessSetup(xid, pSesInfo, | 3636 | else if (extended_security |
3639 | first_time, nls_info); | 3637 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
3640 | else if (extended_security | 3638 | && (pSesInfo->server->secType == NTLMSSP)) { |
3641 | && (pSesInfo->capabilities | 3639 | rc = -EOPNOTSUPP; |
3642 | & CAP_EXTENDED_SECURITY) | 3640 | } else if (extended_security |
3643 | && (pSesInfo->server->secType == NTLMSSP)) { | 3641 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
3644 | rc = -EOPNOTSUPP; | 3642 | && (pSesInfo->server->secType == RawNTLMSSP)) { |
3645 | } else if (extended_security | 3643 | cFYI(1, ("NTLMSSP sesssetup")); |
3646 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3644 | rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, |
3647 | && (pSesInfo->server->secType == RawNTLMSSP)) { | 3645 | nls_info); |
3648 | cFYI(1, ("NTLMSSP sesssetup")); | 3646 | if (!rc) { |
3649 | rc = CIFSNTLMSSPNegotiateSessSetup(xid, | 3647 | if (ntlmv2_flag) { |
3650 | pSesInfo, | 3648 | char *v2_response; |
3651 | &ntlmv2_flag, | 3649 | cFYI(1, ("more secure NTLM ver2 hash")); |
3652 | nls_info); | 3650 | if (CalcNTLMv2_partial_mac_key(pSesInfo, |
3653 | if (!rc) { | 3651 | nls_info)) { |
3654 | if (ntlmv2_flag) { | 3652 | rc = -ENOMEM; |
3655 | char *v2_response; | 3653 | goto ss_err_exit; |
3656 | cFYI(1, ("more secure NTLM ver2 hash")); | 3654 | } else |
3657 | if (CalcNTLMv2_partial_mac_key(pSesInfo, | 3655 | v2_response = kmalloc(16 + 64 /* blob*/, |
3658 | nls_info)) { | 3656 | GFP_KERNEL); |
3659 | rc = -ENOMEM; | 3657 | if (v2_response) { |
3660 | goto ss_err_exit; | 3658 | CalcNTLMv2_response(pSesInfo, |
3661 | } else | 3659 | v2_response); |
3662 | v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); | 3660 | /* if (first_time) |
3663 | if (v2_response) { | 3661 | cifs_calculate_ntlmv2_mac_key */ |
3664 | CalcNTLMv2_response(pSesInfo, | 3662 | kfree(v2_response); |
3665 | v2_response); | ||
3666 | /* if (first_time) | ||
3667 | cifs_calculate_ntlmv2_mac_key( | ||
3668 | pSesInfo->server->mac_signing_key, | ||
3669 | response, ntlm_session_key,*/ | ||
3670 | kfree(v2_response); | ||
3671 | /* BB Put dummy sig in SessSetup PDU? */ | 3663 | /* BB Put dummy sig in SessSetup PDU? */ |
3672 | } else { | ||
3673 | rc = -ENOMEM; | ||
3674 | goto ss_err_exit; | ||
3675 | } | ||
3676 | |||
3677 | } else { | 3664 | } else { |
3678 | SMBNTencrypt(pSesInfo->password, | 3665 | rc = -ENOMEM; |
3679 | pSesInfo->server->cryptKey, | 3666 | goto ss_err_exit; |
3680 | ntlm_session_key); | ||
3681 | |||
3682 | if (first_time) | ||
3683 | cifs_calculate_mac_key( | ||
3684 | &pSesInfo->server->mac_signing_key, | ||
3685 | ntlm_session_key, | ||
3686 | pSesInfo->password); | ||
3687 | } | 3667 | } |
3668 | |||
3669 | } else { | ||
3670 | SMBNTencrypt(pSesInfo->password, | ||
3671 | pSesInfo->server->cryptKey, | ||
3672 | ntlm_session_key); | ||
3673 | |||
3674 | if (first_time) | ||
3675 | cifs_calculate_mac_key( | ||
3676 | &pSesInfo->server->mac_signing_key, | ||
3677 | ntlm_session_key, | ||
3678 | pSesInfo->password); | ||
3679 | } | ||
3688 | /* for better security the weaker lanman hash not sent | 3680 | /* for better security the weaker lanman hash not sent |
3689 | in AuthSessSetup so we no longer calculate it */ | 3681 | in AuthSessSetup so we no longer calculate it */ |
3690 | 3682 | ||
3691 | rc = CIFSNTLMSSPAuthSessSetup(xid, | 3683 | rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo, |
3692 | pSesInfo, | 3684 | ntlm_session_key, |
3693 | ntlm_session_key, | 3685 | ntlmv2_flag, |
3694 | ntlmv2_flag, | 3686 | nls_info); |
3695 | nls_info); | 3687 | } |
3696 | } | 3688 | } else { /* old style NTLM 0.12 session setup */ |
3697 | } else { /* old style NTLM 0.12 session setup */ | 3689 | SMBNTencrypt(pSesInfo->password, pSesInfo->server->cryptKey, |
3698 | SMBNTencrypt(pSesInfo->password, | 3690 | ntlm_session_key); |
3699 | pSesInfo->server->cryptKey, | ||
3700 | ntlm_session_key); | ||
3701 | 3691 | ||
3702 | if (first_time) | 3692 | if (first_time) |
3703 | cifs_calculate_mac_key( | 3693 | cifs_calculate_mac_key( |
3704 | &pSesInfo->server->mac_signing_key, | 3694 | &pSesInfo->server->mac_signing_key, |
3705 | ntlm_session_key, pSesInfo->password); | 3695 | ntlm_session_key, pSesInfo->password); |
3706 | 3696 | ||
3707 | rc = CIFSSessSetup(xid, pSesInfo, | 3697 | rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); |
3708 | ntlm_session_key, nls_info); | 3698 | } |
3709 | } | 3699 | if (rc) { |
3710 | if (rc) { | 3700 | cERROR(1, ("Send error in SessSetup = %d", rc)); |
3711 | cERROR(1, ("Send error in SessSetup = %d", rc)); | 3701 | } else { |
3712 | } else { | 3702 | cFYI(1, ("CIFS Session Established successfully")); |
3713 | cFYI(1, ("CIFS Session Established successfully")); | ||
3714 | pSesInfo->status = CifsGood; | 3703 | pSesInfo->status = CifsGood; |
3715 | } | ||
3716 | } | 3704 | } |
3705 | |||
3717 | ss_err_exit: | 3706 | ss_err_exit: |
3718 | return rc; | 3707 | return rc; |
3719 | } | 3708 | } |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index fb69c1fa85c9..e962e75e6f7b 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -226,23 +226,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
226 | /* If Open reported that we actually created a file | 226 | /* If Open reported that we actually created a file |
227 | then we now have to set the mode if possible */ | 227 | then we now have to set the mode if possible */ |
228 | if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { | 228 | if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { |
229 | struct cifs_unix_set_info_args args = { | ||
230 | .mode = mode, | ||
231 | .ctime = NO_CHANGE_64, | ||
232 | .atime = NO_CHANGE_64, | ||
233 | .mtime = NO_CHANGE_64, | ||
234 | .device = 0, | ||
235 | }; | ||
236 | |||
229 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 237 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
230 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, | 238 | args.uid = (__u64) current->fsuid; |
231 | (__u64)current->fsuid, | 239 | if (inode->i_mode & S_ISGID) |
232 | (__u64)current->fsgid, | 240 | args.gid = (__u64) inode->i_gid; |
233 | 0 /* dev */, | 241 | else |
234 | cifs_sb->local_nls, | 242 | args.gid = (__u64) current->fsgid; |
235 | cifs_sb->mnt_cifs_flags & | ||
236 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
237 | } else { | 243 | } else { |
238 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, | 244 | args.uid = NO_CHANGE_64; |
239 | (__u64)-1, | 245 | args.gid = NO_CHANGE_64; |
240 | (__u64)-1, | ||
241 | 0 /* dev */, | ||
242 | cifs_sb->local_nls, | ||
243 | cifs_sb->mnt_cifs_flags & | ||
244 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
245 | } | 246 | } |
247 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | ||
248 | cifs_sb->local_nls, | ||
249 | cifs_sb->mnt_cifs_flags & | ||
250 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
246 | } else { | 251 | } else { |
247 | /* BB implement mode setting via Windows security | 252 | /* BB implement mode setting via Windows security |
248 | descriptors e.g. */ | 253 | descriptors e.g. */ |
@@ -267,7 +272,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
267 | (cifs_sb->mnt_cifs_flags & | 272 | (cifs_sb->mnt_cifs_flags & |
268 | CIFS_MOUNT_SET_UID)) { | 273 | CIFS_MOUNT_SET_UID)) { |
269 | newinode->i_uid = current->fsuid; | 274 | newinode->i_uid = current->fsuid; |
270 | newinode->i_gid = current->fsgid; | 275 | if (inode->i_mode & S_ISGID) |
276 | newinode->i_gid = | ||
277 | inode->i_gid; | ||
278 | else | ||
279 | newinode->i_gid = | ||
280 | current->fsgid; | ||
271 | } | 281 | } |
272 | } | 282 | } |
273 | } | 283 | } |
@@ -357,21 +367,24 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
357 | if (full_path == NULL) | 367 | if (full_path == NULL) |
358 | rc = -ENOMEM; | 368 | rc = -ENOMEM; |
359 | else if (pTcon->unix_ext) { | 369 | else if (pTcon->unix_ext) { |
360 | mode &= ~current->fs->umask; | 370 | struct cifs_unix_set_info_args args = { |
371 | .mode = mode & ~current->fs->umask, | ||
372 | .ctime = NO_CHANGE_64, | ||
373 | .atime = NO_CHANGE_64, | ||
374 | .mtime = NO_CHANGE_64, | ||
375 | .device = device_number, | ||
376 | }; | ||
361 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 377 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
362 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 378 | args.uid = (__u64) current->fsuid; |
363 | mode, (__u64)current->fsuid, | 379 | args.gid = (__u64) current->fsgid; |
364 | (__u64)current->fsgid, | ||
365 | device_number, cifs_sb->local_nls, | ||
366 | cifs_sb->mnt_cifs_flags & | ||
367 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
368 | } else { | 380 | } else { |
369 | rc = CIFSSMBUnixSetPerms(xid, pTcon, | 381 | args.uid = NO_CHANGE_64; |
370 | full_path, mode, (__u64)-1, (__u64)-1, | 382 | args.gid = NO_CHANGE_64; |
371 | device_number, cifs_sb->local_nls, | ||
372 | cifs_sb->mnt_cifs_flags & | ||
373 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
374 | } | 383 | } |
384 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, | ||
385 | &args, cifs_sb->local_nls, | ||
386 | cifs_sb->mnt_cifs_flags & | ||
387 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
375 | 388 | ||
376 | if (!rc) { | 389 | if (!rc) { |
377 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 390 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e692c42f24b5..ff14d14903a0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -310,18 +310,19 @@ int cifs_open(struct inode *inode, struct file *file) | |||
310 | /* time to set mode which we can not set earlier due to | 310 | /* time to set mode which we can not set earlier due to |
311 | problems creating new read-only files */ | 311 | problems creating new read-only files */ |
312 | if (pTcon->unix_ext) { | 312 | if (pTcon->unix_ext) { |
313 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 313 | struct cifs_unix_set_info_args args = { |
314 | inode->i_mode, | 314 | .mode = inode->i_mode, |
315 | (__u64)-1, (__u64)-1, 0 /* dev */, | 315 | .uid = NO_CHANGE_64, |
316 | .gid = NO_CHANGE_64, | ||
317 | .ctime = NO_CHANGE_64, | ||
318 | .atime = NO_CHANGE_64, | ||
319 | .mtime = NO_CHANGE_64, | ||
320 | .device = 0, | ||
321 | }; | ||
322 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | ||
316 | cifs_sb->local_nls, | 323 | cifs_sb->local_nls, |
317 | cifs_sb->mnt_cifs_flags & | 324 | cifs_sb->mnt_cifs_flags & |
318 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 325 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
319 | } else { | ||
320 | /* BB implement via Windows security descriptors eg | ||
321 | CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, | ||
322 | -1, -1, local_nls); | ||
323 | in the meantime could set r/o dos attribute when | ||
324 | perms are eg: mode & 0222 == 0 */ | ||
325 | } | 326 | } |
326 | } | 327 | } |
327 | 328 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 46e54d39461d..28a22092d450 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -737,7 +737,7 @@ psx_del_no_retry: | |||
737 | /* ATTRS set to normal clears r/o bit */ | 737 | /* ATTRS set to normal clears r/o bit */ |
738 | pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); | 738 | pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); |
739 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) | 739 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) |
740 | rc = CIFSSMBSetTimes(xid, pTcon, full_path, | 740 | rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, |
741 | pinfo_buf, | 741 | pinfo_buf, |
742 | cifs_sb->local_nls, | 742 | cifs_sb->local_nls, |
743 | cifs_sb->mnt_cifs_flags & | 743 | cifs_sb->mnt_cifs_flags & |
@@ -767,9 +767,10 @@ psx_del_no_retry: | |||
767 | cifs_sb->mnt_cifs_flags & | 767 | cifs_sb->mnt_cifs_flags & |
768 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 768 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
769 | if (rc == 0) { | 769 | if (rc == 0) { |
770 | rc = CIFSSMBSetFileTimes(xid, pTcon, | 770 | rc = CIFSSMBSetFileInfo(xid, pTcon, |
771 | pinfo_buf, | 771 | pinfo_buf, |
772 | netfid); | 772 | netfid, |
773 | current->tgid); | ||
773 | CIFSSMBClose(xid, pTcon, netfid); | 774 | CIFSSMBClose(xid, pTcon, netfid); |
774 | } | 775 | } |
775 | } | 776 | } |
@@ -984,32 +985,41 @@ mkdir_get_info: | |||
984 | * failed to get it from the server or was set bogus */ | 985 | * failed to get it from the server or was set bogus */ |
985 | if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) | 986 | if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) |
986 | direntry->d_inode->i_nlink = 2; | 987 | direntry->d_inode->i_nlink = 2; |
988 | |||
987 | mode &= ~current->fs->umask; | 989 | mode &= ~current->fs->umask; |
990 | /* must turn on setgid bit if parent dir has it */ | ||
991 | if (inode->i_mode & S_ISGID) | ||
992 | mode |= S_ISGID; | ||
993 | |||
988 | if (pTcon->unix_ext) { | 994 | if (pTcon->unix_ext) { |
995 | struct cifs_unix_set_info_args args = { | ||
996 | .mode = mode, | ||
997 | .ctime = NO_CHANGE_64, | ||
998 | .atime = NO_CHANGE_64, | ||
999 | .mtime = NO_CHANGE_64, | ||
1000 | .device = 0, | ||
1001 | }; | ||
989 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 1002 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
990 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 1003 | args.uid = (__u64)current->fsuid; |
991 | mode, | 1004 | if (inode->i_mode & S_ISGID) |
992 | (__u64)current->fsuid, | 1005 | args.gid = (__u64)inode->i_gid; |
993 | (__u64)current->fsgid, | 1006 | else |
994 | 0 /* dev_t */, | 1007 | args.gid = (__u64)current->fsgid; |
995 | cifs_sb->local_nls, | ||
996 | cifs_sb->mnt_cifs_flags & | ||
997 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
998 | } else { | 1008 | } else { |
999 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 1009 | args.uid = NO_CHANGE_64; |
1000 | mode, (__u64)-1, | 1010 | args.gid = NO_CHANGE_64; |
1001 | (__u64)-1, 0 /* dev_t */, | ||
1002 | cifs_sb->local_nls, | ||
1003 | cifs_sb->mnt_cifs_flags & | ||
1004 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1005 | } | 1011 | } |
1012 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | ||
1013 | cifs_sb->local_nls, | ||
1014 | cifs_sb->mnt_cifs_flags & | ||
1015 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1006 | } else { | 1016 | } else { |
1007 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | 1017 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && |
1008 | (mode & S_IWUGO) == 0) { | 1018 | (mode & S_IWUGO) == 0) { |
1009 | FILE_BASIC_INFO pInfo; | 1019 | FILE_BASIC_INFO pInfo; |
1010 | memset(&pInfo, 0, sizeof(pInfo)); | 1020 | memset(&pInfo, 0, sizeof(pInfo)); |
1011 | pInfo.Attributes = cpu_to_le32(ATTR_READONLY); | 1021 | pInfo.Attributes = cpu_to_le32(ATTR_READONLY); |
1012 | CIFSSMBSetTimes(xid, pTcon, full_path, | 1022 | CIFSSMBSetPathInfo(xid, pTcon, full_path, |
1013 | &pInfo, cifs_sb->local_nls, | 1023 | &pInfo, cifs_sb->local_nls, |
1014 | cifs_sb->mnt_cifs_flags & | 1024 | cifs_sb->mnt_cifs_flags & |
1015 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1025 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -1024,8 +1034,12 @@ mkdir_get_info: | |||
1024 | CIFS_MOUNT_SET_UID) { | 1034 | CIFS_MOUNT_SET_UID) { |
1025 | direntry->d_inode->i_uid = | 1035 | direntry->d_inode->i_uid = |
1026 | current->fsuid; | 1036 | current->fsuid; |
1027 | direntry->d_inode->i_gid = | 1037 | if (inode->i_mode & S_ISGID) |
1028 | current->fsgid; | 1038 | direntry->d_inode->i_gid = |
1039 | inode->i_gid; | ||
1040 | else | ||
1041 | direntry->d_inode->i_gid = | ||
1042 | current->fsgid; | ||
1029 | } | 1043 | } |
1030 | } | 1044 | } |
1031 | } | 1045 | } |
@@ -1310,10 +1324,11 @@ int cifs_revalidate(struct dentry *direntry) | |||
1310 | /* if (S_ISDIR(direntry->d_inode->i_mode)) | 1324 | /* if (S_ISDIR(direntry->d_inode->i_mode)) |
1311 | shrink_dcache_parent(direntry); */ | 1325 | shrink_dcache_parent(direntry); */ |
1312 | if (S_ISREG(direntry->d_inode->i_mode)) { | 1326 | if (S_ISREG(direntry->d_inode->i_mode)) { |
1313 | if (direntry->d_inode->i_mapping) | 1327 | if (direntry->d_inode->i_mapping) { |
1314 | wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); | 1328 | wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); |
1315 | if (wbrc) | 1329 | if (wbrc) |
1316 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; | 1330 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; |
1331 | } | ||
1317 | /* may eventually have to do this for open files too */ | 1332 | /* may eventually have to do this for open files too */ |
1318 | if (list_empty(&(cifsInode->openFileList))) { | 1333 | if (list_empty(&(cifsInode->openFileList))) { |
1319 | /* changed on server - flush read ahead pages */ | 1334 | /* changed on server - flush read ahead pages */ |
@@ -1489,30 +1504,228 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1489 | return rc; | 1504 | return rc; |
1490 | } | 1505 | } |
1491 | 1506 | ||
1492 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | 1507 | static int |
1508 | cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | ||
1509 | char *full_path, __u32 dosattr) | ||
1510 | { | ||
1511 | int rc; | ||
1512 | int oplock = 0; | ||
1513 | __u16 netfid; | ||
1514 | __u32 netpid; | ||
1515 | bool set_time = false; | ||
1516 | struct cifsFileInfo *open_file; | ||
1517 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
1518 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1519 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
1520 | FILE_BASIC_INFO info_buf; | ||
1521 | |||
1522 | if (attrs->ia_valid & ATTR_ATIME) { | ||
1523 | set_time = true; | ||
1524 | info_buf.LastAccessTime = | ||
1525 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); | ||
1526 | } else | ||
1527 | info_buf.LastAccessTime = 0; | ||
1528 | |||
1529 | if (attrs->ia_valid & ATTR_MTIME) { | ||
1530 | set_time = true; | ||
1531 | info_buf.LastWriteTime = | ||
1532 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); | ||
1533 | } else | ||
1534 | info_buf.LastWriteTime = 0; | ||
1535 | |||
1536 | /* | ||
1537 | * Samba throws this field away, but windows may actually use it. | ||
1538 | * Do not set ctime unless other time stamps are changed explicitly | ||
1539 | * (i.e. by utimes()) since we would then have a mix of client and | ||
1540 | * server times. | ||
1541 | */ | ||
1542 | if (set_time && (attrs->ia_valid & ATTR_CTIME)) { | ||
1543 | cFYI(1, ("CIFS - CTIME changed")); | ||
1544 | info_buf.ChangeTime = | ||
1545 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); | ||
1546 | } else | ||
1547 | info_buf.ChangeTime = 0; | ||
1548 | |||
1549 | info_buf.CreationTime = 0; /* don't change */ | ||
1550 | info_buf.Attributes = cpu_to_le32(dosattr); | ||
1551 | |||
1552 | /* | ||
1553 | * If the file is already open for write, just use that fileid | ||
1554 | */ | ||
1555 | open_file = find_writable_file(cifsInode); | ||
1556 | if (open_file) { | ||
1557 | netfid = open_file->netfid; | ||
1558 | netpid = open_file->pid; | ||
1559 | goto set_via_filehandle; | ||
1560 | } | ||
1561 | |||
1562 | /* | ||
1563 | * NT4 apparently returns success on this call, but it doesn't | ||
1564 | * really work. | ||
1565 | */ | ||
1566 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) { | ||
1567 | rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, | ||
1568 | &info_buf, cifs_sb->local_nls, | ||
1569 | cifs_sb->mnt_cifs_flags & | ||
1570 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1571 | if (rc != -EOPNOTSUPP && rc != -EINVAL) | ||
1572 | goto out; | ||
1573 | } | ||
1574 | |||
1575 | cFYI(1, ("calling SetFileInfo since SetPathInfo for " | ||
1576 | "times not supported by this server")); | ||
1577 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, | ||
1578 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, | ||
1579 | CREATE_NOT_DIR, &netfid, &oplock, | ||
1580 | NULL, cifs_sb->local_nls, | ||
1581 | cifs_sb->mnt_cifs_flags & | ||
1582 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1583 | |||
1584 | if (rc != 0) { | ||
1585 | if (rc == -EIO) | ||
1586 | rc = -EINVAL; | ||
1587 | goto out; | ||
1588 | } | ||
1589 | |||
1590 | netpid = current->tgid; | ||
1591 | |||
1592 | set_via_filehandle: | ||
1593 | rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid); | ||
1594 | if (open_file == NULL) | ||
1595 | CIFSSMBClose(xid, pTcon, netfid); | ||
1596 | else | ||
1597 | atomic_dec(&open_file->wrtPending); | ||
1598 | out: | ||
1599 | return rc; | ||
1600 | } | ||
1601 | |||
1602 | static int | ||
1603 | cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | ||
1493 | { | 1604 | { |
1605 | int rc; | ||
1494 | int xid; | 1606 | int xid; |
1495 | struct cifs_sb_info *cifs_sb; | ||
1496 | struct cifsTconInfo *pTcon; | ||
1497 | char *full_path = NULL; | 1607 | char *full_path = NULL; |
1498 | int rc = -EACCES; | ||
1499 | FILE_BASIC_INFO time_buf; | ||
1500 | bool set_time = false; | ||
1501 | bool set_dosattr = false; | ||
1502 | __u64 mode = 0xFFFFFFFFFFFFFFFFULL; | ||
1503 | __u64 uid = 0xFFFFFFFFFFFFFFFFULL; | ||
1504 | __u64 gid = 0xFFFFFFFFFFFFFFFFULL; | ||
1505 | struct cifsInodeInfo *cifsInode; | ||
1506 | struct inode *inode = direntry->d_inode; | 1608 | struct inode *inode = direntry->d_inode; |
1609 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
1610 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1611 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
1612 | struct cifs_unix_set_info_args *args = NULL; | ||
1613 | |||
1614 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | ||
1615 | direntry->d_name.name, attrs->ia_valid)); | ||
1616 | |||
1617 | xid = GetXid(); | ||
1618 | |||
1619 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | ||
1620 | /* check if we have permission to change attrs */ | ||
1621 | rc = inode_change_ok(inode, attrs); | ||
1622 | if (rc < 0) | ||
1623 | goto out; | ||
1624 | else | ||
1625 | rc = 0; | ||
1626 | } | ||
1627 | |||
1628 | full_path = build_path_from_dentry(direntry); | ||
1629 | if (full_path == NULL) { | ||
1630 | rc = -ENOMEM; | ||
1631 | goto out; | ||
1632 | } | ||
1633 | |||
1634 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { | ||
1635 | /* | ||
1636 | Flush data before changing file size or changing the last | ||
1637 | write time of the file on the server. If the | ||
1638 | flush returns error, store it to report later and continue. | ||
1639 | BB: This should be smarter. Why bother flushing pages that | ||
1640 | will be truncated anyway? Also, should we error out here if | ||
1641 | the flush returns error? | ||
1642 | */ | ||
1643 | rc = filemap_write_and_wait(inode->i_mapping); | ||
1644 | if (rc != 0) { | ||
1645 | cifsInode->write_behind_rc = rc; | ||
1646 | rc = 0; | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | if (attrs->ia_valid & ATTR_SIZE) { | ||
1651 | rc = cifs_set_file_size(inode, attrs, xid, full_path); | ||
1652 | if (rc != 0) | ||
1653 | goto out; | ||
1654 | } | ||
1655 | |||
1656 | /* skip mode change if it's just for clearing setuid/setgid */ | ||
1657 | if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) | ||
1658 | attrs->ia_valid &= ~ATTR_MODE; | ||
1659 | |||
1660 | args = kmalloc(sizeof(*args), GFP_KERNEL); | ||
1661 | if (args == NULL) { | ||
1662 | rc = -ENOMEM; | ||
1663 | goto out; | ||
1664 | } | ||
1665 | |||
1666 | /* set up the struct */ | ||
1667 | if (attrs->ia_valid & ATTR_MODE) | ||
1668 | args->mode = attrs->ia_mode; | ||
1669 | else | ||
1670 | args->mode = NO_CHANGE_64; | ||
1671 | |||
1672 | if (attrs->ia_valid & ATTR_UID) | ||
1673 | args->uid = attrs->ia_uid; | ||
1674 | else | ||
1675 | args->uid = NO_CHANGE_64; | ||
1676 | |||
1677 | if (attrs->ia_valid & ATTR_GID) | ||
1678 | args->gid = attrs->ia_gid; | ||
1679 | else | ||
1680 | args->gid = NO_CHANGE_64; | ||
1681 | |||
1682 | if (attrs->ia_valid & ATTR_ATIME) | ||
1683 | args->atime = cifs_UnixTimeToNT(attrs->ia_atime); | ||
1684 | else | ||
1685 | args->atime = NO_CHANGE_64; | ||
1686 | |||
1687 | if (attrs->ia_valid & ATTR_MTIME) | ||
1688 | args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime); | ||
1689 | else | ||
1690 | args->mtime = NO_CHANGE_64; | ||
1691 | |||
1692 | if (attrs->ia_valid & ATTR_CTIME) | ||
1693 | args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime); | ||
1694 | else | ||
1695 | args->ctime = NO_CHANGE_64; | ||
1696 | |||
1697 | args->device = 0; | ||
1698 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, | ||
1699 | cifs_sb->local_nls, | ||
1700 | cifs_sb->mnt_cifs_flags & | ||
1701 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1702 | |||
1703 | if (!rc) | ||
1704 | rc = inode_setattr(inode, attrs); | ||
1705 | out: | ||
1706 | kfree(args); | ||
1707 | kfree(full_path); | ||
1708 | FreeXid(xid); | ||
1709 | return rc; | ||
1710 | } | ||
1711 | |||
1712 | static int | ||
1713 | cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | ||
1714 | { | ||
1715 | int xid; | ||
1716 | struct inode *inode = direntry->d_inode; | ||
1717 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1718 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
1719 | char *full_path = NULL; | ||
1720 | int rc = -EACCES; | ||
1721 | __u32 dosattr = 0; | ||
1722 | __u64 mode = NO_CHANGE_64; | ||
1507 | 1723 | ||
1508 | xid = GetXid(); | 1724 | xid = GetXid(); |
1509 | 1725 | ||
1510 | cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", | 1726 | cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", |
1511 | direntry->d_name.name, attrs->ia_valid)); | 1727 | direntry->d_name.name, attrs->ia_valid)); |
1512 | 1728 | ||
1513 | cifs_sb = CIFS_SB(inode->i_sb); | ||
1514 | pTcon = cifs_sb->tcon; | ||
1515 | |||
1516 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | 1729 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { |
1517 | /* check if we have permission to change attrs */ | 1730 | /* check if we have permission to change attrs */ |
1518 | rc = inode_change_ok(inode, attrs); | 1731 | rc = inode_change_ok(inode, attrs); |
@@ -1528,7 +1741,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1528 | FreeXid(xid); | 1741 | FreeXid(xid); |
1529 | return -ENOMEM; | 1742 | return -ENOMEM; |
1530 | } | 1743 | } |
1531 | cifsInode = CIFS_I(inode); | ||
1532 | 1744 | ||
1533 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { | 1745 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { |
1534 | /* | 1746 | /* |
@@ -1559,21 +1771,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1559 | * CIFSACL support + proper Windows to Unix idmapping, we may be | 1771 | * CIFSACL support + proper Windows to Unix idmapping, we may be |
1560 | * able to support this in the future. | 1772 | * able to support this in the future. |
1561 | */ | 1773 | */ |
1562 | if (!pTcon->unix_ext && | 1774 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) |
1563 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { | ||
1564 | attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); | 1775 | attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); |
1565 | } else { | ||
1566 | if (attrs->ia_valid & ATTR_UID) { | ||
1567 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | ||
1568 | uid = attrs->ia_uid; | ||
1569 | } | ||
1570 | if (attrs->ia_valid & ATTR_GID) { | ||
1571 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | ||
1572 | gid = attrs->ia_gid; | ||
1573 | } | ||
1574 | } | ||
1575 | |||
1576 | time_buf.Attributes = 0; | ||
1577 | 1776 | ||
1578 | /* skip mode change if it's just for clearing setuid/setgid */ | 1777 | /* skip mode change if it's just for clearing setuid/setgid */ |
1579 | if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) | 1778 | if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) |
@@ -1584,13 +1783,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1584 | mode = attrs->ia_mode; | 1783 | mode = attrs->ia_mode; |
1585 | } | 1784 | } |
1586 | 1785 | ||
1587 | if ((pTcon->unix_ext) | 1786 | if (attrs->ia_valid & ATTR_MODE) { |
1588 | && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) | ||
1589 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, | ||
1590 | 0 /* dev_t */, cifs_sb->local_nls, | ||
1591 | cifs_sb->mnt_cifs_flags & | ||
1592 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1593 | else if (attrs->ia_valid & ATTR_MODE) { | ||
1594 | rc = 0; | 1787 | rc = 0; |
1595 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1788 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
1596 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 1789 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
@@ -1599,24 +1792,19 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1599 | #endif | 1792 | #endif |
1600 | if (((mode & S_IWUGO) == 0) && | 1793 | if (((mode & S_IWUGO) == 0) && |
1601 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 1794 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1602 | set_dosattr = true; | 1795 | |
1603 | time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | | 1796 | dosattr = cifsInode->cifsAttrs | ATTR_READONLY; |
1604 | ATTR_READONLY); | 1797 | |
1605 | /* fix up mode if we're not using dynperm */ | 1798 | /* fix up mode if we're not using dynperm */ |
1606 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | 1799 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) |
1607 | attrs->ia_mode = inode->i_mode & ~S_IWUGO; | 1800 | attrs->ia_mode = inode->i_mode & ~S_IWUGO; |
1608 | } else if ((mode & S_IWUGO) && | 1801 | } else if ((mode & S_IWUGO) && |
1609 | (cifsInode->cifsAttrs & ATTR_READONLY)) { | 1802 | (cifsInode->cifsAttrs & ATTR_READONLY)) { |
1610 | /* If file is readonly on server, we would | 1803 | |
1611 | not be able to write to it - so if any write | 1804 | dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; |
1612 | bit is enabled for user or group or other we | 1805 | /* Attributes of 0 are ignored */ |
1613 | need to at least try to remove r/o dos attr */ | 1806 | if (dosattr == 0) |
1614 | set_dosattr = true; | 1807 | dosattr |= ATTR_NORMAL; |
1615 | time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs & | ||
1616 | (~ATTR_READONLY)); | ||
1617 | /* Windows ignores set to zero */ | ||
1618 | if (time_buf.Attributes == 0) | ||
1619 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); | ||
1620 | 1808 | ||
1621 | /* reset local inode permissions to normal */ | 1809 | /* reset local inode permissions to normal */ |
1622 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | 1810 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { |
@@ -1634,82 +1822,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1634 | } | 1822 | } |
1635 | } | 1823 | } |
1636 | 1824 | ||
1637 | if (attrs->ia_valid & ATTR_ATIME) { | 1825 | if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) || |
1638 | set_time = true; | 1826 | ((attrs->ia_valid & ATTR_MODE) && dosattr)) { |
1639 | time_buf.LastAccessTime = | 1827 | rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); |
1640 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); | 1828 | /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */ |
1641 | } else | ||
1642 | time_buf.LastAccessTime = 0; | ||
1643 | |||
1644 | if (attrs->ia_valid & ATTR_MTIME) { | ||
1645 | set_time = true; | ||
1646 | time_buf.LastWriteTime = | ||
1647 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); | ||
1648 | } else | ||
1649 | time_buf.LastWriteTime = 0; | ||
1650 | /* Do not set ctime explicitly unless other time | ||
1651 | stamps are changed explicitly (i.e. by utime() | ||
1652 | since we would then have a mix of client and | ||
1653 | server times */ | ||
1654 | 1829 | ||
1655 | if (set_time && (attrs->ia_valid & ATTR_CTIME)) { | ||
1656 | set_time = true; | ||
1657 | /* Although Samba throws this field away | ||
1658 | it may be useful to Windows - but we do | ||
1659 | not want to set ctime unless some other | ||
1660 | timestamp is changing */ | ||
1661 | cFYI(1, ("CIFS - CTIME changed")); | ||
1662 | time_buf.ChangeTime = | ||
1663 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); | ||
1664 | } else | ||
1665 | time_buf.ChangeTime = 0; | ||
1666 | |||
1667 | if (set_time || set_dosattr) { | ||
1668 | time_buf.CreationTime = 0; /* do not change */ | ||
1669 | /* In the future we should experiment - try setting timestamps | ||
1670 | via Handle (SetFileInfo) instead of by path */ | ||
1671 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) | ||
1672 | rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, | ||
1673 | cifs_sb->local_nls, | ||
1674 | cifs_sb->mnt_cifs_flags & | ||
1675 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1676 | else | ||
1677 | rc = -EOPNOTSUPP; | ||
1678 | |||
1679 | if (rc == -EOPNOTSUPP) { | ||
1680 | int oplock = 0; | ||
1681 | __u16 netfid; | ||
1682 | |||
1683 | cFYI(1, ("calling SetFileInfo since SetPathInfo for " | ||
1684 | "times not supported by this server")); | ||
1685 | /* BB we could scan to see if we already have it open | ||
1686 | and pass in pid of opener to function */ | ||
1687 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, | ||
1688 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, | ||
1689 | CREATE_NOT_DIR, &netfid, &oplock, | ||
1690 | NULL, cifs_sb->local_nls, | ||
1691 | cifs_sb->mnt_cifs_flags & | ||
1692 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1693 | if (rc == 0) { | ||
1694 | rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf, | ||
1695 | netfid); | ||
1696 | CIFSSMBClose(xid, pTcon, netfid); | ||
1697 | } else { | ||
1698 | /* BB For even older servers we could convert time_buf | ||
1699 | into old DOS style which uses two second | ||
1700 | granularity */ | ||
1701 | |||
1702 | /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path, | ||
1703 | &time_buf, cifs_sb->local_nls); */ | ||
1704 | } | ||
1705 | } | ||
1706 | /* Even if error on time set, no sense failing the call if | 1830 | /* Even if error on time set, no sense failing the call if |
1707 | the server would set the time to a reasonable value anyway, | 1831 | the server would set the time to a reasonable value anyway, |
1708 | and this check ensures that we are not being called from | 1832 | and this check ensures that we are not being called from |
1709 | sys_utimes in which case we ought to fail the call back to | 1833 | sys_utimes in which case we ought to fail the call back to |
1710 | the user when the server rejects the call */ | 1834 | the user when the server rejects the call */ |
1711 | if ((rc) && (attrs->ia_valid & | 1835 | if ((rc) && (attrs->ia_valid & |
1712 | (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) | 1836 | (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) |
1713 | rc = 0; | 1837 | rc = 0; |
1714 | } | 1838 | } |
1715 | 1839 | ||
@@ -1723,6 +1847,21 @@ cifs_setattr_exit: | |||
1723 | return rc; | 1847 | return rc; |
1724 | } | 1848 | } |
1725 | 1849 | ||
1850 | int | ||
1851 | cifs_setattr(struct dentry *direntry, struct iattr *attrs) | ||
1852 | { | ||
1853 | struct inode *inode = direntry->d_inode; | ||
1854 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1855 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
1856 | |||
1857 | if (pTcon->unix_ext) | ||
1858 | return cifs_setattr_unix(direntry, attrs); | ||
1859 | |||
1860 | return cifs_setattr_nounix(direntry, attrs); | ||
1861 | |||
1862 | /* BB: add cifs_setattr_legacy for really old servers */ | ||
1863 | } | ||
1864 | |||
1726 | #if 0 | 1865 | #if 0 |
1727 | void cifs_delete_inode(struct inode *inode) | 1866 | void cifs_delete_inode(struct inode *inode) |
1728 | { | 1867 | { |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 000ac509c98a..e286db9f5ee2 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -265,6 +265,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
265 | cFYI(1, ("Sending smb: total_len %d", total_len)); | 265 | cFYI(1, ("Sending smb: total_len %d", total_len)); |
266 | dump_smb(smb_buffer, len); | 266 | dump_smb(smb_buffer, len); |
267 | 267 | ||
268 | i = 0; | ||
268 | while (total_len) { | 269 | while (total_len) { |
269 | rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec], | 270 | rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec], |
270 | n_vec - first_vec, total_len); | 271 | n_vec - first_vec, total_len); |