Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
[CIFS] list entry can not return null
turn cifs_setattr into a multiplexor that calls the correct function
move file time and dos attribute setting logic into new function
spin off cifs_setattr with unix extensions to its own function
[CIFS] Code cleanup in old sessionsetup code
[CIFS] cifs_mkdir and cifs_create should respect the setgid bit on parent dir
Rename CIFSSMBSetFileTimes to CIFSSMBSetFileInfo and add PID arg
change CIFSSMBSetTimes to CIFSSMBSetPathInfo
[CIFS] fix trailing whitespace
bundle up Unix SET_PATH_INFO args into a struct and change name
Fix missing braces in cifs_revalidate()
remove locking around tcpSesAllocCount atomic variable
[CIFS] properly account for new user= field in SPNEGO upcall string allocation
[CIFS] remove level of indentation from decode_negTokenInit
[CIFS] cifs send2 not retrying enough in some cases on full socket
[CIFS] oid should also be checked against class in cifs asn

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